commit d9897564e5671fba0de104919545f9c7c4ea2174 Author: wangyan Date: Mon Apr 25 15:37:43 2022 +0800 项目初始化 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..0b1fd00 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,118 @@ +/* + * Copyright 2007-present the original author or authors. + * + * 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 + * + * https://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. + */ + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..2cc7d4a Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..642d572 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9630b9 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# 吉林省农业资源薪资平台 + +# 创建项目必须要做的事 + +1. 基于`jeecg_base_2.4_java`项目的后台开发版。所有新项目以此为基准检出 +2. 基于此git创建项目后,更改`pom.xml`中的`artifactId`和`description` + +# 常见问题 + +### 启动类 + +`com.nd.QnModuleApplication` + +### 权限 + +将`org.jeecg.config.shiro.ShiroConfig.java.bak`去除后缀`.bak` + +注意,如果`jeecg_base_2.4_java`中的`org.jeecg.config.shiro.ShiroConfig.java`与本项目的不一致,将会导致`jeecg_base_2.4_java`中的更改丢失 + + + + + + + diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..8465a1c --- /dev/null +++ b/build.bat @@ -0,0 +1,3 @@ +@echo off +call mvn clean package +pause \ No newline at end of file diff --git a/db/Dockerfile b/db/Dockerfile new file mode 100644 index 0000000..da6132f --- /dev/null +++ b/db/Dockerfile @@ -0,0 +1,9 @@ +FROM mysql:8.0.19 + +MAINTAINER jeecgos@163.com + +ENV TZ=Asia/Shanghai + +RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +COPY ./jeecgboot-mysql-5.7.sql /docker-entrypoint-initdb.d \ No newline at end of file diff --git a/db/nyzy_jeecg_db.sql b/db/nyzy_jeecg_db.sql new file mode 100644 index 0000000..87fdf43 --- /dev/null +++ b/db/nyzy_jeecg_db.sql @@ -0,0 +1,4241 @@ +/* + Navicat Premium Data Transfer + + Source Server : mysql@local_pwd_admin + Source Server Type : MySQL + Source Server Version : 50717 + Source Host : localhost:3306 + Source Schema : nyzy_jeecg_db + + Target Server Type : MySQL + Target Server Version : 50717 + File Encoding : 65001 + + Date: 25/04/2022 15:33:02 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for ces_field_kongj +-- ---------------------------- +DROP TABLE IF EXISTS `ces_field_kongj`; +CREATE TABLE `ces_field_kongj` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名', + `sex` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '下拉框', + `radio` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'radio', + `checkbox` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'checkbox', + `sel_mut` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '下拉多选', + `sel_search` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '下拉搜索', + `birthday` datetime(0) NULL DEFAULT NULL COMMENT '时间', + `pic` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图片', + `files` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件', + `remakr` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT 'markdown', + `fuwenb` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '富文本', + `user_sel` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '选择用户', + `dep_sel` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '选择部门', + `ddd` double(10, 0) NULL DEFAULT NULL COMMENT 'DD类型', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of ces_field_kongj +-- ---------------------------- +INSERT INTO `ces_field_kongj` VALUES ('1260185893546840066', 'admin', '2020-05-12 20:31:44', 'admin', '2020-09-11 17:02:30', 'A01', 'A011', '2', '2', '1,2', '', '', NULL, '', '', '', '', 'zhagnxiao', 'A01', NULL); +INSERT INTO `ces_field_kongj` VALUES ('1260185911146139650', 'admin', '2020-05-12 20:31:49', 'admin', '2020-07-20 17:10:05', 'A01', 'A011', NULL, '1', '1,2', NULL, 'admin', NULL, 'd52a2834349b033b6d20d5cc16ce36d3d539bd7f_1594438138364.jpg', '', '', NULL, 'admin', 'A01', NULL); +INSERT INTO `ces_field_kongj` VALUES ('1285112866127577089', 'admin', '2020-07-20 15:22:38', 'admin', '2020-09-11 14:07:22', 'A01', '张三2', '', '2', '', '', '', NULL, '', '', '', '', '', '', NULL); + +-- ---------------------------- +-- Table structure for ces_order_customer +-- ---------------------------- +DROP TABLE IF EXISTS `ces_order_customer`; +CREATE TABLE `ces_order_customer` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户名字', + `sex` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客户性别', + `birthday` datetime(0) NULL DEFAULT NULL COMMENT '客户生日', + `age` int(11) NULL DEFAULT NULL COMMENT '年龄', + `address` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '常用地址', + `order_main_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '订单ID', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of ces_order_customer +-- ---------------------------- +INSERT INTO `ces_order_customer` VALUES ('1281792646935842818', 'admin', '2020-07-11 11:29:16', NULL, NULL, 'A01', NULL, NULL, NULL, NULL, NULL, '1260135645520654338'); +INSERT INTO `ces_order_customer` VALUES ('1281794386984779777', 'admin', '2020-07-11 11:36:11', NULL, NULL, 'A01', '管理员', '1', '2018-12-05 00:00:00', NULL, NULL, '1281794386716344321'); +INSERT INTO `ces_order_customer` VALUES ('15889531549290863128', 'admin', '2020-05-08 23:54:00', NULL, NULL, 'A01', '小王', '1', '2020-05-08 00:00:00', 1, '', '1258787241599250433'); +INSERT INTO `ces_order_customer` VALUES ('15889531551231672264', 'admin', '2020-05-08 23:54:00', NULL, NULL, 'A01', '校长', '2', '2020-05-23 00:00:00', 2, '', '1258787241599250433'); +INSERT INTO `ces_order_customer` VALUES ('15889531554322486243', 'admin', '2020-05-08 23:54:00', NULL, NULL, 'A01', '小明', '2', '2020-05-03 00:00:00', 3, '', '1258787241599250433'); +INSERT INTO `ces_order_customer` VALUES ('15892741044590530487', 'admin', '2020-05-12 17:02:32', NULL, NULL, 'A01A05', '111', '1', '2020-05-12 00:00:00', NULL, '', '1260133243631562754'); +INSERT INTO `ces_order_customer` VALUES ('15892741436981375151', 'admin', '2020-05-12 17:02:32', NULL, NULL, 'A01A05', '11', '1', '2020-05-14 00:00:00', NULL, '', '1260133243631562754'); + +-- ---------------------------- +-- Table structure for ces_order_goods +-- ---------------------------- +DROP TABLE IF EXISTS `ces_order_goods`; +CREATE TABLE `ces_order_goods` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `good_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品名字', + `price` double NULL DEFAULT NULL COMMENT '价格', + `num` int(11) NULL DEFAULT NULL COMMENT '数量', + `zong_price` double NULL DEFAULT NULL COMMENT '单品总价', + `order_main_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '订单ID', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of ces_order_goods +-- ---------------------------- +INSERT INTO `ces_order_goods` VALUES ('15889531536650244013', 'admin', '2020-05-08 23:54:00', NULL, NULL, 'A01', '显示器', 11, 1, 11, '1258787241599250433'); +INSERT INTO `ces_order_goods` VALUES ('15889531538491119218', 'admin', '2020-05-08 23:54:00', NULL, NULL, 'A01', '鼠标', 22, 2, 44, '1258787241599250433'); +INSERT INTO `ces_order_goods` VALUES ('15889532051192650399', 'admin', '2020-05-08 23:54:00', NULL, NULL, 'A01', '键盘', 33, 3, 99, '1258787241599250433'); +INSERT INTO `ces_order_goods` VALUES ('15892741033410312304', 'admin', '2020-05-12 17:02:32', NULL, NULL, 'A01A05', '雷蛇键盘', 200, 2, NULL, '1260133243631562754'); +INSERT INTO `ces_order_goods` VALUES ('15892741162151118866', 'admin', '2020-05-12 17:02:32', NULL, NULL, 'A01A05', '樱桃键盘', 200, 4, NULL, '1260133243631562754'); +INSERT INTO `ces_order_goods` VALUES ('15892747180850346324', 'admin', '2020-07-11 11:29:16', NULL, NULL, 'A01', '11', 11, NULL, NULL, '1260135645520654338'); +INSERT INTO `ces_order_goods` VALUES ('15892934593221167669', 'admin', '2020-07-11 11:29:16', NULL, NULL, 'A01', '', NULL, NULL, NULL, '1260135645520654338'); +INSERT INTO `ces_order_goods` VALUES ('15892934594762635052', 'admin', '2020-07-11 11:29:16', NULL, NULL, 'A01', '', NULL, NULL, NULL, '1260135645520654338'); +INSERT INTO `ces_order_goods` VALUES ('15944385645060861881', 'admin', '2020-07-11 11:36:11', NULL, NULL, 'A01', '11', NULL, NULL, NULL, '1281794386716344321'); +INSERT INTO `ces_order_goods` VALUES ('15944385663981814101', 'admin', '2020-07-11 11:36:11', NULL, NULL, 'A01', '22', NULL, NULL, NULL, '1281794386716344321'); + +-- ---------------------------- +-- Table structure for ces_order_main +-- ---------------------------- +DROP TABLE IF EXISTS `ces_order_main`; +CREATE TABLE `ces_order_main` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `order_code` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '订单编码', + `xd_date` datetime(0) NULL DEFAULT NULL COMMENT '下单时间', + `money` double NULL DEFAULT NULL COMMENT '订单总额', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of ces_order_main +-- ---------------------------- +INSERT INTO `ces_order_main` VALUES ('1258787241599250433', 'admin', '2020-05-08 23:54:00', NULL, NULL, 'A01', '20200508-0001', '2020-05-08 23:52:32', 50000, NULL); +INSERT INTO `ces_order_main` VALUES ('1260133243631562754', 'admin', '2020-05-12 17:02:32', NULL, NULL, 'A01A05', '202005120001', '2020-05-12 17:01:39', NULL, NULL); +INSERT INTO `ces_order_main` VALUES ('1260135645520654338', 'admin', '2020-05-12 17:12:04', 'admin', '2020-07-11 11:29:16', 'A01', 'JDFX2020051217115656', '2020-07-11 11:29:12', NULL, NULL); +INSERT INTO `ces_order_main` VALUES ('1281794386716344321', 'admin', '2020-07-11 11:36:11', NULL, NULL, 'A01', 'CN2020071111360067', '2020-07-11 11:36:00', NULL, NULL); + +-- ---------------------------- +-- Table structure for ces_shop_goods +-- ---------------------------- +DROP TABLE IF EXISTS `ces_shop_goods`; +CREATE TABLE `ces_shop_goods` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品名字', + `price` decimal(10, 5) NULL DEFAULT NULL COMMENT '价格', + `chuc_date` datetime(0) NULL DEFAULT NULL COMMENT '出厂时间', + `contents` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '商品简介', + `good_type_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品分类', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of ces_shop_goods +-- ---------------------------- +INSERT INTO `ces_shop_goods` VALUES ('1258408897326149634', 'admin', '2020-05-07 22:50:35', 'admin', '2020-05-07 22:52:17', 'A01', '华为手机note', 5000.00000, '2020-05-07 00:00:00', '
\n
\n
\"img\"
\n
快速开发
\n
\n
\n
\"img\"
\n
数据权限
\n
\n
\n
\"img\"
\n
工作流
\n
\n
\n
\"img\"
\n
丰富组件库
\n
\n
\n
\n
\n
\"img\"
\n
代码生成器
\n
\n
\n
\"img\"
\n
Online在线开发
\n
\n
\n
\"img\"
\n
表单设计器
\n
\n
\n
\"img\"
\n
流程设计器
\n
\n
', '1258408044439597058'); +INSERT INTO `ces_shop_goods` VALUES ('1258783909887422466', 'admin', '2020-05-08 23:40:45', 'admin', '2020-05-08 23:43:03', 'A01', '雷蛇鼠标', 500.00000, '2020-05-08 00:00:00', '', '1258408003595464706'); +INSERT INTO `ces_shop_goods` VALUES ('1285114089585082370', 'admin', '2020-07-20 15:27:29', NULL, NULL, 'A01', NULL, NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for ces_shop_type +-- ---------------------------- +DROP TABLE IF EXISTS `ces_shop_type`; +CREATE TABLE `ces_shop_type` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类名字', + `content` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述', + `pics` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图片', + `pid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级节点', + `has_child` varchar(3) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否有子节点', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of ces_shop_type +-- ---------------------------- +INSERT INTO `ces_shop_type` VALUES ('1258408003595464706', 'admin', '2020-05-07 22:47:02', NULL, NULL, 'A01', '衣服', NULL, 'e1fe9925bc315c60addea1b98eb1cb1349547719_1588862821565.jpg', '0', '0'); +INSERT INTO `ces_shop_type` VALUES ('1258408044439597058', 'admin', '2020-05-07 22:47:12', NULL, NULL, 'A01', '鞋子', NULL, 'jeewxshop测试号_1588862831749.jpg', '0', '1'); +INSERT INTO `ces_shop_type` VALUES ('1258408076693794818', 'admin', '2020-05-07 22:47:20', 'admin', '2020-07-10 16:51:10', 'A01', '耐克', NULL, 'd52a2834349b033b6d20d5cc16ce36d3d539bd7f_1594371069797.jpg', '1258408044439597058', '0'); +INSERT INTO `ces_shop_type` VALUES ('1258408105487691777', 'admin', '2020-05-07 22:47:27', 'admin', '2020-11-26 15:21:57', 'A01', '阿迪', '', 'temp/20180607175028Fn1Lq7zw_1589293474710.png', '1258408044439597058', '0'); + +-- ---------------------------- +-- Table structure for demo +-- ---------------------------- +DROP TABLE IF EXISTS `demo`; +CREATE TABLE `demo` ( + `id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键ID', + `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名', + `key_word` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '关键词', + `punch_time` datetime(0) NULL DEFAULT NULL COMMENT '打卡时间', + `salary_money` decimal(10, 3) NULL DEFAULT NULL COMMENT '工资', + `bonus_money` double(10, 2) NULL DEFAULT NULL COMMENT '奖金', + `sex` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别 {男:1,女:2}', + `age` int(11) NULL DEFAULT NULL COMMENT '年龄', + `birthday` date NULL DEFAULT NULL COMMENT '生日', + `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱', + `content` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '个人简介', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `sys_org_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '所属部门编码', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of demo +-- ---------------------------- +INSERT INTO `demo` VALUES ('1260935385049055234', '111', '111', NULL, NULL, NULL, NULL, 20, NULL, NULL, NULL, 'jeecg', '2020-05-14 22:09:57', 'admin', '2020-09-10 17:19:44', 'A02A01'); +INSERT INTO `demo` VALUES ('1260935402346364930', '22', '222', NULL, NULL, NULL, '', 19, NULL, '', '', 'jeecg', '2020-05-14 22:10:02', 'admin', '2020-09-10 17:19:39', 'A02A01'); +INSERT INTO `demo` VALUES ('1c2ba51b29a42d9de02bbd708ea8121a', '777777', '777', '2018-12-07 19:43:17', NULL, NULL, NULL, 7, '2018-12-07', NULL, NULL, NULL, NULL, 'admin', '2019-02-21 18:26:04', NULL); +INSERT INTO `demo` VALUES ('1dc29e80be14d1400f165b5c6b30c707', 'zhang daihao', NULL, NULL, NULL, NULL, '2', NULL, NULL, 'zhangdaiscott@163.com', NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `demo` VALUES ('304e651dc769d5c9b6e08fb30457a602', '小白兔', NULL, NULL, NULL, NULL, '2', 28, NULL, NULL, NULL, 'scott', '2019-01-19 13:12:53', 'qinfeng', '2019-01-19 13:13:12', NULL); +INSERT INTO `demo` VALUES ('4', 'Sandy', '开源,很好', '2018-12-15 00:00:00', NULL, NULL, '2', 21, '2018-12-15', 'test4@baomidou.com', '聪明00', NULL, NULL, 'admin', '2019-02-25 16:29:27', NULL); +INSERT INTO `demo` VALUES ('4436302a0de50bb83025286bc414d6a9', 'zhang daihao', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'zhangdaiscott@163.com', NULL, 'admin', '2019-01-19 15:39:04', NULL, NULL, NULL); +INSERT INTO `demo` VALUES ('4981637bf71b0c1ed1365241dfcfa0ea', '小虎', NULL, NULL, NULL, NULL, '2', 28, NULL, NULL, NULL, 'scott5', '2019-01-19 13:12:53', 'qinfeng', '2019-01-19 13:13:12', 'A02'); +INSERT INTO `demo` VALUES ('7', 'zhangdaiscott', NULL, NULL, NULL, NULL, '1', NULL, '2019-01-03', NULL, NULL, NULL, NULL, NULL, NULL, 'A02A01A01'); +INSERT INTO `demo` VALUES ('73bc58611012617ca446d8999379e4ac', '郭靖', '777', '2018-12-07 00:00:00', NULL, NULL, '1', NULL, NULL, NULL, NULL, 'jeecg-boot', '2019-03-28 18:16:39', 'admin', '2020-05-02 18:14:14', 'A02A01A02'); +INSERT INTO `demo` VALUES ('917e240eaa0b1b2d198ae869b64a81c3', 'zhang daihao', NULL, NULL, NULL, NULL, '2', 0, '2018-11-29', 'zhangdaiscott@163.com', NULL, NULL, NULL, NULL, NULL, 'A02'); +INSERT INTO `demo` VALUES ('94420c5d8fc4420dde1e7196154b3a24', '秦风', NULL, NULL, NULL, NULL, '2', NULL, NULL, NULL, NULL, 'scott', '2019-01-19 12:54:58', 'admin', '2020-05-02 18:14:33', NULL); +INSERT INTO `demo` VALUES ('b86897900c770503771c7bb88e5d1e9b', 'scott1', '开源、很好、hello', NULL, NULL, NULL, '1', NULL, NULL, 'zhangdaiscott@163.com', NULL, 'scott', '2019-01-19 12:22:34', NULL, NULL, NULL); +INSERT INTO `demo` VALUES ('c28fa8391ef81d6fabd8bd894a7615aa', '小麦', NULL, NULL, NULL, NULL, '2', NULL, NULL, 'zhangdaiscott@163.com', NULL, 'jeecg-boot', '2019-04-04 17:18:09', NULL, NULL, NULL); +INSERT INTO `demo` VALUES ('c2c0d49e3c01913067cf8d1fb3c971d2', 'zhang daihao', NULL, NULL, NULL, NULL, '2', NULL, NULL, 'zhangdaiscott@163.com', NULL, 'admin', '2019-01-19 23:37:18', 'admin', '2019-01-21 16:49:06', NULL); +INSERT INTO `demo` VALUES ('c96279c666b4b82e3ef1e4e2978701ce', '报名时间', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'jeecg-boot', '2019-03-28 18:00:52', NULL, NULL, NULL); +INSERT INTO `demo` VALUES ('d24668721446e8478eeeafe4db66dcff', 'zhang daihao999', NULL, NULL, NULL, NULL, '1', NULL, NULL, 'zhangdaiscott@163.com', NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `demo` VALUES ('eaa6c1116b41dc10a94eae34cf990133', 'zhang daihao', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'zhangdaiscott@163.com', NULL, NULL, NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for demo_field_def_val_main +-- ---------------------------- +DROP TABLE IF EXISTS `demo_field_def_val_main`; +CREATE TABLE `demo_field_def_val_main` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '编码', + `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名', + `sex` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '性别', + `address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址', + `address_param` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址(传参)', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of demo_field_def_val_main +-- ---------------------------- +INSERT INTO `demo_field_def_val_main` VALUES ('1256548579457114114', 'q', 'q', '1', 'q', 'q', 'admin', '2020-05-02 19:38:21', 'admin', '2020-05-03 01:02:51', 'A01'); + +-- ---------------------------- +-- Table structure for demo_field_def_val_sub +-- ---------------------------- +DROP TABLE IF EXISTS `demo_field_def_val_sub`; +CREATE TABLE `demo_field_def_val_sub` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '编码', + `name` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称', + `date` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '日期', + `main_id` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '主表ID', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of demo_field_def_val_sub +-- ---------------------------- +INSERT INTO `demo_field_def_val_sub` VALUES ('15884194974080425602', '133', '管理员', '2020-05-02', '1256548579457114114', 'admin', '2020-05-03 01:02:51', NULL, NULL, 'A01'); +INSERT INTO `demo_field_def_val_sub` VALUES ('15884194979201535108', '1144', '管理员', '2020-05-02', '1256548579457114114', 'admin', '2020-05-03 01:02:51', NULL, NULL, 'A01'); + +-- ---------------------------- +-- Table structure for jeecg_monthly_growth_analysis +-- ---------------------------- +DROP TABLE IF EXISTS `jeecg_monthly_growth_analysis`; +CREATE TABLE `jeecg_monthly_growth_analysis` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `month` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '月份', + `main_income` decimal(18, 2) NULL DEFAULT 0.00 COMMENT '佣金/主营收入', + `other_income` decimal(18, 2) NULL DEFAULT 0.00 COMMENT '其他收入', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 25 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of jeecg_monthly_growth_analysis +-- ---------------------------- +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (1, '2018', '1月', 114758.90, 4426054.19); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (2, '2018', '2月', 8970734.12, 1230188.67); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (3, '2018', '3月', 26755421.23, 2048836.84); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (4, '2018', '4月', 2404990.63, 374171.44); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (5, '2018', '5月', 5450793.02, 502306.10); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (6, '2018', '6月', 17186212.11, 1375154.97); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (7, '2018', '7月', 579975.67, 461483.99); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (8, '2018', '8月', 1393590.06, 330403.76); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (9, '2018', '9月', 735761.21, 1647474.92); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (10, '2018', '10月', 1670442.44, 3423368.33); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (11, '2018', '11月', 2993130.34, 3552024.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (12, '2018', '12月', 4206227.26, 3645614.92); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (13, '2019', '1月', 483834.66, 418046.77); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (14, '2019', '2月', 11666578.65, 731352.20); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (15, '2019', '3月', 27080982.08, 1878538.81); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (16, '2019', '4月', 0.00, 0.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (17, '2019', '5月', 0.00, 0.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (18, '2019', '6月', 0.00, 0.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (19, '2019', '7月', 0.00, 0.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (20, '2019', '8月', 0.00, 0.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (21, '2019', '9月', 0.00, 0.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (22, '2019', '10月', 0.00, 0.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (23, '2019', '11月', 0.00, 0.00); +INSERT INTO `jeecg_monthly_growth_analysis` VALUES (24, '2019', '12月', 0.00, 0.00); + +-- ---------------------------- +-- Table structure for jeecg_order_customer +-- ---------------------------- +DROP TABLE IF EXISTS `jeecg_order_customer`; +CREATE TABLE `jeecg_order_customer` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', + `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '客户名', + `sex` varchar(4) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别', + `idcard` varchar(18) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '身份证号码', + `idcard_pic` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '身份证扫描件', + `telphone` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电话1', + `order_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '外键', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of jeecg_order_customer +-- ---------------------------- +INSERT INTO `jeecg_order_customer` VALUES ('1256527640480821249', 'scott', '2', NULL, NULL, NULL, 'b190737bd04cca8360e6f87c9ef9ec4e', 'admin', '2020-05-02 18:15:09', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('1256527640531152898', 'x秦风', '1', NULL, NULL, NULL, 'b190737bd04cca8360e6f87c9ef9ec4e', 'admin', '2020-05-02 18:15:09', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('1256527874216800257', '小王1', '1', '', NULL, '', '9a57c850e4f68cf94ef7d8585dbaf7e6', 'admin', '2020-05-02 18:17:37', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('15538561502720', '3333', '1', '', NULL, '', '0d4a2e67b538ee1bc881e5ed34f670f0', 'jeecg-boot', '2019-03-29 18:42:55', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('15538561512681', '3332333', '2', '', NULL, '', '0d4a2e67b538ee1bc881e5ed34f670f0', 'jeecg-boot', '2019-03-29 18:42:55', 'admin', '2019-03-29 18:43:12'); +INSERT INTO `jeecg_order_customer` VALUES ('15538561550142', '4442', '2', '', NULL, '', '0d4a2e67b538ee1bc881e5ed34f670f0', 'jeecg-boot', '2019-03-29 18:42:55', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('15541168497342', '444', '', '', '', '', 'f71f7f8930b5b6b1703d9948d189982b', 'admin', '2019-04-01 19:08:45', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('15541168499553', '5555', '', '', '', '', 'f71f7f8930b5b6b1703d9948d189982b', 'admin', '2019-04-01 19:08:45', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('18dc5eb1068ccdfe90e358951ca1a3d6', 'dr2', '', '', '', '', '8ab1186410a65118c4d746eb085d3bed', 'admin', '2019-04-04 17:25:33', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('195d280490fe88ca1475512ddcaf2af9', '12', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('217a2bf83709775d2cd85bf598392327', '2', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('22bc052ae53ed09913b946abba93fa89', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('23bafeae88126c3bf3322a29a04f0d5e', 'x秦风', NULL, NULL, NULL, NULL, '163e2efcbc6d7d54eb3f8a137da8a75a', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('25c4a552c6843f36fad6303bfa99a382', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('2d32144e2bee63264f3f16215c258381', '33333', '2', NULL, NULL, NULL, 'd908bfee3377e946e59220c4a4eb414a', 'admin', '2019-04-01 16:27:03', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('2d43170d6327f941bd1a017999495e25', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('2e5f62a8b6e0a0ce19b52a6feae23d48', '3', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('34a1c5cf6cee360ed610ed0bed70e0f9', '导入秦风', NULL, NULL, NULL, NULL, 'a2cce75872cc8fcc47f78de9ffd378c2', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('3c87400f8109b4cf43c5598f0d40e34d', '2', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('40964bcbbecb38e5ac15e6d08cf3cd43', '233', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('41e3dee0b0b6e6530eccb7fbb22fd7a3', '4555', '1', '370285198602058823', NULL, '18611788674', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('4808ae8344c7679a4a2f461db5dc3a70', '44', '1', '370285198602058823', NULL, '18611788674', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('4b6cef12f195fad94d57279b2241770d', 'dr12', '', '', '', '', '8ab1186410a65118c4d746eb085d3bed', 'admin', '2019-04-04 17:25:33', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('524e695283f8e8c256cc24f39d6d8542', '小王', '2', '370285198604033222', NULL, '18611788674', 'eb13ab35d2946a2b0cfe3452bca1e73f', 'admin', '2019-02-25 16:29:41', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('57c2a8367db34016114cbc9fa368dba0', '2', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('5df36a1608b8c7ac99ad9bc408fe54bf', '4', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('6c6fd2716c2dcd044ed03c2c95d261f8', '李四', '2', '370285198602058833', '', '18611788676', 'f71f7f8930b5b6b1703d9948d189982b', 'admin', '2019-04-01 19:08:45', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('742d008214dee0afff2145555692973e', '秦风', '1', '370285198602058822', NULL, '18611788676', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('7469c3e5d371767ff90a739d297689b5', '导入秦风', '2', NULL, NULL, NULL, '3a867ebf2cebce9bae3f79676d8d86f3', 'jeecg-boot', '2019-03-29 18:43:59', 'admin', '2019-04-08 17:35:02'); +INSERT INTO `jeecg_order_customer` VALUES ('7a96e2c7b24847d4a29940dbc0eda6e5', 'drscott', NULL, NULL, NULL, NULL, 'e73434dad84ebdce2d4e0c2a2f06d8ea', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('7f5a40818e225ee18bda6da7932ac5f9', '2', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('8011575abfd7c8085e71ff66df1124b9', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('8404f31d7196221a573c9bd6c8f15003', '小张', '1', '370285198602058211', NULL, '18611788676', 'eb13ab35d2946a2b0cfe3452bca1e73f', 'admin', '2019-02-25 16:29:41', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('859020e10a2f721f201cdbff78cf7b9f', 'scott', NULL, NULL, NULL, NULL, '163e2efcbc6d7d54eb3f8a137da8a75a', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('8cc3c4d26e3060975df3a2adb781eeb4', 'dr33', NULL, NULL, NULL, NULL, 'b2feb454e43c46b2038768899061e464', 'jeecg-boot', '2019-04-04 17:23:09', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('8d1725c23a6a50685ff0dedfd437030d', '4', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('933cae3a79f60a93922d59aace5346ce', '小王', NULL, '370285198604033222', NULL, '18611788674', '6a719071a29927a14f19482f8693d69a', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('9bdb5400b709ba4eaf3444de475880d7', 'dr22', NULL, NULL, NULL, NULL, '22c17790dcd04b296c4a2a089f71895f', 'jeecg-boot', '2019-04-04 17:23:09', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('9f87677f70e5f864679314389443a3eb', '33', '2', '370285198602058823', NULL, '18611788674', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('a2c2b7101f75c02deb328ba777137897', '44', '2', '370285198602058823', NULL, '18611788674', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('ab4d002dc552c326147e318c87d3bed4', '小红1', '1', '370285198604033222', NULL, '18611755848', '9a57c850e4f68cf94ef7d8585dbaf7e6', 'admin', '2020-05-02 18:17:37', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('ad116f722a438e5f23095a0b5fcc8e89', 'dr秦风', NULL, NULL, NULL, NULL, 'e73434dad84ebdce2d4e0c2a2f06d8ea', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('b1ba147b75f5eaa48212586097fc3fd1', '2', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('b43bf432c251f0e6b206e403b8ec29bc', 'lisi', NULL, NULL, NULL, NULL, 'f8889aaef6d1bccffd98d2889c0aafb5', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('bcdd300a7d44c45a66bdaac14903c801', '33', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('beb983293e47e2dc1a9b3d649aa3eb34', 'ddd3', NULL, NULL, NULL, NULL, 'd908bfee3377e946e59220c4a4eb414a', 'admin', '2019-04-01 16:27:03', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('c219808196406f1b8c7f1062589de4b5', '44', '1', '370285198602058823', NULL, '18611788674', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('c8ed061d4b27c0c7a64e100f2b1c8ab5', '张经理', '2', '370285198602058823', NULL, '18611788674', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('cc5de4af7f06cd6d250965ebe92a0395', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('cf8817bd703bf7c7c77a2118edc26cc7', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('d72b26fae42e71270fce2097a88da58a', '导入scott', NULL, 'www', NULL, NULL, '3a867ebf2cebce9bae3f79676d8d86f3', 'jeecg-boot', '2019-03-29 18:43:59', 'admin', '2019-04-08 17:35:05'); +INSERT INTO `jeecg_order_customer` VALUES ('dbdc60a6ac1a8c43f24afee384039b68', 'xiaowang', NULL, NULL, NULL, NULL, 'f8889aaef6d1bccffd98d2889c0aafb5', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('dc5883b50466de94d900919ed96d97af', '33', '1', '370285198602058823', NULL, '18611788674', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('deeb73e553ad8dc0a0b3cfd5a338de8e', '3333', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('e2570278bf189ac05df3673231326f47', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('e39cb23bb950b2bdedfc284686c6128a', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('e46fe9111a9100844af582a18a2aa402', '1', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('ee7af0acb9beb9bf8d8b3819a8a7fdc3', '2', NULL, NULL, NULL, NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('f5d2605e844192d9e548f9bd240ac908', '小张', NULL, '370285198602058211', NULL, '18611788676', '6a719071a29927a14f19482f8693d69a', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_customer` VALUES ('f6db6547382126613a3e46e7cd58a5f2', '导入scott', NULL, NULL, NULL, NULL, 'a2cce75872cc8fcc47f78de9ffd378c2', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); + +-- ---------------------------- +-- Table structure for jeecg_order_main +-- ---------------------------- +DROP TABLE IF EXISTS `jeecg_order_main`; +CREATE TABLE `jeecg_order_main` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', + `order_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '订单号', + `ctype` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '订单类型', + `order_date` datetime(0) NULL DEFAULT NULL COMMENT '订单日期', + `order_money` double(10, 3) NULL DEFAULT NULL COMMENT '订单金额', + `content` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '订单备注', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of jeecg_order_main +-- ---------------------------- +INSERT INTO `jeecg_order_main` VALUES ('163e2efcbc6d7d54eb3f8a137da8a75a', 'B100', NULL, NULL, 3000.000, NULL, 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_main` VALUES ('3a867ebf2cebce9bae3f79676d8d86f3', '导入B100', '2222', NULL, 3000.000, NULL, 'jeecg-boot', '2019-03-29 18:43:59', 'admin', '2019-04-08 17:35:13'); +INSERT INTO `jeecg_order_main` VALUES ('4cba137333127e8e31df7ad168cc3732', '青岛订单A0001', '2', '2019-04-03 10:56:07', NULL, NULL, 'admin', '2019-04-03 10:56:11', NULL, NULL); +INSERT INTO `jeecg_order_main` VALUES ('54e739bef5b67569c963c38da52581ec', 'NC911', '1', '2019-02-18 09:58:51', 40.000, NULL, 'admin', '2019-02-18 09:58:47', 'admin', '2019-02-18 09:58:59'); +INSERT INTO `jeecg_order_main` VALUES ('6a719071a29927a14f19482f8693d69a', 'c100', NULL, NULL, 5000.000, NULL, 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_main` VALUES ('8ab1186410a65118c4d746eb085d3bed', '导入400', '1', '2019-02-18 09:58:51', 40.000, NULL, 'admin', '2019-02-18 09:58:47', 'admin', '2019-02-18 09:58:59'); +INSERT INTO `jeecg_order_main` VALUES ('9a57c850e4f68cf94ef7d8585dbaf7e6', 'halou001', '1', '2019-04-04 17:30:32', 500.000, NULL, 'admin', '2019-04-04 17:30:41', 'admin', '2020-05-02 18:17:36'); +INSERT INTO `jeecg_order_main` VALUES ('a2cce75872cc8fcc47f78de9ffd378c2', '导入B100', NULL, NULL, 3000.000, NULL, 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_main` VALUES ('b190737bd04cca8360e6f87c9ef9ec4e', 'B0018888', '1', NULL, NULL, NULL, 'admin', '2019-02-15 18:39:29', 'admin', '2020-05-02 18:15:09'); +INSERT INTO `jeecg_order_main` VALUES ('d908bfee3377e946e59220c4a4eb414a', 'SSSS001', NULL, NULL, 599.000, NULL, 'admin', '2019-04-01 15:43:03', 'admin', '2019-04-01 16:26:52'); +INSERT INTO `jeecg_order_main` VALUES ('e73434dad84ebdce2d4e0c2a2f06d8ea', '导入200', NULL, NULL, 3000.000, NULL, 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_main` VALUES ('eb13ab35d2946a2b0cfe3452bca1e73f', 'BJ9980', '1', NULL, 90.000, NULL, 'admin', '2019-02-16 17:36:42', 'admin', '2019-02-16 17:46:16'); +INSERT INTO `jeecg_order_main` VALUES ('f71f7f8930b5b6b1703d9948d189982b', 'BY911', NULL, '2019-04-06 19:08:39', NULL, NULL, 'admin', '2019-04-01 16:36:02', 'admin', '2019-04-01 16:36:08'); +INSERT INTO `jeecg_order_main` VALUES ('f8889aaef6d1bccffd98d2889c0aafb5', 'A100', NULL, '2018-10-10 00:00:00', 6000.000, NULL, 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); + +-- ---------------------------- +-- Table structure for jeecg_order_ticket +-- ---------------------------- +DROP TABLE IF EXISTS `jeecg_order_ticket`; +CREATE TABLE `jeecg_order_ticket` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', + `ticket_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '航班号', + `tickect_date` datetime(0) NULL DEFAULT NULL COMMENT '航班时间', + `order_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '外键', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of jeecg_order_ticket +-- ---------------------------- +INSERT INTO `jeecg_order_ticket` VALUES ('0f0e3a40a215958f807eea08a6e1ac0a', '88', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('0fa3bd0bbcf53650c0bb3c0cac6d8cb7', 'ffff', '2019-02-21 00:00:00', 'eb13ab35d2946a2b0cfe3452bca1e73f', 'admin', '2019-02-25 16:29:41', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('1256527640543735810', '222', '2019-02-23 00:00:00', 'b190737bd04cca8360e6f87c9ef9ec4e', 'admin', '2020-05-02 18:15:09', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('1256527640560513025', '111', '2019-02-01 00:00:00', 'b190737bd04cca8360e6f87c9ef9ec4e', 'admin', '2020-05-02 18:15:09', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('14221afb4f5f749c1deef26ac56fdac3', '33', '2019-03-09 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('15538561502730', '222', NULL, '0d4a2e67b538ee1bc881e5ed34f670f0', 'jeecg-boot', '2019-03-29 18:42:55', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('15538561526461', '2244', '2019-03-29 00:00:00', '0d4a2e67b538ee1bc881e5ed34f670f0', 'jeecg-boot', '2019-03-29 18:42:55', 'admin', '2019-03-29 18:43:26'); +INSERT INTO `jeecg_order_ticket` VALUES ('15541168478913', 'hhhhh', NULL, 'f71f7f8930b5b6b1703d9948d189982b', 'admin', '2019-04-01 19:08:45', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('18905bc89ee3851805aab38ed3b505ec', '44', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('1f809cbd26f4e574697e1c10de575d72', 'A100', NULL, 'e73434dad84ebdce2d4e0c2a2f06d8ea', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('21051adb51529bdaa8798b5a3dd7f7f7', 'C10029', '2019-02-20 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('269576e766b917f8b6509a2bb0c4d4bd', 'A100', NULL, '163e2efcbc6d7d54eb3f8a137da8a75a', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('2d473ffc79e5b38a17919e15f8b7078e', '66', '2019-03-29 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('3655b66fca5fef9c6aac6d70182ffda2', 'AA123', '2019-04-01 00:00:00', 'd908bfee3377e946e59220c4a4eb414a', 'admin', '2019-04-01 16:27:03', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('365d5919155473ade45840fd626c51a9', 'dddd', '2019-04-04 17:25:29', '8ab1186410a65118c4d746eb085d3bed', 'admin', '2019-04-04 17:25:33', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('4889a782e78706ab4306a925cfb163a5', 'C34', '2019-04-01 00:00:00', 'd908bfee3377e946e59220c4a4eb414a', 'admin', '2019-04-01 16:35:00', 'admin', '2019-04-01 16:35:07'); +INSERT INTO `jeecg_order_ticket` VALUES ('48d385796382cf87fa4bdf13b42d9a28', '导入A100', NULL, '3a867ebf2cebce9bae3f79676d8d86f3', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('541faed56efbeb4be9df581bd8264d3a', '88', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('57a27a7dfd6a48e7d981f300c181b355', '6', '2019-03-30 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('5ce4dc439c874266e42e6c0ff8dc8b5c', '导入A100', NULL, 'a2cce75872cc8fcc47f78de9ffd378c2', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('645a06152998a576c051474157625c41', '88', '2019-04-04 17:25:31', '8ab1186410a65118c4d746eb085d3bed', 'admin', '2019-04-04 17:25:33', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('6e3562f2571ea9e96b2d24497b5f5eec', '55', '2019-03-23 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('8fd2b389151568738b1cc4d8e27a6110', '导入A100', NULL, 'a2cce75872cc8fcc47f78de9ffd378c2', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('93f1a84053e546f59137432ff5564cac', '55', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('969ddc5d2e198d50903686917f996470', 'A10029', '2019-04-01 00:00:00', 'f71f7f8930b5b6b1703d9948d189982b', 'admin', '2019-04-01 19:08:45', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('96e7303a8d22a5c384e08d7bcf7ac2bf', 'A100', NULL, 'e73434dad84ebdce2d4e0c2a2f06d8ea', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('9e8a3336f6c63f558f2b68ce2e1e666e', '深圳1001', '2020-05-02 00:00:00', '9a57c850e4f68cf94ef7d8585dbaf7e6', 'admin', '2020-05-02 18:17:37', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('a28db02c810c65660015095cb81ed434', 'A100', NULL, 'f8889aaef6d1bccffd98d2889c0aafb5', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('b217bb0e4ec6a45b6cbf6db880060c0f', 'A100', NULL, '6a719071a29927a14f19482f8693d69a', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('ba708df70bb2652ed1051a394cfa0bb3', '333', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('beabbfcb195d39bedeeafe8318794562', 'A1345', '2019-04-01 00:00:00', 'd908bfee3377e946e59220c4a4eb414a', 'admin', '2019-04-01 16:27:04', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('bf450223cb505f89078a311ef7b6ed16', '777', '2019-03-30 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('c06165b6603e3e1335db187b3c841eef', '北京2001', '2020-05-23 00:00:00', '9a57c850e4f68cf94ef7d8585dbaf7e6', 'admin', '2020-05-02 18:17:37', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('c113136abc26ace3a6da4e41d7dc1c7e', '44', '2019-03-15 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('c1abdc2e30aeb25de13ad6ee3488ac24', '77', '2019-03-22 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('c23751a7deb44f553ce50a94948c042a', '33', '2019-03-09 00:00:00', '8ab1186410a65118c4d746eb085d3bed', 'admin', '2019-04-04 17:25:33', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('c64547666b634b3d6a0feedcf05f25ce', 'C10019', '2019-04-01 00:00:00', 'f71f7f8930b5b6b1703d9948d189982b', 'admin', '2019-04-01 19:08:45', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('c8b8d3217f37da78dddf711a1f7da485', 'A100', NULL, '163e2efcbc6d7d54eb3f8a137da8a75a', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('cab691c1c1ff7a6dfd7248421917fd3c', 'A100', NULL, 'f8889aaef6d1bccffd98d2889c0aafb5', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('cca10a9a850b456d9b72be87da7b0883', '77', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('d2fbba11f4814d9b1d3cb1a3f342234a', 'C10019', '2019-02-18 00:00:00', '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('dbdb07a16826808e4276e84b2aa4731a', '导入A100', NULL, '3a867ebf2cebce9bae3f79676d8d86f3', 'jeecg-boot', '2019-03-29 18:43:59', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('e7075639c37513afc0bbc4bf7b5d98b9', '88', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('fa759dc104d0371f8aa28665b323dab6', '888', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); +INSERT INTO `jeecg_order_ticket` VALUES ('ff197da84a9a3af53878eddc91afbb2e', '33', NULL, '54e739bef5b67569c963c38da52581ec', 'admin', '2019-03-15 16:50:15', NULL, NULL); + +-- ---------------------------- +-- Table structure for jeecg_project_nature_income +-- ---------------------------- +DROP TABLE IF EXISTS `jeecg_project_nature_income`; +CREATE TABLE `jeecg_project_nature_income` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `nature` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '项目性质', + `insurance_fee` decimal(18, 2) NULL DEFAULT 0.00 COMMENT '保险经纪佣金费', + `risk_consulting_fee` decimal(18, 2) NULL DEFAULT 0.00 COMMENT '风险咨询费', + `evaluation_fee` decimal(18, 2) NULL DEFAULT 0.00 COMMENT '承保公估评估费', + `insurance_evaluation_fee` decimal(18, 2) NULL DEFAULT 0.00 COMMENT '保险公估费', + `bidding_consulting_fee` decimal(18, 2) NULL DEFAULT 0.00 COMMENT '投标咨询费', + `interol_consulting_fee` decimal(18, 2) NULL DEFAULT 0.00 COMMENT '内控咨询费', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of jeecg_project_nature_income +-- ---------------------------- +INSERT INTO `jeecg_project_nature_income` VALUES (1, '市场化-电商业务', 4865.41, 0.00, 0.00, 0.00, 0.00, 0.00); +INSERT INTO `jeecg_project_nature_income` VALUES (2, '统筹型', 35767081.88, 0.00, 0.00, 0.00, 0.00, 0.00); +INSERT INTO `jeecg_project_nature_income` VALUES (3, '市场化-非股东', 1487045.35, 0.00, 0.00, 0.00, 0.00, 0.00); +INSERT INTO `jeecg_project_nature_income` VALUES (4, '市场化-参控股', 382690.56, 0.00, 0.00, 0.00, 0.00, 0.00); +INSERT INTO `jeecg_project_nature_income` VALUES (5, '市场化-员工福利', 256684.91, 0.00, 0.00, 0.00, 0.00, 0.00); +INSERT INTO `jeecg_project_nature_income` VALUES (6, '市场化-再保险', 563451.03, 0.00, 0.00, 0.00, 0.00, 0.00); +INSERT INTO `jeecg_project_nature_income` VALUES (7, '市场化-海外业务', 760576.25, 770458.75, 0.00, 0.00, 0.00, 0.00); +INSERT INTO `jeecg_project_nature_income` VALUES (8, '市场化-风险咨询', 910183.93, 0.00, 0.00, 0.00, 0.00, 226415.09); + +-- ---------------------------- +-- Table structure for joa_demo +-- ---------------------------- +DROP TABLE IF EXISTS `joa_demo`; +CREATE TABLE `joa_demo` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'ID', + `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请假人', + `days` int(11) NULL DEFAULT NULL COMMENT '请假天数', + `begin_date` datetime(0) NULL DEFAULT NULL COMMENT '开始时间', + `end_date` datetime(0) NULL DEFAULT NULL COMMENT '请假结束时间', + `reason` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请假原因', + `bpm_status` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '流程状态', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人id', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人id' +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '流程测试' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for onl_auth_data +-- ---------------------------- +DROP TABLE IF EXISTS `onl_auth_data`; +CREATE TABLE `onl_auth_data` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `cgform_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'online表ID', + `rule_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则名', + `rule_column` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则列', + `rule_operator` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则条件 大于小于like', + `rule_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则值', + `status` int(11) NULL DEFAULT NULL COMMENT '1有效 0无效', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for onl_auth_page +-- ---------------------------- +DROP TABLE IF EXISTS `onl_auth_page`; +CREATE TABLE `onl_auth_page` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT ' 主键', + `cgform_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'online表id', + `code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '字段名/按钮编码', + `type` int(11) NULL DEFAULT NULL COMMENT '1字段 2按钮', + `control` int(11) NULL DEFAULT NULL COMMENT '3可编辑 5可见(仅支持两种状态值3,5)', + `page` int(11) NULL DEFAULT NULL COMMENT '3列表 5表单(仅支持两种状态值3,5)', + `status` int(11) NULL DEFAULT NULL COMMENT '1有效 0无效', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for onl_auth_relation +-- ---------------------------- +DROP TABLE IF EXISTS `onl_auth_relation`; +CREATE TABLE `onl_auth_relation` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `role_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '角色id', + `auth_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '权限id', + `type` int(11) NULL DEFAULT NULL COMMENT '1字段 2按钮 3数据权限', + `cgform_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'online表单ID', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for onl_cgform_button +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgform_button`; +CREATE TABLE `onl_cgform_button` ( + `ID` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键ID', + `BUTTON_CODE` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮编码', + `BUTTON_ICON` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮图标', + `BUTTON_NAME` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮名称', + `BUTTON_STATUS` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮状态', + `BUTTON_STYLE` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮样式', + `EXP` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表达式', + `CGFORM_HEAD_ID` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表单ID', + `OPT_TYPE` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮类型', + `ORDER_NUM` int(11) NULL DEFAULT NULL COMMENT '排序', + `OPT_POSITION` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮位置1侧面 2底部', + PRIMARY KEY (`ID`) USING BTREE, + INDEX `index_formid`(`CGFORM_HEAD_ID`) USING BTREE, + INDEX `index_button_code`(`BUTTON_CODE`) USING BTREE, + INDEX `index_button_status`(`BUTTON_STATUS`) USING BTREE, + INDEX `index_button_order`(`ORDER_NUM`) USING BTREE, + INDEX `idx_ocb_CGFORM_HEAD_ID`(`CGFORM_HEAD_ID`) USING BTREE, + INDEX `idx_ocb_BUTTON_CODE`(`BUTTON_CODE`) USING BTREE, + INDEX `idx_ocb_BUTTON_STATUS`(`BUTTON_STATUS`) USING BTREE, + INDEX `idx_ocb_ORDER_NUM`(`ORDER_NUM`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Online表单自定义按钮' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of onl_cgform_button +-- ---------------------------- +INSERT INTO `onl_cgform_button` VALUES ('108a564643763de3f4c81bc2deb463df', 'bt1', NULL, '激活', '1', 'button', NULL, '05a3a30dada7411c9109306aa4117068', 'js', NULL, '2'); +INSERT INTO `onl_cgform_button` VALUES ('7c140322fb6b1da7a5daed8b6edc0fb7', 'tjbpm', NULL, '提交流程', '1', 'link', NULL, '05a3a30dada7411c9109306aa4117068', 'js', NULL, '2'); +INSERT INTO `onl_cgform_button` VALUES ('a45bc1c6fba96be6b0c91ffcdd6b54aa', 'genereate_person_config', 'icon-edit', '生成配置', '1', 'link', NULL, 'e2faf977fdaf4b25a524f58c2441a51c', 'js', NULL, '2'); +INSERT INTO `onl_cgform_button` VALUES ('cc1d12de57a1a41d3986ed6d13e3ac11', '链接按钮测试', 'icon-edit', '自定义link', '1', 'link', NULL, 'd35109c3632c4952a19ecc094943dd71', 'js', NULL, '2'); +INSERT INTO `onl_cgform_button` VALUES ('e2a339b9fdb4091bee98408c233ab36d', 'zuofei', NULL, '作废', '1', 'form', NULL, '05a3a30dada7411c9109306aa4117068', 'js', NULL, '2'); +INSERT INTO `onl_cgform_button` VALUES ('ebcc48ef0bde4433a6faf940a5e170c1', 'button按钮测试', 'icon-edit', '自定义button', '1', 'button', NULL, 'd35109c3632c4952a19ecc094943dd71', 'js', NULL, '2'); + +-- ---------------------------- +-- Table structure for onl_cgform_enhance_java +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgform_enhance_java`; +CREATE TABLE `onl_cgform_enhance_java` ( + `ID` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `BUTTON_CODE` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮编码', + `CG_JAVA_TYPE` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '类型', + `CG_JAVA_VALUE` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '数值', + `CGFORM_HEAD_ID` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '表单ID', + `ACTIVE_STATUS` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '生效状态', + `EVENT` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'end' COMMENT '事件状态(end:结束,start:开始)', + PRIMARY KEY (`ID`) USING BTREE, + INDEX `index_fmid`(`CGFORM_HEAD_ID`) USING BTREE, + INDEX `index_buttoncode`(`BUTTON_CODE`) USING BTREE, + INDEX `index_status`(`ACTIVE_STATUS`) USING BTREE, + INDEX `idx_ejava_cgform_head_id`(`CGFORM_HEAD_ID`) USING BTREE, + INDEX `idx_ocej_BUTTON_CODE`(`BUTTON_CODE`) USING BTREE, + INDEX `idx_ocej_ACTIVE_STATUS`(`ACTIVE_STATUS`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for onl_cgform_enhance_js +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgform_enhance_js`; +CREATE TABLE `onl_cgform_enhance_js` ( + `ID` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键ID', + `CG_JS` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'JS增强内容', + `CG_JS_TYPE` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '类型', + `CONTENT` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + `CGFORM_HEAD_ID` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表单ID', + PRIMARY KEY (`ID`) USING BTREE, + INDEX `index_fmid`(`CGFORM_HEAD_ID`) USING BTREE, + INDEX `index_jstype`(`CG_JS_TYPE`) USING BTREE, + INDEX `idx_ejs_cgform_head_id`(`CGFORM_HEAD_ID`) USING BTREE, + INDEX `idx_ejs_cg_js_type`(`CG_JS_TYPE`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of onl_cgform_enhance_js +-- ---------------------------- +INSERT INTO `onl_cgform_enhance_js` VALUES ('0b326acbbc8e52c9c9ecdb19342fc3cf', '', 'form', NULL, '05a3a30dada7411c9109306aa4117068'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('274b5d741a0262d3411958f0c465c5f0', 'genereate_person_config(row){\nconsole.log(\'选择\',row)\nalert(row.name + \',个人积分配置生成成功!\');\n}', 'list', NULL, 'e2faf977fdaf4b25a524f58c2441a51c'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('2cbaf25f1edb620bea2d8de07f8233a1', 'air_china_post_materiel_item_onlChange(){\n return {\n wl_name(){\n \n let id = event.row.id\n let cnum = event.row.num\n let value = event.value\n let targrt = event.target\n let columnKey = event.column.key\n let nval = 200*cnum\n console.log(\'row\',event.row);\n console.log(\'cnum\',cnum);\n let otherValues = {\'jifen\': nval}\n \n that.triggleChangeValues(targrt,id,otherValues)\n\n }\n }\n}', 'form', NULL, 'e67d26b610dd414c884c4dbb24e71ce3'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('32e7b7373abe0fb9c4dd608b4517f814', '', 'form', NULL, '53a3e82b54b946c2b904f605875a275c'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('35d4ef464e5e8c87c9aa82ea89215fc1', '', 'list', NULL, 'e67d26b610dd414c884c4dbb24e71ce3'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('44cad4eec436328ed3cc134855f8d1d5', ' onlChange(){\n   return {\n   name(that, event) {\n that.executeMainFillRule()\n }\n }\n }', 'form', NULL, '4adec929a6594108bef5b35ee9966e9f'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('4569bc0e6126d2b8a0e0c69b9a47e8db', '', 'list', NULL, '56efb74326e74064b60933f6f8af30ea'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('6dd82d8eac166627302230a809233481', 'ces_order_goods_onlChange(){\n return {\n num(){\n \n let id = event.row.id\n let num = event.row.num\n let price = event.row.price\n\n let targrt = event.target\n \n let nval = price*num\n console.log(\'row\',event.row);\n console.log(\'num\',num);\n console.log(\'that\',that);\n let otherValues = {\'zong_price\': nval}\n \n that.triggleChangeValues(otherValues,id,targrt)\n \n\n }\n }\n}', 'form', NULL, '56efb74326e74064b60933f6f8af30ea'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('85e7acd772c8ec322b97a1fd548007e0', '', 'form', NULL, '09fd28e4b7184c1a9668496a5c496450'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('8b76f282ddc81ce99a129e90fdd977ce', '', 'form', NULL, '86bf17839a904636b7ed96201b2fa6ea'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('90394fbc3d48978cc0937bc56f2d5370', '', 'list', NULL, 'deea5a8ec619460c9245ba85dbc59e80'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('ae9cf52fbe13cc718de2de6e1b3d6792', '', 'list', NULL, '18f064d1ef424c93ba7a16148851664f'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('beec235f0b2d633ff3a6c395affdf59d', '', 'list', NULL, '4adec929a6594108bef5b35ee9966e9f'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('c5ac9a2b2fd92ef68274f630b8aec78a', 'tjbpm(row){\n alert(\'提交流程\')\n console.log(\'row\',row)\n}\n\nbt1(){\n console.log(\'that.table.selectionRows\',that.table.selectionRows)\n console.log(\'that.table.selectedRowKeys\',that.table.selectedRowKeys)\n console.log(\'that.table.dataSource\',that.table.dataSource)\n alert(\'激活全部数据\')\n}', 'list', NULL, '05a3a30dada7411c9109306aa4117068'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('d7ddb7aa407f6deed75aac11f0a25f0e', '222', 'list', NULL, '09fd28e4b7184c1a9668496a5c496450'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('f6f8f230566d09d4b66338955ffb5691', '', 'form', NULL, '18f064d1ef424c93ba7a16148851664f'); +INSERT INTO `onl_cgform_enhance_js` VALUES ('fd711738f58d5481ca0ce9bc3a415223', '', 'list', NULL, '86bf17839a904636b7ed96201b2fa6ea'); + +-- ---------------------------- +-- Table structure for onl_cgform_enhance_sql +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgform_enhance_sql`; +CREATE TABLE `onl_cgform_enhance_sql` ( + `ID` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键ID', + `BUTTON_CODE` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮编码', + `CGB_SQL` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'SQL内容', + `CGB_SQL_NAME` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Sql名称', + `CONTENT` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + `CGFORM_HEAD_ID` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表单ID', + PRIMARY KEY (`ID`) USING BTREE, + INDEX `index_formid`(`CGFORM_HEAD_ID`) USING BTREE, + INDEX `idx_oces_CGFORM_HEAD_ID`(`CGFORM_HEAD_ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of onl_cgform_enhance_sql +-- ---------------------------- +INSERT INTO `onl_cgform_enhance_sql` VALUES ('0ebf418bd02f486342123eaf84cd39ad', 'add', '', NULL, '', '18f064d1ef424c93ba7a16148851664f'); +INSERT INTO `onl_cgform_enhance_sql` VALUES ('5ab418a13fd0bbf30ee9dd04203f3c28', 'add', '', NULL, '', '4adec929a6594108bef5b35ee9966e9f'); +INSERT INTO `onl_cgform_enhance_sql` VALUES ('8750b93ba5332460c76c492359d7a06b', 'edit', '', NULL, '', '18f064d1ef424c93ba7a16148851664f'); +INSERT INTO `onl_cgform_enhance_sql` VALUES ('c1ba45b6ee70e4662b5ec95f8fdcb31f', 'add', '', NULL, '', '05a3a30dada7411c9109306aa4117068'); +INSERT INTO `onl_cgform_enhance_sql` VALUES ('edfab059050b19328ac81e6833b5ebc2', 'delete', '', NULL, '', '18f064d1ef424c93ba7a16148851664f'); + +-- ---------------------------- +-- Table structure for onl_cgform_field +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgform_field`; +CREATE TABLE `onl_cgform_field` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键ID', + `cgform_head_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '表ID', + `db_field_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字段名字', + `db_field_txt` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段备注', + `db_field_name_old` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '原字段名', + `db_is_key` tinyint(1) NULL DEFAULT NULL COMMENT '是否主键 0否 1是', + `db_is_null` tinyint(1) NULL DEFAULT NULL COMMENT '是否允许为空0否 1是', + `db_type` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '数据库字段类型', + `db_length` int(11) NOT NULL COMMENT '数据库字段长度', + `db_point_length` int(11) NULL DEFAULT NULL COMMENT '小数点', + `db_default_val` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表字段默认值', + `dict_field` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字典code', + `dict_table` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字典表', + `dict_text` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字典Text', + `field_show_type` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表单控件类型', + `field_href` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '跳转URL', + `field_length` int(11) NULL DEFAULT NULL COMMENT '表单控件长度', + `field_valid_type` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表单字段校验规则', + `field_must_input` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段是否必填', + `field_extend_json` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '扩展参数JSON', + `field_default_value` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '控件默认值,不同的表达式展示不同的结果。\r\n1. 纯字符串直接赋给默认值;\r\n2. #{普通变量};\r\n3. {{ 动态JS表达式 }};\r\n4. ${填值规则编码};\r\n填值规则表达式只允许存在一个,且不能和其他规则混用。', + `is_query` tinyint(1) NULL DEFAULT NULL COMMENT '是否查询条件0否 1是', + `is_show_form` tinyint(1) NULL DEFAULT NULL COMMENT '表单是否显示0否 1是', + `is_show_list` tinyint(1) NULL DEFAULT NULL COMMENT '列表是否显示0否 1是', + `is_read_only` tinyint(1) NULL DEFAULT 0 COMMENT '是否是只读(1是 0否)', + `query_mode` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询模式', + `main_table` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '外键主表名', + `main_field` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '外键主键字段', + `order_num` int(11) NULL DEFAULT NULL COMMENT '排序', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `converter` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '自定义值转换器', + `query_def_val` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询默认值', + `query_dict_text` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询配置字典text', + `query_dict_field` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询配置字典code', + `query_dict_table` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询配置字典table', + `query_show_type` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询显示控件', + `query_config_flag` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否启用查询配置1是0否', + `query_valid_type` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询字段校验类型', + `query_must_input` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询字段是否必填1是0否', + `sort_flag` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否支持排序1是0否', + PRIMARY KEY (`id`) USING BTREE, + INDEX `inex_table_id`(`cgform_head_id`) USING BTREE, + INDEX `idx_ocf_cgform_head_id`(`cgform_head_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of onl_cgform_field +-- ---------------------------- +INSERT INTO `onl_cgform_field` VALUES ('0021c969dc23a9150d6f70a13b52e73e', '402860816aa5921f016aa5921f480000', 'begin_date', '开始时间', 'begin_date', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('020c1622c3df0aef30185f57874f6959', '79091e8277c744158530321513119c68', 'bpm_status', '流程状态', NULL, 0, 1, 'String', 32, 0, '1', 'bpm_status', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 1, 0, 'single', '', '', 8, 'admin', '2019-05-11 15:29:47', '2019-05-11 15:29:26', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('02b20e692456403e2fed1a89a06833b4', '402860816bff91c0016bff91d2810005', 'phone', '联系方式', 'phone', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 8, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('02b4ee2612d569cd187877eea6559e87', '402881e6760269a20176026a22e70001', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 5, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('03668009f0ad92b20abb1a377197ee47', 'deea5a8ec619460c9245ba85dbc59e80', 'order_fk_id', '订单外键ID', NULL, 0, 0, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', 'test_order_main', 'id', 10, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:42:53', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('03709092184fdf4a66b0cdb4dd10a159', '402860816bff91c0016bffa220a9000b', 'bpm_status', '流程状态', NULL, 0, 1, 'String', 32, 0, '1', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 46, 'admin', '2019-07-22 16:15:32', '2019-07-19 15:34:44', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('03988419d751a330c2b0f0519a531880', '997ee931515a4620bc30a9c1246429a9', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('03c105d2706c8286416833684de67406', '79091e8277c744158530321513119c68', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-05-11 15:29:47', '2019-05-11 15:27:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('03fd5ab69f331ff760c3f7d86b4a93f8', '4028318169e81b970169e81b97650000', 'log_content', '日志内容', 'log_content', 0, 1, 'string', 1000, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 3, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('045eb432c418b2b103b1e1b8e8a8a75d', 'fb7125a344a649b990c12949945cb6c1', 'age', '年龄', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', NULL, NULL, NULL, '2019-03-26 19:24:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('048229c6a73858062de7d918be88ef6c', '2c91a0817fc4c754017fc4c754210000', 'id', 'id', 'id', 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2022-03-26 13:58:50', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('04e4185a503e6aaaa31c243829ff4ac7', 'd35109c3632c4952a19ecc094943dd71', 'birthday', '生日', NULL, 0, 1, 'Date', 32, 0, '', '', '', '', 'date', '', 120, '', '0', '', '', 1, 1, 1, 0, 'single', '', '', 10, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('04ff134cb4aae845059e10b3b85f1451', '7ea60a25fa27470e9080d6a921aabbd1', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2019-04-17 00:22:21', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('051dd70c504c97a028daab2af261ea35', '1acb6f81a1d9439da6cc4e868617b565', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('052dcc6f34976b66754fd99415bd22ce', '79091e8277c744158530321513119c68', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-05-11 15:29:47', '2019-05-11 15:27:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('054db05394e83b318f097a60bc044134', '402860816bff91c0016bffa220a9000b', 'residence_address', '户籍地址', 'residence_address', 0, 1, 'string', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 28, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('05dbdd8d9f0f84c8504faa6f24c7d4ac', '402880eb71d61d3d0171d61d3de30000', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 9, 'admin', '2020-05-03 00:54:16', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('05ed6a78a2e9d0c82bfa2c55898570b8', '997ee931515a4620bc30a9c1246429a9', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0604945c206e867644e9a44b4c9b20c6', 'fb19fb067cd841f9ae93d4eb3b883dc0', '2', '4', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 5, NULL, NULL, '2019-03-23 11:39:48', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0617de6d735b37a3f80f2f35ad5d1511', '4028839a6de2ebd3016de2ebd3870000', 'size_type', '尺码类型', 'size_type', 0, 1, 'string', 2, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 13, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0619dfc3fbf9e193534bb3460a1a9d92', 'cb2d8534a2f544bc9c618dd49da66336', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-02-24 17:22:42', '2020-02-24 15:15:13', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('06a1badae6119abf4ec48858a3e94e1c', '402860816bff91c0016bffa220a9000b', 'sys_org_code', '组织机构编码', 'sys_org_code', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 43, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('06f1cfff58395ff62526b894f6182641', 'e67d26b610dd414c884c4dbb24e71ce3', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-04-24 11:03:32', '2019-04-24 11:02:57', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('07a307972076a392ffc61b11437f89dd', '402860816bff91c0016bff91c0cb0000', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 13, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('07f4776fd641389a8c98a85713990dce', '402860816bff91c0016bff91c0cb0000', 'update_by', '更新人', 'update_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 14, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('07f9887ef8d337effb7e570d9e817fe6', '2d3bbeafdc364ecb974971a2d82adb9b', 'record_number', '备案号', NULL, 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 12, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('08a3353c11efd5f062c3076d0554b5c5', '402881e6760269a20176026d25650002', 'salary_money', '工资', 'salary_money', 0, 1, 'BigDecimal', 10, 3, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 5, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('08f002095da7c1886c86648fcec38ca9', '56efb74326e74064b60933f6f8af30ea', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('09450359eb90b40d224ec43588a62f9e', '402860816bff91c0016bff91c0cb0000', 'user_id', '用户ID', 'user_id', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0a453a63e33654aa1b9ee2affa854a6d', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0a4cdcb7e54f614ab952024f6c72bb6d', 'beee191324fd40c1afec4fda18bd9d47', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-04-13 13:41:13', '2019-04-13 13:40:56', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0a8b162ad6c8c259e551198e556dec32', '2c91a0817fc4c754017fc4c757850002', 'sys_org_code', '所属部门', 'sys_org_code', 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0acfc27e493c204f72d42b6dc00a2ded', '53a3e82b54b946c2b904f605875a275c', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0adc06d9b497684bcbb5a781e044517c', '1acb6f81a1d9439da6cc4e868617b565', 'supplier', '供应商', NULL, 0, 1, 'String', 32, 0, '', 'air_china_ supplier', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 15, 'admin', '2019-06-10 14:47:14', '2019-04-24 16:52:00', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0ae4bc5d4921aa240d814e018ddb7779', '56efb74326e74064b60933f6f8af30ea', 'money', '订单总额', NULL, 0, 1, 'double', 10, 3, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0b3e833ac4aae3a13ec2f8ae460708f8', '4028839a6de2ebd3016de2ebd3870000', 'no', '预算表序号', 'no', 0, 1, 'string', 50, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 8, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0b63bd30b8646901310d8d0374df5587', '18f064d1ef424c93ba7a16148851664f', 'fuwenb', '富文本', NULL, 0, 1, 'Text', 0, 0, '', '', '', '', 'umeditor', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 17, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0ba1bf74e2a6a94a7a63010ec7230706', '402860816bff91c0016bffa220a9000b', 'update_time', '更新时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 42, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0bd10d416252bdc6b169056d2a1a4a68', '402880e5721355dd01721355dd390000', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 3, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0bf9c178173bd86eec4144b819cfac0b', '18f064d1ef424c93ba7a16148851664f', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0c34ebfe2e2a619d42db13f93d2a2d40', 'b81de38db24047b497d476516f8a0865', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2020-02-24 14:56:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0cba94f0497d4d3d829fc573f58eff9f', '402860816bff91c0016bffa220a9000b', 'graduation_time', '毕业时间', 'graduation_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 16, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0cbc49f419e3545613d0b2eb9c025eae', '402881e6760269a20176026a22e70001', 'fuwenb', '富文本', NULL, 0, 1, 'Text', 0, 0, '', '', '', '', 'umeditor', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 17, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0ccd1787e69a1e1b9aaa22afe2b7f67c', '2c91a0817fc4c754017fc4c756050001', 'nameen', '名称-英文版', 'nameen', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0d00c51a4ddad2598a587fadc968a8b2', '402860816bff91c0016bff91cfea0004', 'sys_org_code', '组织机构编码', 'sys_org_code', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 13, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0ddd0c0afc967a9ab6050401ca62a4be', 'e67d26b610dd414c884c4dbb24e71ce3', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-04-24 11:03:32', '2019-04-24 11:02:57', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('0e157503e648653836a602f5bbad4e83', '402881e6760269a201760269a2af0000', 'files', '文件', NULL, 0, 1, 'string', 1000, 0, '', '', '', '', 'file', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 15, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0e5fb96c3f5a37c758eb7f5d1322694f', '402880e5721355dd01721355dd390000', 'good_name', '商品名字', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 7, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0e6952db23d5a578ab74344a299c2322', '18f064d1ef424c93ba7a16148851664f', 'birthday', '时间', NULL, 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 13, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0f4c07621dcd465f7954b4297962db9b', '18f064d1ef424c93ba7a16148851664f', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('0fb6fa76c5c78a1e957dbb411e110738', '402860816bff91c0016bff91d8830007', 'politically_status', '政治面貌', 'politically_status', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('101932e3b19235ce5ad400d379c26880', '910984408e1948519e2fcf5ac08fe9ad', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('101a73df0aa5199ac05c4ce92a4f0e3e', '4adec929a6594108bef5b35ee9966e9f', 'name', '姓名', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{sysUserCode}', 0, 1, 1, 0, 'single', '', '', 3, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('105be0f7d827a0324216cf8af268fb9e', '09fd28e4b7184c1a9668496a5c496450', 'birthday', '客户生日', NULL, 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('105c8e44ad13026b641f0363601f30f3', 'e5464aa8fa7b47c580e91593cf9b46dc', 'num', '循环数量', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2019-04-24 17:09:49', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('105e112bddec9cc23e853b9c68af1b05', '18f064d1ef424c93ba7a16148851664f', 'radio', 'radio', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'radio', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('10b78ee7954f230117689a226c44c0db', '402880e570a5d7000170a5d700f50000', 'descc', '描述', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 11, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1130f1e252533529bb1167b896dffe32', 'deea5a8ec619460c9245ba85dbc59e80', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('117fc4ba649d6690a3ac482ad5e4ad38', '56870166aba54ebfacb20ba6c770bd73', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-11-28 00:02:01', '2019-04-20 11:38:39', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('12aa08f8e948e2b60b40a7b6429c866b', '56efb74326e74064b60933f6f8af30ea', 'order_code', '订单编码', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '${shop_order_num}', 0, 1, 1, 1, 'single', '', '', 7, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('13246645b7650491b70205d99703ca06', '402860816aa5921f016aa5dedcb90009', 'bpm_status', '流程状态', 'bpm_status', 0, 1, 'string', 32, 0, '1', 'bpm_status', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 1, 0, 'group', '', '', 8, 'admin', '2019-05-11 15:56:47', '2019-05-11 15:50:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('135dd0ee50712722db65b8762bd487ea', '8994f2817b5a45d9890aa04497a317c5', 'update_time', '更新日期', NULL, 0, 1, 'date', 20, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 4, NULL, NULL, '2019-03-23 11:39:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('13d9c22ba0a4f09111d115022a148d23', '09fd28e4b7184c1a9668496a5c496450', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('14b7e6161d1f908e13026439af302a66', '3b5e18da618247539481816995b6bf9f', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('14ec4c83c29966ab42b6b718c5a3e774', '7ea60a25fa27470e9080d6a921aabbd1', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2019-04-17 00:22:21', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('154ba4ca5328866010e042086ffc2b81', '56efb74326e74064b60933f6f8af30ea', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('16363d0bc125125e395772278d0cf22e', '4b556f0168f64976a3d20bfb932bc798', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2019-04-12 23:38:28', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('168426cf1016cf0b99705ae1c4c8591e', '402880e5721355dd01721355dd390000', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', NULL, NULL, 1, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('16918ac159cb6313fec1dea7ac4bd0a0', '402880eb71d52dc30171d52dc3a10000', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 10, NULL, NULL, '2020-05-02 19:37:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('169318fa19cf5acf77c58a98c2d5a6bf', '18f064d1ef424c93ba7a16148851664f', 'remakr', 'markdown', NULL, 0, 1, 'Text', 0, 0, '', '', '', '', 'markdown', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 16, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('179c290e383009810fb738f07bd5af8d', '402860816bff91c0016bff91d2810005', 'id', 'id', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('17cbda69da9dd3632625a0647c259070', '73162c3b8161413e8ecdca7eb288d0c9', 'wl_name', '物料名字', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('18177ddac5c50c2943fa26ed07091a23', '910984408e1948519e2fcf5ac08fe9ad', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('182d038554a6ee7ddfd07763aaa10686', '53a3e82b54b946c2b904f605875a275c', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('18fefb2257901f05508f8ec13ada78a3', 'e5464aa8fa7b47c580e91593cf9b46dc', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-04-24 17:09:48', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('191705159cea35e8cbacb326f172be94', 'd35109c3632c4952a19ecc094943dd71', 'search_sel', '搜索下拉', NULL, 0, 1, 'string', 100, 0, '', 'role_code', 'sys_role', 'role_name', 'sel_search', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 18, 'admin', '2020-11-28 00:03:03', '2020-11-26 18:02:20', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1973ef1d3728fbff2db6a352e001f5f7', 'fb7125a344a649b990c12949945cb6c1', 'name', '用户名', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 5, 'admin', '2019-03-26 19:24:11', '2019-03-26 19:01:52', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('19a9bf071cf3aa3b2ef94344d2300616', '402881e6760269a20176026d25650002', 'create_by', '创建人', 'create_by', 0, 1, 'string', 32, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 12, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1ab5be1f937f393b3e5cc214ef1b855c', '7ea60a25fa27470e9080d6a921aabbd1', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2019-04-17 00:22:21', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1b071c02de2830f9fe82a542b31cce7f', '3b5e18da618247539481816995b6bf9f', 'age', '年龄', NULL, 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1b488cbd0463acd031e55b09f0959ff2', '2c91a0817fc4c754017fc4c754210000', 'create_by', '创建人', 'create_by', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 2, 'admin', '2022-03-26 13:58:50', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1b6c7b95028bed9ff656d65557dd2bdf', '402860816bff91c0016bffa220a9000b', 'user_id', '用户id', 'user_id', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1c2f307e315bac77a6d3f02e88387a43', 'deea5a8ec619460c9245ba85dbc59e80', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1c3b2ad0a52ecb47fa7fd53f25875beb', 'deea5a8ec619460c9245ba85dbc59e80', 'price', '价格', NULL, 0, 1, 'double', 32, 0, '', '', '', '', 'text', '', 120, 'n', '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1c4d25a12388c80d397bb4f4664fe4e6', '4b556f0168f64976a3d20bfb932bc798', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2019-04-12 23:38:28', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1cfe967bb457cbaa6e041e45d019b583', '402860816bff91c0016bff91c7010001', 'update_time', '更新时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 10, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1d0037eba10efd76be45150479399a7e', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1d712db19506ee40b2c1ef5a611baf88', '53a3e82b54b946c2b904f605875a275c', 'name', '商品名字', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1d95bdf1120c5a1776df022d0a571f21', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 7, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1df2c5e1adc37430369fec8167227102', '2c91a0817fc4c754017fc4c756050001', 'sys_org_code', '所属部门', 'sys_org_code', 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1e37ae77c0d406d4ff3c5442ec63cd1f', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1e3d8cfbf12155559666a23ee2c6c5ca', 'e5464aa8fa7b47c580e91593cf9b46dc', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-04-24 17:09:49', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1ed46fdeb289bd7805c9b83332ccd3b4', '402860816bff91c0016bff91d2810005', 'relation', '关系', 'relation', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1eda61dece35abd76b8d8d49e1b139b8', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'content', '描述', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('1f0c6d33b79713fe79fb30373c81f6f7', '758334cb1e7445e2822b60e807aec4a3', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2019-10-18 18:02:09', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('1fa5f07b3e70d4925b69b2bf51309421', '56870166aba54ebfacb20ba6c770bd73', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-11-28 00:02:01', '2019-04-20 11:38:39', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('209ddb923d8dab9f454d56d82c0cc725', '3d447fa919b64f6883a834036c14aa67', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-02-21 17:58:46', '2020-02-20 16:19:00', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('20ff34fb0466089cb633d73d5a6f08d6', 'd35109c3632c4952a19ecc094943dd71', 'update_time', '更新日期', NULL, 0, 1, 'date', 20, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2113a4ec7b88b4820dcbbdf96e46bbb7', 'fbc35f067da94a70adb622ddba259352', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2019-07-03 19:44:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2150e48b2cb6072d2d8ecd79a7daf7cc', '402860816bff91c0016bff91ca7e0002', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 10, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('21c2a8b06f50d71f901f3897d7afb8a5', '2c91a0817fc4c754017fc4c757850002', 'logo', 'logo url', 'logo', 0, 1, 'string', 2000, 0, '', '', '', '', 'image', '', 120, NULL, '1', '', '', 0, 1, 1, 0, 'single', '', '', 13, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2323239efb5a40b73034411868dfc41d', 'fb19fb067cd841f9ae93d4eb3b883dc0', 'update_by', '更新人登录名称', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 3, NULL, NULL, '2019-03-23 11:39:48', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('232c3b4250c5a1ea643b6e160a730ba4', '2d3bbeafdc364ecb974971a2d82adb9b', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('233de79c48dcbc0eaeeb57f85d8dd17e', '2c91a0817fc4c754017fc4c754210000', 'cover', '封面图url', 'cover', 0, 1, 'string', 2000, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('239448a05801af1b07232d30d8e610b1', '402881e6760269a20176026a22e70001', 'dep_sel', '选择部门', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'sel_depart', '', 120, NULL, '0', '', '#{sysOrgCode}', 0, 1, 1, 0, 'single', NULL, NULL, 19, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('23f42061ed218bdbc1262913c071e1cd', 'e5464aa8fa7b47c580e91593cf9b46dc', 'iz_valid', '启动状态', NULL, 0, 1, 'int', 2, 0, '', 'air_china_valid', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 12, 'admin', '2019-04-24 17:09:49', '2019-04-24 14:09:06', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('242cc59b23965a92161eca69ffdbf018', 'd35109c3632c4952a19ecc094943dd71', 'age', '年龄', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', 'http://www.baidu.com', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('24588340313096179b9ec0b49f40bed3', '18f064d1ef424c93ba7a16148851664f', 'sel_mut', '下拉多选', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list_multi', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2640235b9638547f1776b930bd8c12b4', '997ee931515a4620bc30a9c1246429a9', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('265702edb8872e322fe72d3640e34ac5', '402860816bff91c0016bff91cfea0004', 'from_time', '开始日期', 'from_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('26645f6f6eb2646033bad11e0402d7e4', '18f064d1ef424c93ba7a16148851664f', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2739ab1ece4d6053ba931bb6572f4ed8', '4028839a6de2ebd3016de2ebd3870000', 'iz_valid', '启用状态', 'iz_valid', 0, 1, 'string', 2, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 9, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('273b0fd37640a9ef1614e987e2bc44a0', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'pics', '图片', NULL, 0, 1, 'string', 500, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('281ce0b5343cd42b28825d7df16422f1', 'b81de38db24047b497d476516f8a0865', 'vv', 'vv', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, NULL, NULL, '2020-02-24 14:56:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('283f42283b9d0bf3b95ba3384ab2d255', '758334cb1e7445e2822b60e807aec4a3', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2019-10-18 18:02:09', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('284864d99fddfdcb00e188e3a512cb28', '1acb6f81a1d9439da6cc4e868617b565', 'no', '预算表序号', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2889d3cef706f91e092d76a56b8055be', '402860816bff91c0016bff91cda80003', 'order_no', '序号', 'order_no', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 8, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('28900c8e76dd0e77193cbd85b5bc6af8', '402881e6760269a201760269a2af0000', 'remakr', 'markdown', NULL, 0, 1, 'Text', 0, 0, '', '', '', '', 'markdown', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 16, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('29e4abea55d9fa7dbbd0c8dbbb2b3756', '402860816bff91c0016bff91cda80003', 'update_time', '更新时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 12, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2ae06cbebe686119ad538d7a3fbf3887', '2c91a0817fc4c754017fc4c754210000', 'is_release', '是否发布(Y:是N:否)', 'is_release', 0, 1, 'string', 2, 0, '', '', 'yn', '', 'switch', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 18, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2aef31179964d0a5a945df7bddff00ae', '53a3e82b54b946c2b904f605875a275c', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2c70edc7d5a9861239c6537ae0eb39c7', '18f064d1ef424c93ba7a16148851664f', 'dep_sel', '选择部门', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'sel_depart', '', 120, NULL, '0', '', '#{sysOrgCode}', 0, 1, 1, 0, 'single', '', '', 19, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2c9be627e7cab7f5a2ae9c7ca7ce94a2', 'cb2d8534a2f544bc9c618dd49da66336', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-02-24 17:22:42', '2020-02-24 15:15:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2d53a66f0b72d820b86ff445e2181d76', 'beee191324fd40c1afec4fda18bd9d47', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-04-13 13:41:13', '2019-04-13 13:40:56', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2d8366d934e3c3a060496c115c7a438e', '402881e6760269a20176026a22e70001', 'sex', '下拉框', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 8, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('2dfc4c81926f678c5f8d5ffd27858201', 'e2faf977fdaf4b25a524f58c2441a51c', 'account', '用户编码', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2e0374878fb3d5be3b0b3f868a97fb59', '09fd28e4b7184c1a9668496a5c496450', 'sex', '客户性别', NULL, 0, 1, 'string', 1, 0, '', 'sex', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2e5275b6407e1b4265af8519077fa4a5', 'd3ae1c692b9640e0a091f8c46e17bb01', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, NULL, NULL, '2019-07-24 14:47:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2e582152fd7472bba0b70230d42a6e00', '2d3bbeafdc364ecb974971a2d82adb9b', 'footer_logo_url', '门户尾部logo', NULL, 0, 1, 'string', 2000, 0, '', '', '', '', 'file', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2e66b9db37648389e0846e2204111732', '73162c3b8161413e8ecdca7eb288d0c9', 'has_child', '是否有子节点', NULL, 0, 1, 'string', 3, 0, '', 'valid_status', '', '', 'list', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 10, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2e6740e79d51ac935d673b7d207611d2', '18f064d1ef424c93ba7a16148851664f', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2e6f741fa96a49a0adccc7b4682c1cef', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'name', '名称', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{sysUserName}', 0, 1, 1, 0, 'single', '', '', 3, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('2ee58d8e4844dfe1fa6b1b841ae0b312', '402860816bff91c0016bff91d2810005', 'politically_status', '政治面貌', 'politically_status', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('2f111722eb3a994450e67e3211fd69a8', '402860816bff91c0016bff91ca7e0002', 'id', 'id', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('30143cc3de69c413828f9fba20662026', '402860816bff91c0016bffa220a9000b', 'healthy', '健康状况', 'healthy', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 12, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('306e3fb9c87ca6442cefbd61f498f1f7', '402881e6760269a201760269a2af0000', 'dep_sel', '选择部门', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'sel_depart', '', 120, NULL, '0', '', '#{sysOrgCode}', 0, 1, 1, 0, 'single', NULL, NULL, 19, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('3087aa8f38c787e066a886d950a9edfa', '05a3a30dada7411c9109306aa4117068', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('30b013b3016f0b7d5670abb395351093', '2d3bbeafdc364ecb974971a2d82adb9b', 'heard_logo_url', '门户头部logo', NULL, 0, 1, 'string', 2000, 0, '', '', '', '', 'file', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('310d2db6eb4b4d30025cdcf38186b38d', '2d3bbeafdc364ecb974971a2d82adb9b', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('31193dc8ceacf979e4042e784ea8278a', '402880e570a5d7000170a5d700f50000', 'order_fk_id', '订单外键ID', NULL, 0, 0, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 10, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('315eab14c7d9de37434b3cb7fa7b054d', '18f064d1ef424c93ba7a16148851664f', 'files', '文件', NULL, 0, 1, 'string', 1000, 0, '', '', '', '', 'file', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 15, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('31dec4a3c5648732a44b85da7a6961ee', '2c91a0817fc4c754017fc4c754210000', 'title', '标题', 'title', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 7, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('31fd90306c3942f09cb79deabbf2f541', '402860816bff91c0016bff91d2810005', 'employee_id', '员工ID', 'employee_id', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', 'oa_employee_info', 'id', 2, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('336495117e3a31351fed6963b950dddb', '402860816bff91c0016bffa220a9000b', 'inside_transfer', '内部工作调动情况', 'inside_transfer', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 37, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('34138092d743d4232341a920efd2699e', '402880eb71d52dc30171d52dc3a10000', 'name', '名称', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{sysUserName}', 0, 1, 1, 0, 'single', NULL, NULL, 3, NULL, NULL, '2020-05-02 19:37:58', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('345c8b48e1e128e77c4c6e2b36512804', '402860816aa5921f016aa5dedcb90009', 'create_by', '创建人', 'create_by', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 2, 'admin', '2019-05-11 15:56:47', '2019-05-11 15:50:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('34625a911b39e0596690c1a15f784448', '402880e570a5d7000170a5d700f50000', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 5, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3489a6451bbbcabc0f39ca04b0dd62f2', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('351faaeb2dd8105e9c66f678211c9d4f', 'dbf4675875e14676a3f9a8b2b8941140', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2019-05-27 18:02:07', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('35417ba3993afe3405e1e0b9abbd7e1b', '402880e5721355dd01721355dd390000', 'num', '数量', NULL, 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 9, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('354b2ce39c5e8ec3f0bbb01bf8ff0fb7', '32f75e4043ef4070919dbd4337186a3d', 'content', '描述', NULL, 0, 1, 'String', 300, 0, '', '', '', '', 'textarea', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2019-04-11 10:15:31', '2019-03-28 15:24:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('35ca1c8aa1501bc8a79c880928841f18', '402860816aa5921f016aa5921f480000', 'update_by', '修改人id', 'update_by', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 11, 'admin', '2019-05-11 15:31:55', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3635793767371c6db9f76b4b79f9d321', '402860816bff91c0016bff91d8830007', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 11, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('370a6eebc2d732eaf121fe0830d853a6', 'e5464aa8fa7b47c580e91593cf9b46dc', 'wl_code', '物料编码', NULL, 0, 1, 'String', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 7, 'admin', '2019-04-24 17:09:49', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3729dc4c35048f2c1e1a975b704b8115', '2c91a0817fc4c754017fc4c757850002', 'create_by', '创建人', 'create_by', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 2, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('37462a4d78968d0e432d746423603b81', '3d447fa919b64f6883a834036c14aa67', 'province', '省份', NULL, 0, 1, 'String', 100, 0, '', '', '{table:\'sys_category\',txt:\'name\',key:\'id\',linkField:\'city,area\',idField:\'id\',pidField:\'pid\', condition:\" pid = \'1230769196661510146\' \" }', '', 'link_down', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 2, 'admin', '2020-02-21 17:58:46', '2020-02-20 16:19:00', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('37e2548874f09ef7d08642a30bc918fa', 'fbc35f067da94a70adb622ddba259352', 'group_name', '小组名', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, NULL, NULL, '2019-07-03 19:44:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('391e7cbd9f29743b11bb555c50547b1f', '32f75e4043ef4070919dbd4337186a3d', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('396c36fa5320975851d06772d10ea7b1', 'cb2d8534a2f544bc9c618dd49da66336', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-02-24 17:22:42', '2020-02-24 15:15:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3976fd992599c099a84ad8a2a73b1fa3', '2c91a0817fc4c754017fc4c754210000', 'update_by', '更新人', 'update_by', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 4, 'admin', '2022-03-26 13:58:50', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('3ab3275b6d6b9faa5428bd80f35c7a0e', '2d3bbeafdc364ecb974971a2d82adb9b', 'address', '地址', NULL, 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('3acd1b022fd8cb6b99534161fa3d6a24', 'd35109c3632c4952a19ecc094943dd71', 'ceck', 'checkbox', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'checkbox', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 16, 'admin', '2020-11-28 00:03:03', '2020-11-26 18:02:20', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('3b439859f98e30e34d25e983eb22e408', '402860816bff91c0016bff91c7010001', 'award_time', '获奖时间', 'award_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3b67be0187044a0d023fc2c4c7eceabc', '402881e6760269a20176026d25650002', 'bonus_money', '奖金', 'bonus_money', 0, 1, 'double', 10, 2, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 6, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3bf44e68de518f3ddf72b87671d0ff90', '8994f2817b5a45d9890aa04497a317c5', 'update_by', '更新人登录名称', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 3, NULL, NULL, '2019-03-23 11:39:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3cd2061ea15ce9eeb4b7cf2e544ccb6b', 'd35109c3632c4952a19ecc094943dd71', 'file_kk', '附件', NULL, 0, 1, 'String', 500, 0, '', '', '', '', 'file', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 13, 'admin', '2020-11-28 00:03:03', '2019-06-10 20:06:57', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('3cfd4d60c7d8409ae716a579bcb0910d', '402860816bff91c0016bff91c0cb0000', 'sys_org_code', '组织机构编码', 'sys_org_code', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 16, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3e32f6c30c9028872388f70743c5d6a5', '402860816bff91c0016bff91c0cb0000', 'reason', '申请理由', 'reason', 0, 1, 'string', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 9, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3e70d1c516c3533c6698300665c669e1', '402860816bff91c0016bff91c0cb0000', 'id', 'id', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:31', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3ef0a9ed04605267f7fa304a8c353576', '05a3a30dada7411c9109306aa4117068', 'name', '用户名', NULL, 0, 1, 'string', 32, 0, '', 'username', 'tj_user_report', 'name', 'popup', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('3eff1d21b946e23d7f83de977962d9cf', '402880eb71d61d3d0171d61d3de30000', 'main_id', '主表ID', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-11-26 17:28:14', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('3f2ace8f968a0e5b91d1340ee2957cda', '402860816bff91c0016bff91d8830007', 'real_name', '姓名', 'real_name', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('3f7f7720ee65648cb2850fccedf7be9d', '53a3e82b54b946c2b904f605875a275c', 'contents', '商品简介', NULL, 0, 1, 'Text', 0, 0, '', '', '', '', 'umeditor', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('3f9deca6c193f0b2609113713956ad19', '86bf17839a904636b7ed96201b2fa6ea', 'order_main_id', '订单ID', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', 'ces_order_main', 'id', 11, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('40471eb4560bf0bbd2ffef17d48a269d', 'dbf4675875e14676a3f9a8b2b8941140', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2019-05-27 18:02:07', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('404b516d4f2229f292783db595b02ba1', '402860816bff91c0016bff91d8830007', 'update_time', '更新时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 13, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('405de5ea82e54138a0613dd41b006dfb', '56870166aba54ebfacb20ba6c770bd73', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-11-28 00:02:01', '2019-04-20 11:38:39', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('40675bb9f053aabf8823ddf4b5389141', 'b81de38db24047b497d476516f8a0865', 'aa', 'aa', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, NULL, NULL, '2020-02-24 14:56:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4164314d6a51d100169a29872b7504d8', '402860816bff91c0016bff91ca7e0002', 'cert_time', '发证时间', 'cert_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('41d4215c01b0d26871f2cb83d3e532ae', '402860816bff91c0016bff91c0cb0000', 'bpm_status', '流程状态', NULL, 0, 1, 'String', 32, 0, '1', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 17, 'admin', '2019-07-19 18:09:01', '2019-07-19 15:35:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('422a44a15fa39fd57c3c23eb601f7c03', '56870166aba54ebfacb20ba6c770bd73', 'descc', '描述', NULL, 0, 1, 'String', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-11-28 00:02:01', '2019-04-20 11:38:39', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('42cccfa014c9e131a0a1b23f563d3688', '402860816bff91c0016bffa220a9000b', 'sex', '性别', 'sex', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4312f618c83e07db82e468b81a1eaa45', '402860816bff91c0016bffa220a9000b', 'photo', '照片', 'photo', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 20, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4332b736a4c7e885c85ee9ff0cc133d5', '2c91a0817fc4c754017fc4c754210000', 'author', '作者', 'author', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 12, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('435b57180fc995e3c4ec42516963bca3', '4028839a6de2ebd3016de2ebd3870000', 'wl_code', '物料编码', 'wl_code', 0, 1, 'string', 60, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 6, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('44bdc595f1e565fc053e01134b92bb47', 'd3ae1c692b9640e0a091f8c46e17bb01', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2019-07-24 14:47:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('44e81e24d2384b0f187e8f69eda55390', '402860816bff91c0016bff91cda80003', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 10, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('44f53dc7d34dfca63a98e441f5a51c21', '2c91a0817fc4c754017fc4c754210000', 'column_id', '分类-栏目表ID', 'column_id', 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 9, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('457705f8472e0acedf2a42c453d0976f', '910984408e1948519e2fcf5ac08fe9ad', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('45c0a1a89a1e2a72533b9af894be1011', '27fc5f91274344afa7673a732b279939', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-07-01 16:28:20', '2019-07-01 16:26:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('45d59eb647257fcbcb9d143ff1ba2080', 'deea5a8ec619460c9245ba85dbc59e80', 'pro_type', '产品类型', NULL, 0, 1, 'String', 32, 0, '', 'sex', '', '', 'radio', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-05-03 01:01:18', '2019-04-23 20:54:08', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('45d7e2bd8300dabd0dc65059a2d32e80', '2d3bbeafdc364ecb974971a2d82adb9b', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('469b250595f15dfebe69991d72e4bfb2', 'e9faf717024b4aae95cff224ae9b6d97', 'name', '员工姓名', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('46be01bef342519e268902d0d36a7473', 'deea5a8ec619460c9245ba85dbc59e80', 'descc', '描述', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('46f1a875f86a4f48d0540ad0d5e667d7', '56870166aba54ebfacb20ba6c770bd73', 'order_date', '下单时间', NULL, 0, 1, 'Date', 32, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-11-28 00:02:01', '2019-04-20 11:38:39', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('47c21a6b45e59a6b70bb9c0cc4510a68', '1acb6f81a1d9439da6cc4e868617b565', 'integral_val', '积分值', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 13, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('47fa05530f3537a1be8f9e7a9e98be82', 'd35109c3632c4952a19ecc094943dd71', 'sex', '性别', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list', '', 120, '', '0', '', '', 1, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('4851697fdf63709d2bc7451b7415f4af', '32f75e4043ef4070919dbd4337186a3d', 'sex', '性别', NULL, 0, 1, 'String', 32, 0, '1', 'sex', '', '', 'list', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('485a8ddce2c033f88af674ec98b68e32', '402860816bff91c0016bffa220a9000b', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 40, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('48fad8b8ac3f9226294c1078807646ae', '402881e6760269a20176026a22e70001', 'birthday', '时间', NULL, 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 13, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('492a462b212fc34b0ee70e872684ed7e', '7ea60a25fa27470e9080d6a921aabbd1', 'name', '用户名', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, NULL, NULL, '2019-04-17 00:22:21', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('499a5dac033a01ce58009e4c5b786697', 'e9faf717024b4aae95cff224ae9b6d97', 'age', '员工年龄', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('49cd3dbd4f7f7cf0d19b1ee1045cfa69', 'e67d26b610dd414c884c4dbb24e71ce3', 'post_code', '岗位编码', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-04-24 11:03:32', '2019-04-24 11:02:57', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4ad94222c025b56fb0833a88a1514aeb', '86bf17839a904636b7ed96201b2fa6ea', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('4b136f953675fffcc1b6d7d6d414d57e', '402880eb71d61d3d0171d61d3de30000', 'date', '日期', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{date}', 0, 1, 1, 0, 'single', '', '', 4, 'admin', '2020-11-26 17:28:14', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('4ba7c553ca4babcec75273c531cd65e1', '402860816bff91c0016bff91cfea0004', 'workplace', '工作单位', 'workplace', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4c2cba9fc950333421c4193576b8384d', '32f75e4043ef4070919dbd4337186a3d', 'salary', '工资', NULL, 0, 1, 'double', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2019-04-11 10:15:32', '2019-03-28 15:24:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4c4f4067fa31737f3ff9e088130ef793', '4adec929a6594108bef5b35ee9966e9f', 'sex', '性别', NULL, 0, 1, 'String', 200, 0, '', 'sex', '', '', 'list', '', 120, NULL, '0', '', '{{ 2 }}', 0, 1, 1, 0, 'single', '', '', 4, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('4c570c5cf05590348e12621ca62773cf', '402860816aa5921f016aa5921f480000', 'name', '请假人', 'name', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 2, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4cacfa054e96791ab938b5c8f8e02cd1', '27fc5f91274344afa7673a732b279939', 'bpm_status', '流程状态', NULL, 0, 1, 'String', 2, 0, '', 'bpm_status', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, NULL, NULL, '2019-07-01 16:28:20', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4d3945ef20f2c8af62b0c0cf935ae83d', '910984408e1948519e2fcf5ac08fe9ad', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('4dc3f7e772564de45773a8379adc4335', '3b5e18da618247539481816995b6bf9f', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('4e3760f9068aee4318123d85fbf2ebf9', '53a3e82b54b946c2b904f605875a275c', 'good_type_id', '商品分类', NULL, 0, 1, 'string', 32, 0, '', '0', 'ces_shop_type', 'id,pid,name,has_child', 'sel_tree', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:51:42', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('4f39f2213568b1259f8117a2ff248811', '2c91a0817fc4c754017fc4c754210000', 'authoren', '作者-英文版', 'authoren', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 13, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('4f718d95ad9de33eac18fd0663e4c1f1', '32f75e4043ef4070919dbd4337186a3d', 'birthday', '生日', NULL, 0, 1, 'Date', 32, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 8, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4f7cba71de7afe6efbd024f5f9935521', '402860816bff91c0016bff91cda80003', 'to_time', '截止时间', 'to_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('4fa29e880104e0ed0cb9143d801b209f', '18f064d1ef424c93ba7a16148851664f', 'checkbox', 'checkbox', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'checkbox', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('4faa7848b92f05bcb3cf03de34af9ff2', 'cb2d8534a2f544bc9c618dd49da66336', 'ddd', 'dd', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-02-24 17:22:42', '2020-02-24 15:15:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('506c9b0b2331a24e5c284274d28fe569', '27fc5f91274344afa7673a732b279939', 'kkk', '描述', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2019-07-01 16:28:20', '2019-07-01 16:26:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('508eb28e1409a2a9501cdf6fd7eb24c7', 'dbf4675875e14676a3f9a8b2b8941140', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2019-05-27 18:02:07', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('509a4f63f02e784bc04499a6a9be8528', 'd35109c3632c4952a19ecc094943dd71', 'update_by', '更新人登录名称', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('50f12777fae30133ca05b111f7f0c936', '2c91a0817fc4c754017fc4c757850002', 'url', '链接', 'url', 0, 1, 'string', 2000, 0, '', '', '', '', 'text', '', 120, 'url', '1', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('519f68557b953fc2d38400182b187366', '402860816bff91c0016bffa220a9000b', 'residence_type', '户籍类别', 'residence_type', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 13, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('52ee861bc1b62cd8e4f10632b3d9d1b2', '79091e8277c744158530321513119c68', 'name', '顺序会签标题', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-05-11 15:29:47', '2019-05-11 15:27:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5531fb261c77e9d12f7cca1af528f70a', '05a3a30dada7411c9109306aa4117068', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('553a250fb89de39e4ba9f8450fd72ade', '05a3a30dada7411c9109306aa4117068', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('555f9d43db20204128d76e22226ca36e', '402881e6760269a201760269a2af0000', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 2, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5562a7242e4978f02e6d3a08d5828bbf', '53a3e82b54b946c2b904f605875a275c', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5562ad3165b1399f97a48f5f06d7fa06', '3b5e18da618247539481816995b6bf9f', 'ccc', 'cc', NULL, 0, 1, 'string', 1000, 0, '', '', '', '', 'umeditor', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('56a7800e4e476812c74217c2aad781aa', '32feeb502544416c9bf41329c10a88f4', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('56cd0a76f922bf76d982b24a509e4782', '4028839a6de2ebd3016de2ebd3870000', 'create_time', '创建日期', 'create_time', 0, 1, 'Date', 0, 0, NULL, NULL, NULL, NULL, 'date', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 3, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('56e247f12d62b49cd9bd537e3efecf16', '402860816bff91c0016bff91c0cb0000', 'create_by', '创建人', 'create_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 12, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('57552a4f0b7b5c096ab8985ced57cc7d', 'cb2d8534a2f544bc9c618dd49da66336', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-02-24 17:22:42', '2020-02-24 15:15:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('579cc11a36576bc89e15dc7efaf9a14f', '2c91a0817fc4c754017fc4c756050001', 'create_by', '创建人', 'create_by', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 2, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('581d8e8ce270b762458121b1dea0be9a', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('588400f6ebcdd0bc9bb560dd36636af9', 'e2faf977fdaf4b25a524f58c2441a51c', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('58a96f945912d33b64ebf5dee98156dc', '402860816bff91c0016bffa220a9000b', 'mobile', '手机号', 'mobile', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 19, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('58eea85add4788b83c893092434bc413', 'fb19fb067cd841f9ae93d4eb3b883dc0', 'update_time', '更新日期', NULL, 0, 1, 'date', 20, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 4, NULL, NULL, '2019-03-23 11:39:48', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('593f9be11e07af0a9eb644ff752a81de', '2c91a0817fc4c754017fc4c754210000', 'create_time', '创建日期', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 3, 'admin', '2022-03-26 13:58:50', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('59ae1e853668c676e85329aa029c68a6', '402860816bff91c0016bff91c0cb0000', 'status', '状态(1:申请中 2:通过)', 'status', 0, 1, 'string', 2, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 11, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5a043c7ae042e48f50d1fb0bb3d760a8', '402880eb71d61d3d0171d61d3de30000', 'code', '编码', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '${order_num_rule_param}', 0, 1, 1, 0, 'single', '', '', 2, 'admin', '2020-11-26 17:28:14', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5a1ab458d88bb766f92c3d791495cdcd', '402860816bff91c0016bff91d2810005', 'age', '年龄', 'age', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5a4ef083dd572114aeb581b6828de545', '402860816bff91c0016bff91c7010001', 'award_name', '获奖名称', 'award_name', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5a621f27aa443fe9eccc73717e4fa172', '4028318169e81b970169e81b97650000', 'method', '请求java方法', 'method', 0, 1, 'string', 500, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 8, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5a655b208d6318ed02f236f15a319b5f', 'fbc35f067da94a70adb622ddba259352', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2019-07-03 19:44:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5a6f88710c49bbe8e2e0ca58e149abad', '402860816bff91c0016bff91cda80003', 'create_by', '创建人', 'create_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 9, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5a7ce5af50f28d613d8beea7c866ae0c', '402881e6760269a20176026d25650002', 'update_by', '修改人', 'update_by', 0, 1, 'string', 32, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 14, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5ab702dbc37d6fd8d3a1093fda7223bf', '53a3e82b54b946c2b904f605875a275c', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5b17ba693745c258f6b66380ac851e5f', 'd35109c3632c4952a19ecc094943dd71', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 1, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5b8718b995d541028e7f6a8e73d54211', '2c91a0817fc4c754017fc4c756050001', 'parent', '上级ID 0为顶级', 'parent', 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5ba2a4950a90235d05f9673b58778b2e', '2c91a0817fc4c754017fc4c757850002', 'update_by', '更新人', 'update_by', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 4, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5c1803c06268e4f57cff02da5b6ef672', '2c91a0817fc4c754017fc4c757850002', 'is_enable', '是否启用', 'is_enable', 0, 1, 'string', 2, 0, '', '', 'yn', '', 'switch', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 15, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5c76f5ecc774d7339eb0c2199c0052bc', '402860816bff91c0016bff91c0cb0000', 'biz_no', '编号', 'biz_no', 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 2, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5c8c8d573e01e4f40b5a7c451515e1d2', '32feeb502544416c9bf41329c10a88f4', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5dfbea516ee2390d712eace5405c5219', '402860816bff91c0016bff91ca7e0002', 'create_by', '创建人', 'create_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 9, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5e1d11197e9dd2a99e2019c37236161f', '2c91a0817fc4c754017fc4c757850002', 'titleen', '标题-英文版', 'titleen', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 12, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5e4484b7348dc3e59a0c58bdc3828cc0', '27fc5f91274344afa7673a732b279939', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-07-01 16:28:20', '2019-07-01 16:26:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5e4ac29ac2007ceabf93368330290a42', '402860816bff91c0016bff91d8830007', 'order_no', '序号', 'order_no', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 9, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('5e729f9823b5cc96c50b0b7c0f07eb05', '402880e5721355dd01721355dd390000', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 2, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5e991844962b2f3c42237445fdf2cd19', '402881e6760269a20176026a22e70001', 'remakr', 'markdown', NULL, 0, 1, 'Text', 0, 0, '', '', '', '', 'markdown', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 16, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5f13f7087caa0bbf47e5eba01d0d0443', '05a3a30dada7411c9109306aa4117068', 'contents', '请假原因', NULL, 0, 1, 'string', 500, 0, '', '', '', '', 'markdown', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5f5ac4d37fd1a3a09e2b19f0d4d99c0f', '4adec929a6594108bef5b35ee9966e9f', 'code', '编码', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '${order_num_rule_param}', 0, 1, 1, 0, 'single', '', '', 2, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('5f718d8968d908cd2e4de6ee4c74d644', '402880eb71d61d3d0171d61d3de30000', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 7, 'admin', '2020-05-03 00:54:16', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('60b3b452232904f5a1130348bc1eab53', '402881e6760269a20176026d25650002', 'sys_org_code', '所属部门编码', 'sys_org_code', 0, 1, 'string', 64, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 16, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('6130dbb6d36bab8ee9154e7ab58af34c', '402880e570a5d7000170a5d700f50000', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 1, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('617349b18dab429009ccd304fd7d459c', '4028839a6de2ebd3016de2ebd3870000', 'update_by', '更新人', 'update_by', 0, 1, 'string', 50, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 4, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('61c7a0058c264dd746eb35e6f50fc15b', '402860816aa5921f016aa5dedcb90009', 'update_time', '更新日期', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 5, 'admin', '2019-05-11 15:56:47', '2019-05-11 15:50:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('6232ade7e2a0c1e97e2c0945b32e61b6', '402860816bff91c0016bffa220a9000b', 'paying_social_insurance', '是否上社保', 'paying_social_insurance', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 32, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('6352d477b6b2751780c5852e92d0daa6', '402880eb71d61d3d0171d61d3de30000', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-05-03 00:54:16', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('635e09afc01aad757faacf1321465c23', 'b81de38db24047b497d476516f8a0865', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2020-02-24 14:56:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('6490a98dccb6df218feaeb4ce11bc03b', '402860816aa5921f016aa5921f480000', 'update_time', '修改时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 10, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('654362725195829005036b3db47ec826', '402860816bff91c0016bffa220a9000b', 'post', '职务', 'post', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('6603058186832c4ff9e8c6e43baa5c3d', '86bf17839a904636b7ed96201b2fa6ea', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('66a7ef842bc34e105a90186e48167ef2', 'dbf4675875e14676a3f9a8b2b8941140', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2019-05-27 18:02:07', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('671e62c685bc86bde3cef0e023418fb4', '05a3a30dada7411c9109306aa4117068', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('67b5e120cd014ee9ff684e8d66f9d411', '2c91a0817fc4c754017fc4c757850002', 'logoen', 'logo url-英文版', 'logoen', 0, 1, 'string', 2000, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 14, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6831d3231369ebc978992c7e5b3f141f', '910984408e1948519e2fcf5ac08fe9ad', 'identification', '语言标识', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 0, 1, 1, 1, 'single', '', '', 7, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('686dea2621feadcd9b4c611df046adb4', '86bf17839a904636b7ed96201b2fa6ea', 'price', '价格', NULL, 0, 1, 'double', 10, 3, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('68769fa7e4696e3a28f4cecf63076b7b', '402860816bff91c0016bff91ca7e0002', 'order_no', '序号', 'order_no', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 8, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('68861523516849eff46a0df045f1031b', '402881e6760269a201760269a2af0000', 'birthday', '时间', NULL, 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 13, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6915257f75506f72789e61bb155f49bd', '402881e6760269a20176026a22e70001', 'sel_search', '下拉搜索', NULL, 0, 1, 'string', 32, 0, '', 'username', 'sys_user', 'username', 'sel_search', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 12, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('69666f21896136af16a6303aff440156', '402860816bff91c0016bffa220a9000b', 'nation', '民族', 'nation', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 11, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('69d11490788fecfc9fb7d74bf449ba86', '32f75e4043ef4070919dbd4337186a3d', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('69e568501d10281d061311d3db15e6af', '18f064d1ef424c93ba7a16148851664f', 'user_sel', '选择用户', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'sel_user', '', 120, NULL, '0', '', '#{sysUserCode}', 0, 1, 1, 0, 'single', '', '', 18, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6a0082c8ffbae092e99689520f1c83f7', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 9, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6a30c2e6f01ddd24349da55a37025cc0', 'd35109c3632c4952a19ecc094943dd71', 'top_pic', '头像', NULL, 0, 1, 'String', 500, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 12, 'admin', '2020-11-28 00:03:03', '2019-06-10 20:06:56', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6ab2e3d9b944701b405fb1a5ed167012', '86bf17839a904636b7ed96201b2fa6ea', 'zong_price', '单品总价', NULL, 0, 1, 'double', 10, 3, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6b21f5239671023ca769b6717a51130e', '402880eb71d61d3d0171d61d3de30000', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 8, 'admin', '2020-05-03 00:54:16', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6b6f3aa00b8e73fb785154e795189739', '402860816aa5921f016aa5dedcb90009', 'start_time', '会签发起时间', 'start_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-05-11 15:56:47', '2019-05-11 15:50:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('6beb40bdd28af22e06b26640bc0c3f4d', '3b5e18da618247539481816995b6bf9f', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6c35eb97737e9f86279939d264454a94', '86bf17839a904636b7ed96201b2fa6ea', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6ce89fbe0120fc95693819f3f038a365', '910984408e1948519e2fcf5ac08fe9ad', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6cfb5acbbb69782bf0c7043b53f595b2', '402860816bff91c0016bff91cda80003', 'update_by', '更新人', 'update_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 11, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('6d03a7774a50c6e6f76dbc7a8269beba', '3b5e18da618247539481816995b6bf9f', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6d4a4414b55ad5b6f31c8fb327dad834', '09fd28e4b7184c1a9668496a5c496450', 'address', '常用地址', NULL, 0, 1, 'string', 300, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6e5c9d8e8b7eb6980ec246cb813b180b', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 10, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6ed8d9acef3cccd1b8fd659b3b538023', '53a3e82b54b946c2b904f605875a275c', 'price', '价格', NULL, 0, 1, 'BigDecimal', 10, 5, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6f38a07ea2b1065315a6b89a02af5bb4', '3b5e18da618247539481816995b6bf9f', 'name', '用户名', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('6f73e96a659c200c083006b6fce1f043', '402860816bff91c0016bff91ca7e0002', 'cert_name', '证书名称', 'cert_name', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('71197d255e05c9f6db67fd30380953c7', '402881e6760269a201760269a2af0000', 'sel_mut', '下拉多选', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list_multi', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 11, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('7154c75d754a5f88bef2b68829baf576', '4028318169e81b970169e81b97650000', 'operate_type', '操作类型', 'operate_type', 0, 1, 'string', 10, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 4, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('71afb00a1971125ecfa13b4dfa49665e', '402860816bff91c0016bff91cfea0004', 'order_no', '序号', 'order_no', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 8, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('71d5b0675df5aba71688c9d7d75cccee', '4028318169e81b970169e81b97650000', 'log_type', '日志类型(1登录日志,2操作日志)', 'log_type', 0, 1, 'string', 10, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 2, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('71e9ab74dae687837365e50eed090591', '1acb6f81a1d9439da6cc4e868617b565', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7280c56a210e6a47794fda855d0c6abb', 'fbc35f067da94a70adb622ddba259352', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2019-07-03 19:44:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('72e784af5c47bbbc0534b29bf656bd61', '4028839a6de2ebd3016de2ebd3870000', 'id', '主键', 'id', 1, 0, 'string', 36, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 0, 0, 0, 'group', NULL, NULL, 1, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7365f05f551092716223d5d449efd8c7', 'beee191324fd40c1afec4fda18bd9d47', 'name', 'ss', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-04-13 13:41:13', '2019-04-13 13:40:56', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('73d3b57df0c6cf15c21970f4dd979319', '402880e5721355dd01721355dd390000', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 5, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('73dc6089556f3446e39d42df3dedb2db', '402880e570a5d7000170a5d700f50000', 'num', '数量', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, 'n', '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 8, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('74134505542ad8d48ecb119840028ed8', '2c91a0817fc4c754017fc4c754210000', 'contenten', '文章内容-英文版', 'contenten', 0, 1, 'Text', 0, 0, '', '', '', '', 'umeditor', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 17, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('742329ccdb185cf5d3e0b5b0c05dcffa', '402860816bff91c0016bffa220a9000b', 'interest', '兴趣爱好', 'interest', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 34, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('744444a7ada3bbb05c6b114b5ba0d477', '402860816aa5921f016aa5dedcb90009', 'id', 'id', 'id', 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-05-11 15:56:47', '2019-05-11 15:50:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('74af99545de724a4abd2022581a36026', 'fb7125a344a649b990c12949945cb6c1', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-03-26 19:24:11', '2019-03-26 19:01:52', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('756b07656386dbd91245f7ffda32ae61', '402860816bff91c0016bff91d8830007', 'id', 'id', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('75841fa7c75ebdc94655bd5e44fbc9f6', '402860816bff91c0016bffa220a9000b', 'native_place', '籍贯', 'native_place', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 10, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('75ba781c67711bed71bba1c3e3c68e11', '8994f2817b5a45d9890aa04497a317c5', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 0, NULL, NULL, '2019-03-23 11:39:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('75e82f151e8cc12455f7f0d25bf4dac0', '4028839a6de2ebd3016de2ebd3870000', 'wl_name', '物料名称', 'wl_name', 0, 1, 'string', 100, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 7, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7639c1bc4327f1f674ffeab2ca261134', '32f75e4043ef4070919dbd4337186a3d', 'update_by', '更新人登录名称', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('766ca866b72d118f5d8883de46a8c043', '4028839a6de2ebd3016de2ebd3870000', 'supplier', '供应商', 'supplier', 0, 1, 'string', 32, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 15, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('768e29bb93a68fa37bcb0d6722a6f6de', '2c91a0817fc4c754017fc4c756050001', 'create_time', '创建日期', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 3, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('76c64fdb02faecd86c817cbb58d293c2', '402881e6760269a201760269a2af0000', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 6, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('783a5ff64c6b0da3fd4cd540ddc662bf', '402881e6760269a20176026a22e70001', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', NULL, NULL, 1, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('78a40344207c791b8d7ac7de721ce1c4', '79091e8277c744158530321513119c68', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-05-11 15:29:47', '2019-05-11 15:27:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('78eb7e3b77cd49f9acb9b024cfe834e1', '402860816aa5921f016aa5dedcb90009', 'create_time', '创建日期', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 3, 'admin', '2019-05-11 15:56:47', '2019-05-11 15:50:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('78fd804d93dc716fd8c2ccc45f788565', 'fb7125a344a649b990c12949945cb6c1', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-03-26 19:24:11', '2019-03-26 19:01:52', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('790c9f3dba773ed9a6ea3ad627393f57', '402860816bff91c0016bffa220a9000b', 'archives_location', '档案所在地', 'archives_location', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 36, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7a665ed90ef64b4d65632c941e5795b2', '4b556f0168f64976a3d20bfb932bc798', 'sex', '性别', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, NULL, NULL, '2019-04-12 23:38:29', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7a697e4053445f07ad1a56a246f593e7', '86bf17839a904636b7ed96201b2fa6ea', 'good_name', '商品名字', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('7abe873f542bb5d7ce1cd8c798a62073', '402881e6760269a20176026a22e70001', 'checkbox', 'checkbox', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'checkbox', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 10, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('7af06f4d732ff15c114ed51acc1c8891', '402881e6760269a20176026a22e70001', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 4, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('7b2ffcf3e43a5d7b8d6f77d2a96b8491', '2d3bbeafdc364ecb974971a2d82adb9b', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('7b4c181e4ebd76022f75535ed6fd9de3', '4adec929a6594108bef5b35ee9966e9f', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 10, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('7b642d983ac06bfef91edde2c932dbe7', '1acb6f81a1d9439da6cc4e868617b565', 'xg_shangxian', '选购上限', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 14, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7b849e57debfb889caea5e0fef09062b', 'beee191324fd40c1afec4fda18bd9d47', 'sex2', 'dd', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-04-13 13:41:13', '2019-04-13 13:40:56', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7beb639aa9ffda07edb5ce1e49c2287f', '402860816bff91c0016bff91d2810005', 'update_time', '更新时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 13, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7bf091da401b74d55b107fe9f930ea54', '4028839a6de2ebd3016de2ebd3870000', 'create_by', '创建人', 'create_by', 0, 1, 'string', 50, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 2, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7c6aecc377816c69147f1193b17dfcc5', 'e9faf717024b4aae95cff224ae9b6d97', 'sex', '员工性别', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7cadf4e0be0b173bb5b8d39613e25190', '402860816bff91c0016bffa220a9000b', 'residence_postcode', '户籍邮编', 'residence_postcode', 0, 1, 'string', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 29, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7cc13710a3ff2046364204b7e5158467', '402881e6760269a20176026a22e70001', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 6, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('7cce797000cec08416fb027d1a4013cb', '402881e6760269a20176026d25650002', 'sex', '性别 {男:1,女:2}', 'sex', 0, 1, 'string', 2, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 7, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7cdbe0d563e15f3fb1fb32d996fe4ba7', '3d447fa919b64f6883a834036c14aa67', 'area', '区', NULL, 0, 1, 'String', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 4, 'admin', '2020-02-21 17:58:46', '2020-02-20 16:19:00', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7d107728408c21ece332406a21f2d692', '402860816bff91c0016bff91cfea0004', 'update_by', '更新人', 'update_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 11, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7e066f60680158d47b328ef519d80e49', 'beee191324fd40c1afec4fda18bd9d47', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-04-13 13:41:13', '2019-04-13 13:40:56', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7e331396f6e544ae801690cf475e7615', '402881e6760269a201760269a2af0000', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 3, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('7f10901c6ade3aa9d9ff46ed7039c70f', '1acb6f81a1d9439da6cc4e868617b565', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('7ff9dbe4ac71bb64d057a3a2063fca2c', '402881e6760269a20176026a22e70001', 'radio', 'radio', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'radio', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 9, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('809a9fafe0b79c9997de32cb6e831c6f', '05a3a30dada7411c9109306aa4117068', 'birthday', '生日', NULL, 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8119d3de514092232935b038531828c5', '05a3a30dada7411c9109306aa4117068', 'sex', '性别', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('813a5ebf7335309c7edb3803f7e4b204', '402880e570a5d7000170a5d700f50000', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 2, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('817cc5e277e88164dffd4caee1169276', '56efb74326e74064b60933f6f8af30ea', 'remark', '备注', NULL, 0, 1, 'string', 500, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('81ed9556c9fda1bbb46d94a53a6c90c7', '402860816bff91c0016bff91c0cb0000', 'depart_name', '部门名称', 'depart', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('840343a59a8e705821d393506c2bc1fe', '402880e570a5d7000170a5d700f50000', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 3, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8419278effeb3a6531247fbfdb3b10e3', '402881e6760269a201760269a2af0000', 'user_sel', '选择用户', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'sel_user', '', 120, NULL, '0', '', '#{sysUserCode}', 0, 1, 1, 0, 'single', NULL, NULL, 18, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8422485e1cbf4455f9ded7d0af59379c', '402860816bff91c0016bff91cfea0004', 'to_time', '截止时间', 'to_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('845c70568d44a074f067d6d277950525', '402860816bff91c0016bffa220a9000b', 'entrytime', '入职时间', 'entrytime', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 23, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8529ddaed8d5f3d9084e873203d55cac', '402860816bff91c0016bffa220a9000b', 'marital_status', '婚姻状况', 'marital_status', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 24, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('857a0daa9cd8a058f2f15fc7c5fb3571', '402860816bff91c0016bffa220a9000b', 'email', '邮箱', 'email', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 17, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('85e43fa87074845f86cf52606a23a57c', 'b81de38db24047b497d476516f8a0865', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2020-02-24 14:56:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8652ca69a947fd4c961a3ac7c0fa252a', 'fb19fb067cd841f9ae93d4eb3b883dc0', 'create_by', '创建人登录名称', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 1, NULL, NULL, '2019-03-23 11:39:48', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('86bbafef5683674a736cf7241c458d44', '27fc5f91274344afa7673a732b279939', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-07-01 16:28:20', '2019-07-01 16:26:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('86e0f3a8f31c60698157f139ed993954', '402860816bff91c0016bffa220a9000b', 'having_reserve_funds', '是否有公积金', 'having_reserve_funds', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 33, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('86f29e9919766e0d1128263608c016a0', '997ee931515a4620bc30a9c1246429a9', 'type_name', '商品分类', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('873e2bb041b17bff77d3aca72900ea1b', '56870166aba54ebfacb20ba6c770bd73', 'order_code', '订单编码', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2020-11-28 00:02:01', '2019-04-20 11:38:39', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8756fbb5c23a0258e029e0cb3c0a045c', '402880e5721355dd01721355dd390000', 'price', '价格', NULL, 0, 1, 'double', 10, 3, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 8, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('877391ae770a4ce2c95181ef410982ce', '4028318169e81b970169e81b97650000', 'request_param', '请求参数', 'request_param', 0, 1, 'string', 255, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 10, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('87e22ceeb12312250c16741929586c4b', '402881e6760269a20176026a22e70001', 'sel_mut', '下拉多选', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list_multi', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 11, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('87e82e3c723a6abb020122babdac6bd1', '8994f2817b5a45d9890aa04497a317c5', 'create_by', '创建人登录名称', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 1, NULL, NULL, '2019-03-23 11:39:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('87f7a2703c5850f0b063dd866d0e2917', '402860816bff91c0016bffa220a9000b', 'birthday', '出生日期', 'birthday', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('87fafe1a4a8a626e3875697574c19f15', '402860816bff91c0016bff91d2810005', 'sys_org_code', '组织机构编码', 'sys_org_code', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 14, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('883265736ad6db0c98a7517d1f4a2488', '402880eb71d52dc30171d52dc3a10000', 'main_id', '主表ID', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 5, NULL, NULL, '2020-05-02 19:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8845c67217ff1ce16acc0f6b84f22a6d', '2c91a0817fc4c754017fc4c754210000', 'update_time', '更新日期', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 5, 'admin', '2022-03-26 13:58:50', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('88a12570e14c9f6f442e731ae5ad0eb1', 'beee191324fd40c1afec4fda18bd9d47', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-04-13 13:41:13', '2019-04-13 13:40:56', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('88de72456c03410c364c80095aaa96eb', 'd35109c3632c4952a19ecc094943dd71', 'pop', '弹窗', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 15, 'admin', '2020-11-28 00:03:03', '2020-11-26 18:02:20', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('89370ae67e241fa5d1e47d22adeaca7b', '402880eb71d52dc30171d52dc3a10000', 'date', '日期', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{date}', 0, 1, 1, 0, 'single', NULL, NULL, 4, NULL, NULL, '2020-05-02 19:37:58', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('89ab9eedbac6141e7a0df6d37a3655d0', 'e67d26b610dd414c884c4dbb24e71ce3', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-04-24 11:03:32', '2019-04-24 11:02:57', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8a24fb45e2af120c253c8b61c0085f7a', '402860816bff91c0016bff91cda80003', 'sys_org_code', '组织机构编码', 'sys_org_code', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 13, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8a2f97fde739720e86fbcd3ce311c037', '09fd28e4b7184c1a9668496a5c496450', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8a6440c447ca97b1ceac40fa8576044e', '3b5e18da618247539481816995b6bf9f', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8a9d6bbbe45fd3539a8cb3ba2cee470a', '402881e6760269a201760269a2af0000', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 5, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8ac8a0c0087469a4e7579229ff17f273', 'e5464aa8fa7b47c580e91593cf9b46dc', 'jifen', '合计积分', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2019-04-24 17:09:49', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8bd4deadc9e96c1a6d7abd77033105f6', 'e67d26b610dd414c884c4dbb24e71ce3', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-04-24 11:03:32', '2019-04-24 11:02:57', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8c1b6fff73650b8650947c2a29c63492', '402881e6760269a201760269a2af0000', 'sex', '下拉框', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 8, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('8c6518fec11fc4769ba4eb770c9e00f7', '4028839a6de2ebd3016de2ebd3870000', 'integral_val', '积分值', 'integral_val', 0, 1, 'int', 10, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 11, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8c960ed82ba23e19580307c0e9434de0', '18f064d1ef424c93ba7a16148851664f', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8ca56210938fbe649f840e505eb9fd41', '56870166aba54ebfacb20ba6c770bd73', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-11-28 00:02:01', '2019-04-20 11:38:39', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8d03979d053b758473c8d777996aef46', '2c91a0817fc4c754017fc4c757850002', 'update_time', '更新日期', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 5, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8e080f4ded1e3b2a1daa5b11eca4a0ff', '4adec929a6594108bef5b35ee9966e9f', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 7, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8e1212df6a94ed8f5102a327564e5af6', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'name', '分类名字', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8e131d4a438c907b3272474780be7603', '402880eb71d52dc30171d52dc3a10000', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 8, NULL, NULL, '2020-05-02 19:37:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8e1e4cb5c41ba685c48ebabf0aacc469', '402880eb71d61d3d0171d61d3de30000', 'name', '名称', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{sysUserName}', 0, 1, 0, 0, 'single', '', '', 3, 'admin', '2020-11-26 17:28:14', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('8ea43fd1e4ce82becee61b2f1e2e843f', '32feeb502544416c9bf41329c10a88f4', 'sex', '性别', NULL, 0, 1, 'String', 32, 0, '', 'sex', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8f1d302868640b72cef52171a023a203', 'e9faf717024b4aae95cff224ae9b6d97', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8f3e6fb68179c690f748f3c541fb50f1', '7ea60a25fa27470e9080d6a921aabbd1', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2019-04-17 00:22:21', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('8fc0be84bed1216635c69af918e097ff', '402860816aa5921f016aa5dedcb90009', 'name', '并行会签标题', 'name', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-05-11 15:56:47', '2019-05-11 15:50:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('903c33f7d18175a269b783cd4288216f', '402881e6760269a20176026d25650002', 'update_time', '修改时间', 'update_time', 0, 1, 'Date', 0, 0, NULL, NULL, NULL, NULL, 'date', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 15, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('909b3de0c8a48a21ef8cf98eb4831689', '56efb74326e74064b60933f6f8af30ea', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('90a822b8a63bbbc1e9575c9f4e21e021', 'd35109c3632c4952a19ecc094943dd71', 'descc', '描述', NULL, 0, 1, 'string', 500, 0, '', '', '', '', 'umeditor', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('90f39a6e29dae2e1fbb59d7d605f7c09', '1acb6f81a1d9439da6cc4e868617b565', 'iz_valid', '启用状态', NULL, 0, 1, 'String', 2, 0, '', 'air_china_valid', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9189717f24edba06c6f7ad734e24d395', '2c91a0817fc4c754017fc4c754210000', 'content', '文章内容', 'content', 0, 1, 'Text', 0, 0, '', '', '', '', 'umeditor', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 16, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('918b8d661e480624713ddcff1bdda4f4', '402881e6760269a20176026d25650002', 'birthday', '生日', 'birthday', 0, 1, 'Date', 0, 0, NULL, NULL, NULL, NULL, 'date', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 9, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('91be98b96dea1528abc943f9f131fd16', '402880e570a5d7000170a5d700f50000', 'price', '价格', NULL, 0, 1, 'double', 32, 0, '', '', '', '', 'text', '', 120, 'n', '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 7, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('91f7cd9b59c0da033363f8a09b02ec96', '3d447fa919b64f6883a834036c14aa67', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-02-21 17:58:46', '2020-02-20 16:19:00', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('921cc5a92a79e1e21e9e631a1b7f3fbd', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, NULL, NULL, '2020-05-07 22:46:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('9341a3b2a734d8c73455c136e1cac8ad', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 8, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('9370c9304af30b8d29defe0a5ada6e5b', '62e29cdb81ac44d1a2d8ff89851b853d', 'DC_DDSA', 'DD', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, NULL, NULL, '2019-05-11 14:01:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9371f61d39c5d57ddb0a2db96b2e2412', '402860816bff91c0016bffa220a9000b', 'speciality', '专业', 'speciality', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 15, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('947174892512ea97fafde899d427ea7e', '402860816bff91c0016bff91c0cb0000', 'real_name', '姓名', 'real_name', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('94b8bf435175cc545366e11992280757', '32f75e4043ef4070919dbd4337186a3d', 'age', '年龄', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('94e682cb802777fe4205536888f69353', '402860816bff91c0016bff91d2810005', 'create_by', '创建人', 'create_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 10, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('951c51699d728072d88196d30f7aad10', '4adec929a6594108bef5b35ee9966e9f', 'address', '地址', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '{{ demoFieldDefVal_getAddress() }}', 0, 1, 1, 0, 'single', '', '', 5, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('957386b500be42a200d6a56d54345392', 'deea5a8ec619460c9245ba85dbc59e80', 'num', '数量', NULL, 0, 1, 'int', 32, 0, '', '', '', '', 'text', '', 120, 'n', '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('95fbb1d279402b9d1c0e17665340febb', '402881e6760269a20176026a22e70001', 'pic', '图片', NULL, 0, 1, 'string', 1000, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 14, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('960d2847922b61dadeb3518ef55fb0c1', '1acb6f81a1d9439da6cc4e868617b565', 'wl_name', '物料名称', NULL, 0, 1, 'String', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9665f02764774fdd77c19923d3ff3c3e', '4028318169e81b970169e81b97650000', 'cost_time', '耗时', 'cost_time', 0, 1, 'string', 19, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 12, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('966a4988298d5cb0be47848735ce8cb7', '4028839a6de2ebd3016de2ebd3870000', 'xg_shangxian', '选购上限', 'xg_shangxian', 0, 1, 'int', 10, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 12, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9698964a9e06edf12fc88df976080984', '09fd28e4b7184c1a9668496a5c496450', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('96c585a4f71e5c38ed25b9741366365b', '402860816bff91c0016bff91c7010001', 'sys_org_code', '组织机构编码', 'sys_org_code', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 11, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9765efa2cafde6d0ede2215848c9e80b', '32f75e4043ef4070919dbd4337186a3d', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 0, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('982f9669faf4d655d4aa1fec3c519a0e', '2c91a0817fc4c754017fc4c754210000', 'source', '来源', 'source', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 14, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('98e82cb1595609a3b42fa75c60ac1229', '402860816bff91c0016bff91d2810005', 'update_by', '更新人', 'update_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 12, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9914a0c84805e72c4b6075e36edb13f9', '402860816aa5921f016aa5921f480000', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 9, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9920ecec9c9109fc6b93e86f8fdfa03b', '402860816bff91c0016bffa220a9000b', 'depart_name', '所在部门', 'depart_name', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'group', '', '', 2, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('99b43bbb23237815ebb74b12b4d7ea2f', '62e29cdb81ac44d1a2d8ff89851b853d', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, NULL, NULL, '2019-05-11 14:01:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9a462d83210cad30f0e12b98e8a172a7', '3b5e18da618247539481816995b6bf9f', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('9a4dc8718000c30953a3923eb7db5096', '402880eb71d52dc30171d52dc3a10000', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', NULL, NULL, 1, NULL, NULL, '2020-05-02 19:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('9a579c506f75f75baf88352a5eb2c249', '1acb6f81a1d9439da6cc4e868617b565', 'bpm_status', '流程状态', NULL, 0, 1, 'String', 2, 0, '1', 'bpm_status', '', '', 'list', '', 120, NULL, '0', '', '', 0, 0, 1, 0, 'single', '', '', 16, 'admin', '2019-06-10 14:47:14', '2019-05-07 16:54:43', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9a9516645cbc8147b23333fea76aa2bb', 'b81de38db24047b497d476516f8a0865', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2020-02-24 14:56:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9aa6738443d3d8a67cf50506199d15ad', 'cb2d8534a2f544bc9c618dd49da66336', 'aaae', 'aae', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, NULL, NULL, '2020-02-24 17:22:43', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9bd056786694d67666f6924cc225b1a0', '3d447fa919b64f6883a834036c14aa67', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2020-02-21 17:58:46', '2020-02-20 16:19:00', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9c40fb4db8afed3c682c6b8a732fd69d', 'e2faf977fdaf4b25a524f58c2441a51c', 'post', '用户岗位', NULL, 0, 1, 'String', 32, 0, '', 'post_code', 'air_china_post_materiel_main', 'post_name', 'sel_search', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9cc60be30026301b9eafb8c310387f54', '402880e570a5d7000170a5d700f50000', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 4, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9ceff249ef81ca6fa145456667c89051', '4adec929a6594108bef5b35ee9966e9f', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 8, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('9d85bafa399f28a40e1de1eeef747223', '4028318169e81b970169e81b97650000', 'ip', 'IP', 'ip', 0, 1, 'string', 100, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 7, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9d88e0661ed4b0969b7f0608a714b14a', '402881e6760269a20176026d25650002', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, NULL, NULL, NULL, NULL, 'date', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 13, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9d89ff1a019f41d80307652041490944', '32feeb502544416c9bf41329c10a88f4', 'name', '请假人', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9e50680eb4e79b3af352a5933d239dff', 'dbf4675875e14676a3f9a8b2b8941140', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, NULL, NULL, '2019-05-27 18:02:07', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('9ec6c73432e57354d7d55dbea0916776', '18f064d1ef424c93ba7a16148851664f', 'name', '用户名', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{sysUserCode}', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('a01a7fe5660206e6f407ed98b6c732d6', '402860816bff91c0016bff91cfea0004', 'phone', '联系方式', 'phone', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a1a2d49b35c185df9f9e149b290aa277', '56efb74326e74064b60933f6f8af30ea', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('a1f5daba36f536e7acf6a939826183b0', 'fb19fb067cd841f9ae93d4eb3b883dc0', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 0, NULL, NULL, '2019-03-23 11:39:48', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a232d608434d15fcecd8a3f31a9044b2', '86bf17839a904636b7ed96201b2fa6ea', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('a3dea64c8009780e213d16c69704c030', '53a3e82b54b946c2b904f605875a275c', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('a45eba33810c485b9d8e6f70818a1dfa', '402860816aa5921f016aa5921f480000', 'bpm_status', '流程状态', 'bpm_status', 0, 1, 'string', 50, 0, '1', 'bpm_status', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 1, 0, 'group', '', '', 7, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a55576228512c4ee873fc68c8f3dd429', '2d3bbeafdc364ecb974971a2d82adb9b', 'mailbox', '邮箱', NULL, 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('a6471d4fb3dbffef01dab1f7d452bb30', '27fc5f91274344afa7673a732b279939', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-07-01 16:28:20', '2019-07-01 16:26:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a6722b498602d7d7b5177b16789d8cc1', 'e5464aa8fa7b47c580e91593cf9b46dc', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-04-24 17:09:48', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a76f561057ac9e43a8ca09e478a1eab8', '402860816bff91c0016bff91ca7e0002', 'update_time', '更新时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 12, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a7822f6e4cffb37fc0729cbd4cfd8655', '32f75e4043ef4070919dbd4337186a3d', 'name', '用户名', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 5, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a7b6ae09441ce36a14c7ce95f17a218e', '86bf17839a904636b7ed96201b2fa6ea', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('a82ca42a76e9d2b8dae6d57dbb5edb54', 'deea5a8ec619460c9245ba85dbc59e80', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('a83c029e021023771f646a20b63c4d4b', '18f064d1ef424c93ba7a16148851664f', 'sel_search', '下拉搜索', NULL, 0, 1, 'string', 32, 0, '', 'username', 'sys_user', 'username', 'sel_search', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 12, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('a940adc4585fa3b5bd2114ea9abe8491', '402860816bff91c0016bff91ca7e0002', 'cert_level', '证书级别', 'cert_level', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a94f1d7da64f3aa35c32155ea00ccb2f', '402860816bff91c0016bffa220a9000b', 'id', 'id', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('a9780eace237a15f26931dd6a9ec02e9', '758334cb1e7445e2822b60e807aec4a3', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2019-10-18 18:02:09', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('aa07931514727913413880b7a2b76dcb', 'd3ae1c692b9640e0a091f8c46e17bb01', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2019-07-24 14:47:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('aa4780601419c21dabb6c42fc511e71c', '402860816bff91c0016bffa220a9000b', 'have_children', '有无子女', 'have_children', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 25, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ab10e0aa029ded2f4420a33420de225d', '1acb6f81a1d9439da6cc4e868617b565', 'wl_code', '物料编码', NULL, 0, 1, 'String', 60, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ab1f880ba593f3757dac70e003945aa2', '402860816bff91c0016bff91c0cb0000', 'depart_id', '部门ID', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-07-19 18:09:01', '2019-07-17 19:38:45', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ab58f43f853fd1f65f83c22966883afb', 'beee191324fd40c1afec4fda18bd9d47', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-04-13 13:41:13', '2019-04-13 13:40:56', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ab8e6f1cca421c5ce395a2c1fdfd2100', '32feeb502544416c9bf41329c10a88f4', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('abe61a8ddf966a979457b763329a537b', 'e5464aa8fa7b47c580e91593cf9b46dc', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-04-24 17:09:49', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ac91565da5fb8fe43a4da3dec660b25f', '402860816bff91c0016bff91c7010001', 'award_place', '获奖地点', 'award_place', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ace01516cca57f1235543dcc9742fde5', '2c91a0817fc4c754017fc4c754210000', 'titleen', '标题-英文版', 'titleen', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('acff5c8aef3b6288b87fd91215012206', 'e5464aa8fa7b47c580e91593cf9b46dc', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-04-24 17:09:49', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ad061417d5b53c67975eb83657505218', '73162c3b8161413e8ecdca7eb288d0c9', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ad93762c6c4a1dd8331e5fa11215b568', 'e2faf977fdaf4b25a524f58c2441a51c', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('adc05e865edbaabce772636632b741bd', '910984408e1948519e2fcf5ac08fe9ad', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ae31da96f38fc2941cb93d1bb1ab9431', 'deea5a8ec619460c9245ba85dbc59e80', 'product_name', '产品名字', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ae77bb317366622698c8ab9bf2325833', 'deea5a8ec619460c9245ba85dbc59e80', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ae9e686072c3c7f9b36bbc4be0fe1384', '402881e6760269a201760269a2af0000', 'name', '用户名', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{sysUserCode}', 0, 1, 1, 0, 'single', NULL, NULL, 7, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('af0fe0df8b626129de62e22212732517', '402860816bff91c0016bff91cda80003', 'speciality', '专业', 'speciality', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('af6c582b902e2f2bf9930eba61ae7938', '73162c3b8161413e8ecdca7eb288d0c9', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('afd3ef1d494a9b69d2c7a3cdde937f6f', '402860816bff91c0016bffa220a9000b', 'create_by', '创建人', 'create_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 39, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b01304904babd7479de2acfe8a77157f', '402860816aa5921f016aa5921f480000', 'id', 'ID', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b05b4cbb74f389a7376f51ed9fd97030', '402860816bff91c0016bff91d8830007', 'create_by', '创建人', 'create_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 10, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b0a06bdbefd304d81a1838d8d94deda9', '4b556f0168f64976a3d20bfb932bc798', 'name', '用户名', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, NULL, NULL, '2019-04-12 23:38:28', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b0a2c8d21782830ec6a2d16cc1231328', '402881e6760269a20176026d25650002', 'punch_time', '打卡时间', 'punch_time', 0, 1, 'Date', 0, 0, NULL, NULL, NULL, NULL, 'date', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 4, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b0ab4e227d74c4de4bea33e6e9b4e7ff', '2c91a0817fc4c754017fc4c757850002', 'urlen', '链接-英文版', 'urlen', 0, 1, 'string', 2000, 0, '', '', '', '', 'text', '', 120, 'url', '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b0b0cc4395c9f08b4dd9e849e622b953', '2c91a0817fc4c754017fc4c756050001', 'is_enable', '是否启用', 'is_enable', 0, 1, 'string', 2, 0, '', '', 'yn', '', 'switch', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 11, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', 'YN', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b0b1cf271dd6b221a902da2d2f8f889a', 'e9faf717024b4aae95cff224ae9b6d97', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b0dfd0f0c36ee46ef483c0c225956ac5', '402881e6760269a201760269a2af0000', 'checkbox', 'checkbox', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'checkbox', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 10, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b18f96f96d979daa7336e81086ea2bc1', 'cb2d8534a2f544bc9c618dd49da66336', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-02-24 17:22:42', '2020-02-24 15:15:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b1fc6e2ca671b19e57b08a4f57fc2454', 'fb7125a344a649b990c12949945cb6c1', 'update_time', '更新日期', NULL, 0, 1, 'date', 20, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-03-26 19:24:11', '2019-03-26 19:01:52', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b22694cf34ffb967b8717647816ad5df', 'e5464aa8fa7b47c580e91593cf9b46dc', 'fk_id', '外键', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', 'air_china_post_materiel_main', 'id', 15, 'admin', '2019-04-24 17:09:49', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b276facab025f9750b0aff391693cc4b', '402860816bff91c0016bff91c7010001', 'id', 'id', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b2b0cb30159639bb1190e150322b7541', '4028839a6de2ebd3016de2ebd3870000', 'wl_unit', '计量单位', 'wl_unit', 0, 1, 'string', 100, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 14, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b319cc124cd7f9bd0c8156712de0ef79', '910984408e1948519e2fcf5ac08fe9ad', 'is_enable', '是否启用(1:是,0:否),同一个标识只能有一个启用的', NULL, 0, 1, 'int', 1, 0, '', '', 'yn', '', 'switch', '', 120, NULL, '0', '', '', 0, 1, 1, 1, 'single', '', '', 9, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('b3542d3e7908ed885ecc4ba9e7300705', '4b556f0168f64976a3d20bfb932bc798', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2019-04-12 23:38:28', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b3b61f9386eb2262919e0835e3c82eb9', '86bf17839a904636b7ed96201b2fa6ea', 'num', '数量', NULL, 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b3c29e47c5093e68c297a7fa29c7e8cc', '2c91a0817fc4c754017fc4c756050001', 'update_by', '更新人', 'update_by', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 4, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b47af4d937e55c6208939bac5378bfad', '62e29cdb81ac44d1a2d8ff89851b853d', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2019-05-11 14:01:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b53203fc52d067bb4730dbcb7e496bd3', '56870166aba54ebfacb20ba6c770bd73', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2020-11-28 00:02:01', '2019-04-20 11:38:39', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b57cfd6922ebb3d75c84e386b7df38d0', '402881e6760269a20176026a22e70001', 'user_sel', '选择用户', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'sel_user', '', 120, NULL, '0', '', '#{sysUserCode}', 0, 1, 1, 0, 'single', NULL, NULL, 18, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b5cfd3c9691a884430f3d9cd5ecb211f', 'e2faf977fdaf4b25a524f58c2441a51c', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b6874a05734cad8bd96ffd2f31f1ebca', '402860816bff91c0016bff91c7010001', 'create_by', '创建人', 'create_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b733fa73519603b22d401fabbf9e9781', '402860816bff91c0016bff91c0cb0000', 'hiredate', '入职时间', 'hiredate', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b78d5ab8bbb5ff9b5308d226629ea19f', '402881e6760269a20176026a22e70001', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 3, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b7938e4518f9062ce62702cf45986e06', 'e2faf977fdaf4b25a524f58c2441a51c', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b7a1243aaa712e2c152c0c7a46f88683', '402860816bff91c0016bff91d8830007', 'age', '年龄', 'age', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b7b311cf4483bd10a93a40891cc39a77', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'has_child', '是否有子节点', NULL, 0, 1, 'string', 3, 0, '', 'yn', '', '', 'list', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 11, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b889cee39613fe2d8121d03ad28a8af4', '2c91a0817fc4c754017fc4c757850002', 'id', 'id', 'id', 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('b91258e3dc15b28c2e3f0d934e6e27e8', 'fb7125a344a649b990c12949945cb6c1', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 0, NULL, NULL, '2019-03-26 19:01:52', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b92572ae142f8dd5f2ac02fb45e6b2c1', 'e2faf977fdaf4b25a524f58c2441a51c', 'name', '用户名', NULL, 0, 1, 'String', 32, 0, '', 'realname,username', 'report_user', 'name,account', 'sel_search', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('b9fbace24688c9c9a8c9be72c1d014e7', '402860816bff91c0016bffa220a9000b', 'phone', '电话', 'phone', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 18, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ba17414716b12b51c85f9d1f6f1e5787', 'd35109c3632c4952a19ecc094943dd71', 'chegnshi', '城市', NULL, 0, 1, 'string', 300, 0, '', '', '', '', 'pca', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 14, 'admin', '2020-11-28 00:03:03', '2020-11-26 16:54:45', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ba5f4b2affa94f36eda7f6f133db7ae3', '402860816bff91c0016bff91d2810005', 'workplace', '工作单位', 'workplace', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ba63a228af579d5a7e8d361b02c0db05', '2c91a0817fc4c754017fc4c756050001', 'update_time', '更新日期', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 5, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ba6f3e762d6e3ea1068a085ec2f7e501', '56efb74326e74064b60933f6f8af30ea', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('bad02e68ea37bf387337516af84a1ddb', '73162c3b8161413e8ecdca7eb288d0c9', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bb44475e1d1738a19745bf9f3ebf9e40', '402860816bff91c0016bff91cfea0004', 'update_time', '更新时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 12, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bbbb38347b1a5340a1d293e455c632ce', 'fb19fb067cd841f9ae93d4eb3b883dc0', '3', '4', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, NULL, NULL, '2019-03-23 11:39:48', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bc648624ad14c826bbc6e9b23a2b9858', '402860816bff91c0016bff91ca7e0002', 'employee_id', '员工ID', 'employee_id', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', 'oa_employee_info', 'id', 2, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bc793fdbef9f6474425456c4eb9d197a', '402860816bff91c0016bff91cfea0004', 'witness', '证明人', 'references', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bc7df6f3cf49f670c36a3de25e25e715', '402860816bff91c0016bff91d2810005', 'order_no', '序号', 'order_no', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 9, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bcf2f5d1390227cf0d9ddfbd6121161f', '402880eb71d61d3d0171d61d3de30000', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-05-03 00:54:16', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('bd39cb237049ac60218b3f4dd844f30c', '402860816bff91c0016bffa220a9000b', 'current_address', '现居住地', 'current_address', 0, 1, 'string', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 30, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bde81809057b1a4c974fa0f090501fdd', '402860816aa5921f016aa5dedcb90009', 'update_by', '更新人', 'update_by', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 4, 'admin', '2019-05-11 15:56:47', '2019-05-11 15:50:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bdea5b776a15897265c43e6ee44af2e1', '997ee931515a4620bc30a9c1246429a9', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('be3f8c157d8a1b40e6f7b836552a8095', '8994f2817b5a45d9890aa04497a317c5', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 2, NULL, NULL, '2019-03-23 11:39:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('be5eeda7d51dace73d3818bd8467b53b', '402860816bff91c0016bff91c0cb0000', 'update_time', '更新时间', 'update_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 15, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('be868eed386da3cfcf49ea9afcdadf11', 'd35109c3632c4952a19ecc094943dd71', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('bec3082fc5f0f194be5cd72cc2866ff4', 'e5464aa8fa7b47c580e91593cf9b46dc', 'wl_name', '物料名字', NULL, 0, 1, 'String', 200, 0, '', 'wl_code', 'air_china_materiel', 'wl_name', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-04-24 17:09:49', '2019-04-24 11:05:10', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bed0bc67f570613eaa6a1bd8bcaaddcc', '4b556f0168f64976a3d20bfb932bc798', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2019-04-12 23:38:28', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bed95ca6dd6bb4b4f7cfd787313a0a4b', '402880e570a5d7000170a5d700f50000', 'product_name', '产品名字', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 6, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bef85fd2846dd7ffc42d747095557d14', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'date', '日期', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{date}', 0, 1, 1, 0, 'single', '', '', 4, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('bf61aa04c5ca77ad54c764f8f8b2bdec', '402860816bff91c0016bff91d8830007', 'update_by', '更新人', 'update_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 12, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('bfb71a6fdbf8b45b0f78197e0ca34663', '2c91a0817fc4c754017fc4c756050001', 'name', '名称', 'name', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 7, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('bfc2f19fae367f885adb8bd82a344391', '4028318169e81b970169e81b97650000', 'userid', '操作用户账号', 'userid', 0, 1, 'string', 32, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 5, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c047ed2cead5bab0307967435f370936', '53a3e82b54b946c2b904f605875a275c', 'chuc_date', '出厂时间', NULL, 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-05-08 23:42:51', '2020-05-07 22:49:47', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c0c80f370e1d400fe670d8702c3b84da', '4adec929a6594108bef5b35ee9966e9f', 'address_param', '地址(传参)', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '{{ demoFieldDefVal_getAddress(\"昌平区\") }}', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:40:53', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c0d66c95773774e7ac1f2a88df307e7a', '402860816aa5921f016aa5921f480000', 'reason', '请假原因', 'reason', 0, 1, 'string', 500, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c29216d975fee50af175bca8c664a475', 'e67d26b610dd414c884c4dbb24e71ce3', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-04-24 11:03:32', '2019-04-24 11:02:56', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c2b9eae184afe56d59ea7940d77cfced', '4adec929a6594108bef5b35ee9966e9f', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:57', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c2dbb6846ab0945a430d095a29e0f53d', '18f064d1ef424c93ba7a16148851664f', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c311cca084580e5fd4b5a2e5b81c4cc5', '402881e6760269a20176026d25650002', 'email', '邮箱', 'email', 0, 1, 'string', 50, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 10, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c382877700a9987f4bcc2deea9ee9daf', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c3b5f7850d0052465fdfa4edeb063a96', '2c91a0817fc4c754017fc4c757850002', 'type', '类型(显示在哪)', 'type', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 8, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c43d87b6340c29c0c354aa9c579f387f', '32feeb502544416c9bf41329c10a88f4', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c456753a9c83e55fa241c4ec72c00f86', '402880eb71d52dc30171d52dc3a10000', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 6, NULL, NULL, '2020-05-02 19:37:58', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c4d71528f3f45661b1a87841b7256204', '402880e5721355dd01721355dd390000', 'order_main_id', '订单ID', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 11, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c52711856d2e81ad1074265833f44328', 'b81de38db24047b497d476516f8a0865', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, NULL, NULL, '2020-02-24 14:56:07', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c596f7f9035c71f9d2d0206d14b0eee8', '402881e6760269a201760269a2af0000', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 4, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c59f39e7b3bb877398f16796b2cd7962', '997ee931515a4620bc30a9c1246429a9', 'pid', '父级节点', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 0, 0, 'single', '', '', 9, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c5a61724b3b1fdfd0eb39c361f22bafd', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c5dd2fc34ae825ebfced2ec74948654c', '402860816aa5921f016aa5921f480000', 'end_date', '请假结束时间', 'end_date', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c5f6ea01a6523a60df153cc61dc92f4d', 'fbc35f067da94a70adb622ddba259352', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2019-07-03 19:44:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c6024742fbc62f2fc39992e6b59ac13d', '05a3a30dada7411c9109306aa4117068', 'age', '年龄', NULL, 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'group', '', '', 8, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('c6730e00df5efd77fedf181df29102de', '402860816bff91c0016bff91c7010001', 'update_by', '更新人', 'update_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 9, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c75a7cb0a21958aa7ca5442f66019669', 'e9faf717024b4aae95cff224ae9b6d97', 'depart', '所属部门', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c772ed9cbe2d1dc69e9ffa73d3487021', '4b556f0168f64976a3d20bfb932bc798', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, NULL, NULL, '2019-04-12 23:38:28', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c8027cf4f2483042445c89ba86c4e51f', '402880e5721355dd01721355dd390000', 'zong_price', '单品总价', NULL, 0, 1, 'double', 10, 3, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 10, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('c91b697b1bcd2be943fc746e2660bc9e', '402860816bff91c0016bff91d2810005', 'real_name', '姓名', 'real_name', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c988bd2b6125c01ceb3579a207dd8784', '3d447fa919b64f6883a834036c14aa67', 'city', '市', NULL, 0, 1, 'String', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 3, 'admin', '2020-02-21 17:58:46', '2020-02-20 16:19:00', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('c9b698d3f75aa780ee1eb67ef090b15b', '73162c3b8161413e8ecdca7eb288d0c9', 'wl_code', '物料编码', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ca7c27f60d2022c7c3ace466dd805498', '2d3bbeafdc364ecb974971a2d82adb9b', 'homepage_url', '学校主页地址', NULL, 0, 1, 'string', 2000, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 14, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('caf5a071f2299c0f9ff2f3038d6d0fc6', '402860816bff91c0016bff91ca7e0002', 'update_by', '更新人', 'update_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 11, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('cb33a708b95e19085f8c9001d2d5c64c', 'e9faf717024b4aae95cff224ae9b6d97', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('cb50a5991ca29e617aa32e49e92c01e7', '09fd28e4b7184c1a9668496a5c496450', 'age', '年龄', NULL, 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('cb7da49a981a1b0acc5f7e8a0130bdcd', 'd35109c3632c4952a19ecc094943dd71', 'user_code', '用户编码', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 1, 1, 0, 0, 'single', '', '', 11, 'admin', '2020-11-28 00:03:03', '2019-05-11 16:26:37', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('cb871284e845e26e88242a96fac9c576', '402860816bff91c0016bff91c7010001', 'order_no', '序号', 'order_no', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('cc025f73d4d88696913ef172f4dae725', '2c91a0817fc4c754017fc4c754210000', 'sourceen', '来源-英文版', 'sourceen', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 15, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('cc1ddc1304d3eb5d9a189da0a509ccd0', '32f75e4043ef4070919dbd4337186a3d', 'create_by', '创建人登录名称', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-04-11 10:15:32', '2019-03-27 15:54:49', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ccda49a8cea079c34f0034361d058c08', '09fd28e4b7184c1a9668496a5c496450', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ccf2f331af46ddc411b8039dd187621b', '4028839a6de2ebd3016de2ebd3870000', 'price', '单价', 'price', 0, 1, 'double', 10, 2, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 10, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('cdd9867c9781be961c626b5e5e9c8010', '2c91a0817fc4c754017fc4c756050001', 'id', 'id', 'id', 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ce2fc04cb4d800d35b4ea84c66b7248b', '402881e6760269a20176026a22e70001', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 2, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('cee3c1dbf67b4a7d9626b8032897a4c7', '402860816bff91c0016bff91d8830007', 'employee_id', '员工ID', 'employee_id', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', 'oa_employee_info', 'id', 2, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('cefb82e2168ab7e3aa57a7e9c3ca950e', '09fd28e4b7184c1a9668496a5c496450', 'order_main_id', '订单ID', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', 'ces_order_main', 'id', 12, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('cf4c5a4c06ae6bac701edfeedfcd16aa', 'd3ae1c692b9640e0a091f8c46e17bb01', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, NULL, NULL, '2019-07-24 14:47:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('cf5dfcb4ccedec473a513414dbd243ef', '18f064d1ef424c93ba7a16148851664f', 'ddd', 'DD类型', NULL, 0, 1, 'double', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 20, 'admin', '2020-09-11 14:35:44', '2020-07-20 15:07:27', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('cfeb6491427aec2b4db9694af867da23', 'e9faf717024b4aae95cff224ae9b6d97', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d0559db07f05c870860f98313eb0f857', 'cb2d8534a2f544bc9c618dd49da66336', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-02-24 17:22:42', '2020-02-24 15:15:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d0d1be336726df9c41f2173f8886ba35', '997ee931515a4620bc30a9c1246429a9', 'has_child', '是否有子节点', NULL, 0, 1, 'string', 3, 0, '', 'yn', '', '', 'list', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 10, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('d14e47befe47925b1440d584f4ca56fc', '09fd28e4b7184c1a9668496a5c496450', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('d2551b70dc96a45a73b304bf755a996f', '402860816bff91c0016bff91d8830007', 'workplace', '工作单位', 'workplace', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d2765121c8b6348c12f6e368a369159f', '2d3bbeafdc364ecb974971a2d82adb9b', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('d29dcdba14ea61808391fff2d927efea', '402860816bff91c0016bff91c0cb0000', 'work_summary', '工作总结', 'work_summary', 0, 1, 'Text', 65535, 0, '', '', '', '', 'textarea', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 10, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d3a701472d27ca8435d6a781a597038d', 'deea5a8ec619460c9245ba85dbc59e80', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-05-03 01:01:18', '2019-04-20 11:41:19', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('d3ba5f990e14f9a1a0bbf6aa4cfa26dc', '56efb74326e74064b60933f6f8af30ea', 'xd_date', '下单时间', NULL, 0, 1, 'Date', 0, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('d44b89cc5f1828f7ceb9be196d549665', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'code', '编码', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '${order_num_rule_param}', 0, 1, 1, 0, 'single', '', '', 2, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:01', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('d48bfd2a840f9b1d00bd3b5599dca0f0', '402860816bff91c0016bff91cda80003', 'post', '职务', 'post', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d4d8cae3cd9ea93e378fc14303eee105', 'd35109c3632c4952a19ecc094943dd71', 'create_by', '创建人登录名称', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('d4dea775487aef5a7aea41791d3a65db', 'e5464aa8fa7b47c580e91593cf9b46dc', 'cycle_time', '发放周期(年)', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2019-04-24 17:09:49', '2019-04-24 14:09:06', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d52c79620e21128fb69b4e8628cf25cc', 'dbf4675875e14676a3f9a8b2b8941140', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, NULL, NULL, '2019-05-27 18:02:07', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d530ab1bc3c51e8249a506a25d1003c7', '79091e8277c744158530321513119c68', 'start_time', '会签发起时间', NULL, 0, 1, 'Date', 32, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-05-11 15:29:47', '2019-05-11 15:27:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d53e70411c206efecb8dcd00174e907c', '62e29cdb81ac44d1a2d8ff89851b853d', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, NULL, NULL, '2019-05-11 14:01:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d5df0a35352ee960053686e959e9084b', '1acb6f81a1d9439da6cc4e868617b565', 'wl_unit', '计量单位', NULL, 0, 1, 'String', 100, 0, '', 'air_china_unit', '', '', 'list_multi', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d6fad89f4f26d733291863c2dfbc5945', '27fc5f91274344afa7673a732b279939', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-07-01 16:28:20', '2019-07-01 16:26:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d6fb7dcec9256d4044199641cb823e5e', '18f064d1ef424c93ba7a16148851664f', 'sex', '下拉框', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('d7082454dac60103fdda3e00b6557d39', '402880eb71d52dc30171d52dc3a10000', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 9, NULL, NULL, '2020-05-02 19:37:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('d766ea5809e2ec9ff2cdbcb18f610ab3', '7ea60a25fa27470e9080d6a921aabbd1', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, NULL, NULL, '2019-04-17 00:22:21', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d7c3b107f004cbc99dfe1fe6c79894d8', '402860816bff91c0016bffa220a9000b', 'social_insurance_type', '参加社保类型', 'social_insurance_type', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 35, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d8234b56acea1a752271a6c911dd91a0', '7ea60a25fa27470e9080d6a921aabbd1', 'age', '年龄', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, NULL, NULL, '2019-04-17 00:22:21', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d86909d794b01ad7fbb5e61d28b6603b', '73162c3b8161413e8ecdca7eb288d0c9', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d949d9157831c2fb7ba9f175081fe036', '402860816bff91c0016bff91cda80003', 'school', '学校', 'school', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d9d308feb95968dbb322c9bff0c18452', '32feeb502544416c9bf41329c10a88f4', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d9dde2f59bb148c6b7e95256acad8972', 'e67d26b610dd414c884c4dbb24e71ce3', 'post_name', '岗位名字', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-04-24 11:03:32', '2019-04-24 11:02:57', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('d9f9ae6986cb85019a3a4030f62f4d1a', '402860816bff91c0016bff91cfea0004', 'employee_id', '员工ID', 'employee_id', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', 'oa_employee_info', 'id', 2, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('db11e7fe2a76680e502007ad82fc08b9', '402881e6760269a20176026d25650002', 'name', '姓名', 'name', 0, 1, 'string', 30, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 2, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('db1fb3e12385cb967b63420cfe97cde6', '402860816bff91c0016bff91cda80003', 'employee_id', '员工ID', 'employee_id', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', 'oa_employee_info', 'id', 2, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('db2a5b044968d599cd35146e8996e69b', '2c91a0817fc4c754017fc4c756050001', 'type', '类型', 'type', 0, 1, 'string', 255, 0, '', '', 'ls', '', 'list', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 9, 'admin', '2022-03-26 13:56:15', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', 'list', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('dbfc8f23823c4091f516635a464b3cc5', '402881e6760269a20176026d25650002', 'content', '个人简介', 'content', 0, 1, 'string', 1000, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 11, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('dc2bec862a4f0d600751c632d246f0ed', '4028839a6de2ebd3016de2ebd3870000', 'update_time', '更新日期', 'update_time', 0, 1, 'Date', 0, 0, NULL, NULL, NULL, NULL, 'date', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 5, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('dc3cacf1747695e33cf54a924aa97729', '2d3bbeafdc364ecb974971a2d82adb9b', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('dd3e1e13d7429807b83a00a090e060b7', '402860816bff91c0016bffa220a9000b', 'join_party_info', '入党(团)时间地点', 'join_party_info', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 26, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ddc302f84c75a5f056855c664b82202a', '402860816aa5921f016aa5921f480000', 'days', '请假天数', 'days', 0, 1, 'int', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ddcc14a2105588982b4ae657f2893d81', '32feeb502544416c9bf41329c10a88f4', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('de34e46a66def956437635585db427b7', 'cb2d8534a2f544bc9c618dd49da66336', 'dde', 'ee', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 10, NULL, NULL, '2020-02-24 17:22:43', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('de3a8a6b042b1821b3dcbd236fd82174', '402881e6760269a201760269a2af0000', 'pic', '图片', NULL, 0, 1, 'string', 1000, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 14, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('de8f510d358f499dcd966e97708f82d4', '997ee931515a4620bc30a9c1246429a9', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('dedb920a5e876e27eb144464209ebe1e', '27fc5f91274344afa7673a732b279939', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, 'admin', '2019-07-01 16:28:20', '2019-07-01 16:26:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('dee21fa8241c351e910056c203e9bfd5', '402881e6760269a20176026a22e70001', 'files', '文件', NULL, 0, 1, 'string', 1000, 0, '', '', '', '', 'file', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 15, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('df489194c6008f3bd21b2c1c11fde337', 'fb19fb067cd841f9ae93d4eb3b883dc0', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 2, NULL, NULL, '2019-03-23 11:39:48', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('df4c5e8411c102f02a6fe6727e858d55', '997ee931515a4620bc30a9c1246429a9', 'pic', '分类图片', NULL, 0, 1, 'string', 500, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('df58a7b1c3ed8f58a1994c0c0855db16', '4adec929a6594108bef5b35ee9966e9f', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 11, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e08af664ffdbc37cfafb779f0692f86e', '402881e6760269a20176026a22e70001', 'name', '用户名', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '#{sysUserCode}', 0, 1, 1, 0, 'single', NULL, NULL, 7, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('e09b191e3c37f9c89ae2192c75220b89', 'b81de38db24047b497d476516f8a0865', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, NULL, NULL, '2020-02-24 14:56:08', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e0c5d6e483897d5c4e7894dc66dd1aff', '32feeb502544416c9bf41329c10a88f4', 'bpm_status', '流程状态', NULL, 0, 1, 'String', 2, 0, '', 'bpm_status', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2019-08-23 20:03:40', '2019-07-02 18:23:58', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e24de426223dc0271a55eccc1d5457d0', '73162c3b8161413e8ecdca7eb288d0c9', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e29510e2a063eebaa763e7ef1be701ff', '2c91a0817fc4c754017fc4c754210000', 'sys_org_code', '所属部门', 'sys_org_code', 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2022-03-26 13:58:50', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e2d73ccda7f10f5a1ccce3c48b1e699e', '402860816bff91c0016bffa220a9000b', 'residence_street', '户口所在街道', 'residence_street', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 27, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e31096aa7a62fc74ad8425108723177a', '2d3bbeafdc364ecb974971a2d82adb9b', 'copyright', '版权所有', NULL, 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e350986acb670f247df30fe4a44e73df', '09fd28e4b7184c1a9668496a5c496450', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e4914fdff68ac72486ada105e6e9fa36', 'e9faf717024b4aae95cff224ae9b6d97', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-07-03 18:23:49', '2019-07-03 18:22:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e4a4c1d50b7b46678bc14fd5b90ee082', '73162c3b8161413e8ecdca7eb288d0c9', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e4d7f95340e73a54e8ff3f66b0613513', '56efb74326e74064b60933f6f8af30ea', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-07-10 16:53:27', '2020-05-08 23:45:32', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e50b4398731e06572c247993a0dcc38d', 'd35109c3632c4952a19ecc094943dd71', 'name', '用户名', NULL, 0, 1, 'string', 200, 0, '', '', '', '', 'text', '', 120, '*', '0', '', '', 1, 1, 1, 0, 'single', '', '', 6, 'admin', '2020-11-28 00:03:03', '2019-03-15 14:24:35', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '1'); +INSERT INTO `onl_cgform_field` VALUES ('e53f53766d1f7718b3ee5eabe105b969', '402860816bff91c0016bffa220a9000b', 'social_insurance_time', '五险一金日期', 'social_insurance_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 38, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e60a8e496b0f7081dbfe4253b3218546', '402880eb71d61d3d0171d61d3de30000', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 10, 'admin', '2020-05-03 00:54:16', '2020-05-02 23:59:33', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e672d5974a06d5c37b3b4c94a6f29f96', '4028318169e81b970169e81b97650000', 'request_url', '请求路径', 'request_url', 0, 1, 'string', 255, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 9, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e7aade12ca722b59c1ec681d14247ff8', '402860816bff91c0016bff91d8830007', 'sys_org_code', '组织机构编码', 'sys_org_code', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 14, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e7c367221181aa9d1fc395e09796be8d', '402880eb71d52dc30171d52dc3a10000', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 7, NULL, NULL, '2020-05-02 19:37:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e7e622076bcbe7bf7ea9fd9acb6f19bc', '18f064d1ef424c93ba7a16148851664f', 'pic', '图片', NULL, 0, 1, 'string', 1000, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 14, 'admin', '2020-09-11 14:35:44', '2020-05-12 20:26:01', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e7ec6838aad8d2dd2e175886a7c6e14e', '402881e6760269a201760269a2af0000', 'sel_search', '下拉搜索', NULL, 0, 1, 'string', 32, 0, '', 'username', 'sys_user', 'username', 'sel_search', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 12, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e824c44d26034ad8eed32e22a3f69043', '402881e6760269a201760269a2af0000', 'ddd', 'DD类型', NULL, 0, 1, 'double', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 20, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e845925368919482df6dac58e6ed708d', '402860816bff91c0016bff91d8830007', 'phone', '联系方式', 'phone', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 8, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e85295979d84bde27615a008d8bbadf1', '3b5e18da618247539481816995b6bf9f', 'sex', '性别', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2020-07-11 11:27:29', '2020-07-11 11:27:17', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e878e70574d0d6180c2f6f0d281c9262', '8d66ea41c7cc4ef9ab3aab9055657fc9', 'pid', '父级节点', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 0, 0, 'single', '', '', 10, NULL, NULL, '2020-05-07 22:46:32', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('e88d328af34dd8a17f51437c52b68a2d', '402860816bff91c0016bff91cfea0004', 'create_by', '创建人', 'create_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 9, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e99cc08f4d88dd8f788399db8d448ee8', '62e29cdb81ac44d1a2d8ff89851b853d', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2019-05-11 14:01:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e9a45935d69f5fd91f0c6880e5e6cfa4', '402881e6760269a20176026d25650002', 'age', '年龄', 'age', 0, 1, 'int', 10, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 8, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('e9fb150adabaaacdd804b1953e6bad24', '05a3a30dada7411c9109306aa4117068', 'create_time', '创建日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ea309f9cd81ede7b9b36a1377a3a40d8', '997ee931515a4620bc30a9c1246429a9', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-05-03 00:57:44', '2020-05-03 00:56:56', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ea644c4c208739640933ba6e568045c1', 'e2faf977fdaf4b25a524f58c2441a51c', 'ruz_date', '入职时间', NULL, 0, 1, 'Date', 32, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ea749346b5eb9e70df2058ade2b0bbfa', '402881e6760269a201760269a2af0000', 'fuwenb', '富文本', NULL, 0, 1, 'Text', 0, 0, '', '', '', '', 'umeditor', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 17, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ea96d1c33f0f0d7245045e70a5793257', '402860816bff91c0016bffa220a9000b', 'current_postcode', '现居住地邮编', 'current_postcode', 0, 1, 'string', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 31, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('eb36b8deedb265f43549723d24265c65', '2d3bbeafdc364ecb974971a2d82adb9b', 'wechat_url', '官方微信', NULL, 0, 1, 'string', 2000, 0, '', '', '', '', 'file', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 13, 'admin', '2022-03-24 12:16:35', '2022-03-24 12:15:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ebc41362681919cc680fcc58bf87fdcb', '1acb6f81a1d9439da6cc4e868617b565', 'price', '单价', NULL, 0, 1, 'double', 10, 2, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 12, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ec20e66d5eb9b8b7f58de9edc0f7630b', '1acb6f81a1d9439da6cc4e868617b565', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ec5e9cb5809b2f8ce1446df4a27693f0', '27fc5f91274344afa7673a732b279939', 'name', '用户名', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2019-07-01 16:28:20', '2019-07-01 16:26:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ed16f23d08e7bcda11a1383fda68057e', '402860816bff91c0016bff91c7010001', 'employee_id', '员工ID', 'employee_id', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', 'oa_employee_info', 'id', 2, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('edaa8951735cedf29d6114354faaae67', '402881e6760269a201760269a2af0000', 'radio', 'radio', NULL, 0, 1, 'string', 32, 0, '', 'sex', '', '', 'radio', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 9, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('edda30c64e1dccee510d40b77a8ca094', 'fb7125a344a649b990c12949945cb6c1', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 0, 0, 0, 'single', '', '', 3, 'admin', '2019-03-26 19:24:11', '2019-03-26 19:01:52', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ee09e0e21fa350b9346b70292dcfca00', '79091e8277c744158530321513119c68', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, 'admin', '2019-05-11 15:29:47', '2019-05-11 15:27:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ee4ffe04a25fcf556e78183f1f521546', '402860816aa5921f016aa5921f480000', 'create_by', '创建人id', 'create_by', 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 8, 'admin', '2019-05-11 15:31:54', '2019-05-11 14:26:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ee5803611f63643059b6375166d71567', '402860816bff91c0016bff91c7010001', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 8, 'admin', '2019-07-19 18:07:47', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ee657ba3e974e3ca00e20592fcd44dbe', '2c91a0817fc4c754017fc4c754210000', 'coveren', '封面图url--英文版', 'coveren', 0, 1, 'string', 2000, 0, '', '', '', '', 'image', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 11, 'admin', '2022-03-26 13:58:51', '2022-03-26 13:51:12', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('eec5bc01720642ccc635c7fc2e9b1eb8', '86bf17839a904636b7ed96201b2fa6ea', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2020-05-14 21:18:49', '2020-05-08 23:48:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ef81373c5fd7130d7e23859d90c9eb3e', '402860816bff91c0016bff91cda80003', 'from_time', '开始日期', 'from_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 3, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('efd1b955a75b5046e9857e00fe94ae2c', 'fbc35f067da94a70adb622ddba259352', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, NULL, NULL, '2019-07-03 19:44:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f015cc2ffdcc2c4be1e9b3622eb69b52', 'fbc35f067da94a70adb622ddba259352', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, NULL, NULL, '2019-07-03 19:44:23', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f06b2bb01ea1fae487b7e3c3eb521d5b', 'd3ae1c692b9640e0a091f8c46e17bb01', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2019-07-24 14:47:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f0967fd139b440f79f21248bf4e4a209', 'd3ae1c692b9640e0a091f8c46e17bb01', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, NULL, NULL, '2019-07-24 14:47:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f0a453930aa16ca32f2e3be860bfe542', '402860816bff91c0016bffa220a9000b', 'education', '学历', 'education', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 14, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f12753b4a3815697a72017a7436fe733', 'e2faf977fdaf4b25a524f58c2441a51c', 'update_time', '更新日期', NULL, 0, 1, 'Date', 20, 0, '', '', '', '', 'datetime', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 5, 'admin', '2019-06-10 17:27:00', '2019-04-24 17:12:11', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f18bb17ae2b9274e4ce77d66445284ac', '402881e6760269a20176026a22e70001', 'ddd', 'DD类型', NULL, 0, 1, 'double', 10, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 20, NULL, NULL, '2020-11-26 10:37:59', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f1ab7d3b55ade57eeac6c55b32ce813a', '1acb6f81a1d9439da6cc4e868617b565', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f1c7fde21f26c7ed64a0ef1095900c52', '4028318169e81b970169e81b97650000', 'request_type', '请求类型', 'request_type', 0, 1, 'string', 10, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 11, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f3284a1ce6da9b887dce89091eaa0f6b', '402880e570a5d7000170a5d700f50000', 'pro_type', '产品类型', NULL, 0, 1, 'String', 32, 0, '', 'sex', '', '', 'radio', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', NULL, NULL, 9, NULL, NULL, '2020-03-04 21:58:16', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f38319e2add8da6a7223d77359144a22', '402880e5721355dd01721355dd390000', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 4, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f3fcc5cf657a726fd4e08a1908975bbb', '2c91a0817fc4c754017fc4c757850002', 'title', '标题', 'title', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 11, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f4632c462c662edccee10aeb4900071b', '910984408e1948519e2fcf5ac08fe9ad', 'i18n_json', '国际化JSON', NULL, 0, 1, 'Text', 0, 0, '', '', '', '', 'textarea', '', 120, NULL, '1', '', '', 0, 1, 0, 0, 'single', '', '', 8, 'admin', '2022-03-24 12:24:00', '2022-03-24 12:21:06', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f4647a91a4ac5d6d32bb0692b800bffe', '402860816bff91c0016bff91c0cb0000', 'probation_post', '试用期职位', 'probation_post', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 8, 'admin', '2019-07-19 18:09:01', '2019-07-17 18:54:32', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f4b0bc7f3d6562e28d7c5e2d56510ecd', 'e5464aa8fa7b47c580e91593cf9b46dc', 'first_num', '首次数量', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 8, 'admin', '2019-04-24 17:09:49', '2019-04-24 14:31:31', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f558359b06aea79a992c102ce3563a4d', '4028318169e81b970169e81b97650000', 'username', '操作用户名称', 'username', 0, 1, 'string', 100, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 6, NULL, NULL, '2019-04-04 19:28:36', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f5d2475aec4b9016dfc0c8772e1704ea', '402880eb71d52dc30171d52dc3a10000', 'code', '编码', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '${order_num_rule_param}', 0, 1, 1, 0, 'single', NULL, NULL, 2, NULL, NULL, '2020-05-02 19:37:59', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f6076d9c662a0adddb39a91cccb4c993', 'd35109c3632c4952a19ecc094943dd71', 'xiamuti', '下拉多选', NULL, 0, 1, 'string', 100, 0, '', 'sex', '', '', 'list_multi', '', 120, NULL, '0', '', '', 1, 1, 1, 0, 'single', '', '', 17, 'admin', '2020-11-28 00:03:03', '2020-11-26 18:02:20', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f6431abe33976df2491df14db01591fe', '402881e6760269a20176026d25650002', 'key_word', '关键词', 'key_word', 0, 1, 'string', 255, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'single', NULL, NULL, 3, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f6465f5de23ced98051167dae5ef6db9', '2c91a0817fc4c754017fc4c757850002', 'name', '名称', 'name', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '1', '', '', 1, 1, 1, 0, 'single', '', '', 7, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f6afcb7d8ea81879593ff737b55ddcc0', '402860816bff91c0016bff91cda80003', 'id', 'id', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-07-19 18:06:36', '2019-07-17 18:54:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f6f8aed87ec73994f6a12abbc079dbb1', '402860816bff91c0016bffa220a9000b', 'update_by', '更新人', 'update_by', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 41, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f7332af7586c83c87f7b9ea144a5292d', '62e29cdb81ac44d1a2d8ff89851b853d', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, NULL, NULL, '2019-05-11 14:01:14', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f759a7e4d74ebaa95b2e19d9f442ccef', '2c91a0817fc4c754017fc4c757850002', 'create_time', '创建日期', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 3, 'admin', '2022-03-26 13:59:39', '2022-03-26 13:51:13', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f76719783433487f4710232e2ae0e521', '402860816bff91c0016bff91cfea0004', 'id', 'id', 'id', 1, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'group', '', '', 1, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f7e7eb84ddc34d7e09d10af213ac6667', '402860816bff91c0016bff91d2810005', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 11, 'admin', '2019-07-19 18:05:55', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f81d7103c0c857e5c744cda2bc4c000a', '402860816bff91c0016bff91ca7e0002', 'cert_organizations', '发证机关', 'cert_organizations', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 6, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f82db8edef5babf741914b0fa221329b', '4028839a6de2ebd3016de2ebd3870000', 'bpm_status', '流程状态', 'bpm_status', 0, 1, 'string', 2, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 1, 1, 0, 'group', NULL, NULL, 16, NULL, NULL, '2019-10-19 15:29:30', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f857d4fd2d63c1ad94ed4698f5b173f5', '05a3a30dada7411c9109306aa4117068', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', '', '', 1, 'admin', '2020-05-12 22:39:41', '2020-05-06 11:34:31', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f8a0fd20a1173270afdfed1129d5c669', '402860816bff91c0016bffa220a9000b', 'depart_id', '所在部门id', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 44, 'admin', '2019-07-22 16:15:32', '2019-07-19 15:33:44', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f8cc6be747fec10802eb625ac529c16f', '402860816bff91c0016bff91cfea0004', 'create_time', '创建时间', 'create_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 10, 'admin', '2019-07-19 18:05:13', '2019-07-17 18:54:35', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f90bcb38fb89988bd40d1618aa75cea0', '758334cb1e7445e2822b60e807aec4a3', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 1, NULL, NULL, '2019-10-18 18:02:09', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f93dcb2aa091b8e1038019d8f07cbd3f', '402881e6760269a201760269a2af0000', 'id', '主键', NULL, 1, 0, 'string', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 1, 'single', NULL, NULL, 1, NULL, NULL, '2020-11-26 10:37:26', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('f94db83e41c69f407d3c9a81c5892269', '402860816bff91c0016bffa220a9000b', 'first_job_time', '首次工作时间', 'first_job_time', 0, 1, 'Date', 0, 0, '', '', '', '', 'date', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 22, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('f95d2cbefd25444909c83aaf8c4f72fb', '402860816bff91c0016bff91ca7e0002', 'memo', '备注', 'memo', 0, 1, 'string', 255, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 7, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fa3a12d7abf72b23afe425f8dbd57f86', '1acb6f81a1d9439da6cc4e868617b565', 'size_type', '尺码类型', NULL, 0, 1, 'String', 2, 0, '', 'air_china_size', '', '', 'list', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2019-06-10 14:47:14', '2019-04-23 22:58:19', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fa8f5a0ba673e0208934567462844eab', '402860816bff91c0016bff91ca7e0002', 'sys_org_code', '组织机构编码', 'sys_org_code', 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 13, 'admin', '2019-07-19 18:07:13', '2019-07-17 18:54:33', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('faaaca21b7b2b16089c885f3224e4dc5', '4fb8e12a697f4d5bbe9b9fb1e9009486', 'main_id', '主表ID', NULL, 0, 1, 'String', 200, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', 'demo_field_def_val_main', 'id', 5, 'admin', '2020-11-26 17:28:14', '2020-04-10 19:47:55', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('fafb32cf7e63bca93bbd70b0a0ea11fc', '758334cb1e7445e2822b60e807aec4a3', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 6, NULL, NULL, '2019-10-18 18:02:09', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fb56aeb6b3a5a0a974ef62f34727eea6', '402880e5721355dd01721355dd390000', 'sys_org_code', '所属部门', NULL, 0, 1, 'string', 64, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', NULL, NULL, 6, NULL, NULL, '2020-05-14 21:18:14', 'admin', '', '', '', '', '', NULL, '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('fc55d467102c2c782286f546d7820c3d', '73162c3b8161413e8ecdca7eb288d0c9', 'pid', '父物料', NULL, 0, 1, 'String', 36, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 9, 'admin', '2019-07-01 14:23:32', '2019-06-10 15:18:34', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fc76a3832d232829852cae6c66e44f67', '402860816bff91c0016bffa220a9000b', 'identity_no', '身份证号', 'identity_no', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 21, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fcd519058d68fa4dab192335602b5d24', '402860816bff91c0016bffa220a9000b', 'real_name', '姓名', 'real_name', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 5, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fd0586cae06685959415d9017b2bdf49', '758334cb1e7445e2822b60e807aec4a3', 'create_by', '创建人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 2, NULL, NULL, '2019-10-18 18:02:09', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fde00160a5d664effaa4b5552e814e74', 'fb7125a344a649b990c12949945cb6c1', 'sex', '性别', NULL, 0, 1, 'string', 32, 0, '', '', '', '', 'text', '', 120, '', '0', '', '', 0, 1, 1, 0, 'single', '', '', 6, 'admin', '2019-03-26 19:24:11', '2019-03-26 19:01:52', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fe05080f0cd87dd11710b83ce77fefb7', '402881e6760269a20176026d25650002', 'id', '主键ID', 'id', 1, 0, 'string', 50, 0, NULL, NULL, NULL, NULL, 'text', NULL, 120, NULL, '0', NULL, NULL, 0, 0, 0, 1, 'single', NULL, NULL, 1, NULL, NULL, '2020-11-26 10:41:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('fed133a00f57245d4cfb02dd3c3ce7c1', '4adec929a6594108bef5b35ee9966e9f', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 9, 'admin', '2020-04-10 19:43:38', '2020-04-10 19:35:58', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('fef2add806c5e1ddd01c79c7e84f5a65', 'cb2d8534a2f544bc9c618dd49da66336', 'cc', 'cc', NULL, 0, 1, 'String', 32, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, NULL, NULL, '2020-02-24 17:22:42', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ff2a099186b13d3ecb0764f7f22b1fbf', '09fd28e4b7184c1a9668496a5c496450', 'name', '客户名字', NULL, 0, 1, 'string', 32, 0, '', 'realname,sex,birthday', 'tj_user_report', 'name,sex,birthday', 'popup', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'single', '', '', 7, 'admin', '2020-05-14 21:19:21', '2020-05-08 23:51:49', 'admin', '', '', '', '', '', 'text', '0', NULL, NULL, '0'); +INSERT INTO `onl_cgform_field` VALUES ('ff49b468e54e137032f7e4d976b83b5a', '402860816bff91c0016bffa220a9000b', 'politically_status', '政治面貌', 'politically_status', 0, 1, 'string', 20, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 8, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ff601f75d0e7ced226748eb8fba2c896', '402860816bff91c0016bff91d8830007', 'relation', '关系', 'relation', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 4, 'admin', '2019-07-19 18:04:41', '2019-07-17 18:54:37', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ffacafee9fa46eb297ca3252f95acef9', '402860816bff91c0016bffa220a9000b', 'school', '毕业学校', 'school', 0, 1, 'string', 100, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 1, 1, 0, 'group', '', '', 9, 'admin', '2019-07-22 16:15:32', '2019-07-17 19:12:24', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO `onl_cgform_field` VALUES ('ffcbf379fffabbd13aa2c22ce565ec12', '79091e8277c744158530321513119c68', 'update_by', '更新人', NULL, 0, 1, 'string', 50, 0, '', '', '', '', 'text', '', 120, NULL, '0', '', '', 0, 0, 0, 0, 'single', '', '', 4, 'admin', '2019-05-11 15:29:47', '2019-05-11 15:27:17', 'admin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for onl_cgform_head +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgform_head`; +CREATE TABLE `onl_cgform_head` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键ID', + `table_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '表名', + `table_type` int(11) NOT NULL COMMENT '表类型: 0单表、1主表、2附表', + `table_version` int(11) NULL DEFAULT 1 COMMENT '表版本', + `table_txt` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '表说明', + `is_checkbox` varchar(5) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '是否带checkbox', + `is_db_synch` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'N' COMMENT '同步数据库状态', + `is_page` varchar(5) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '是否分页', + `is_tree` varchar(5) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '是否是树', + `id_sequence` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '主键生成序列', + `id_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '主键类型', + `query_mode` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '查询模式', + `relation_type` int(11) NULL DEFAULT NULL COMMENT '映射关系 0一对多 1一对一', + `sub_table_str` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '子表', + `tab_order_num` int(11) NULL DEFAULT NULL COMMENT '附表排序序号', + `tree_parent_id_field` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '树形表单父id', + `tree_id_field` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '树表主键字段', + `tree_fieldname` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '树开表单列字段', + `form_category` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'bdfl_ptbd' COMMENT '表单分类', + `form_template` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'PC表单模板', + `form_template_mobile` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表单模板样式(移动端)', + `scroll` int(11) NULL DEFAULT 0 COMMENT '是否有横向滚动条', + `copy_version` int(11) NULL DEFAULT NULL COMMENT '复制版本号', + `copy_type` int(11) NULL DEFAULT 0 COMMENT '复制表类型1为复制表 0为原始表', + `physic_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '原始表ID', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `theme_template` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '主题模板', + `is_des_form` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否用设计器表单', + `des_form_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '设计器表单编码', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `index_onlineform_table_name`(`table_name`) USING BTREE, + INDEX `index_form_templdate`(`form_template`) USING BTREE, + INDEX `index_templdate_mobile`(`form_template_mobile`) USING BTREE, + INDEX `index_onlineform_table_version`(`table_version`) USING BTREE, + INDEX `idx_och_cgform_head_id`(`table_name`) USING BTREE, + INDEX `idx_och_table_name`(`form_template`) USING BTREE, + INDEX `idx_och_form_template_mobile`(`form_template_mobile`) USING BTREE, + INDEX `idx_och_table_version`(`table_version`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of onl_cgform_head +-- ---------------------------- +INSERT INTO `onl_cgform_head` VALUES ('05a3a30dada7411c9109306aa4117068', 'test_note', 1, 10, '测试请假单', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-05-12 22:39:41', 'admin', '2020-05-06 11:34:31', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('09fd28e4b7184c1a9668496a5c496450', 'ces_order_customer', 3, 5, '订单客户', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', 1, 'ces_order_customer', 3, NULL, NULL, NULL, 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-05-14 21:19:21', 'admin', '2020-05-08 23:51:49', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('18f064d1ef424c93ba7a16148851664f', 'ces_field_kongj', 1, 14, 'online表单控件', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'temp', '2', NULL, 1, NULL, 0, NULL, 'admin', '2020-09-11 14:35:44', 'admin', '2020-05-12 20:26:01', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('2c91a0817fc4c754017fc4c754210000', 'tqd_gateway_article', 1, 3, '门户-文章', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'group', NULL, NULL, NULL, NULL, NULL, NULL, 'bdfl_include', '1', NULL, 1, NULL, 0, NULL, 'admin', '2022-03-26 14:00:27', 'admin', '2022-03-26 13:51:12', 'normal', 'N', NULL); +INSERT INTO `onl_cgform_head` VALUES ('2c91a0817fc4c754017fc4c756050001', 'tqd_gateway_column', 1, 4, '门户-栏目', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'group', NULL, NULL, NULL, NULL, NULL, NULL, 'bdfl_include', '1', NULL, 1, NULL, 0, NULL, 'admin', '2022-03-26 14:00:04', 'admin', '2022-03-26 13:51:13', 'normal', 'N', NULL); +INSERT INTO `onl_cgform_head` VALUES ('2c91a0817fc4c754017fc4c757850002', 'tqd_gateway_links', 1, 3, '门户-友情链接,快速导航', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'group', NULL, NULL, NULL, NULL, NULL, NULL, 'bdfl_include', '1', NULL, 1, NULL, 0, NULL, 'admin', '2022-03-26 14:00:24', 'admin', '2022-03-26 13:51:13', 'normal', 'N', NULL); +INSERT INTO `onl_cgform_head` VALUES ('2d3bbeafdc364ecb974971a2d82adb9b', 'tqc_gateway_common', 1, 2, '基本信息表', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2022-03-24 12:24:35', 'admin', '2022-03-24 12:15:06', 'normal', 'N', NULL); +INSERT INTO `onl_cgform_head` VALUES ('3d447fa919b64f6883a834036c14aa67', 'test_enhance_select', 1, 5, 'js增强实现下拉联动效果', 'N', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'bdfl_include', '1', NULL, 0, NULL, 0, NULL, 'admin', '2020-02-21 17:58:46', 'admin', '2020-02-20 16:19:00', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('402880e570a5d7000170a5d700f50000', 'test_order_product$1', 1, 11, '订单产品明细', 'N', 'N', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'bdfl_include', '1', NULL, 0, 1, 1, 'deea5a8ec619460c9245ba85dbc59e80', NULL, NULL, 'admin', '2020-03-04 21:58:16', NULL, NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('402880e5721355dd01721355dd390000', 'ces_order_goods$1', 1, 1, '订单商品', 'Y', 'N', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'temp', '1', NULL, 1, 1, 1, '86bf17839a904636b7ed96201b2fa6ea', NULL, NULL, 'admin', '2020-05-14 21:18:14', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('402880eb71d61d3d0171d61d3de30000', 'demo_field_def_val_sub$1', 1, 2, '示例:控件默认值(子表)', 'Y', 'N', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'demo', '1', NULL, 1, 1, 1, '4fb8e12a697f4d5bbe9b9fb1e9009486', 'admin', '2020-05-03 00:54:16', 'admin', '2020-05-02 23:59:33', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('402881e6760269a20176026a22e70001', 'ces_field_kongj$0', 1, 1, 'online表单控件', 'Y', 'N', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'temp', '2', NULL, 1, 14, 1, '18f064d1ef424c93ba7a16148851664f', NULL, NULL, 'admin', '2020-11-26 10:37:59', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('402881e6760269a20176026d25650002', 'demo', 1, 1, 'demo', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'group', NULL, NULL, NULL, NULL, NULL, NULL, 'bdfl_include', '1', NULL, 1, NULL, 0, NULL, NULL, NULL, 'admin', '2020-11-26 10:41:17', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('4adec929a6594108bef5b35ee9966e9f', 'demo_field_def_val_main', 2, 1, '示例:控件默认值(主表)', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, 'demo_field_def_val_sub', NULL, NULL, NULL, NULL, 'demo', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-11-26 17:28:14', 'admin', '2020-04-10 19:35:57', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('4fb8e12a697f4d5bbe9b9fb1e9009486', 'demo_field_def_val_sub', 3, 2, '示例:控件默认值(子表)', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'group', 0, NULL, 1, NULL, NULL, NULL, 'demo', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-11-26 17:28:14', 'admin', '2020-04-10 19:47:01', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('53a3e82b54b946c2b904f605875a275c', 'ces_shop_goods', 1, 7, '商品', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-05-08 23:42:51', 'admin', '2020-05-07 22:49:47', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('56870166aba54ebfacb20ba6c770bd73', 'test_order_main', 2, 16, '测试订单主表', 'N', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, 'test_order_product', NULL, NULL, NULL, NULL, 'bdfl_include', '2', NULL, 0, NULL, 0, NULL, 'admin', '2020-11-28 00:02:01', 'admin', '2019-04-20 11:38:39', 'tab', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('56efb74326e74064b60933f6f8af30ea', 'ces_order_main', 2, 9, '商城订单表', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, 'ces_order_goods,ces_order_customer', NULL, NULL, NULL, NULL, 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-07-10 16:53:27', 'admin', '2020-05-08 23:45:32', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('86bf17839a904636b7ed96201b2fa6ea', 'ces_order_goods', 3, 2, '订单商品', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', 0, NULL, 2, NULL, NULL, NULL, 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-05-14 21:18:49', 'admin', '2020-05-08 23:48:31', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('8d66ea41c7cc4ef9ab3aab9055657fc9', 'ces_shop_type', 1, 1, '商品分类', 'Y', 'Y', 'Y', 'Y', NULL, 'UUID', 'single', NULL, NULL, NULL, 'pid', 'has_child', 'name', 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-05-07 22:46:40', 'admin', '2020-05-07 22:46:31', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('910984408e1948519e2fcf5ac08fe9ad', 'tqc_i18n_config', 1, 3, '国际化配置', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'single', NULL, NULL, NULL, NULL, NULL, NULL, 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2022-03-24 12:24:28', 'admin', '2022-03-24 12:21:06', 'normal', 'N', NULL); +INSERT INTO `onl_cgform_head` VALUES ('997ee931515a4620bc30a9c1246429a9', 'test_shoptype_tree', 1, 2, '商品分类', 'Y', 'Y', 'Y', 'Y', NULL, 'UUID', 'single', NULL, NULL, NULL, 'pid', 'has_child', 'type_name', 'temp', '1', NULL, 1, NULL, 0, NULL, 'admin', '2020-05-03 00:57:47', 'admin', '2020-05-03 00:56:56', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('d35109c3632c4952a19ecc094943dd71', 'test_demo', 1, 30, '测试用户表', 'Y', 'Y', 'Y', 'N', NULL, 'UUID', 'group', NULL, NULL, NULL, NULL, NULL, NULL, 'bdfl_include', '1', NULL, 0, NULL, 0, NULL, 'admin', '2020-11-28 00:03:03', 'admin', '2019-03-15 14:24:35', 'normal', NULL, NULL); +INSERT INTO `onl_cgform_head` VALUES ('deea5a8ec619460c9245ba85dbc59e80', 'test_order_product', 3, 12, '订单产品明细', 'N', 'Y', 'Y', 'N', NULL, 'UUID', 'single', 0, NULL, 1, NULL, NULL, NULL, 'bdfl_include', '1', NULL, 0, NULL, 0, NULL, 'admin', '2020-05-03 01:01:18', 'admin', '2019-04-20 11:41:19', 'normal', NULL, NULL); + +-- ---------------------------- +-- Table structure for onl_cgform_index +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgform_index`; +CREATE TABLE `onl_cgform_index` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', + `cgform_head_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '主表id', + `index_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '索引名称', + `index_field` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '索引栏位', + `index_type` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '索引类型', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人登录名称', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人登录名称', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `is_db_synch` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'N' COMMENT '是否同步数据库 N未同步 Y已同步', + `del_flag` int(11) NULL DEFAULT 0 COMMENT '是否删除 0未删除 1删除', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_table_id`(`cgform_head_id`) USING BTREE, + INDEX `idx_oci_cgform_head_id`(`cgform_head_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for onl_cgreport_head +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgreport_head`; +CREATE TABLE `onl_cgreport_head` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '报表编码', + `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '报表名字', + `cgr_sql` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '报表SQL', + `return_val_field` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '返回值字段', + `return_txt_field` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '返回文本字段', + `return_type` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '返回类型,单选或多选', + `db_source` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '动态数据源', + `content` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人id', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人id', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `index_onlinereport_code`(`code`) USING BTREE, + INDEX `idx_och_code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of onl_cgreport_head +-- ---------------------------- +INSERT INTO `onl_cgreport_head` VALUES ('1256627801873821698', 'report002', '统计登录每日登录次数', 'select DATE_FORMAT(create_time, \'%Y-%m-%d\') as date,count(*) as num from sys_log group by DATE_FORMAT(create_time, \'%Y-%m-%d\')', NULL, NULL, '1', NULL, NULL, '2020-11-26 19:22:04', 'admin', '2020-05-03 00:53:10', 'admin'); +INSERT INTO `onl_cgreport_head` VALUES ('1260179852088135681', 'tj_user_report', '统一有效系统用户', 'select * from sys_user', NULL, NULL, '1', NULL, NULL, '2020-11-26 19:50:35', 'admin', '2020-05-12 20:07:44', 'admin'); +INSERT INTO `onl_cgreport_head` VALUES ('6c7f59741c814347905a938f06ee003c', 'report_user', '统计在线用户', 'select * from sys_user', NULL, NULL, '1', '', NULL, '2020-05-03 02:35:28', 'admin', '2019-03-25 11:20:45', 'admin'); +INSERT INTO `onl_cgreport_head` VALUES ('87b55a515d3441b6b98e48e5b35474a6', 'demo', 'Report Demo', 'select * from demo', NULL, NULL, '1', '', NULL, '2020-05-03 01:14:35', 'admin', '2019-03-12 11:25:16', 'admin'); + +-- ---------------------------- +-- Table structure for onl_cgreport_item +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgreport_item`; +CREATE TABLE `onl_cgreport_item` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `cgrhead_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '报表ID', + `field_name` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字段名字', + `field_txt` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段文本', + `field_width` int(11) NULL DEFAULT NULL, + `field_type` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段类型', + `search_mode` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '查询模式', + `is_order` int(11) NULL DEFAULT 0 COMMENT '是否排序 0否,1是', + `is_search` int(11) NULL DEFAULT 0 COMMENT '是否查询 0否,1是', + `dict_code` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字典CODE', + `field_href` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段跳转URL', + `is_show` int(11) NULL DEFAULT 1 COMMENT '是否显示 0否,1显示', + `order_num` int(11) NULL DEFAULT NULL COMMENT '排序', + `replace_val` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '取值表达式', + `is_total` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否合计 0否,1是(仅对数值有效)', + `group_title` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '分组标题', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_CGRHEAD_ID`(`cgrhead_id`) USING BTREE, + INDEX `index_isshow`(`is_show`) USING BTREE, + INDEX `index_order_num`(`order_num`) USING BTREE, + INDEX `idx_oci_cgrhead_id`(`cgrhead_id`) USING BTREE, + INDEX `idx_oci_is_show`(`is_show`) USING BTREE, + INDEX `idx_oci_order_num`(`order_num`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of onl_cgreport_item +-- ---------------------------- +INSERT INTO `onl_cgreport_item` VALUES ('1256627802020622337', '1256627801873821698', 'date', '日期', NULL, 'String', NULL, 0, 0, '', '', 1, 1, '', NULL, NULL, 'admin', '2020-09-11 14:50:45', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1256627802075148289', '1256627801873821698', 'num', '登录次数', NULL, 'String', NULL, 0, 0, '', '', 1, 2, '', '1', NULL, 'admin', '2020-09-11 14:50:45', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1260179881129496577', '1260179852088135681', 'id', 'ID', NULL, 'String', NULL, 0, 0, '', '', 0, 1, '', NULL, NULL, 'admin', '2020-09-11 14:07:38', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1260179881129496578', '1260179852088135681', 'username', '账号', NULL, 'String', NULL, 0, 0, '', '', 1, 2, '', NULL, '用户信息', 'admin', '2020-09-11 14:07:38', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1260179881129496579', '1260179852088135681', 'realname', '用户名字', NULL, 'String', NULL, 0, 0, '', '', 1, 3, '', NULL, '用户信息', 'admin', '2020-09-11 14:07:38', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1260179881129496584', '1260179852088135681', 'sex', '性别', NULL, 'String', NULL, 0, 1, 'sex', '', 1, 4, '', NULL, '用户信息', 'admin', '2020-09-11 14:07:38', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1260179881129496585', '1260179852088135681', 'email', '邮箱', NULL, 'String', 'single', 0, 1, '', '', 1, 5, '', NULL, NULL, 'admin', '2020-09-11 14:07:38', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1260179881129496586', '1260179852088135681', 'phone', '电话', NULL, 'String', NULL, 0, 0, '', '', 1, 6, '', NULL, NULL, 'admin', '2020-09-11 14:07:38', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('15884396588465896672', '87b55a515d3441b6b98e48e5b35474a6', 'id', 'ID', NULL, 'String', NULL, 0, 0, '', '', 0, 1, '', NULL, NULL, 'admin', '2020-05-03 01:14:35', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('15892858611256977947', '1260179852088135681', 'birthday', '生日', NULL, 'Date', NULL, 0, 0, '', '', 1, 7, '', NULL, NULL, 'admin', '2020-09-11 14:07:38', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1740bb02519db90c44cb2cba8b755136', '6c7f59741c814347905a938f06ee003c', 'realname', '用户名称', NULL, 'String', NULL, 0, 0, '', 'https://www.baidu.com', 1, 1, '', NULL, NULL, 'admin', '2020-05-03 02:35:28', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('1b181e6d2813bcb263adc39737f9df46', '87b55a515d3441b6b98e48e5b35474a6', 'name', '用户名', NULL, 'String', 'single', 0, 1, '', '', 1, 2, '', NULL, NULL, 'admin', '2020-05-03 01:14:35', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('61ef5b323134938fdd07ad5e3ea16cd3', '87b55a515d3441b6b98e48e5b35474a6', 'key_word', '关键词', NULL, 'String', 'single', 0, 1, '', '', 1, 3, '', NULL, NULL, 'admin', '2020-05-03 01:14:35', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('627768efd9ba2c41e905579048f21000', '6c7f59741c814347905a938f06ee003c', 'username', '用户账号', NULL, 'String', 'single', 0, 1, '', '', 1, 2, '', NULL, NULL, 'admin', '2020-05-03 02:35:28', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('8bb087a9aa2000bcae17a1b3f5768435', '6c7f59741c814347905a938f06ee003c', 'sex', '性别', NULL, 'String', 'single', 0, 1, 'sex', '', 1, 3, '', NULL, NULL, 'admin', '2020-05-03 02:35:28', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('90d4fa57d301801abb26a9b86b6b94c4', '6c7f59741c814347905a938f06ee003c', 'birthday', '生日', NULL, 'Date', 'single', 0, 0, '', '', 1, 4, '', NULL, NULL, 'admin', '2020-05-03 02:35:28', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('a4ac355f07a05218854e5f23e2930163', '6c7f59741c814347905a938f06ee003c', 'avatar', '头像', NULL, 'String', NULL, 0, 0, '', '', 0, 5, '', NULL, NULL, 'admin', '2020-05-03 02:35:28', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('d6e86b5ffd096ddcc445c0f320a45004', '6c7f59741c814347905a938f06ee003c', 'phone', '手机号', NULL, 'String', NULL, 0, 0, '', '', 1, 6, '', NULL, NULL, 'admin', '2020-05-03 02:35:28', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('df365cd357699eea96c29763d1dd7f9d', '6c7f59741c814347905a938f06ee003c', 'email', '邮箱', NULL, 'String', NULL, 0, 0, '', '', 1, 7, '', NULL, NULL, 'admin', '2020-05-03 02:35:28', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('edf9932912b81ad01dd557d3d593a559', '87b55a515d3441b6b98e48e5b35474a6', 'age', '年龄', NULL, 'String', NULL, 0, 0, '', '', 1, 4, '', NULL, NULL, 'admin', '2020-05-03 01:14:35', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('f985883e509a6faaaf62ca07fd24a73c', '87b55a515d3441b6b98e48e5b35474a6', 'birthday', '生日', NULL, 'Date', 'single', 0, 1, '', '', 1, 5, '', NULL, NULL, 'admin', '2020-05-03 01:14:35', NULL, NULL); +INSERT INTO `onl_cgreport_item` VALUES ('fce83e4258de3e2f114ab3116397670c', '87b55a515d3441b6b98e48e5b35474a6', 'punch_time', '发布时间', NULL, 'String', NULL, 0, 0, '', '', 1, 6, '', NULL, NULL, 'admin', '2020-05-03 01:14:35', NULL, NULL); + +-- ---------------------------- +-- Table structure for onl_cgreport_param +-- ---------------------------- +DROP TABLE IF EXISTS `onl_cgreport_param`; +CREATE TABLE `onl_cgreport_param` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `cgrhead_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '动态报表ID', + `param_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '参数字段', + `param_txt` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数文本', + `param_value` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数默认值', + `order_num` int(11) NULL DEFAULT NULL COMMENT '排序', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人登录名称', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人登录名称', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`) USING BTREE, + INDEX `idx_cgrheadid`(`cgrhead_id`) USING BTREE, + INDEX `idx_ocp_cgrhead_id`(`cgrhead_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for oss_file +-- ---------------------------- +DROP TABLE IF EXISTS `oss_file`; +CREATE TABLE `oss_file` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id', + `file_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名称', + `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件地址', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人登录名称', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人登录名称', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Oss File' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_blob_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_blob_triggers`; +CREATE TABLE `qrtz_blob_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `BLOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_calendars +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_calendars`; +CREATE TABLE `qrtz_calendars` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CALENDAR_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CALENDAR` blob NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_cron_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_cron_triggers`; +CREATE TABLE `qrtz_cron_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CRON_EXPRESSION` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TIME_ZONE_ID` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_fired_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_fired_triggers`; +CREATE TABLE `qrtz_fired_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `ENTRY_ID` varchar(95) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `INSTANCE_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `FIRED_TIME` bigint(20) NOT NULL, + `SCHED_TIME` bigint(20) NOT NULL, + `PRIORITY` int(11) NOT NULL, + `STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `ENTRY_ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_job_details +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_job_details`; +CREATE TABLE `qrtz_job_details` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `JOB_CLASS_NAME` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_DURABLE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_UPDATE_DATA` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_locks +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_locks`; +CREATE TABLE `qrtz_locks` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `LOCK_NAME` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `LOCK_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_locks +-- ---------------------------- +INSERT INTO `qrtz_locks` VALUES ('MyScheduler', 'STATE_ACCESS'); +INSERT INTO `qrtz_locks` VALUES ('MyScheduler', 'TRIGGER_ACCESS'); + +-- ---------------------------- +-- Table structure for qrtz_paused_trigger_grps +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`; +CREATE TABLE `qrtz_paused_trigger_grps` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_scheduler_state +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_scheduler_state`; +CREATE TABLE `qrtz_scheduler_state` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `INSTANCE_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `LAST_CHECKIN_TIME` bigint(20) NOT NULL, + `CHECKIN_INTERVAL` bigint(20) NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_scheduler_state +-- ---------------------------- +INSERT INTO `qrtz_scheduler_state` VALUES ('MyScheduler', 'DESKTOP-7S2OTTP1650869951872', 1650870244990, 10000); + +-- ---------------------------- +-- Table structure for qrtz_simple_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simple_triggers`; +CREATE TABLE `qrtz_simple_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `REPEAT_COUNT` bigint(20) NOT NULL, + `REPEAT_INTERVAL` bigint(20) NOT NULL, + `TIMES_TRIGGERED` bigint(20) NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_simprop_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simprop_triggers`; +CREATE TABLE `qrtz_simprop_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `STR_PROP_1` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `STR_PROP_2` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `STR_PROP_3` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `INT_PROP_1` int(11) NULL DEFAULT NULL, + `INT_PROP_2` int(11) NULL DEFAULT NULL, + `LONG_PROP_1` bigint(20) NULL DEFAULT NULL, + `LONG_PROP_2` bigint(20) NULL DEFAULT NULL, + `DEC_PROP_1` decimal(13, 4) NULL DEFAULT NULL, + `DEC_PROP_2` decimal(13, 4) NULL DEFAULT NULL, + `BOOL_PROP_1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `BOOL_PROP_2` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for qrtz_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_triggers`; +CREATE TABLE `qrtz_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `NEXT_FIRE_TIME` bigint(20) NULL DEFAULT NULL, + `PREV_FIRE_TIME` bigint(20) NULL DEFAULT NULL, + `PRIORITY` int(11) NULL DEFAULT NULL, + `TRIGGER_STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_TYPE` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `START_TIME` bigint(20) NOT NULL, + `END_TIME` bigint(20) NULL DEFAULT NULL, + `CALENDAR_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `MISFIRE_INSTR` smallint(6) NULL DEFAULT NULL, + `JOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `SCHED_NAME`(`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, + CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for sys_announcement +-- ---------------------------- +DROP TABLE IF EXISTS `sys_announcement`; +CREATE TABLE `sys_announcement` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `titile` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '标题', + `msg_content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '内容', + `start_time` datetime(0) NULL DEFAULT NULL COMMENT '开始时间', + `end_time` datetime(0) NULL DEFAULT NULL COMMENT '结束时间', + `sender` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发布人', + `priority` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '优先级(L低,M中,H高)', + `msg_category` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '2' COMMENT '消息类型1:通知公告2:系统消息', + `msg_type` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '通告对象类型(USER:指定用户,ALL:全体用户)', + `send_status` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发布状态(0未发布,1已发布,2已撤销)', + `send_time` datetime(0) NULL DEFAULT NULL COMMENT '发布时间', + `cancel_time` datetime(0) NULL DEFAULT NULL COMMENT '撤销时间', + `del_flag` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '删除状态(0,正常,1已删除)', + `bus_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '业务类型(email:邮件 bpm:流程)', + `bus_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '业务id', + `open_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '打开方式(组件:component 路由:url)', + `open_page` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件/路由 地址', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `user_ids` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '指定用户', + `msg_abstract` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '摘要', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统通告表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_announcement +-- ---------------------------- +INSERT INTO `sys_announcement` VALUES ('1256486502931722242', 'JeecgBoot 2.2.0版本发布', '
升级不兼容
\n\n
较大改造
\n\n
ONLINE升级
\n\n
Online代码生成器升级
\n
\n

后期重点维护ONLINE模式的代码生成器,GUI模式逐步弃用。

\n
\n\n
平台基础升级
\n\n
UI组件升级
\n\n
Issues处理
\n', '2020-05-01 15:30:56', '2020-05-30 15:31:00', 'admin', 'H', '1', 'ALL', '1', '2020-05-02 15:31:44', NULL, '0', NULL, NULL, NULL, NULL, 'admin', '2020-05-02 15:31:41', 'admin', '2020-05-02 15:31:44', NULL, '重磅版本发布'); +INSERT INTO `sys_announcement` VALUES ('1256486817286418434', '放假通知', '

放假通知

', '2020-05-02 15:32:38', '2020-05-30 15:32:40', 'admin', 'M', '1', 'USER', '1', '2020-05-02 15:32:59', NULL, '0', NULL, NULL, NULL, NULL, 'admin', '2020-05-02 15:32:56', 'admin', '2020-05-02 15:32:59', 'e9ca23d68d884d4ebb19d07889727dae,a75d45a015c44384a04449ee80dc3503,', '放假通知'); +INSERT INTO `sys_announcement` VALUES ('1256529336858685441', '1', '

22

', '2020-05-02 18:21:41', '2020-05-30 18:21:44', 'admin', 'M', '1', 'ALL', '2', '2020-05-02 18:21:57', '2020-05-02 18:22:07', '0', NULL, NULL, NULL, NULL, 'admin', '2020-05-02 18:21:54', 'admin', '2020-05-02 18:22:07', NULL, '22'); +INSERT INTO `sys_announcement` VALUES ('1b714f8ebc3cc33f8b4f906103b6a18d', '5467567', NULL, NULL, NULL, 'admin', NULL, '2', NULL, '1', '2019-03-30 12:40:38', NULL, '1', NULL, NULL, NULL, NULL, 'admin', '2019-02-26 17:23:26', 'admin', '2020-05-02 15:30:42', NULL, NULL); +INSERT INTO `sys_announcement` VALUES ('3d11237ccdf62450d20bb8abdb331178', '111222', NULL, NULL, NULL, NULL, NULL, '2', NULL, '0', NULL, NULL, '1', NULL, NULL, NULL, NULL, 'admin', '2019-03-29 17:19:47', 'admin', '2019-03-29 17:19:50', NULL, NULL); +INSERT INTO `sys_announcement` VALUES ('7ef04e95f8de030b1d5f7a9144090dc6', '111', NULL, '2019-02-06 17:28:10', '2019-03-08 17:28:11', NULL, NULL, '2', NULL, '0', NULL, NULL, '1', NULL, NULL, NULL, NULL, 'admin', '2019-02-26 17:28:17', 'admin', '2019-03-26 19:59:49', NULL, NULL); +INSERT INTO `sys_announcement` VALUES ('93a9060a1c20e4bf98b3f768a02c2ff9', '111', '111', '2019-02-06 17:20:17', '2019-02-21 17:20:20', 'admin', 'M', '2', 'ALL', '1', '2019-02-26 17:24:29', NULL, '1', NULL, NULL, NULL, NULL, 'admin', '2019-02-26 17:16:26', 'admin', '2020-05-02 15:30:42', NULL, NULL); +INSERT INTO `sys_announcement` VALUES ('de1dc57f31037079e1e55c8347fe6ef7', '222', '2222', '2019-02-06 17:28:26', '2019-02-23 17:28:28', 'admin', 'M', '2', 'ALL', '1', '2019-03-29 17:19:56', NULL, '1', NULL, NULL, NULL, NULL, 'admin', '2019-02-26 17:28:36', 'admin', '2019-02-26 17:28:40', NULL, NULL); +INSERT INTO `sys_announcement` VALUES ('e52f3eb6215f139cb2224c52517af3bd', '334', '334', NULL, NULL, NULL, NULL, '2', NULL, '0', NULL, NULL, '1', NULL, NULL, NULL, NULL, 'admin', '2019-03-30 12:40:28', 'admin', '2019-03-30 12:40:32', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_announcement_send +-- ---------------------------- +DROP TABLE IF EXISTS `sys_announcement_send`; +CREATE TABLE `sys_announcement_send` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `annt_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '通告ID', + `user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户id', + `read_flag` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '阅读状态(0未读,1已读)', + `read_time` datetime(0) NULL DEFAULT NULL COMMENT '阅读时间', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间' +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户通告阅读标记表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_announcement_send +-- ---------------------------- +INSERT INTO `sys_announcement_send` VALUES ('646c0c405ec643d4dc4160db2446f8ff', '93a9060a1c20e4bf98b3f768a02c2ff9', 'e9ca23d68d884d4ebb19d07889727dae', '1', '2019-11-21 16:30:01', 'admin', '2019-05-17 11:50:56', 'admin', '2019-11-21 16:30:01'); +INSERT INTO `sys_announcement_send` VALUES ('1197434450981543938', '93a9060a1c20e4bf98b3f768a02c2ff9', 'a75d45a015c44384a04449ee80dc3503', '0', NULL, 'jeecg', '2019-11-21 16:39:55', NULL, NULL); +INSERT INTO `sys_announcement_send` VALUES ('1256486817319972866', '1256486817286418434', 'e9ca23d68d884d4ebb19d07889727dae', '1', '2020-05-02 15:33:05', 'admin', '2020-05-02 15:32:56', 'admin', '2020-05-02 15:33:05'); +INSERT INTO `sys_announcement_send` VALUES ('1256486817349332993', '1256486817286418434', 'a75d45a015c44384a04449ee80dc3503', '0', '2020-05-02 15:32:56', 'admin', '2020-05-02 15:32:56', NULL, NULL); +INSERT INTO `sys_announcement_send` VALUES ('1256527099214278657', '1256486502931722242', 'e9ca23d68d884d4ebb19d07889727dae', '1', '2020-05-02 18:22:00', 'admin', '2020-05-02 18:12:59', 'admin', '2020-05-02 18:22:00'); +INSERT INTO `sys_announcement_send` VALUES ('1260927781673484290', '1256486502931722242', 'a75d45a015c44384a04449ee80dc3503', '0', NULL, 'jeecg', '2020-05-14 21:39:45', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_category +-- ---------------------------- +DROP TABLE IF EXISTS `sys_category`; +CREATE TABLE `sys_category` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `pid` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '父级节点', + `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '类型名称', + `code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '类型编码', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `has_child` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否有子节点', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `index_code`(`code`) USING BTREE, + INDEX `idx_sc_code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_category +-- ---------------------------- +INSERT INTO `sys_category` VALUES ('1183693424827564034', '0', '物料树', 'B02', 'admin', '2019-10-14 18:37:59', 'admin', '2019-10-14 18:38:15', 'A01', '1'); +INSERT INTO `sys_category` VALUES ('1183693491043041282', '1183693424827564034', '上衣', 'B02A01', 'admin', '2019-10-14 18:38:15', 'admin', '2019-10-14 18:38:43', 'A01', '1'); +INSERT INTO `sys_category` VALUES ('1183693534173069314', '1183693424827564034', '裤子', 'B02A02', 'admin', '2019-10-14 18:38:25', NULL, NULL, 'A01', NULL); +INSERT INTO `sys_category` VALUES ('1183693610534567937', '1183693491043041282', '秋衣', 'B02A01A01', 'admin', '2019-10-14 18:38:43', NULL, NULL, 'A01', NULL); +INSERT INTO `sys_category` VALUES ('1183693700254924802', '1183693491043041282', '兵装', 'B02A01A02', 'admin', '2019-10-14 18:39:05', NULL, NULL, 'A01', NULL); +INSERT INTO `sys_category` VALUES ('1183693773974011906', '1183693491043041282', '女装', 'B02A01A03', 'admin', '2019-10-14 18:39:22', NULL, NULL, 'A01', NULL); +INSERT INTO `sys_category` VALUES ('1185039122143719425', '0', '电脑产品', 'A01', 'admin', '2019-10-18 11:45:18', 'admin', '2019-10-18 11:45:31', 'A01', '1'); +INSERT INTO `sys_category` VALUES ('1185039176799694850', '1185039122143719425', 'thinkpad', 'A01A01', 'admin', '2019-10-18 11:45:31', NULL, NULL, 'A01', NULL); +INSERT INTO `sys_category` VALUES ('1185039255115739138', '1185039122143719425', 'mackbook', 'A01A02', 'admin', '2019-10-18 11:45:50', NULL, NULL, 'A01', NULL); +INSERT INTO `sys_category` VALUES ('1185039299051073537', '1185039122143719425', '华为电脑', 'A01A03', 'admin', '2019-10-18 11:46:01', NULL, NULL, 'A01', NULL); +INSERT INTO `sys_category` VALUES ('1230769196661510146', '0', '省', NULL, 'admin', '2020-02-21 16:20:16', 'admin', '2020-02-21 16:20:31', 'A01A03', '1'); +INSERT INTO `sys_category` VALUES ('1230769253267836929', '1230769196661510146', '安徽省', NULL, 'admin', '2020-02-21 16:20:31', 'admin', '2020-02-21 16:20:53', 'A01A03', '1'); +INSERT INTO `sys_category` VALUES ('1230769290609725441', '1230769196661510146', '山东省', NULL, 'admin', '2020-02-21 16:20:40', 'admin', '2020-02-21 16:21:23', 'A01A03', '1'); +INSERT INTO `sys_category` VALUES ('1230769347157331969', '1230769253267836929', '合肥市', NULL, 'admin', '2020-02-21 16:20:53', 'admin', '2020-02-21 16:21:08', 'A01A03', '1'); +INSERT INTO `sys_category` VALUES ('1230769407907631106', '1230769347157331969', '包河区', NULL, 'admin', '2020-02-21 16:21:08', NULL, NULL, 'A01A03', NULL); +INSERT INTO `sys_category` VALUES ('1230769470889299970', '1230769290609725441', '济南市', NULL, 'admin', '2020-02-21 16:21:23', 'admin', '2020-02-21 16:21:41', 'A01A03', '1'); +INSERT INTO `sys_category` VALUES ('1230769547519234050', '1230769470889299970', 'A区', NULL, 'admin', '2020-02-21 16:21:41', NULL, NULL, 'A01A03', NULL); +INSERT INTO `sys_category` VALUES ('1230769620021972993', '1230769470889299970', 'B区', NULL, 'admin', '2020-02-21 16:21:58', NULL, NULL, 'A01A03', NULL); +INSERT INTO `sys_category` VALUES ('1230769769930592257', '1230769253267836929', '淮南市', NULL, 'admin', '2020-02-21 16:22:34', 'admin', '2020-02-21 16:22:54', 'A01A03', '1'); +INSERT INTO `sys_category` VALUES ('1230769855347593217', '1230769769930592257', 'C区', NULL, 'admin', '2020-02-21 16:22:54', NULL, NULL, 'A01A03', NULL); +INSERT INTO `sys_category` VALUES ('22a50b413c5e1ef661fb8aea9469cf52', 'e9ded10fd33e5753face506f4f1564b5', 'MacBook', 'B01-2-1', 'admin', '2019-06-10 15:43:13', NULL, NULL, 'A01', NULL); +INSERT INTO `sys_category` VALUES ('5c8f68845e57f68ab93a2c8d82d26ae1', '0', '笔记本', 'B01', 'admin', '2019-06-10 15:34:11', 'admin', '2019-06-10 15:34:24', 'A01', '1'); +INSERT INTO `sys_category` VALUES ('937fd2e9aa13b8bab1da1ca36d3fd344', 'e9ded10fd33e5753face506f4f1564b5', '台式机', 'B02-2-2', 'admin', '2019-06-10 15:43:32', 'admin', '2019-08-21 12:01:59', 'A01', NULL); +INSERT INTO `sys_category` VALUES ('e9ded10fd33e5753face506f4f1564b5', '5c8f68845e57f68ab93a2c8d82d26ae1', '苹果电脑', 'B01-2', 'admin', '2019-06-10 15:41:14', 'admin', '2019-06-10 15:43:13', 'A01', '1'); +INSERT INTO `sys_category` VALUES ('f39a06bf9f390ba4a53d11bc4e0018d7', '5c8f68845e57f68ab93a2c8d82d26ae1', '华为', 'B01-1', 'admin', '2019-06-10 15:34:24', 'admin', '2019-08-21 12:01:56', 'A01', NULL); + +-- ---------------------------- +-- Table structure for sys_check_rule +-- ---------------------------- +DROP TABLE IF EXISTS `sys_check_rule`; +CREATE TABLE `sys_check_rule` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id', + `rule_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则名称', + `rule_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则Code', + `rule_json` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则JSON', + `rule_description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则描述', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uni_sys_check_rule_code`(`rule_code`) USING BTREE, + UNIQUE INDEX `uk_scr_rule_code`(`rule_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_check_rule +-- ---------------------------- +INSERT INTO `sys_check_rule` VALUES ('1224980593992388610', '通用编码规则', 'common', '[{\"digits\":\"1\",\"pattern\":\"^[a-z|A-Z]$\",\"message\":\"第一位只能是字母\"},{\"digits\":\"*\",\"pattern\":\"^[0-9|a-z|A-Z|_]{0,}$\",\"message\":\"只能填写数字、大小写字母、下划线\"},{\"digits\":\"*\",\"pattern\":\"^.{3,}$\",\"message\":\"最少输入3位数\"},{\"digits\":\"*\",\"pattern\":\"^.{3,12}$\",\"message\":\"最多输入12位数\"}]', '规则:1、首位只能是字母;2、只能填写数字、大小写字母、下划线;3、最少3位数,最多12位数。', 'admin', '2020-02-07 11:25:48', 'admin', '2020-02-05 16:58:27'); +INSERT INTO `sys_check_rule` VALUES ('1225001845524004866', '负责的功能测试', 'test', '[{\"digits\":\"*\",\"pattern\":\"^.{3,12}$\",\"message\":\"只能输入3-12位字符\"},{\"digits\":\"3\",\"pattern\":\"^\\\\d{3}$\",\"message\":\"前3位必须是数字\"},{\"digits\":\"*\",\"pattern\":\"^[^pP]*$\",\"message\":\"不能输入P\"},{\"digits\":\"4\",\"pattern\":\"^@{4}$\",\"message\":\"第4-7位必须都为 @\"},{\"digits\":\"2\",\"pattern\":\"^#=$\",\"message\":\"第8-9位必须是 #=\"},{\"digits\":\"1\",\"pattern\":\"^O$\",\"message\":\"第10位必须为大写的O\"},{\"digits\":\"*\",\"pattern\":\"^.*。$\",\"message\":\"必须以。结尾\"}]', '包含长度校验、特殊字符校验等', 'admin', '2020-02-07 11:57:31', 'admin', '2020-02-05 18:22:54'); + +-- ---------------------------- +-- Table structure for sys_data_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_log`; +CREATE TABLE `sys_data_log` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'id', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人登录名称', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人登录名称', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `data_table` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表名', + `data_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '数据ID', + `data_content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '数据内容', + `data_version` int(11) NULL DEFAULT NULL COMMENT '版本号', + PRIMARY KEY (`id`) USING BTREE, + INDEX `sindex`(`data_table`, `data_id`) USING BTREE, + INDEX `idx_sdl_data_table_id`(`data_table`, `data_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for sys_data_source +-- ---------------------------- +DROP TABLE IF EXISTS `sys_data_source`; +CREATE TABLE `sys_data_source` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据源编码', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据源名称', + `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `db_type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据库类型', + `db_driver` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '驱动类', + `db_url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据源地址', + `db_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '数据库名称', + `db_username` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名', + `db_password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `sys_data_source_code_uni`(`code`) USING BTREE, + UNIQUE INDEX `uk_sdc_rule_code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_data_source +-- ---------------------------- +INSERT INTO `sys_data_source` VALUES ('1209779538310004737', 'local_mysql', 'MySQL5.7', '本地数据库MySQL5.7', '1', 'com.mysql.jdbc.Driver', 'jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false', 'jeecg-boot', 'root', 'f5b6775e8d1749483f2320627de0e706', 'admin', '2019-12-25 18:14:53', 'admin', '2020-07-10 16:54:42', 'A01'); + +-- ---------------------------- +-- Table structure for sys_depart +-- ---------------------------- +DROP TABLE IF EXISTS `sys_depart`; +CREATE TABLE `sys_depart` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', + `parent_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '父机构ID', + `depart_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '机构/部门名称', + `depart_name_en` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '英文名', + `depart_name_abbr` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '缩写', + `depart_order` int(11) NULL DEFAULT 0 COMMENT '排序', + `description` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `org_category` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '1' COMMENT '机构类别 1组织机构,2岗位', + `org_type` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '机构类型 1一级部门 2子部门', + `org_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '机构编码', + `mobile` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号', + `fax` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '传真', + `address` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址', + `memo` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + `status` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '状态(1启用,0不启用)', + `del_flag` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '删除状态(0,正常,1已删除)', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uniq_depart_org_code`(`org_code`) USING BTREE, + INDEX `index_depart_parent_id`(`parent_id`) USING BTREE, + INDEX `index_depart_depart_order`(`depart_order`) USING BTREE, + INDEX `index_depart_org_code`(`org_code`) USING BTREE, + INDEX `idx_sd_parent_id`(`parent_id`) USING BTREE, + INDEX `idx_sd_depart_order`(`depart_order`) USING BTREE, + INDEX `idx_sd_org_code`(`org_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '组织机构表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_depart +-- ---------------------------- +INSERT INTO `sys_depart` VALUES ('743ba9dbdc114af8953a11022ef3096a', 'f28c6f53abd841ac87ead43afc483433', '财务部', NULL, NULL, 0, NULL, '1', '2', 'A03A01', NULL, NULL, NULL, NULL, NULL, '0', 'admin', '2019-03-22 16:45:43', NULL, NULL); +INSERT INTO `sys_depart` VALUES ('c6d7cb4deeac411cb3384b1b31278596', '', '吉林农业大学', NULL, NULL, 0, NULL, '1', '1', 'A01', NULL, NULL, NULL, NULL, NULL, '0', 'admin', '2019-02-11 14:21:51', 'admin', '2022-03-31 17:36:37'); + +-- ---------------------------- +-- Table structure for sys_depart_permission +-- ---------------------------- +DROP TABLE IF EXISTS `sys_depart_permission`; +CREATE TABLE `sys_depart_permission` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `depart_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部门id', + `permission_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限id', + `data_rule_ids` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '数据规则id', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部门权限表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for sys_depart_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_depart_role`; +CREATE TABLE `sys_depart_role` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `depart_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部门id', + `role_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部门角色名称', + `role_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部门角色编码', + `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部门角色表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for sys_depart_role_permission +-- ---------------------------- +DROP TABLE IF EXISTS `sys_depart_role_permission`; +CREATE TABLE `sys_depart_role_permission` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `depart_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部门id', + `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色id', + `permission_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限id', + `data_rule_ids` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '数据权限ids', + `operate_date` datetime(0) NULL DEFAULT NULL COMMENT '操作时间', + `operate_ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作ip', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_group_role_per_id`(`role_id`, `permission_id`) USING BTREE, + INDEX `index_group_role_id`(`role_id`) USING BTREE, + INDEX `index_group_per_id`(`permission_id`) USING BTREE, + INDEX `idx_sdrp_role_per_id`(`role_id`, `permission_id`) USING BTREE, + INDEX `idx_sdrp_role_id`(`role_id`) USING BTREE, + INDEX `idx_sdrp_per_id`(`permission_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部门角色权限表' ROW_FORMAT = Compact; + +-- ---------------------------- +-- Table structure for sys_depart_role_user +-- ---------------------------- +DROP TABLE IF EXISTS `sys_depart_role_user`; +CREATE TABLE `sys_depart_role_user` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id', + `user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户id', + `drole_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色id', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部门角色用户表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for sys_dict +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict`; +CREATE TABLE `sys_dict` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `dict_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典名称', + `dict_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典编码', + `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `del_flag` int(11) NULL DEFAULT NULL COMMENT '删除状态', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `type` int(1) UNSIGNED ZEROFILL NULL DEFAULT 0 COMMENT '字典类型0为string,1为number', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `indextable_dict_code`(`dict_code`) USING BTREE, + UNIQUE INDEX `uk_sd_dict_code`(`dict_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_dict +-- ---------------------------- +INSERT INTO `sys_dict` VALUES ('0b5d19e1fce4b2e6647e6b4a17760c14', '通告类型', 'msg_category', '消息类型1:通知公告2:系统消息', 0, 'admin', '2019-04-22 18:01:35', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1174509082208395266', '职务职级', 'position_rank', '职务表职级字典', 0, 'admin', '2019-09-19 10:22:41', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1174511106530525185', '机构类型', 'org_category', '机构类型 1公司,2部门 3岗位', 0, 'admin', '2019-09-19 10:30:43', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1178295274528845826', '表单权限策略', 'form_perms_type', '', 0, 'admin', '2019-09-29 21:07:39', 'admin', '2019-09-29 21:08:26', NULL); +INSERT INTO `sys_dict` VALUES ('1199517671259906049', '紧急程度', 'urgent_level', '日程计划紧急程度', 0, 'admin', '2019-11-27 10:37:53', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1199518099888414722', '日程计划类型', 'eoa_plan_type', '', 0, 'admin', '2019-11-27 10:39:36', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1199520177767587841', '分类栏目类型', 'eoa_cms_menu_type', '', 0, 'admin', '2019-11-27 10:47:51', 'admin', '2019-11-27 10:49:35', 0); +INSERT INTO `sys_dict` VALUES ('1199525215290306561', '日程计划状态', 'eoa_plan_status', '', 0, 'admin', '2019-11-27 11:07:52', 'admin', '2019-11-27 11:10:11', 0); +INSERT INTO `sys_dict` VALUES ('1209733563293962241', '数据库类型', 'database_type', '', 0, 'admin', '2019-12-25 15:12:12', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1232913193820581889', 'Online表单业务分类', 'ol_form_biz_type', '', 0, 'admin', '2020-02-27 14:19:46', 'admin', '2020-02-27 14:20:23', 0); +INSERT INTO `sys_dict` VALUES ('1250687930947620866', '定时任务状态', 'quartz_status', '', 0, 'admin', '2020-04-16 15:30:14', '', NULL, NULL); +INSERT INTO `sys_dict` VALUES ('1280401766745718786', '租户状态', 'tenant_status', '租户状态', 0, 'admin', '2020-07-07 15:22:25', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1508267152743739393', '门户栏目类型', 'gateway_column_type', '', 0, 'admin', '2022-03-28 10:18:06', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1508267496747970562', '门户友情链接类型', 'gateway_links_type', '', 0, 'admin', '2022-03-28 10:19:28', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('1508286776285790210', '门户文章类型', 'gateway_article_type', '', 0, 'admin', '2022-03-28 11:36:05', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('236e8a4baff0db8c62c00dd95632834f', '同步工作流引擎', 'activiti_sync', '同步工作流引擎', 0, 'admin', '2019-05-15 15:27:33', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('2e02df51611a4b9632828ab7e5338f00', '权限策略', 'perms_type', '权限策略', 0, 'admin', '2019-04-26 18:26:55', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('2f0320997ade5dd147c90130f7218c3e', '推送类别', 'msg_type', '', 0, 'admin', '2019-03-17 21:21:32', 'admin', '2019-03-26 19:57:45', 0); +INSERT INTO `sys_dict` VALUES ('3486f32803bb953e7155dab3513dc68b', '删除状态', 'del_flag', NULL, 0, 'admin', '2019-01-18 21:46:26', 'admin', '2019-03-30 11:17:11', 0); +INSERT INTO `sys_dict` VALUES ('3d9a351be3436fbefb1307d4cfb49bf2', '性别', 'sex', NULL, 0, NULL, '2019-01-04 14:56:32', 'admin', '2019-03-30 11:28:27', 1); +INSERT INTO `sys_dict` VALUES ('4274efc2292239b6f000b153f50823ff', '全局权限策略', 'global_perms_type', '全局权限策略', 0, 'admin', '2019-05-10 17:54:05', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('4c03fca6bf1f0299c381213961566349', 'Online图表展示模板', 'online_graph_display_template', 'Online图表展示模板', 0, 'admin', '2019-04-12 17:28:50', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('4c753b5293304e7a445fd2741b46529d', '字典状态', 'dict_item_status', NULL, 0, 'admin', '2020-06-18 23:18:42', 'admin', '2019-03-30 19:33:52', 1); +INSERT INTO `sys_dict` VALUES ('4d7fec1a7799a436d26d02325eff295e', '优先级', 'priority', '优先级', 0, 'admin', '2019-03-16 17:03:34', 'admin', '2019-04-16 17:39:23', 0); +INSERT INTO `sys_dict` VALUES ('4e4602b3e3686f0911384e188dc7efb4', '条件规则', 'rule_conditions', '', 0, 'admin', '2019-04-01 10:15:03', 'admin', '2019-04-01 10:30:47', 0); +INSERT INTO `sys_dict` VALUES ('4f69be5f507accea8d5df5f11346181a', '发送消息类型', 'msgType', NULL, 0, 'admin', '2019-04-11 14:27:09', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('68168534ff5065a152bfab275c2136f8', '有效无效状态', 'valid_status', '有效无效状态', 0, 'admin', '2020-09-26 19:21:14', 'admin', '2019-04-26 19:21:23', 0); +INSERT INTO `sys_dict` VALUES ('6b78e3f59faec1a4750acff08030a79b', '用户类型', 'user_type', NULL, 0, NULL, '2019-01-04 14:59:01', 'admin', '2019-03-18 23:28:18', 0); +INSERT INTO `sys_dict` VALUES ('72cce0989df68887546746d8f09811aa', 'Online表单类型', 'cgform_table_type', '', 0, 'admin', '2019-01-27 10:13:02', 'admin', '2019-03-30 11:37:36', 0); +INSERT INTO `sys_dict` VALUES ('78bda155fe380b1b3f175f1e88c284c6', '流程状态', 'bpm_status', '流程状态', 0, 'admin', '2019-05-09 16:31:52', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('83bfb33147013cc81640d5fd9eda030c', '日志类型', 'log_type', NULL, 0, 'admin', '2019-03-18 23:22:19', NULL, NULL, 1); +INSERT INTO `sys_dict` VALUES ('845da5006c97754728bf48b6a10f79cc', '状态', 'status', NULL, 0, 'admin', '2019-03-18 21:45:25', 'admin', '2019-03-18 21:58:25', 0); +INSERT INTO `sys_dict` VALUES ('880a895c98afeca9d9ac39f29e67c13e', '操作类型', 'operate_type', '操作类型', 0, 'admin', '2019-07-22 10:54:29', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('8dfe32e2d29ea9430a988b3b558bf233', '发布状态', 'send_status', '发布状态', 0, 'admin', '2019-04-16 17:40:42', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('a7adbcd86c37f7dbc9b66945c82ef9e6', '1是0否', 'yn', '', 0, 'admin', '2019-05-22 19:29:29', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('a9d9942bd0eccb6e89de92d130ec4c4a', '消息发送状态', 'msgSendStatus', NULL, 0, 'admin', '2019-04-12 18:18:17', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('ac2f7c0c5c5775fcea7e2387bcb22f01', '菜单类型', 'menu_type', NULL, 0, 'admin', '2020-12-18 23:24:32', 'admin', '2019-04-01 15:27:06', 1); +INSERT INTO `sys_dict` VALUES ('ad7c65ba97c20a6805d5dcdf13cdaf36', 'onlineT类型', 'ceshi_online', NULL, 0, 'admin', '2019-03-22 16:31:49', 'admin', '2019-03-22 16:34:16', 0); +INSERT INTO `sys_dict` VALUES ('bd1b8bc28e65d6feefefb6f3c79f42fd', 'Online图表数据类型', 'online_graph_data_type', 'Online图表数据类型', 0, 'admin', '2019-04-12 17:24:24', 'admin', '2019-04-12 17:24:57', 0); +INSERT INTO `sys_dict` VALUES ('c36169beb12de8a71c8683ee7c28a503', '部门状态', 'depart_status', NULL, 0, 'admin', '2019-03-18 21:59:51', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('c5a14c75172783d72cbee6ee7f5df5d1', 'Online图表类型', 'online_graph_type', 'Online图表类型', 0, 'admin', '2019-04-12 17:04:06', NULL, NULL, 0); +INSERT INTO `sys_dict` VALUES ('d6e1152968b02d69ff358c75b48a6ee1', '流程类型', 'bpm_process_type', NULL, 0, 'admin', '2021-02-22 19:26:54', 'admin', '2019-03-30 18:14:44', 0); +INSERT INTO `sys_dict` VALUES ('fc6cd58fde2e8481db10d3a1e68ce70c', '用户状态', 'user_status', NULL, 0, 'admin', '2019-03-18 21:57:25', 'admin', '2019-03-18 23:11:58', 1); + +-- ---------------------------- +-- Table structure for sys_dict_item +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_item`; +CREATE TABLE `sys_dict_item` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `dict_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字典id', + `item_text` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典项文本', + `item_value` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '字典项值', + `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `sort_order` int(11) NULL DEFAULT NULL COMMENT '排序', + `status` int(11) NULL DEFAULT NULL COMMENT '状态(1启用 0不启用)', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `create_time` datetime(0) NULL DEFAULT NULL, + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `update_time` datetime(0) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_table_dict_id`(`dict_id`) USING BTREE, + INDEX `index_table_sort_order`(`sort_order`) USING BTREE, + INDEX `index_table_dict_status`(`status`) USING BTREE, + INDEX `idx_sdi_role_dict_id`(`dict_id`) USING BTREE, + INDEX `idx_sdi_role_sort_order`(`sort_order`) USING BTREE, + INDEX `idx_sdi_status`(`status`) USING BTREE, + INDEX `idx_sdi_dict_val`(`dict_id`, `item_value`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_dict_item +-- ---------------------------- +INSERT INTO `sys_dict_item` VALUES ('0072d115e07c875d76c9b022e2179128', '4d7fec1a7799a436d26d02325eff295e', '低', 'L', '低', 3, 1, 'admin', '2019-04-16 17:04:59', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('05a2e732ce7b00aa52141ecc3e330b4e', '3486f32803bb953e7155dab3513dc68b', '已删除', '1', NULL, NULL, 1, 'admin', '2025-10-18 21:46:56', 'admin', '2019-03-28 22:23:20'); +INSERT INTO `sys_dict_item` VALUES ('096c2e758d823def3855f6376bc736fb', 'bd1b8bc28e65d6feefefb6f3c79f42fd', 'SQL', 'sql', NULL, 1, 1, 'admin', '2019-04-12 17:26:26', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('0c9532916f5cd722017b46bc4d953e41', '2f0320997ade5dd147c90130f7218c3e', '指定用户', 'USER', NULL, NULL, 1, 'admin', '2019-03-17 21:22:19', 'admin', '2019-03-17 21:22:28'); +INSERT INTO `sys_dict_item` VALUES ('0ca4beba9efc4f9dd54af0911a946d5c', '72cce0989df68887546746d8f09811aa', '附表', '3', NULL, 3, 1, 'admin', '2019-03-27 10:13:43', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1030a2652608f5eac3b49d70458b8532', '2e02df51611a4b9632828ab7e5338f00', '禁用', '2', '禁用', 2, 1, 'admin', '2021-03-26 18:27:28', 'admin', '2019-04-26 18:39:11'); +INSERT INTO `sys_dict_item` VALUES ('1174509082208395266', '1174511106530525185', '岗位', '3', '岗位', 1, 1, 'admin', '2019-09-19 10:31:16', '', NULL); +INSERT INTO `sys_dict_item` VALUES ('1174509601047994369', '1174509082208395266', '员级', '1', '', 1, 1, 'admin', '2019-09-19 10:24:45', 'admin', '2019-09-23 11:46:39'); +INSERT INTO `sys_dict_item` VALUES ('1174509667297026049', '1174509082208395266', '助级', '2', '', 2, 1, 'admin', '2019-09-19 10:25:01', 'admin', '2019-09-23 11:46:47'); +INSERT INTO `sys_dict_item` VALUES ('1174509713568587777', '1174509082208395266', '中级', '3', '', 3, 1, 'admin', '2019-09-19 10:25:12', 'admin', '2019-09-23 11:46:56'); +INSERT INTO `sys_dict_item` VALUES ('1174509788361416705', '1174509082208395266', '副高级', '4', '', 4, 1, 'admin', '2019-09-19 10:25:30', 'admin', '2019-09-23 11:47:06'); +INSERT INTO `sys_dict_item` VALUES ('1174509835803189250', '1174509082208395266', '正高级', '5', '', 5, 1, 'admin', '2019-09-19 10:25:41', 'admin', '2019-09-23 11:47:12'); +INSERT INTO `sys_dict_item` VALUES ('1174511197735665665', '1174511106530525185', '公司', '1', '公司', 1, 1, 'admin', '2019-09-19 10:31:05', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1174511244036587521', '1174511106530525185', '部门', '2', '部门', 1, 1, 'admin', '2019-09-19 10:31:16', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1178295553450061826', '1178295274528845826', '可编辑(未授权禁用)', '2', '', 2, 1, 'admin', '2019-09-29 21:08:46', 'admin', '2019-09-29 21:09:18'); +INSERT INTO `sys_dict_item` VALUES ('1178295639554928641', '1178295274528845826', '可见(未授权不可见)', '1', '', 1, 1, 'admin', '2019-09-29 21:09:06', 'admin', '2019-09-29 21:09:24'); +INSERT INTO `sys_dict_item` VALUES ('1199517884758368257', '1199517671259906049', '一般', '1', '', 1, 1, 'admin', '2019-11-27 10:38:44', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199517914017832962', '1199517671259906049', '重要', '2', '', 1, 1, 'admin', '2019-11-27 10:38:51', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199517941339529217', '1199517671259906049', '紧急', '3', '', 1, 1, 'admin', '2019-11-27 10:38:58', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199518186144276482', '1199518099888414722', '日常记录', '1', '', 1, 1, 'admin', '2019-11-27 10:39:56', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199518214858481666', '1199518099888414722', '本周工作', '2', '', 1, 1, 'admin', '2019-11-27 10:40:03', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199518235943247874', '1199518099888414722', '下周计划', '3', '', 1, 1, 'admin', '2019-11-27 10:40:08', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199520817285701634', '1199520177767587841', '列表', '1', '', 1, 1, 'admin', '2019-11-27 10:50:24', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199520835035996161', '1199520177767587841', '链接', '2', '', 1, 1, 'admin', '2019-11-27 10:50:28', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199525468672405505', '1199525215290306561', '未开始', '0', '', 1, 1, 'admin', '2019-11-27 11:08:52', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199525490575060993', '1199525215290306561', '进行中', '1', '', 1, 1, 'admin', '2019-11-27 11:08:58', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1199525506429530114', '1199525215290306561', '已完成', '2', '', 1, 1, 'admin', '2019-11-27 11:09:02', 'admin', '2019-11-27 11:10:02'); +INSERT INTO `sys_dict_item` VALUES ('1199607547704647681', '4f69be5f507accea8d5df5f11346181a', '系统', '4', '', 1, 1, 'admin', '2019-11-27 16:35:02', 'admin', '2019-11-27 19:37:46'); +INSERT INTO `sys_dict_item` VALUES ('1209733775114702850', '1209733563293962241', 'MySQL', '1', '', 1, 1, 'admin', '2019-12-25 15:13:02', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1209733839933476865', '1209733563293962241', 'Oracle', '2', '', 1, 1, 'admin', '2019-12-25 15:13:18', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1209733903020003330', '1209733563293962241', 'SQLServer', '3', '', 1, 1, 'admin', '2019-12-25 15:13:33', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1232913424813486081', '1232913193820581889', '官方示例', 'demo', '', 1, 1, 'admin', '2020-02-27 14:20:42', 'admin', '2020-02-27 14:21:37'); +INSERT INTO `sys_dict_item` VALUES ('1232913493717512194', '1232913193820581889', '流程表单', 'bpm', '', 2, 1, 'admin', '2020-02-27 14:20:58', 'admin', '2020-02-27 14:22:20'); +INSERT INTO `sys_dict_item` VALUES ('1232913605382467585', '1232913193820581889', '测试表单', 'temp', '', 4, 1, 'admin', '2020-02-27 14:21:25', 'admin', '2020-02-27 14:22:16'); +INSERT INTO `sys_dict_item` VALUES ('1232914232372195330', '1232913193820581889', '导入表单', 'bdfl_include', '', 5, 1, 'admin', '2020-02-27 14:23:54', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1234371726545010689', '4e4602b3e3686f0911384e188dc7efb4', '左模糊', 'LEFT_LIKE', '左模糊', 7, 1, 'admin', '2020-03-02 14:55:27', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1234371809495760898', '4e4602b3e3686f0911384e188dc7efb4', '右模糊', 'RIGHT_LIKE', '右模糊', 7, 1, 'admin', '2020-03-02 14:55:47', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1250688147579228161', '1250687930947620866', '正常', '0', '', 1, 1, 'admin', '2020-04-16 15:31:05', '', NULL); +INSERT INTO `sys_dict_item` VALUES ('1250688201064992770', '1250687930947620866', '停止', '-1', '', 1, 1, 'admin', '2020-04-16 15:31:18', '', NULL); +INSERT INTO `sys_dict_item` VALUES ('1280401815068295170', '1280401766745718786', '正常', '1', '', 1, 1, 'admin', '2020-07-07 15:22:36', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1280401847607705602', '1280401766745718786', '冻结', '0', '', 1, 1, 'admin', '2020-07-07 15:22:44', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1305827309355302914', 'bd1b8bc28e65d6feefefb6f3c79f42fd', 'API', 'api', '', 3, 1, 'admin', '2020-09-15 19:14:26', 'admin', '2020-09-15 19:14:41'); +INSERT INTO `sys_dict_item` VALUES ('147c48ff4b51545032a9119d13f3222a', 'd6e1152968b02d69ff358c75b48a6ee1', '测试流程', 'test', NULL, 1, 1, 'admin', '2019-03-22 19:27:05', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1508267608446480386', '1508267496747970562', '友情链接', '友情链接', '', 1, 1, 'admin', '2022-03-28 10:19:55', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1508267676817829890', '1508267496747970562', '快速导航', '快速导航', '', 1, 1, 'admin', '2022-03-28 10:20:11', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1508286880648462337', '1508286776285790210', '首页轮播', '首页轮播', '', 1, 1, 'admin', '2022-03-28 11:36:30', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1508322441442557954', '1508267152743739393', '隐藏在头部显示', '隐藏在头部显示', '', 1, 1, 'admin', '2022-03-28 13:57:48', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1543fe7e5e26fb97cdafe4981bedc0c8', '4c03fca6bf1f0299c381213961566349', '单排布局', 'single', NULL, 2, 1, 'admin', '2022-07-12 17:43:39', 'admin', '2019-04-12 17:43:57'); +INSERT INTO `sys_dict_item` VALUES ('1ce390c52453891f93514c1bd2795d44', 'ad7c65ba97c20a6805d5dcdf13cdaf36', '000', '00', NULL, 1, 1, 'admin', '2019-03-22 16:34:34', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('1db531bcff19649fa82a644c8a939dc4', '4c03fca6bf1f0299c381213961566349', '组合布局', 'combination', '', 4, 1, 'admin', '2019-05-11 16:07:08', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('222705e11ef0264d4214affff1fb4ff9', '4f69be5f507accea8d5df5f11346181a', '短信', '1', '', 1, 1, 'admin', '2023-02-28 10:50:36', 'admin', '2019-04-28 10:58:11'); +INSERT INTO `sys_dict_item` VALUES ('23a5bb76004ed0e39414e928c4cde155', '4e4602b3e3686f0911384e188dc7efb4', '不等于', '!=', '不等于', 3, 1, 'admin', '2019-04-01 16:46:15', 'admin', '2019-04-01 17:48:40'); +INSERT INTO `sys_dict_item` VALUES ('25847e9cb661a7c711f9998452dc09e6', '4e4602b3e3686f0911384e188dc7efb4', '小于等于', '<=', '小于等于', 6, 1, 'admin', '2019-04-01 16:44:34', 'admin', '2019-04-01 17:49:10'); +INSERT INTO `sys_dict_item` VALUES ('2d51376643f220afdeb6d216a8ac2c01', '68168534ff5065a152bfab275c2136f8', '有效', '1', '有效', 2, 1, 'admin', '2019-04-26 19:22:01', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('308c8aadf0c37ecdde188b97ca9833f5', '8dfe32e2d29ea9430a988b3b558bf233', '已发布', '1', '已发布', 2, 1, 'admin', '2019-04-16 17:41:24', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('333e6b2196e01ef9a5f76d74e86a6e33', '8dfe32e2d29ea9430a988b3b558bf233', '未发布', '0', '未发布', 1, 1, 'admin', '2019-04-16 17:41:12', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('337ea1e401bda7233f6258c284ce4f50', 'bd1b8bc28e65d6feefefb6f3c79f42fd', 'JSON', 'json', NULL, 1, 1, 'admin', '2019-04-12 17:26:33', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('33bc9d9f753cf7dc40e70461e50fdc54', 'a9d9942bd0eccb6e89de92d130ec4c4a', '发送失败', '2', NULL, 3, 1, 'admin', '2019-04-12 18:20:02', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('3fbc03d6c994ae06d083751248037c0e', '78bda155fe380b1b3f175f1e88c284c6', '已完成', '3', '已完成', 3, 1, 'admin', '2019-05-09 16:33:25', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('41d7aaa40c9b61756ffb1f28da5ead8e', '0b5d19e1fce4b2e6647e6b4a17760c14', '通知公告', '1', NULL, 1, 1, 'admin', '2019-04-22 18:01:57', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('41fa1e9571505d643aea87aeb83d4d76', '4e4602b3e3686f0911384e188dc7efb4', '等于', '=', '等于', 4, 1, 'admin', '2019-04-01 16:45:24', 'admin', '2019-04-01 17:49:00'); +INSERT INTO `sys_dict_item` VALUES ('43d2295b8610adce9510ff196a49c6e9', '845da5006c97754728bf48b6a10f79cc', '正常', '1', NULL, NULL, 1, 'admin', '2019-03-18 21:45:51', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('4f05fb5376f4c61502c5105f52e4dd2b', '83bfb33147013cc81640d5fd9eda030c', '操作日志', '2', NULL, NULL, 1, 'admin', '2019-03-18 23:22:49', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('50223341bfb5ba30bf6319789d8d17fe', 'd6e1152968b02d69ff358c75b48a6ee1', '业务办理', 'business', NULL, 3, 1, 'admin', '2023-04-22 19:28:05', 'admin', '2019-03-22 23:24:39'); +INSERT INTO `sys_dict_item` VALUES ('51222413e5906cdaf160bb5c86fb827c', 'a7adbcd86c37f7dbc9b66945c82ef9e6', '是', '1', '', 1, 1, 'admin', '2019-05-22 19:29:45', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('538fca35afe004972c5f3947c039e766', '2e02df51611a4b9632828ab7e5338f00', '显示', '1', '显示', 1, 1, 'admin', '2025-03-26 18:27:13', 'admin', '2019-04-26 18:39:07'); +INSERT INTO `sys_dict_item` VALUES ('5584c21993bde231bbde2b966f2633ac', '4e4602b3e3686f0911384e188dc7efb4', '自定义SQL表达式', 'USE_SQL_RULES', '自定义SQL表达式', 9, 1, 'admin', '2019-04-01 10:45:24', 'admin', '2019-04-01 17:49:27'); +INSERT INTO `sys_dict_item` VALUES ('58b73b344305c99b9d8db0fc056bbc0a', '72cce0989df68887546746d8f09811aa', '主表', '2', NULL, 2, 1, 'admin', '2019-03-27 10:13:36', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('5b65a88f076b32e8e69d19bbaadb52d5', '2f0320997ade5dd147c90130f7218c3e', '全体用户', 'ALL', NULL, NULL, 1, 'admin', '2020-10-17 21:22:43', 'admin', '2019-03-28 22:17:09'); +INSERT INTO `sys_dict_item` VALUES ('5d833f69296f691843ccdd0c91212b6b', '880a895c98afeca9d9ac39f29e67c13e', '修改', '3', '', 3, 1, 'admin', '2019-07-22 10:55:07', 'admin', '2019-07-22 10:55:41'); +INSERT INTO `sys_dict_item` VALUES ('5d84a8634c8fdfe96275385075b105c9', '3d9a351be3436fbefb1307d4cfb49bf2', '女', '2', NULL, 2, 1, NULL, '2019-01-04 14:56:56', NULL, '2019-01-04 17:38:12'); +INSERT INTO `sys_dict_item` VALUES ('66c952ae2c3701a993e7db58f3baf55e', '4e4602b3e3686f0911384e188dc7efb4', '大于', '>', '大于', 1, 1, 'admin', '2019-04-01 10:45:46', 'admin', '2019-04-01 17:48:29'); +INSERT INTO `sys_dict_item` VALUES ('6937c5dde8f92e9a00d4e2ded9198694', 'ad7c65ba97c20a6805d5dcdf13cdaf36', 'easyui', '3', NULL, 1, 1, 'admin', '2019-03-22 16:32:15', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('69cacf64e244100289ddd4aa9fa3b915', 'a9d9942bd0eccb6e89de92d130ec4c4a', '未发送', '0', NULL, 1, 1, 'admin', '2019-04-12 18:19:23', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('6a7a9e1403a7943aba69e54ebeff9762', '4f69be5f507accea8d5df5f11346181a', '邮件', '2', '', 2, 1, 'admin', '2031-02-28 10:50:44', 'admin', '2019-04-28 10:59:03'); +INSERT INTO `sys_dict_item` VALUES ('6c682d78ddf1715baf79a1d52d2aa8c2', '72cce0989df68887546746d8f09811aa', '单表', '1', NULL, 1, 1, 'admin', '2019-03-27 10:13:29', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('6d404fd2d82311fbc87722cd302a28bc', '4e4602b3e3686f0911384e188dc7efb4', '模糊', 'LIKE', '模糊', 7, 1, 'admin', '2019-04-01 16:46:02', 'admin', '2019-04-01 17:49:20'); +INSERT INTO `sys_dict_item` VALUES ('6d4e26e78e1a09699182e08516c49fc4', '4d7fec1a7799a436d26d02325eff295e', '高', 'H', '高', 1, 1, 'admin', '2019-04-16 17:04:24', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('700e9f030654f3f90e9ba76ab0713551', '6b78e3f59faec1a4750acff08030a79b', '333', '333', NULL, NULL, 1, 'admin', '2019-02-21 19:59:47', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('7050c1522702bac3be40e3b7d2e1dfd8', 'c5a14c75172783d72cbee6ee7f5df5d1', '柱状图', 'bar', NULL, 1, 1, 'admin', '2019-04-12 17:05:17', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('71b924faa93805c5c1579f12e001c809', 'd6e1152968b02d69ff358c75b48a6ee1', 'OA办公', 'oa', NULL, 2, 1, 'admin', '2021-03-22 19:27:17', 'admin', '2019-03-22 23:24:36'); +INSERT INTO `sys_dict_item` VALUES ('75b260d7db45a39fc7f21badeabdb0ed', 'c36169beb12de8a71c8683ee7c28a503', '不启用', '0', NULL, NULL, 1, 'admin', '2019-03-18 23:29:41', 'admin', '2019-03-18 23:29:54'); +INSERT INTO `sys_dict_item` VALUES ('7688469db4a3eba61e6e35578dc7c2e5', 'c36169beb12de8a71c8683ee7c28a503', '启用', '1', NULL, NULL, 1, 'admin', '2019-03-18 23:29:28', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('78ea6cadac457967a4b1c4eb7aaa418c', 'fc6cd58fde2e8481db10d3a1e68ce70c', '正常', '1', NULL, NULL, 1, 'admin', '2019-03-18 23:30:28', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('7ccf7b80c70ee002eceb3116854b75cb', 'ac2f7c0c5c5775fcea7e2387bcb22f01', '按钮权限', '2', NULL, NULL, 1, 'admin', '2019-03-18 23:25:40', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('81fb2bb0e838dc68b43f96cc309f8257', 'fc6cd58fde2e8481db10d3a1e68ce70c', '冻结', '2', NULL, NULL, 1, 'admin', '2019-03-18 23:30:37', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('83250269359855501ec4e9c0b7e21596', '4274efc2292239b6f000b153f50823ff', '可见/可访问(授权后可见/可访问)', '1', '', 1, 1, 'admin', '2019-05-10 17:54:51', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('84778d7e928bc843ad4756db1322301f', '4e4602b3e3686f0911384e188dc7efb4', '大于等于', '>=', '大于等于', 5, 1, 'admin', '2019-04-01 10:46:02', 'admin', '2019-04-01 17:49:05'); +INSERT INTO `sys_dict_item` VALUES ('848d4da35ebd93782029c57b103e5b36', 'c5a14c75172783d72cbee6ee7f5df5d1', '饼图', 'pie', NULL, 3, 1, 'admin', '2019-04-12 17:05:49', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('84dfc178dd61b95a72900fcdd624c471', '78bda155fe380b1b3f175f1e88c284c6', '处理中', '2', '处理中', 2, 1, 'admin', '2019-05-09 16:33:01', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('86f19c7e0a73a0bae451021ac05b99dd', 'ac2f7c0c5c5775fcea7e2387bcb22f01', '子菜单', '1', NULL, NULL, 1, 'admin', '2019-03-18 23:25:27', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('8bccb963e1cd9e8d42482c54cc609ca2', '4f69be5f507accea8d5df5f11346181a', '微信', '3', NULL, 3, 1, 'admin', '2021-05-11 14:29:12', 'admin', '2019-04-11 14:29:31'); +INSERT INTO `sys_dict_item` VALUES ('8c618902365ca681ebbbe1e28f11a548', '4c753b5293304e7a445fd2741b46529d', '启用', '1', '', 0, 1, 'admin', '2020-07-18 23:19:27', 'admin', '2019-05-17 14:51:18'); +INSERT INTO `sys_dict_item` VALUES ('8cdf08045056671efd10677b8456c999', '4274efc2292239b6f000b153f50823ff', '可编辑(未授权时禁用)', '2', '', 2, 1, 'admin', '2019-05-10 17:55:38', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('8ff48e657a7c5090d4f2a59b37d1b878', '4d7fec1a7799a436d26d02325eff295e', '中', 'M', '中', 2, 1, 'admin', '2019-04-16 17:04:40', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('948923658baa330319e59b2213cda97c', '880a895c98afeca9d9ac39f29e67c13e', '添加', '2', '', 2, 1, 'admin', '2019-07-22 10:54:59', 'admin', '2019-07-22 10:55:36'); +INSERT INTO `sys_dict_item` VALUES ('9a96c4a4e4c5c9b4e4d0cbf6eb3243cc', '4c753b5293304e7a445fd2741b46529d', '不启用', '0', NULL, 1, 1, 'admin', '2019-03-18 23:19:53', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('a1e7d1ca507cff4a480c8caba7c1339e', '880a895c98afeca9d9ac39f29e67c13e', '导出', '6', '', 6, 1, 'admin', '2019-07-22 12:06:50', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('a2be752dd4ec980afaec1efd1fb589af', '8dfe32e2d29ea9430a988b3b558bf233', '已撤销', '2', '已撤销', 3, 1, 'admin', '2019-04-16 17:41:39', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('aa0d8a8042a18715a17f0a888d360aa4', 'ac2f7c0c5c5775fcea7e2387bcb22f01', '一级菜单', '0', NULL, NULL, 1, 'admin', '2019-03-18 23:24:52', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('adcf2a1fe93bb99a84833043f475fe0b', '4e4602b3e3686f0911384e188dc7efb4', '包含', 'IN', '包含', 8, 1, 'admin', '2019-04-01 16:45:47', 'admin', '2019-04-01 17:49:24'); +INSERT INTO `sys_dict_item` VALUES ('b029a41a851465332ee4ee69dcf0a4c2', '0b5d19e1fce4b2e6647e6b4a17760c14', '系统消息', '2', NULL, 1, 1, 'admin', '2019-02-22 18:02:08', 'admin', '2019-04-22 18:02:13'); +INSERT INTO `sys_dict_item` VALUES ('b2a8b4bb2c8e66c2c4b1bb086337f393', '3486f32803bb953e7155dab3513dc68b', '正常', '0', NULL, NULL, 1, 'admin', '2022-10-18 21:46:48', 'admin', '2019-03-28 22:22:20'); +INSERT INTO `sys_dict_item` VALUES ('b57f98b88363188daf38d42f25991956', '6b78e3f59faec1a4750acff08030a79b', '22', '222', NULL, NULL, 0, 'admin', '2019-02-21 19:59:43', 'admin', '2019-03-11 21:23:27'); +INSERT INTO `sys_dict_item` VALUES ('b5f3bd5f66bb9a83fecd89228c0d93d1', '68168534ff5065a152bfab275c2136f8', '无效', '0', '无效', 1, 1, 'admin', '2019-04-26 19:21:49', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('b9fbe2a3602d4a27b45c100ac5328484', '78bda155fe380b1b3f175f1e88c284c6', '待提交', '1', '待提交', 1, 1, 'admin', '2019-05-09 16:32:35', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('ba27737829c6e0e582e334832703d75e', '236e8a4baff0db8c62c00dd95632834f', '同步', '1', '同步', 1, 1, 'admin', '2019-05-15 15:28:15', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('bcec04526b04307e24a005d6dcd27fd6', '880a895c98afeca9d9ac39f29e67c13e', '导入', '5', '', 5, 1, 'admin', '2019-07-22 12:06:41', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('c53da022b9912e0aed691bbec3c78473', '880a895c98afeca9d9ac39f29e67c13e', '查询', '1', '', 1, 1, 'admin', '2019-07-22 10:54:51', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('c5700a71ad08994d18ad1dacc37a71a9', 'a7adbcd86c37f7dbc9b66945c82ef9e6', '否', '0', '', 1, 1, 'admin', '2019-05-22 19:29:55', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('cbfcc5b88fc3a90975df23ffc8cbe29c', 'c5a14c75172783d72cbee6ee7f5df5d1', '曲线图', 'line', NULL, 2, 1, 'admin', '2019-05-12 17:05:30', 'admin', '2019-04-12 17:06:06'); +INSERT INTO `sys_dict_item` VALUES ('d217592908ea3e00ff986ce97f24fb98', 'c5a14c75172783d72cbee6ee7f5df5d1', '数据列表', 'table', NULL, 4, 1, 'admin', '2019-04-12 17:05:56', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('df168368dcef46cade2aadd80100d8aa', '3d9a351be3436fbefb1307d4cfb49bf2', '男', '1', NULL, 1, 1, NULL, '2027-08-04 14:56:49', 'admin', '2019-03-23 22:44:44'); +INSERT INTO `sys_dict_item` VALUES ('e6329e3a66a003819e2eb830b0ca2ea0', '4e4602b3e3686f0911384e188dc7efb4', '小于', '<', '小于', 2, 1, 'admin', '2019-04-01 16:44:15', 'admin', '2019-04-01 17:48:34'); +INSERT INTO `sys_dict_item` VALUES ('e94eb7af89f1dbfa0d823580a7a6e66a', '236e8a4baff0db8c62c00dd95632834f', '不同步', '0', '不同步', 2, 1, 'admin', '2019-05-15 15:28:28', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('f0162f4cc572c9273f3e26b2b4d8c082', 'ad7c65ba97c20a6805d5dcdf13cdaf36', 'booostrap', '1', NULL, 1, 1, 'admin', '2021-08-22 16:32:04', 'admin', '2019-03-22 16:33:57'); +INSERT INTO `sys_dict_item` VALUES ('f16c5706f3ae05c57a53850c64ce7c45', 'a9d9942bd0eccb6e89de92d130ec4c4a', '发送成功', '1', NULL, 2, 1, 'admin', '2019-04-12 18:19:43', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('f2a7920421f3335afdf6ad2b342f6b5d', '845da5006c97754728bf48b6a10f79cc', '冻结', '2', NULL, NULL, 1, 'admin', '2019-03-18 21:46:02', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('f37f90c496ec9841c4c326b065e00bb2', '83bfb33147013cc81640d5fd9eda030c', '登录日志', '1', NULL, NULL, 1, 'admin', '2019-03-18 23:22:37', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('f753aff60ff3931c0ecb4812d8b5e643', '4c03fca6bf1f0299c381213961566349', '双排布局', 'double', NULL, 3, 1, 'admin', '2019-04-12 17:43:51', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('f80a8f6838215753b05e1a5ba3346d22', '880a895c98afeca9d9ac39f29e67c13e', '删除', '4', '', 4, 1, 'admin', '2019-07-22 10:55:14', 'admin', '2019-07-22 10:55:30'); +INSERT INTO `sys_dict_item` VALUES ('fcec03570f68a175e1964808dc3f1c91', '4c03fca6bf1f0299c381213961566349', 'Tab风格', 'tab', NULL, 1, 1, 'admin', '2019-04-12 17:43:31', NULL, NULL); +INSERT INTO `sys_dict_item` VALUES ('fe50b23ae5e68434def76f67cef35d2d', '78bda155fe380b1b3f175f1e88c284c6', '已作废', '4', '已作废', 4, 1, 'admin', '2021-09-09 16:33:43', 'admin', '2019-05-09 16:34:40'); + +-- ---------------------------- +-- Table structure for sys_fill_rule +-- ---------------------------- +DROP TABLE IF EXISTS `sys_fill_rule`; +CREATE TABLE `sys_fill_rule` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键ID', + `rule_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则名称', + `rule_code` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则Code', + `rule_class` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则实现类', + `rule_params` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '规则参数', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uni_sys_fill_rule_code`(`rule_code`) USING BTREE, + UNIQUE INDEX `uk_sfr_rule_code`(`rule_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_fill_rule +-- ---------------------------- +INSERT INTO `sys_fill_rule` VALUES ('1202551334738382850', '机构编码生成', 'org_num_role', 'org.jeecg.modules.system.rule.OrgCodeRule', '{\"parentId\":\"c6d7cb4deeac411cb3384b1b31278596\"}', 'admin', '2019-12-09 10:37:06', 'admin', '2019-12-05 19:32:35'); +INSERT INTO `sys_fill_rule` VALUES ('1202787623203065858', '分类字典编码生成', 'category_code_rule', 'org.jeecg.modules.system.rule.CategoryCodeRule', '{\"pid\":\"\"}', 'admin', '2019-12-09 10:36:54', 'admin', '2019-12-06 11:11:31'); +INSERT INTO `sys_fill_rule` VALUES ('1260134137920090113', '商城订单流水号', 'shop_order_num', 'org.jeecg.modules.system.rule.OrderNumberRule', '{}', 'admin', '2020-07-11 11:35:00', 'admin', '2020-05-12 17:06:05'); + +-- ---------------------------- +-- Table structure for sys_gateway_route +-- ---------------------------- +DROP TABLE IF EXISTS `sys_gateway_route`; +CREATE TABLE `sys_gateway_route` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `router_id` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路由ID', + `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '服务名', + `uri` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '服务地址', + `predicates` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '断言', + `filters` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '过滤器', + `retryable` int(11) NULL DEFAULT NULL COMMENT '是否重试:0-否 1-是', + `strip_prefix` int(11) NULL DEFAULT NULL COMMENT '是否忽略前缀0-否 1-是', + `persist` int(11) NULL DEFAULT NULL COMMENT '是否为保留数据:0-否 1-是', + `show_api` int(11) NULL DEFAULT NULL COMMENT '是否在接口文档中展示:0-否 1-是', + `status` int(11) NULL DEFAULT NULL COMMENT '状态:0-无效 1-有效', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '所属部门', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; + +-- ---------------------------- +-- Records of sys_gateway_route +-- ---------------------------- +INSERT INTO `sys_gateway_route` VALUES ('1331051599401857026', 'jeecg-demo-websocket', 'jeecg-demo-websocket', 'lb:ws://jeecg-demo', '[{\"args\":[\"/vxeSocket/**\"],\"name\":\"Path\"}]', '[]', NULL, NULL, NULL, NULL, 1, 'admin', '2020-11-24 09:46:46', NULL, NULL, NULL); +INSERT INTO `sys_gateway_route` VALUES ('jeecg-cloud-websocket', 'jeecg-system-websocket', 'jeecg-system-websocket', 'lb:ws://jeecg-system', '[{\"args\":[\"/websocket/**\",\"/eoaSocket/**\",\"/newsWebsocket/**\"],\"name\":\"Path\"}]', '[]', NULL, NULL, NULL, NULL, 1, 'admin', '2020-11-16 19:41:51', NULL, NULL, NULL); +INSERT INTO `sys_gateway_route` VALUES ('jeecg-demo', 'jeecg-demo', 'jeecg-demo', 'lb://jeecg-demo', '[{\"args\":[\"/mock/**\",\"/test/**\",\"/bigscreen/template1/**\",\"/bigscreen/template2/**\"],\"name\":\"Path\"}]', '[]', NULL, NULL, NULL, NULL, 1, 'admin', '2020-11-16 19:41:51', NULL, NULL, NULL); +INSERT INTO `sys_gateway_route` VALUES ('jeecg-system', 'jeecg-system', 'jeecg-system', 'lb://jeecg-system', '[{\"args\":[\"/sys/**\",\"/eoa/**\",\"/joa/**\",\"/online/**\",\"/bigscreen/**\",\"/jmreport/**\",\"/desform/**\",\"/process/**\",\"/act/**\",\"/plug-in/***/\",\"/druid/**\",\"/generic/**\"],\"name\":\"Path\"}]', '[]', NULL, NULL, NULL, NULL, 1, 'admin', '2020-11-16 19:41:51', NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_log`; +CREATE TABLE `sys_log` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `log_type` int(11) NULL DEFAULT NULL COMMENT '日志类型(1登录日志,2操作日志)', + `log_content` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '日志内容', + `operate_type` int(11) NULL DEFAULT NULL COMMENT '操作类型', + `userid` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作用户账号', + `username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作用户名称', + `ip` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'IP', + `method` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求java方法', + `request_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求路径', + `request_param` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '请求参数', + `request_type` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求类型', + `cost_time` bigint(20) NULL DEFAULT NULL COMMENT '耗时', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_table_userid`(`userid`) USING BTREE, + INDEX `index_logt_ype`(`log_type`) USING BTREE, + INDEX `index_operate_type`(`operate_type`) USING BTREE, + INDEX `index_log_type`(`log_type`) USING BTREE, + INDEX `idx_sl_userid`(`userid`) USING BTREE, + INDEX `idx_sl_log_type`(`log_type`) USING BTREE, + INDEX `idx_sl_operate_type`(`operate_type`) USING BTREE, + INDEX `idx_sl_create_time`(`create_time`) USING BTREE +) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统日志表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_log +-- ---------------------------- +INSERT INTO `sys_log` VALUES ('1509739970689593345', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@531e175f', NULL, 111, NULL, '2022-04-01 11:50:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509739970966417410', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@14a5ea2c', NULL, 184, NULL, '2022-04-01 11:50:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509739974992949251', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@106772a', NULL, 44, NULL, '2022-04-01 11:50:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509739974992949250', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6e097bb3', NULL, 50, NULL, '2022-04-01 11:50:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509739975030697985', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5bc19cbf', NULL, 56, NULL, '2022-04-01 11:50:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509739975055863811', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6b0209fc', NULL, 66, NULL, '2022-04-01 11:50:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509739975055863809', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@86c82f0', NULL, 64, NULL, '2022-04-01 11:50:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509739975055863810', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@132d4e0d', NULL, 45, NULL, '2022-04-01 11:50:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803897117077506', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@45544c42', NULL, 70, NULL, '2022-04-01 16:04:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803897301626882', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4b85865e', NULL, 121, NULL, '2022-04-01 16:04:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803897834303489', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7e3f7fae', NULL, 52, NULL, '2022-04-01 16:04:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803897834303490', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6b2d73b7', NULL, 49, NULL, '2022-04-01 16:04:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803897855275010', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@ee8c5d0', NULL, 58, NULL, '2022-04-01 16:04:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803897863663618', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3e04ecf6', NULL, 57, NULL, '2022-04-01 16:04:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803897867857921', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1dd13900', NULL, 57, NULL, '2022-04-01 16:04:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803897905606658', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7bfa85d9', NULL, 70, NULL, '2022-04-01 16:04:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803915836256257', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@42676640', NULL, 11, NULL, '2022-04-01 16:04:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803915882393602', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254914', NULL, 24, NULL, '2022-04-01 16:04:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803920458379265', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1d607615', NULL, 9, NULL, '2022-04-01 16:04:40', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803920462573569', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@23202e06', NULL, 9, NULL, '2022-04-01 16:04:40', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803920466767873', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@17c70f38', NULL, 10, NULL, '2022-04-01 16:04:40', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803922735886337', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@57a8ae6b', NULL, 6, NULL, '2022-04-01 16:04:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803922740080642', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4f04114e', NULL, 5, NULL, '2022-04-01 16:04:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803929052508161', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508281679451451394, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@717d0cca', NULL, 6, NULL, '2022-04-01 16:04:42', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803929052508162', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2f2de568', NULL, 7, NULL, '2022-04-01 16:04:42', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803929136394242', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508281679451451394, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@72365476', NULL, 5, NULL, '2022-04-01 16:04:42', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803929178337281', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@25dcf7b4', NULL, 6, NULL, '2022-04-01 16:04:42', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803931413901314', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7b1aea86', NULL, 5, NULL, '2022-04-01 16:04:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803931413901313', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293703577305089, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7e301076', NULL, 5, NULL, '2022-04-01 16:04:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803933615910913', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293987569434626, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@11d9a306', NULL, 6, NULL, '2022-04-01 16:04:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803933607522305', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293987569434626, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3bd1d4e4', NULL, 6, NULL, '2022-04-01 16:04:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803947239010306', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1f92b20b', NULL, 5, NULL, '2022-04-01 16:04:46', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803947239010305', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293703577305089, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@21e7cc34', NULL, 5, NULL, '2022-04-01 16:04:46', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803948904148994', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293987569434626, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2456b135', NULL, 5, NULL, '2022-04-01 16:04:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803948904148993', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293987569434626, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5bb23f7a', NULL, 5, NULL, '2022-04-01 16:04:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803950397321218', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293703577305089, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3d3ac04b', NULL, 4, NULL, '2022-04-01 16:04:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803950397321219', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2467446c', NULL, 5, NULL, '2022-04-01 16:04:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803951932436482', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6c98df7e', NULL, 6, NULL, '2022-04-01 16:04:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803951936630786', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508281679451451394, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@562e57b4', NULL, 5, NULL, '2022-04-01 16:04:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803953501106177', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@81ae4ec', NULL, 12, NULL, '2022-04-01 16:04:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803953513689090', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@198266d2', NULL, 13, NULL, '2022-04-01 16:04:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803953513689089', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@454d9efb', NULL, 13, NULL, '2022-04-01 16:04:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803953526272002', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@592d1af0', NULL, 18, NULL, '2022-04-01 16:04:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803953538854914', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@52decadb', NULL, 19, NULL, '2022-04-01 16:04:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803953559826434', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@66fb9ef2', NULL, 24, NULL, '2022-04-01 16:04:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803955799584769', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508281679451451394, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@77bbcb7d', NULL, 7, NULL, '2022-04-01 16:04:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803955816361985', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5ead6a9e', NULL, 11, NULL, '2022-04-01 16:04:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803955812167682', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6eb77e9c', NULL, 9, NULL, '2022-04-01 16:04:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803957376643073', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@dc55e42', NULL, 4, NULL, '2022-04-01 16:04:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803957393420289', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293703577305089, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@222dad74', NULL, 7, NULL, '2022-04-01 16:04:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803958836260865', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293987569434626, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1c921df3', NULL, 5, NULL, '2022-04-01 16:04:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803958836260866', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293987569434626, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@328b7b69', NULL, 5, NULL, '2022-04-01 16:04:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803960086163458', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293703577305089, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@52d7d02d', NULL, 5, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803960094552066', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@41f4169', NULL, 8, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803961289928706', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508281679451451394, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@39613a4c', NULL, 6, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803961289928707', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@670a6e6', NULL, 7, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803963030564865', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@9f1c608', NULL, 9, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803963038953473', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@566d0405', NULL, 11, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803963030564866', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@45d4ab7f', NULL, 8, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803963047342082', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@16559af0', NULL, 13, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803963064119297', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@48a16d0e', NULL, 17, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803963080896513', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@640db289', NULL, 21, NULL, '2022-04-01 16:04:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803965668782081', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@397a987e', NULL, 5, NULL, '2022-04-01 16:04:51', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803965668782082', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508281679451451394, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@515a2e7d', NULL, 4, NULL, '2022-04-01 16:04:51', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803965672976386', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@34740577', NULL, 7, NULL, '2022-04-01 16:04:51', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803968403468290', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293987569434626, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@22ce65b6', NULL, 5, NULL, '2022-04-01 16:04:52', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803968403468291', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293987569434626, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7291fbde', NULL, 5, NULL, '2022-04-01 16:04:52', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803970324459522', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293703577305089, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@56f964a7', NULL, 4, NULL, '2022-04-01 16:04:52', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509803970324459523', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@73522f5e', NULL, 4, NULL, '2022-04-01 16:04:52', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509805720116785154', 1, '用户名: admin,登录成功!', NULL, 'admin', '管理员', '127.0.0.1', NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-01 16:11:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806633510367234', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@63ab18de', NULL, 10, NULL, '2022-04-01 16:15:27', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806749126356994', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@70a3bf6c', NULL, 8, NULL, '2022-04-01 16:15:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806749218631682', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@744f1ffa', NULL, 18, NULL, '2022-04-01 16:15:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806750162350082', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@90cee00', NULL, 13, NULL, '2022-04-01 16:15:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806750200098818', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@77752eaa', NULL, 19, NULL, '2022-04-01 16:15:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806750216876033', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@66cfe1d9', NULL, 23, NULL, '2022-04-01 16:15:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806750216876034', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@e68d206', NULL, 23, NULL, '2022-04-01 16:15:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806750237847553', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@429fc7f4', NULL, 26, NULL, '2022-04-01 16:15:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509806750237847554', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@790ed294', NULL, 27, NULL, '2022-04-01 16:15:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807021219246082', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801019350,\"id\":\"1509807021152137217\",\"isEnable\":\"Y\",\"name\":\"中意合作办学项目\",\"nameen\":\"China&Italy Project\",\"parent\":\"1508293987569434626\"}]', NULL, 20, NULL, '2022-04-01 16:16:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807021563179010', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@449d553f', NULL, 7, NULL, '2022-04-01 16:16:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807071005634561', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801031232,\"id\":\"1509807070959497217\",\"isEnable\":\"N\",\"name\":\"中美合作办学项目\",\"nameen\":\"China&U.S.A Project\",\"parent\":\"1508293987569434626\"}]', NULL, 11, NULL, '2022-04-01 16:17:11', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807071395704833', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4a995d24', NULL, 9, NULL, '2022-04-01 16:17:11', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807132091478017', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801045796,\"id\":\"1509807132049534978\",\"isEnable\":\"Y\",\"name\":\"管理办法\",\"nameen\":\"Management measure\",\"parent\":\"1508294063201124354\"}]', NULL, 11, NULL, '2022-04-01 16:17:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807132443799554', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5733e361', NULL, 9, NULL, '2022-04-01 16:17:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807149359427585', 2, '门户-栏目-编辑', 3, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.edit()', NULL, '[{\"createTime\":1648742400000,\"id\":\"1509807070959497217\",\"isEnable\":\"Y\",\"name\":\"中美合作办学项目\",\"nameen\":\"China&U.S.A Project\",\"parent\":\"1508293987569434626\",\"updateTime\":1648801049911}]', NULL, 14, NULL, '2022-04-01 16:17:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807149665611778', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@67f0ae4f', NULL, 8, NULL, '2022-04-01 16:17:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807215985946626', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801065798,\"id\":\"1509807215944003585\",\"isEnable\":\"Y\",\"name\":\"引智项目\",\"nameen\":\"Conference,project\",\"parent\":\"1508294063201124354\"}]', NULL, 12, NULL, '2022-04-01 16:17:46', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807216350851074', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@78241758', NULL, 8, NULL, '2022-04-01 16:17:46', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807287310086146', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801082805,\"id\":\"1509807287272337409\",\"isEnable\":\"Y\",\"name\":\"管理办法\",\"nameen\":\"Management measure\",\"parent\":\"1508294174937382913\"}]', NULL, 10, NULL, '2022-04-01 16:18:03', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807287666601985', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@17639efc', NULL, 8, NULL, '2022-04-01 16:18:03', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807340246396929', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801095424,\"id\":\"1509807340200259585\",\"isEnable\":\"Y\",\"name\":\"办理流程\",\"nameen\":\"Handling process\",\"parent\":\"1508294174937382913\"}]', NULL, 10, NULL, '2022-04-01 16:18:15', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807340556775425', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@71707a42', NULL, 8, NULL, '2022-04-01 16:18:16', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807422614138882', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7b7a04ba', NULL, 14, NULL, '2022-04-01 16:18:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807422630916098', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508288564728627201', NULL, 16, NULL, '2022-04-01 16:18:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807430059028482', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6881b55c', NULL, 6, NULL, '2022-04-01 16:18:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807430075805698', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@72c91b70', NULL, 9, NULL, '2022-04-01 16:18:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807431128576001', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7e1ed5df', NULL, 9, NULL, '2022-04-01 16:18:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807431166324738', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508288564728627201', NULL, 17, NULL, '2022-04-01 16:18:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807436392427522', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@13d0a3f', NULL, 11, NULL, '2022-04-01 16:18:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807436392427521', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@b76da5e', NULL, 11, NULL, '2022-04-01 16:18:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807436438564866', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@39ddb04b', NULL, 22, NULL, '2022-04-01 16:18:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807436438564867', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6f2fbf54', NULL, 19, NULL, '2022-04-01 16:18:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807436438564865', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@70a47027', NULL, 19, NULL, '2022-04-01 16:18:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807436459536386', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7df71193', NULL, 26, NULL, '2022-04-01 16:18:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807443879260162', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@35d3fc9c', NULL, 6, NULL, '2022-04-01 16:18:40', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807443891843074', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@774cc1c2', NULL, 8, NULL, '2022-04-01 16:18:40', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807445657645057', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@354bd846', NULL, 15, NULL, '2022-04-01 16:18:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807445657645059', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1ef82317', NULL, 13, NULL, '2022-04-01 16:18:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807445653450754', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5bff85c0', NULL, 14, NULL, '2022-04-01 16:18:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807445657645058', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@ac5221', NULL, 11, NULL, '2022-04-01 16:18:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807445678616577', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7c5ce7e3', NULL, 17, NULL, '2022-04-01 16:18:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807445674422273', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@560c5980', NULL, 14, NULL, '2022-04-01 16:18:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807458714513410', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294101805498369, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@52310494', NULL, 4, NULL, '2022-04-01 16:18:44', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807458714513411', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294101805498369, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@9cd3432', NULL, 4, NULL, '2022-04-01 16:18:44', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807458718707713', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@267453f1', NULL, 8, NULL, '2022-04-01 16:18:44', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807476041183234', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294243073851393, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@22ded381', NULL, 5, NULL, '2022-04-01 16:18:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807476041183233', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294243073851393, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1d21a0f1', NULL, 5, NULL, '2022-04-01 16:18:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807477735682051', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294281619505153, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2a43f66d', NULL, 5, NULL, '2022-04-01 16:18:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807477735682050', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@38b0f002', NULL, 5, NULL, '2022-04-01 16:18:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807479153356803', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294315236851714, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@71955e20', NULL, 4, NULL, '2022-04-01 16:18:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807479153356802', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294315236851714, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@34aaf5c4', NULL, 4, NULL, '2022-04-01 16:18:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807560334110722', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801147897,\"id\":\"1509807560283779073\",\"isEnable\":\"Y\",\"name\":\"国际会议\",\"nameen\":\"Conference\",\"parent\":\"1508294101805498369\"}]', NULL, 11, NULL, '2022-04-01 16:19:08', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807560711598081', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@139ff8e4', NULL, 12, NULL, '2022-04-01 16:19:08', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807620279103489', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801162190,\"id\":\"1509807620237160449\",\"isEnable\":\"Y\",\"name\":\"港澳台事务\",\"nameen\":\"HK,Macao,Taiwan\",\"parent\":\"1508294243073851393\"}]', NULL, 10, NULL, '2022-04-01 16:19:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807620639813634', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@609dae76', NULL, 9, NULL, '2022-04-01 16:19:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807679704002562', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801176358,\"id\":\"1509807679662059522\",\"isEnable\":\"Y\",\"name\":\"党建工作\",\"nameen\":\"Party Building\",\"parent\":\"1508294281619505153\"}]', NULL, 10, NULL, '2022-04-01 16:19:36', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807680022769665', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4d8c4414', NULL, 8, NULL, '2022-04-01 16:19:36', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807719520530434', 2, '门户-栏目-添加', 2, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.add()', NULL, '[{\"createTime\":1648801185852,\"id\":\"1509807719482781698\",\"isEnable\":\"Y\",\"name\":\"下载专区\",\"nameen\":\"Download\",\"parent\":\"1508294315236851714\"}]', NULL, 9, NULL, '2022-04-01 16:19:46', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807719818326018', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5f745055', NULL, 7, NULL, '2022-04-01 16:19:46', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807730505412609', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@157fb2a4', NULL, 6, NULL, '2022-04-01 16:19:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807730517995521', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@31a410c9', NULL, 9, NULL, '2022-04-01 16:19:48', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807731440742401', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294315236851714, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7811d60d', NULL, 7, NULL, '2022-04-01 16:19:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807731440742402', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294315236851714, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@55fd52e', NULL, 8, NULL, '2022-04-01 16:19:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509807731482685441', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@315551f', NULL, 16, NULL, '2022-04-01 16:19:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809564871684097', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@64c61007', NULL, 5, NULL, '2022-04-01 16:27:06', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809564892655618', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807679662059522, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@12a3a392', NULL, 10, NULL, '2022-04-01 16:27:06', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809564951375874', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4e68f738', NULL, 6, NULL, '2022-04-01 16:27:06', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809564963958786', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807679662059522, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@bd9ecd', NULL, 7, NULL, '2022-04-01 16:27:06', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809570387193857', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294281619505153, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4f5b9310', NULL, 6, NULL, '2022-04-01 16:27:07', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809570387193858', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@24b283ba', NULL, 6, NULL, '2022-04-01 16:27:07', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809574472445955', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@464bf95', NULL, 4, NULL, '2022-04-01 16:27:08', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809574472445954', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807679662059522, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@77bca676', NULL, 4, NULL, '2022-04-01 16:27:08', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809576473128961', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@d08bb0c', NULL, 5, NULL, '2022-04-01 16:27:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809576477323265', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294281619505153, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@614a0d86', NULL, 6, NULL, '2022-04-01 16:27:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809581997027329', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@57d84d2e', NULL, 5, NULL, '2022-04-01 16:27:10', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509809582001221634', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807679662059522, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@49ef2cc3', NULL, 6, NULL, '2022-04-01 16:27:10', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810884072566786', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294315236851714, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@58d1413d', NULL, 5, NULL, '2022-04-01 16:32:20', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810884097732609', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294315236851714, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@47d5bfd8', NULL, 10, NULL, '2022-04-01 16:32:20', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810884139675649', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294315236851714, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5f783b91', NULL, 5, NULL, '2022-04-01 16:32:20', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810884152258562', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294315236851714, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3460756e', NULL, 5, NULL, '2022-04-01 16:32:20', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810885637042178', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294281619505153, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@76b14de', NULL, 3, NULL, '2022-04-01 16:32:21', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810885637042177', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7bbe8d35', NULL, 3, NULL, '2022-04-01 16:32:21', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810887218294786', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294243073851393, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6ff6d07f', NULL, 5, NULL, '2022-04-01 16:32:21', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810887222489089', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294243073851393, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@b13b731', NULL, 6, NULL, '2022-04-01 16:32:21', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810888707272707', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294174937382913, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6e4eb636', NULL, 6, NULL, '2022-04-01 16:32:21', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810888707272706', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294174937382913, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6181fb0e', NULL, 5, NULL, '2022-04-01 16:32:21', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810890393382913', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294101805498369, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@41537c2e', NULL, 4, NULL, '2022-04-01 16:32:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810890393382914', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294101805498369, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@553f81ea', NULL, 4, NULL, '2022-04-01 16:32:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810891832029185', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294063201124354, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6728ebc7', NULL, 4, NULL, '2022-04-01 16:32:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810891836223489', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508294063201124354, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@304dd04b', NULL, 5, NULL, '2022-04-01 16:32:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810893572665346', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293987569434626, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6d734af7', NULL, 3, NULL, '2022-04-01 16:32:23', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810893572665347', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293987569434626, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6ec24b97', NULL, 4, NULL, '2022-04-01 16:32:23', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810896361877506', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293703577305089, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7821911d', NULL, 3, NULL, '2022-04-01 16:32:23', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810896361877507', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@60316127', NULL, 4, NULL, '2022-04-01 16:32:23', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810897913769986', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508281679451451394, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3997fdf7', NULL, 4, NULL, '2022-04-01 16:32:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810897913769987', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2a9077f7', NULL, 5, NULL, '2022-04-01 16:32:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810900405186561', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4fb107ff', NULL, 16, NULL, '2022-04-01 16:32:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810900421963777', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6c485bcc', NULL, 19, NULL, '2022-04-01 16:32:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810900447129602', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@48f4ae4e', NULL, 12, NULL, '2022-04-01 16:32:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810900480684034', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6e392669', NULL, 30, NULL, '2022-04-01 16:32:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810900480684035', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@68276df5', NULL, 20, NULL, '2022-04-01 16:32:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509810900514238466', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@146ddf29', NULL, 39, NULL, '2022-04-01 16:32:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509813751810486273', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@62d81da', NULL, 8, NULL, '2022-04-01 16:43:44', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509813773847359490', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=null, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@e600b3b', NULL, 9, NULL, '2022-04-01 16:43:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509816656659607554', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5b2d876c', NULL, 7, NULL, '2022-04-01 16:55:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509816677283000322', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1faf51fe', NULL, 7, NULL, '2022-04-01 16:55:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509816692621570050', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=null, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3cfb84a', NULL, 8, NULL, '2022-04-01 16:55:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509816711013593089', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@18ef6fad', NULL, 7, NULL, '2022-04-01 16:55:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825615021862914', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=null, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@945738f', NULL, 8, NULL, '2022-04-01 17:30:52', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825665911353346', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1518676c', NULL, 11, NULL, '2022-04-01 17:31:05', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825667488411650', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=null, fpid=null, fid=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@193e4d0f', NULL, 8, NULL, '2022-04-01 17:31:05', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825759591133185', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@74cf1bf3', NULL, 15, NULL, '2022-04-01 17:31:27', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825759607910402', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 29, NULL, '2022-04-01 17:31:27', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825785507737601', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5b2d47', NULL, 7, NULL, '2022-04-01 17:31:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825785511931905', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2c284ca7', NULL, 8, NULL, '2022-04-01 17:31:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825785524514817', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@17c9e26b', NULL, 11, NULL, '2022-04-01 17:31:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825794747789314', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2f37df46', NULL, 8, NULL, '2022-04-01 17:31:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509825794768760834', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 14, NULL, '2022-04-01 17:31:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509826303630110722', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@124ac8a0', NULL, 6, NULL, '2022-04-01 17:33:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509826303663665153', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@ab3961d', NULL, 15, NULL, '2022-04-01 17:33:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509826304401862657', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1d96097', NULL, 8, NULL, '2022-04-01 17:33:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509826304439611393', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 17, NULL, '2022-04-01 17:33:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509826384852807682', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@20328475', NULL, 8, NULL, '2022-04-01 17:33:56', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509826384877973506', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 13, NULL, '2022-04-01 17:33:56', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509826494902956034', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3b383586', NULL, 9, NULL, '2022-04-01 17:34:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1509826494932316161', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 15, NULL, '2022-04-01 17:34:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550364802809858', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@795b9719', NULL, 78, NULL, '2022-04-06 11:44:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550365020913665', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@390a0de4', NULL, 134, NULL, '2022-04-06 11:44:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550366027546626', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4ec3fd03', NULL, 43, NULL, '2022-04-06 11:44:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550366035935234', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@23969433', NULL, 37, NULL, '2022-04-06 11:44:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550366052712449', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@58f108eb', NULL, 55, NULL, '2022-04-06 11:44:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550366073683970', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3c35fb08', NULL, 51, NULL, '2022-04-06 11:44:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550366086266881', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6df66d83', NULL, 53, NULL, '2022-04-06 11:44:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550366111432706', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@20035fb0', NULL, 69, NULL, '2022-04-06 11:44:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550390274818050', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7b09461a', NULL, 9, NULL, '2022-04-06 11:44:31', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550390308372481', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2875bc7a', NULL, 17, NULL, '2022-04-06 11:44:31', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550392657182722', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@41e4b916', NULL, 13, NULL, '2022-04-06 11:44:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550392690737154', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@11ce49e1', NULL, 24, NULL, '2022-04-06 11:44:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550392694931458', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@14f1295f', NULL, 22, NULL, '2022-04-06 11:44:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550392724291585', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@323e8f8e', NULL, 26, NULL, '2022-04-06 11:44:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550392724291586', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@453b37f7', NULL, 22, NULL, '2022-04-06 11:44:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550392728485889', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@66a2802', NULL, 29, NULL, '2022-04-06 11:44:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550483061211137', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6d332ebb', NULL, 8, NULL, '2022-04-06 11:44:53', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550483086376961', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@44dd0293', NULL, 14, NULL, '2022-04-06 11:44:53', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550484982202369', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1508287d', NULL, 16, NULL, '2022-04-06 11:44:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550484986396674', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@45e706ea', NULL, 23, NULL, '2022-04-06 11:44:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550484986396673', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@38cf398f', NULL, 17, NULL, '2022-04-06 11:44:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550484998979585', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@39e08319', NULL, 20, NULL, '2022-04-06 11:44:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550484994785281', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2a5e6095', NULL, 28, NULL, '2022-04-06 11:44:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1511550485032534017', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1df333bd', NULL, 29, NULL, '2022-04-06 11:44:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512313112849039361', 1, '用户名: 管理员,退出成功!', NULL, 'admin', '管理员', '127.0.0.1', NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-08 14:15:18', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512313188216487938', 1, '用户名: admin,登录成功!', NULL, 'admin', '管理员', '127.0.0.1', NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-08 14:15:36', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512313193140600833', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3bf0d705', NULL, 90, NULL, '2022-04-08 14:15:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512314248511373314', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4032a221', NULL, 25, NULL, '2022-04-08 14:19:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315063011729409', 2, '门户-文章-编辑', 3, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.edit()', NULL, '[{\"author\":\"cscs\",\"columnId\":\"3\",\"content\":\"

cscscscs

\",\"contenten\":\"

啊实打实大三

\",\"cover\":\"temp/banner_1648471837761.png\",\"createTime\":1648396800000,\"files\":\"fujian/604d562fa40ee8e7a846b2b303c6b98b1f1d893a_1649398900692.jpg\",\"filesen\":\"fujianen/604d562fa40ee8e7a846b2b303c6b98b1f1d893a_1649398906385.jpg,fujianen/1f1e86dfff42ca428e79b5e13011d288349c2bf9_1649398915307.png,fujianen/604d562fa40ee8e7a846b2b303c6b98b1f1d893a_1649398974343.jpg\",\"id\":\"1508426630185254913\",\"isRelease\":\"Y\",\"source\":\"cscsc\",\"title\":\"cscs\",\"titleen\":\"csccsc\",\"updateTime\":1649398983098}]', NULL, 32, NULL, '2022-04-08 14:23:03', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315064299380738', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@302d6887', NULL, 123, NULL, '2022-04-08 14:23:03', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315537995685889', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3d101c10', NULL, 21, NULL, '2022-04-08 14:24:56', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315547793580034', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3596549a', NULL, 38, NULL, '2022-04-08 14:24:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315547856494594', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@70413567', NULL, 55, NULL, '2022-04-08 14:24:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315549290946561', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@667544d1', NULL, 48, NULL, '2022-04-08 14:24:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315549290946562', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2d326228', NULL, 47, NULL, '2022-04-08 14:24:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315549416775681', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6f40e07e', NULL, 88, NULL, '2022-04-08 14:24:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315549475495938', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@f5ae1ef', NULL, 51, NULL, '2022-04-08 14:24:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315549475495940', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@337e3bad', NULL, 88, NULL, '2022-04-08 14:24:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512315549475495939', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4f5749a1', NULL, 58, NULL, '2022-04-08 14:24:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512316754402594818', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@604e7140', NULL, 98, NULL, '2022-04-08 14:29:46', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512316754582949889', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@39b023af', NULL, 150, NULL, '2022-04-08 14:29:46', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512316755262427137', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1f36af4b', NULL, 34, NULL, '2022-04-08 14:29:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512316755279204353', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@186d8f99', NULL, 43, NULL, '2022-04-08 14:29:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512316755295981570', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5a438742', NULL, 40, NULL, '2022-04-08 14:29:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512316755321147394', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7a68dbb1', NULL, 54, NULL, '2022-04-08 14:29:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512316755337924610', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@365837a', NULL, 60, NULL, '2022-04-08 14:29:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512316755367284738', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3ae6421e', NULL, 66, NULL, '2022-04-08 14:29:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317134133866498', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4dd29bd6', NULL, 52, NULL, '2022-04-08 14:31:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317134339387393', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6c01e19c', NULL, 107, NULL, '2022-04-08 14:31:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317136201658370', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7ce6e046', NULL, 54, NULL, '2022-04-08 14:31:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317136214241282', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@40e086a2', NULL, 44, NULL, '2022-04-08 14:31:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317136235212801', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@73ae95e7', NULL, 68, NULL, '2022-04-08 14:31:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317136264572930', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6a536455', NULL, 60, NULL, '2022-04-08 14:31:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317136298127362', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@28df3c18', NULL, 78, NULL, '2022-04-08 14:31:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317136298127363', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@75a2a1ee', NULL, 78, NULL, '2022-04-08 14:31:17', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317181277843457', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@733ae49c', NULL, 9, NULL, '2022-04-08 14:31:28', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317181319786498', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5d0f688e', NULL, 18, NULL, '2022-04-08 14:31:28', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317183492435970', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6ceab60d', NULL, 22, NULL, '2022-04-08 14:31:29', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317183496630274', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2979778b', NULL, 18, NULL, '2022-04-08 14:31:29', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317183496630275', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@450d4ebe', NULL, 22, NULL, '2022-04-08 14:31:29', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317183496630276', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4dd02e21', NULL, 22, NULL, '2022-04-08 14:31:29', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317183538573313', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@67db10c7', NULL, 30, NULL, '2022-04-08 14:31:29', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317183551156226', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@414008db', NULL, 29, NULL, '2022-04-08 14:31:29', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317228086276098', 1, '用户名: 管理员,退出成功!', NULL, 'admin', '管理员', '127.0.0.1', NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-08 14:31:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317247455571969', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@56c6184a', NULL, 8, NULL, '2022-04-08 14:31:44', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317247476543490', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2e52795c', NULL, 13, NULL, '2022-04-08 14:31:44', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317250618077185', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@59b33b9c', NULL, 10, NULL, '2022-04-08 14:31:45', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317250634854401', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@722cdcae', NULL, 17, NULL, '2022-04-08 14:31:45', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317250622271490', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@e71f17a', NULL, 11, NULL, '2022-04-08 14:31:45', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317250664214529', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6e225dc6', NULL, 24, NULL, '2022-04-08 14:31:45', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317250685186050', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2252f627', NULL, 26, NULL, '2022-04-08 14:31:45', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512317250701963266', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@68e7af4b', NULL, 27, NULL, '2022-04-08 14:31:45', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318678002667522', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@22a99f2e', NULL, 109, NULL, '2022-04-08 14:37:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318678396932097', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2448ff55', NULL, 213, NULL, '2022-04-08 14:37:25', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318681299390467', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@683688ca', NULL, 52, NULL, '2022-04-08 14:37:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318681299390466', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@530a3dfb', NULL, 55, NULL, '2022-04-08 14:37:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318681349722114', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@fb8ff23', NULL, 32, NULL, '2022-04-08 14:37:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318681349722113', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@312f5a2a', NULL, 67, NULL, '2022-04-08 14:37:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318681362305026', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3266826b', NULL, 72, NULL, '2022-04-08 14:37:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318681383276546', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4629d886', NULL, 43, NULL, '2022-04-08 14:37:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318692800172034', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@149ec6a4', NULL, 21, NULL, '2022-04-08 14:37:29', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318692884058114', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254914', NULL, 39, NULL, '2022-04-08 14:37:29', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318701746622466', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7678cae1', NULL, 12, NULL, '2022-04-08 14:37:31', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318701759205378', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@a29a1a0', NULL, 16, NULL, '2022-04-08 14:37:31', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318701759205377', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@550b366c', NULL, 17, NULL, '2022-04-08 14:37:31', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318707140497410', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@167d196e', NULL, 14, NULL, '2022-04-08 14:37:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318707161468929', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 21, NULL, '2022-04-08 14:37:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318718645473282', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7e316b6b', NULL, 8, NULL, '2022-04-08 14:37:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318718645473281', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@695797b2', NULL, 8, NULL, '2022-04-08 14:37:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318718666444802', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@761e2871', NULL, 13, NULL, '2022-04-08 14:37:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318722596507649', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293863887798274, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5bb23f7a', NULL, 6, NULL, '2022-04-08 14:37:36', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318722596507650', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@12bffde4', NULL, 6, NULL, '2022-04-08 14:37:36', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318722688782338', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508293863887798274, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4cee8e19', NULL, 7, NULL, '2022-04-08 14:37:36', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318722705559553', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293703577305089, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@19d9ff70', NULL, 9, NULL, '2022-04-08 14:37:36', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318727822610435', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293987569434626, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4c83ebb7', NULL, 9, NULL, '2022-04-08 14:37:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318727822610434', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807021152137217, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1f31080e', NULL, 7, NULL, '2022-04-08 14:37:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318727923273729', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807021152137217, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@37aa29e3', NULL, 7, NULL, '2022-04-08 14:37:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318727931662337', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293987569434626, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6c3cea93', NULL, 8, NULL, '2022-04-08 14:37:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318732004331521', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807070959497217, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@39e64ec6', NULL, 6, NULL, '2022-04-08 14:37:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318732012720129', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508293987569434626, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@736d6166', NULL, 7, NULL, '2022-04-08 14:37:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318734231506946', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508282344655482882, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@519bdb0e', NULL, 5, NULL, '2022-04-08 14:37:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318734231506947', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@22471697', NULL, 6, NULL, '2022-04-08 14:37:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318734357336066', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508282344655482882, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7e301076', NULL, 5, NULL, '2022-04-08 14:37:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318734357336065', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6553b27f', NULL, 6, NULL, '2022-04-08 14:37:38', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318737997991937', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5950b958', NULL, 16, NULL, '2022-04-08 14:37:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318738018963457', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@42e99223', NULL, 14, NULL, '2022-04-08 14:37:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318738035740674', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@15955ade', NULL, 20, NULL, '2022-04-08 14:37:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318738052517890', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2acf54fb', NULL, 21, NULL, '2022-04-08 14:37:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318738052517889', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6df4aae8', NULL, 23, NULL, '2022-04-08 14:37:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318738073489409', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1d67a44c', NULL, 30, NULL, '2022-04-08 14:37:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318788686155778', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7da5da13', NULL, 12, NULL, '2022-04-08 14:37:51', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318788723904514', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 22, NULL, '2022-04-08 14:37:51', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318797569691649', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@47b4c968', NULL, 7, NULL, '2022-04-08 14:37:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318797586468865', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@70a0f3dd', NULL, 10, NULL, '2022-04-08 14:37:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318797599051778', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@73d76de4', NULL, 12, NULL, '2022-04-08 14:37:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318800086274049', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6751c694', NULL, 6, NULL, '2022-04-08 14:37:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318800094662658', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@54297eb5', NULL, 7, NULL, '2022-04-08 14:37:54', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318805274628097', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6381497', NULL, 11, NULL, '2022-04-08 14:37:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512318805312376833', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 19, NULL, '2022-04-08 14:37:55', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512319354271272961', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4d4112f0', NULL, 23, NULL, '2022-04-08 14:40:06', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512319354283855873', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 29, NULL, '2022-04-08 14:40:06', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321217502744577', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5942983', NULL, 26, NULL, '2022-04-08 14:47:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321217544687617', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 33, NULL, '2022-04-08 14:47:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321227749429250', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@57d5048c', NULL, 9, NULL, '2022-04-08 14:47:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321227749429251', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@397a987e', NULL, 13, NULL, '2022-04-08 14:47:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321227808149505', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@fbb9159', NULL, 22, NULL, '2022-04-08 14:47:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321231385890818', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6b5419ab', NULL, 10, NULL, '2022-04-08 14:47:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321231432028162', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254914', NULL, 21, NULL, '2022-04-08 14:47:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321235286593538', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5c85290', NULL, 12, NULL, '2022-04-08 14:47:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321235286593539', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7b0961c3', NULL, 10, NULL, '2022-04-08 14:47:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321235299176450', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3fd72cdb', NULL, 15, NULL, '2022-04-08 14:47:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321299618828289', 1, '用户名: admin,登录成功!', NULL, 'admin', '管理员', '127.0.0.1', NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-08 14:47:50', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321327146045441', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@606896c2', NULL, 21, NULL, '2022-04-08 14:47:57', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321395592892417', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@76dabf12', NULL, 8, NULL, '2022-04-08 14:48:13', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321395618058242', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 14, NULL, '2022-04-08 14:48:13', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321599545118721', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=null, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@12284eae', NULL, 15, NULL, '2022-04-08 14:49:02', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321602862813185', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@77677925', NULL, 10, NULL, '2022-04-08 14:49:02', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321620571164674', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4df824ae', NULL, 9, NULL, '2022-04-08 14:49:07', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321809151266817', 2, '国际化配置-编辑', 3, 'admin', '管理员', '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.edit()', NULL, '[{\"createTime\":1648101813000,\"id\":\"1506874335557328898\",\"identification\":\"en\",\"isEnable\":\"Y\",\"name\":\"English\",\"updateBy\":\"admin\",\"updateTime\":1649400591518}]', NULL, 17, NULL, '2022-04-08 14:49:52', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321809453256706', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6282b08e', NULL, 8, NULL, '2022-04-08 14:49:52', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321863643664385', 2, '国际化配置-编辑', 3, 'admin', '管理员', '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.edit()', NULL, '[{\"createTime\":1648101785000,\"id\":\"1506874219039563778\",\"identification\":\"cn\",\"isEnable\":\"Y\",\"name\":\"中文\",\"updateBy\":\"admin\",\"updateTime\":1649400604513}]', NULL, 18, NULL, '2022-04-08 14:50:05', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512321863916294146', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6ecc50e4', NULL, 8, NULL, '2022-04-08 14:50:05', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322258990370817', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6b47279e', NULL, 14, NULL, '2022-04-08 14:51:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322259141365761', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7b81a3da', NULL, 48, NULL, '2022-04-08 14:51:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322263037874177', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@562426b4', NULL, 216, NULL, '2022-04-08 14:51:40', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322263365029889', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 194, NULL, '2022-04-08 14:51:40', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322450191912962', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@875cce5', NULL, 10, NULL, '2022-04-08 14:52:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322450208690178', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@c8ae99c', NULL, 13, NULL, '2022-04-08 14:52:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322450221273089', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@35a1a45f', NULL, 16, NULL, '2022-04-08 14:52:24', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322455120220162', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@37676224', NULL, 11, NULL, '2022-04-08 14:52:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322455149580290', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254914', NULL, 17, NULL, '2022-04-08 14:52:26', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322465165578242', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294281619505153, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@71108120', NULL, 5, NULL, '2022-04-08 14:52:28', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322465165578241', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807679662059522, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@71e70646', NULL, 5, NULL, '2022-04-08 14:52:28', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322465186549761', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2c1b9c8a', NULL, 11, NULL, '2022-04-08 14:52:28', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322473206059009', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807560283779073, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4d8dcfb1', NULL, 7, NULL, '2022-04-08 14:52:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322473252196353', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294101805498369, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7d5927f9', NULL, 4, NULL, '2022-04-08 14:52:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322473285750785', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807560283779073, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@b673ed3', NULL, 5, NULL, '2022-04-08 14:52:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322473323499522', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294101805498369, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@489f56f5', NULL, 4, NULL, '2022-04-08 14:52:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322484228689922', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294063201124354, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3ddfd834', NULL, 6, NULL, '2022-04-08 14:52:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322484224495618', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807132049534978, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@43c50d6c', NULL, 5, NULL, '2022-04-08 14:52:32', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322484291604481', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294063201124354, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@32f44865', NULL, 4, NULL, '2022-04-08 14:52:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322484299993090', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807132049534978, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4769b65c', NULL, 4, NULL, '2022-04-08 14:52:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322488217473026', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294063201124354, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4cbe0806', NULL, 5, NULL, '2022-04-08 14:52:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322488217473025', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807215944003585, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3856c2dc', NULL, 5, NULL, '2022-04-08 14:52:33', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322491879100419', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508282344655482882, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@dc94fb4', NULL, 7, NULL, '2022-04-08 14:52:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322491879100418', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@a7686a', NULL, 8, NULL, '2022-04-08 14:52:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322491958792194', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508281679451451394, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6e8963db', NULL, 5, NULL, '2022-04-08 14:52:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322491967180802', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1508282344655482882, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2eb53198', NULL, 7, NULL, '2022-04-08 14:52:34', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322495431675906', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@71777330', NULL, 13, NULL, '2022-04-08 14:52:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322495469424642', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508288564728627201', NULL, 21, NULL, '2022-04-08 14:52:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322503161778177', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=1509807719482781698, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1bb6c866', NULL, 5, NULL, '2022-04-08 14:52:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322503161778178', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=null, parent=null, isEnable=Y, fpid=1508294315236851714, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7fc9899d', NULL, 5, NULL, '2022-04-08 14:52:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322503165972481', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3ac5b49f', NULL, 7, NULL, '2022-04-08 14:52:37', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322511101595650', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5669b5e0', NULL, 16, NULL, '2022-04-08 14:52:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322511122567170', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7b43d30a', NULL, 23, NULL, '2022-04-08 14:52:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322511168704514', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3f4b1e5e', NULL, 32, NULL, '2022-04-08 14:52:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322511198064641', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@396f784c', NULL, 22, NULL, '2022-04-08 14:52:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322511210647554', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@57b05c7b', NULL, 33, NULL, '2022-04-08 14:52:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322511210647555', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3fa22d4', NULL, 22, NULL, '2022-04-08 14:52:39', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322519876079618', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7ce84316', NULL, 14, NULL, '2022-04-08 14:52:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512322519901245441', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 20, NULL, '2022-04-08 14:52:41', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323135172087810', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5bfcff72', NULL, 12, NULL, '2022-04-08 14:55:08', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323135260168194', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@63a690cd', NULL, 31, NULL, '2022-04-08 14:55:08', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323138678525954', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7261f048', NULL, 22, NULL, '2022-04-08 14:55:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323138783383553', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@14086863', NULL, 47, NULL, '2022-04-08 14:55:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323138804355074', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5e631dbd', NULL, 47, NULL, '2022-04-08 14:55:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323138804355075', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7d37be08', NULL, 54, NULL, '2022-04-08 14:55:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323138842103810', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7ec70924', NULL, 43, NULL, '2022-04-08 14:55:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323138858881025', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6d090018', NULL, 43, NULL, '2022-04-08 14:55:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323152276459522', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1385d63a', NULL, 6, NULL, '2022-04-08 14:55:12', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323152289042433', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7e1ed5df', NULL, 10, NULL, '2022-04-08 14:55:12', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323155673845762', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@47b10f2a', NULL, 10, NULL, '2022-04-08 14:55:13', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323155715788802', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 20, NULL, '2022-04-08 14:55:13', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323290550079490', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@444f0084', NULL, 9, NULL, '2022-04-08 14:55:45', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512323290583633922', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 18, NULL, '2022-04-08 14:55:45', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512324307601690626', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6f2cc99d', NULL, 30, NULL, '2022-04-08 14:59:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512324307748491266', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 50, NULL, '2022-04-08 14:59:47', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512325424599371777', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@268cdea4', NULL, 9, NULL, '2022-04-08 15:04:14', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512325424662286338', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@192797ff', NULL, 24, NULL, '2022-04-08 15:04:14', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512325432505634818', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3422f7aa', NULL, 11, NULL, '2022-04-08 15:04:15', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512325432572743681', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 24, NULL, '2022-04-08 15:04:15', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512325460880101378', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@61b63fc1', NULL, 14, NULL, '2022-04-08 15:04:22', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512326614707965954', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@520c9d58', NULL, 21, NULL, '2022-04-08 15:08:57', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512326614938652674', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@7bb4739e', NULL, 62, NULL, '2022-04-08 15:08:57', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512326662564974594', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@2574b10c', NULL, 10, NULL, '2022-04-08 15:09:09', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512326707246895105', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1534ee0e', NULL, 7, NULL, '2022-04-08 15:09:19', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512326707301421058', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@40b797d7', NULL, 18, NULL, '2022-04-08 15:09:19', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512326753887555585', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@21a27517', NULL, 10, NULL, '2022-04-08 15:09:30', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512327099435290625', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5e5e39b3', NULL, 34, NULL, '2022-04-08 15:10:53', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512327099535953922', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@e63a682', NULL, 46, NULL, '2022-04-08 15:10:53', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512327141206364161', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@12ae383b', NULL, 17, NULL, '2022-04-08 15:11:03', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512327457217810434', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@d8c04c3', NULL, 11, NULL, '2022-04-08 15:12:18', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512327457226199041', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@dfa212b', NULL, 13, NULL, '2022-04-08 15:12:18', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512327528961380353', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@260abcc0', NULL, 6, NULL, '2022-04-08 15:12:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512327528990740481', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6a9f6a63', NULL, 13, NULL, '2022-04-08 15:12:35', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512328169528070145', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@3f9042fb', NULL, 6, NULL, '2022-04-08 15:15:08', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512328169544847362', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@1ffe600d', NULL, 10, NULL, '2022-04-08 15:15:08', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337189961830401', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@e7a6fec', NULL, 16, NULL, '2022-04-08 15:50:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337189991190529', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@542af5f6', NULL, 21, NULL, '2022-04-08 15:50:59', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337196362338306', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@66cfe1d9', NULL, 17, NULL, '2022-04-08 15:51:00', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337196400087041', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@6dc51d56', NULL, 27, NULL, '2022-04-08 15:51:00', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337196429447169', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@f5d59c0', NULL, 29, NULL, '2022-04-08 15:51:00', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337196429447170', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5484e03', NULL, 34, NULL, '2022-04-08 15:51:00', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337196454612994', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@5e9e5c6c', NULL, 40, NULL, '2022-04-08 15:51:00', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337196525916162', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@39e8b71b', NULL, 55, NULL, '2022-04-08 15:51:00', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337207531769857', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4fe92428', NULL, 12, NULL, '2022-04-08 15:51:03', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1512337207565324290', 2, '门户-文章-通过id查询,带栏目', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryArticleById()', NULL, ' id: 1508426630185254913', NULL, 18, NULL, '2022-04-08 15:51:03', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343002734055426', 2, '国际化配置-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.I18nConfigController.queryPageList()', NULL, ' i18NConfig: I18nConfig(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, identification=null, name=null, i18nJson=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4f0daa7b', NULL, 83, NULL, '2022-04-11 10:27:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343002952159234', 2, '门户-栏目-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayColumnController.queryPageList()', NULL, ' gatewayColumn: GatewayColumn(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, nameen=null, type=!!BLANK, parent=null, isEnable=Y, fpid=null, fid=null) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@67136731', NULL, 129, NULL, '2022-04-11 10:27:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343003153485825', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=2, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@11a5c44d', NULL, 174, NULL, '2022-04-11 10:27:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343003153485826', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=3, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 4 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@143ba93', NULL, 172, NULL, '2022-04-11 10:27:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343003153485828', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=首页轮播, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=Y, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 3 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@45679cf9', NULL, 175, NULL, '2022-04-11 10:27:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343003153485827', 2, '基本信息表-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.gatewayCommonController.queryPageList()', NULL, ' gatewayCommon: gatewayCommon(id=1, mailbox=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, heardLogoUrl=null, heardLogoUrlen=null, footerLogoUrl=null, footerLogoUrlen=null, copyright=null, copyrighten=null, mailboxen=null, address=null, addressen=null, recordNumber=null, recordNumberen=null, wechatUrl=null, wechatUrlen=null, homepageUrl=null, homepageUrlen=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@58360fae', NULL, 186, NULL, '2022-04-11 10:27:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343003346423810', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=快速导航, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@553a682d', NULL, 18, NULL, '2022-04-11 10:27:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343003346423811', 2, '门户-友情链接,快速导航-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayLinksController.queryPageList()', NULL, ' gatewayLinks: GatewayLinks(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, name=null, type=友情链接, url=null, urlen=null, title=null, titleen=null, logo=null, logoen=null, isEnable=Y) pageNo: 1 pageSize: -1 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@4273a55e', NULL, 31, NULL, '2022-04-11 10:27:43', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343026251517953', 1, '用户名: 管理员,退出成功!', NULL, 'admin', '管理员', '127.0.0.1', NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-11 10:27:49', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343059348770817', 1, '用户名: admin,登录成功!', NULL, 'admin', '管理员', '127.0.0.1', NULL, NULL, NULL, NULL, NULL, NULL, '2022-04-11 10:27:57', NULL, NULL); +INSERT INTO `sys_log` VALUES ('1513343178559279105', 2, '门户-文章-分页列表查询', 1, NULL, NULL, '127.0.0.1', 'com.nd.gateway.controller.GatewayArticleController.queryPageList()', NULL, ' gatewayArticle: GatewayArticle(id=null, createBy=null, createTime=null, updateBy=null, updateTime=null, sysOrgCode=null, title=null, titleen=null, type=null, columnId=null, cover=null, coveren=null, author=null, authoren=null, source=null, sourceen=null, content=null, contenten=null, files=null, filesen=null, isRelease=null, parentGatewayColumn=null, currentGatewayColumn=null, gatewayColumnList=null) pageNo: 1 pageSize: 10 req: org.apache.shiro.web.servlet.ShiroHttpServletRequest@793d8eec', NULL, 13, NULL, '2022-04-11 10:28:25', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_permission +-- ---------------------------- +DROP TABLE IF EXISTS `sys_permission`; +CREATE TABLE `sys_permission` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id', + `parent_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '父id', + `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单标题', + `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路径', + `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件', + `component_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件名字', + `redirect` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '一级菜单跳转地址', + `menu_type` int(11) NULL DEFAULT NULL COMMENT '菜单类型(0:一级菜单; 1:子菜单:2:按钮权限)', + `perms` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单权限编码', + `perms_type` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '权限策略1显示2禁用', + `sort_no` double(8, 2) NULL DEFAULT NULL COMMENT '菜单排序', + `always_show` tinyint(1) NULL DEFAULT NULL COMMENT '聚合子路由: 1是0否', + `icon` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单图标', + `is_route` tinyint(1) NULL DEFAULT 1 COMMENT '是否路由菜单: 0:不是 1:是(默认值1)', + `is_leaf` tinyint(1) NULL DEFAULT NULL COMMENT '是否叶子节点: 1:是 0:不是', + `keep_alive` tinyint(1) NULL DEFAULT NULL COMMENT '是否缓存该页面: 1:是 0:不是', + `hidden` int(11) NULL DEFAULT 0 COMMENT '是否隐藏路由: 0否,1是', + `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `del_flag` int(11) NULL DEFAULT 0 COMMENT '删除状态 0正常 1已删除', + `rule_flag` int(11) NULL DEFAULT 0 COMMENT '是否添加数据权限1是0否', + `status` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮权限状态(0无效1有效)', + `internal_or_external` tinyint(1) NULL DEFAULT NULL COMMENT '外链菜单打开方式 0/内部打开 1/外部打开', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_prem_pid`(`parent_id`) USING BTREE, + INDEX `index_prem_is_route`(`is_route`) USING BTREE, + INDEX `index_prem_is_leaf`(`is_leaf`) USING BTREE, + INDEX `index_prem_sort_no`(`sort_no`) USING BTREE, + INDEX `index_prem_del_flag`(`del_flag`) USING BTREE, + INDEX `index_menu_type`(`menu_type`) USING BTREE, + INDEX `index_menu_hidden`(`hidden`) USING BTREE, + INDEX `index_menu_status`(`status`) USING BTREE, + INDEX `idx_sp_parent_id`(`parent_id`) USING BTREE, + INDEX `idx_sp_is_route`(`is_route`) USING BTREE, + INDEX `idx_sp_is_leaf`(`is_leaf`) USING BTREE, + INDEX `idx_sp_sort_no`(`sort_no`) USING BTREE, + INDEX `idx_sp_del_flag`(`del_flag`) USING BTREE, + INDEX `idx_sp_menu_type`(`menu_type`) USING BTREE, + INDEX `idx_sp_hidden`(`hidden`) USING BTREE, + INDEX `idx_sp_status`(`status`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '菜单权限表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_permission +-- ---------------------------- +INSERT INTO `sys_permission` VALUES ('00a2a0ae65cdca5e93209cdbde97cbe6', '2e42e3835c2b44ec9f7bc26c146ee531', '成功', '/result/success', 'result/Success', NULL, NULL, 1, NULL, NULL, 1.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('020b06793e4de2eee0007f603000c769', 'f0675b52d89100ee88472b6800754a08', 'ViserChartDemo', '/report/ViserChartDemo', 'jeecg/report/ViserChartDemo', NULL, NULL, 1, NULL, NULL, 3.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-03 19:08:53', 'admin', '2019-04-03 19:08:53', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('024f1fd1283dc632458976463d8984e1', '700b7f95165c46cc7a78bf227aa8fed3', 'Tomcat信息', '/monitor/TomcatInfo', 'modules/monitor/TomcatInfo', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-02 09:44:29', 'admin', '2019-05-07 15:19:10', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('043780fa095ff1b2bec4dc406d76f023', '2a470fc0c3954d9dbb61de6d80846549', '表格合计', '/jeecg/tableTotal', 'jeecg/TableTotal', NULL, NULL, 1, NULL, '1', 3.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-08-14 10:28:46', NULL, NULL, 0, 0, '1', NULL); +INSERT INTO `sys_permission` VALUES ('05b3c82ddb2536a4a5ee1a4c46b5abef', '540a2936940846cb98114ffb0d145cb8', '用户列表', '/list/user-list', 'examples/list/UserList', NULL, NULL, 1, NULL, NULL, 3.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('0620e402857b8c5b605e1ad9f4b89350', '2a470fc0c3954d9dbb61de6d80846549', '异步树列表Demo', '/jeecg/JeecgTreeTable', 'jeecg/JeecgTreeTable', NULL, NULL, 1, NULL, '0', 3.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-05-13 17:30:30', 'admin', '2019-05-13 17:32:17', 0, 0, '1', NULL); +INSERT INTO `sys_permission` VALUES ('078f9558cdeab239aecb2bda1a8ed0d1', 'fb07ca05a3e13674dbf6d3245956da2e', '搜索列表(文章)', '/list/search/article', 'examples/list/TableList', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-02-12 14:00:34', 'admin', '2019-02-12 14:17:54', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('08e6b9dc3c04489c8e1ff2ce6f105aa4', '', '系统监控', '/dashboard3', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 6.00, 0, 'dashboard', 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-03-31 22:19:58', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('0ac2ad938963b6c6d1af25477d5b8b51', '8d4683aacaa997ab86b966b464360338', '代码生成按钮', NULL, NULL, NULL, NULL, 2, 'online:goGenerateCode', '1', 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-06-11 14:20:09', NULL, NULL, 0, 0, '1', NULL); +INSERT INTO `sys_permission` VALUES ('109c78a583d4693ce2f16551b7786786', 'e41b69c57a941a3bbcce45032fe57605', 'Online报表配置', '/online/cgreport', 'modules/online/cgreport/OnlCgreportHeadList', NULL, NULL, 1, NULL, NULL, 2.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-03-08 10:51:07', 'admin', '2019-03-30 19:04:28', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('1166535831146504193', '2a470fc0c3954d9dbb61de6d80846549', '对象存储', '/oss/file', 'modules/oss/OSSFileList', NULL, NULL, 1, NULL, '1', 1.00, 0, '', 1, 1, 0, 0, NULL, 'admin', '2019-08-28 02:19:50', 'admin', '2019-08-28 02:20:57', 0, 0, '1', NULL); +INSERT INTO `sys_permission` VALUES ('1174506953255182338', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '职务管理', '/isystem/position', 'system/SysPositionList', NULL, NULL, 1, NULL, '1', 2.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-09-19 10:14:13', 'admin', '2019-09-19 10:15:22', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1174590283938041857', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '通讯录', '/isystem/addressList', 'system/AddressList', NULL, NULL, 1, NULL, '1', 3.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-09-19 15:45:21', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1192318987661234177', 'e41b69c57a941a3bbcce45032fe57605', '系统编码规则', '/isystem/fillRule', 'system/SysFillRuleList', NULL, NULL, 1, NULL, '1', 3.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-11-07 13:52:53', 'admin', '2020-07-10 16:55:03', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1205097455226462210', '', '大屏设计', '/big/screen', 'layouts/RouteView', NULL, NULL, 0, NULL, '1', 1.10, 0, 'area-chart', 1, 0, 0, 0, NULL, 'admin', '2019-12-12 20:09:58', 'admin', '2020-02-23 23:17:59', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1205098241075453953', '1205097455226462210', '生产销售监控', '{{ window._CONFIG[\'domianURL\'] }}/test/bigScreen/templat/index1', 'layouts/IframePageView', NULL, NULL, 1, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-12-12 20:13:05', 'admin', '2019-12-12 20:15:27', 0, 0, '1', 1); +INSERT INTO `sys_permission` VALUES ('1205306106780364802', '1205097455226462210', '智慧物流监控', '{{ window._CONFIG[\'domianURL\'] }}/test/bigScreen/templat/index2', 'layouts/IframePageView', NULL, NULL, 1, NULL, '1', 2.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-12-13 09:59:04', 'admin', '2019-12-25 09:28:03', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1209731624921534465', 'e41b69c57a941a3bbcce45032fe57605', '多数据源管理', '/isystem/dataSource', 'system/SysDataSourceList', NULL, NULL, 1, NULL, '1', 6.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-12-25 15:04:30', 'admin', '2020-02-23 22:43:37', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1224641973866467330', 'e41b69c57a941a3bbcce45032fe57605', '系统校验规则', '/isystem/checkRule', 'system/SysCheckRuleList', NULL, NULL, 1, NULL, '1', 5.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-11-07 13:52:53', 'admin', '2020-07-10 16:55:12', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1229674163694841857', 'e41b69c57a941a3bbcce45032fe57605', 'AUTO在线表单ERP', '/online/cgformErpList/:code', 'modules/online/cgform/auto/erp/OnlCgformErpList', NULL, NULL, 1, NULL, '1', 5.00, 0, NULL, 1, 1, 0, 1, NULL, 'admin', '2020-02-18 15:49:00', 'admin', '2020-02-18 15:52:25', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1232123780958064642', 'f0675b52d89100ee88472b6800754a08', 'Online报表示例', '/online/cgreport/6c7f59741c814347905a938f06ee003c', 'modules/online/cgreport/auto/OnlCgreportAutoList', NULL, NULL, 1, NULL, '1', 4.00, 0, NULL, 0, 1, 0, 0, NULL, 'admin', '2020-02-25 10:02:56', 'admin', '2020-05-02 15:37:30', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1235823781053313025', 'e41b69c57a941a3bbcce45032fe57605', 'AUTO在线内嵌子表', '/online/cgformInnerTableList/:code', 'modules/online/cgform/auto/innerTable/OnlCgformInnerTableList', NULL, NULL, 1, NULL, '1', 999.00, 0, NULL, 1, 1, 0, 1, NULL, 'admin', '2020-03-06 15:05:24', 'admin', '2020-03-06 15:07:42', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1260922988733255681', '2a470fc0c3954d9dbb61de6d80846549', 'online订单管理', '/online/cgformInnerTableList/56efb74326e74064b60933f6f8af30ea', '111111', NULL, NULL, 1, NULL, '1', 11.00, 0, NULL, 0, 1, 0, 0, NULL, 'admin', '2020-05-14 21:20:42', 'admin', '2020-09-09 15:31:48', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1260923256208216065', '2a470fc0c3954d9dbb61de6d80846549', 'online用户报表', '/online/cgreport/1260179852088135681', '333333', NULL, NULL, 1, NULL, '1', 11.00, 0, NULL, 0, 1, 0, 0, NULL, 'admin', '2020-05-14 21:21:46', 'admin', '2020-09-09 15:31:54', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1260928341675982849', '3f915b2769fc80648e92d04e84ca059d', '添加按钮', NULL, NULL, NULL, NULL, 2, 'user:add', '1', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-05-14 21:41:58', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1260929666434318338', '3f915b2769fc80648e92d04e84ca059d', '用户编辑', NULL, NULL, NULL, NULL, 2, 'user:edit', '1', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-05-14 21:47:14', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1260931366557696001', '3f915b2769fc80648e92d04e84ca059d', '表单性别可见', '', NULL, NULL, NULL, 2, 'user:sex', '1', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-05-14 21:53:59', 'admin', '2020-05-14 21:57:00', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1260933542969458689', '3f915b2769fc80648e92d04e84ca059d', '禁用生日字段', NULL, NULL, NULL, NULL, 2, 'user:form:birthday', '2', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-05-14 22:02:38', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1265162119913824258', '08e6b9dc3c04489c8e1ff2ce6f105aa4', '路由网关', '/isystem/gatewayroute', 'system/SysGatewayRouteList', NULL, NULL, 1, NULL, '1', 0.00, 0, NULL, 1, 1, 0, 0, NULL, NULL, '2020-05-26 14:05:30', 'admin', '2020-09-09 14:47:52', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1280350452934307841', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '租户管理', '/isys/tenant', 'system/TenantList', NULL, NULL, 1, NULL, '1', 10.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-07-07 11:58:30', 'admin', '2020-07-10 15:46:35', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1280464606292099074', '2a470fc0c3954d9dbb61de6d80846549', '图片裁剪', '/jeecg/ImagCropper', 'jeecg/ImagCropper', NULL, NULL, 1, NULL, '1', 9.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-07-07 19:32:06', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1287715272999944193', '2a470fc0c3954d9dbb61de6d80846549', 'JVXETable示例', '/jeecg/j-vxe-table-demo', 'layouts/RouteView', NULL, NULL, 1, NULL, '1', 0.10, 0, '', 1, 0, 0, 0, NULL, 'admin', '2020-07-27 19:43:40', 'admin', '2020-09-09 14:52:06', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1287715783966834689', '1287715272999944193', '普通示例', '/jeecg/j-vxe-table-demo/normal', 'jeecg/JVXETableDemo', NULL, NULL, 1, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-07-27 19:45:42', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1287716451494510593', '1287715272999944193', '布局模板', '/jeecg/j-vxe-table-demo/layout', 'jeecg/JVxeDemo/layout-demo/Index', NULL, NULL, 1, NULL, '1', 2.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-07-27 19:48:21', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1287718919049691137', '1287715272999944193', '即时保存', '/jeecg/j-vxe-table-demo/jsbc', 'jeecg/JVxeDemo/demo/JSBCDemo', NULL, NULL, 1, NULL, '1', 3.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-07-27 19:57:36', 'admin', '2020-07-27 20:03:37', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1287718938179911682', '1287715272999944193', '弹出子表', '/jeecg/j-vxe-table-demo/tczb', 'jeecg/JVxeDemo/demo/PopupSubTable', NULL, NULL, 1, NULL, '1', 4.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-07-27 19:57:41', 'admin', '2020-07-27 20:03:47', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1287718956957810689', '1287715272999944193', '无痕刷新', '/jeecg/j-vxe-table-demo/whsx', 'jeecg/JVxeDemo/demo/SocketReload', NULL, NULL, 1, NULL, '1', 5.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2020-07-27 19:57:44', 'admin', '2020-07-27 20:03:57', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1304032910990495745', 'e41b69c57a941a3bbcce45032fe57605', 'AUTO在线表单TAB', '/online/cgformTabList/:code', 'modules/online/cgform/auto/tab/OnlCgformTabList', NULL, NULL, 1, NULL, '1', 8.00, 0, NULL, 1, 1, 0, 1, NULL, 'admin', '2020-09-10 20:24:08', 'admin', '2020-09-10 20:36:37', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('13212d3416eb690c2e1d5033166ff47a', '2e42e3835c2b44ec9f7bc26c146ee531', '失败', '/result/fail', 'result/Error', NULL, NULL, 1, NULL, NULL, 2.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('1367a93f2c410b169faa7abcbad2f77c', '6e73eb3c26099c191bf03852ee1310a1', '基本设置', '/account/settings/BaseSetting', 'account/settings/BaseSetting', 'account-settings-base', NULL, 1, 'BaseSettings', NULL, NULL, 0, NULL, 1, 1, NULL, 1, NULL, NULL, '2018-12-26 18:58:35', 'admin', '2019-03-20 12:57:31', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('1506850882536177665', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '国际化配置', '/i18nConfig', 'modules/nd/I18nConfigList', NULL, NULL, 1, NULL, '1', 100.00, 0, 'global', 1, 1, 0, 0, NULL, 'admin', '2022-03-24 12:30:21', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1506851094671491074', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '网站设置', '/commonConfig', 'modules/nd/gatewayCommonList', NULL, NULL, 1, NULL, '1', 99.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2022-03-24 12:31:12', 'admin', '2022-03-24 13:52:21', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1507599354151321601', '', '门户管理', '/gateway', 'layouts/RouteView', NULL, NULL, 0, NULL, '1', 1.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2022-03-26 14:04:31', 'admin', '2022-03-26 14:04:46', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1507599736818647042', '1507599354151321601', '栏目管理', '/gateway/GatewayColumnList', 'modules/nd/GatewayColumnList', NULL, NULL, 1, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2022-03-26 14:06:02', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1507599887117336577', '1507599354151321601', '文章管理', '/gateway/GatewayArticleList', 'modules/nd/GatewayArticleList', NULL, NULL, 1, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2022-03-26 14:06:38', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('1507600010484400130', '1507599354151321601', '友情链接管理', '/gateway/GatewayLinksList', 'modules/nd/GatewayLinksList', NULL, NULL, 1, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2022-03-26 14:07:07', NULL, NULL, 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('190c2b43bec6a5f7a4194a85db67d96a', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '角色管理', '/isystem/roleUserList', 'system/RoleUserList', NULL, NULL, 1, NULL, NULL, 1.20, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-04-17 15:13:56', 'admin', '2019-12-25 09:36:31', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('1a0811914300741f4e11838ff37a1d3a', '3f915b2769fc80648e92d04e84ca059d', '手机号禁用', NULL, NULL, NULL, NULL, 2, 'user:form:phone', '2', 1.00, 0, NULL, 0, 1, NULL, 0, NULL, 'admin', '2019-05-11 17:19:30', 'admin', '2019-05-11 18:00:22', 0, 0, '1', NULL); +INSERT INTO `sys_permission` VALUES ('200006f0edf145a2b50eacca07585451', 'fb07ca05a3e13674dbf6d3245956da2e', '搜索列表(应用)', '/list/search/application', 'examples/list/TableList', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-02-12 14:02:51', 'admin', '2019-02-12 14:14:01', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('22d6a3d39a59dd7ea9a30acfa6bfb0a5', 'e41b69c57a941a3bbcce45032fe57605', 'AUTO动态表单', '/online/df/:table/:id', 'modules/online/cgform/auto/OnlineDynamicForm', NULL, NULL, 1, NULL, NULL, 9.00, 0, NULL, 0, 1, NULL, 1, NULL, 'admin', '2019-04-22 15:15:43', 'admin', '2019-04-30 18:18:26', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('265de841c58907954b8877fb85212622', '2a470fc0c3954d9dbb61de6d80846549', '图片拖拽排序', '/jeecg/imgDragSort', 'jeecg/ImgDragSort', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-25 10:43:08', 'admin', '2019-04-25 10:46:26', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('277bfabef7d76e89b33062b16a9a5020', 'e3c13679c73a4f829bcff2aba8fd68b1', '基础表单', '/form/base-form', 'examples/form/BasicForm', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-02-26 17:02:08', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('2a470fc0c3954d9dbb61de6d80846549', '', '常见案例', '/jeecg', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 7.00, 0, 'qrcode', 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-04-02 11:46:42', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('2aeddae571695cd6380f6d6d334d6e7d', 'f0675b52d89100ee88472b6800754a08', '布局统计报表', '/report/ArchivesStatisticst', 'jeecg/report/ArchivesStatisticst', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-03 18:32:48', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('2dbbafa22cda07fa5d169d741b81fe12', '08e6b9dc3c04489c8e1ff2ce6f105aa4', '在线文档', '{{ window._CONFIG[\'domianURL\'] }}/doc.html', 'layouts/IframePageView', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-01-30 10:00:01', 'admin', '2020-09-09 14:48:58', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('2e42e3835c2b44ec9f7bc26c146ee531', '', '结果页', '/result', 'layouts/PageView', NULL, NULL, 0, NULL, NULL, 8.00, 0, 'check-circle-o', 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-04-02 11:46:56', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('339329ed54cf255e1f9392e84f136901', '2a470fc0c3954d9dbb61de6d80846549', 'helloworld', '/jeecg/helloworld', 'jeecg/helloworld', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-02-15 16:24:56', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('3f915b2769fc80648e92d04e84ca059d', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '用户管理', '/isystem/user', 'system/UserList', NULL, NULL, 1, NULL, NULL, 1.10, 0, NULL, 1, 0, 0, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-12-25 09:36:24', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('3fac0d3c9cd40fa53ab70d4c583821f8', '2a470fc0c3954d9dbb61de6d80846549', '分屏', '/jeecg/splitPanel', 'jeecg/SplitPanel', NULL, NULL, 1, NULL, NULL, 6.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-25 16:27:06', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('4148ec82b6acd69f470bea75fe41c357', '2a470fc0c3954d9dbb61de6d80846549', '单表模型示例', '/jeecg/jeecgDemoList', 'jeecg/JeecgDemoList', 'DemoList', NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, 0, 0, NULL, NULL, '2018-12-28 15:57:30', 'jeecg', '2020-05-14 22:09:34', 0, 1, NULL, 0); +INSERT INTO `sys_permission` VALUES ('418964ba087b90a84897b62474496b93', '540a2936940846cb98114ffb0d145cb8', '查询表格', '/list/query-list', 'examples/list/TableList', NULL, NULL, 1, NULL, NULL, 1.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('4356a1a67b564f0988a484f5531fd4d9', '2a470fc0c3954d9dbb61de6d80846549', '内嵌Table', '/jeecg/TableExpandeSub', 'jeecg/TableExpandeSub', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-04 22:48:13', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('45c966826eeff4c99b8f8ebfe74511fc', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '部门管理', '/isystem/depart', 'system/DepartList', NULL, NULL, 1, NULL, NULL, 1.40, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-01-29 18:47:40', 'admin', '2019-12-25 09:36:47', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('4875ebe289344e14844d8e3ea1edd73f', '', '详情页', '/profile', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 8.00, 0, 'profile', 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-04-02 11:46:48', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('4f66409ef3bbd69c1d80469d6e2a885e', '6e73eb3c26099c191bf03852ee1310a1', '账户绑定', '/account/settings/binding', 'account/settings/Binding', NULL, NULL, 1, 'BindingSettings', NULL, NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-26 19:01:20', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('4f84f9400e5e92c95f05b554724c2b58', '540a2936940846cb98114ffb0d145cb8', '角色列表', '/list/role-list', 'examples/list/RoleList', NULL, NULL, 1, NULL, NULL, 4.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('53a9230444d33de28aa11cc108fb1dba', '5c8042bd6c601270b2bbd9b20bccc68b', '我的消息', '/isps/userAnnouncement', 'system/UserAnnouncementList', NULL, NULL, 1, NULL, NULL, 3.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-04-19 10:16:00', 'admin', '2019-12-25 09:54:34', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('54097c6a3cf50fad0793a34beff1efdf', 'e41b69c57a941a3bbcce45032fe57605', 'AUTO在线表单', '/online/cgformList/:code', 'modules/online/cgform/auto/OnlCgformAutoList', NULL, NULL, 1, NULL, NULL, 9.00, 0, NULL, 1, 1, NULL, 1, NULL, 'admin', '2019-03-19 16:03:06', 'admin', '2019-04-30 18:19:03', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('540a2936940846cb98114ffb0d145cb8', '', '列表页', '/list', 'layouts/PageView', NULL, '/list/query-list', 0, NULL, NULL, 9.00, 0, 'table', 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-03-31 22:20:20', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('54dd5457a3190740005c1bfec55b1c34', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '菜单管理', '/isystem/permission', 'system/PermissionList', NULL, NULL, 1, NULL, NULL, 1.30, 0, NULL, 1, 1, 0, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-12-25 09:36:39', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('58857ff846e61794c69208e9d3a85466', '08e6b9dc3c04489c8e1ff2ce6f105aa4', '日志管理', '/isystem/log', 'system/LogList', NULL, NULL, 1, NULL, NULL, 2.00, 0, '', 1, 1, 0, 0, NULL, NULL, '2018-12-26 10:11:18', 'admin', '2020-09-09 14:48:25', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('58b9204feaf07e47284ddb36cd2d8468', '2a470fc0c3954d9dbb61de6d80846549', '图片翻页', '/jeecg/imgTurnPage', 'jeecg/ImgTurnPage', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-25 11:36:42', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('5c2f42277948043026b7a14692456828', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '我的部门', '/isystem/departUserList', 'system/DepartUserList', NULL, NULL, 1, NULL, NULL, 2.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-04-17 15:12:24', 'admin', '2019-12-25 09:35:26', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('5c8042bd6c601270b2bbd9b20bccc68b', '', '消息中心', '/message', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 6.00, 0, 'message', 1, 0, NULL, 0, NULL, 'admin', '2019-04-09 11:05:04', 'admin', '2019-04-11 19:47:54', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('6531cf3421b1265aeeeabaab5e176e6d', 'e3c13679c73a4f829bcff2aba8fd68b1', '分步表单', '/form/step-form', 'examples/form/stepForm/StepForm', NULL, NULL, 1, NULL, NULL, 2.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('655563cd64b75dcf52ef7bcdd4836953', '2a470fc0c3954d9dbb61de6d80846549', '图片预览', '/jeecg/ImagPreview', 'jeecg/ImagPreview', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-17 11:18:45', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('65a8f489f25a345836b7f44b1181197a', 'c65321e57b7949b7a975313220de0422', '403', '/exception/403', 'exception/403', NULL, NULL, 1, NULL, NULL, 1.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('6ad53fd1b220989a8b71ff482d683a5a', '2a470fc0c3954d9dbb61de6d80846549', '一对多Tab示例', '/jeecg/tablist/JeecgOrderDMainList', 'jeecg/tablist/JeecgOrderDMainList', NULL, NULL, 1, NULL, NULL, 2.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-02-20 14:45:09', 'admin', '2019-02-21 16:26:21', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('6e73eb3c26099c191bf03852ee1310a1', '717f6bee46f44a3897eca9abd6e2ec44', '个人设置', '/account/settings/BaseSetting', 'account/settings/Index', NULL, NULL, 1, NULL, NULL, 2.00, 1, NULL, 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-04-19 09:41:05', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('700b7f95165c46cc7a78bf227aa8fed3', '08e6b9dc3c04489c8e1ff2ce6f105aa4', '性能监控', '/monitor', 'layouts/RouteView', NULL, NULL, 1, NULL, NULL, 3.00, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2019-04-02 11:34:34', 'admin', '2020-09-09 14:48:51', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('717f6bee46f44a3897eca9abd6e2ec44', '', '个人页', '/account', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 9.00, 0, 'user', 1, 0, 0, 1, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2020-02-23 22:41:37', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('73678f9daa45ed17a3674131b03432fb', '540a2936940846cb98114ffb0d145cb8', '权限列表', '/list/permission-list', 'examples/list/PermissionList', NULL, NULL, 1, NULL, NULL, 5.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('7960961b0063228937da5fa8dd73d371', '2a470fc0c3954d9dbb61de6d80846549', 'JEditableTable示例', '/jeecg/JEditableTable', 'jeecg/JeecgEditableTableExample', NULL, NULL, 1, NULL, NULL, 2.10, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-03-22 15:22:18', 'admin', '2019-12-25 09:48:16', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('7ac9eb9ccbde2f7a033cd4944272bf1e', '540a2936940846cb98114ffb0d145cb8', '卡片列表', '/list/card', 'examples/list/CardList', NULL, NULL, 1, NULL, NULL, 7.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('841057b8a1bef8f6b4b20f9a618a7fa6', '08e6b9dc3c04489c8e1ff2ce6f105aa4', '数据日志', '/sys/dataLog-list', 'system/DataLogList', NULL, NULL, 1, NULL, NULL, 2.10, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-03-11 19:26:49', 'admin', '2020-09-09 14:48:32', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('882a73768cfd7f78f3a37584f7299656', '6e73eb3c26099c191bf03852ee1310a1', '个性化设置', '/account/settings/custom', 'account/settings/Custom', NULL, NULL, 1, 'CustomSettings', NULL, NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-26 19:00:46', NULL, '2018-12-26 21:13:25', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('8b3bff2eee6f1939147f5c68292a1642', '700b7f95165c46cc7a78bf227aa8fed3', '服务器信息', '/monitor/SystemInfo', 'modules/monitor/SystemInfo', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-02 11:39:19', 'admin', '2019-04-02 15:40:02', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('8d1ebd663688965f1fd86a2f0ead3416', '700b7f95165c46cc7a78bf227aa8fed3', 'Redis监控', '/monitor/redis/info', 'modules/monitor/RedisInfo', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-02 13:11:33', 'admin', '2019-05-07 15:18:54', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('8d4683aacaa997ab86b966b464360338', 'e41b69c57a941a3bbcce45032fe57605', 'Online表单开发', '/online/cgform', 'modules/online/cgform/OnlCgformHeadList', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 0, NULL, 0, NULL, 'admin', '2019-03-12 15:48:14', 'admin', '2019-06-11 14:19:17', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('8fb8172747a78756c11916216b8b8066', '717f6bee46f44a3897eca9abd6e2ec44', '工作台', '/dashboard/workplace', 'dashboard/Workplace', NULL, NULL, 1, NULL, NULL, 3.00, 0, NULL, 1, 1, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-04-02 11:45:02', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('944abf0a8fc22fe1f1154a389a574154', '5c8042bd6c601270b2bbd9b20bccc68b', '消息管理', '/modules/message/sysMessageList', 'modules/message/SysMessageList', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-09 11:27:53', 'admin', '2019-04-09 19:31:23', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('9502685863ab87f0ad1134142788a385', '', '首页', '/dashboard/analysis', 'dashboard/Analysis', NULL, NULL, 0, NULL, NULL, 0.00, 0, 'home', 1, 1, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-03-29 11:04:13', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('97c8629abc7848eccdb6d77c24bb3ebb', '700b7f95165c46cc7a78bf227aa8fed3', '磁盘监控', '/monitor/Disk', 'modules/monitor/DiskMonitoring', NULL, NULL, 1, NULL, NULL, 6.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-25 14:30:06', 'admin', '2019-05-05 14:37:14', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('9a90363f216a6a08f32eecb3f0bf12a3', '2a470fc0c3954d9dbb61de6d80846549', '自定义组件', '/jeecg/SelectDemo', 'jeecg/SelectDemo', NULL, NULL, 1, NULL, NULL, 0.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-03-19 11:19:05', 'admin', '2019-12-25 09:47:04', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('9cb91b8851db0cf7b19d7ecc2a8193dd', '1939e035e803a99ceecb6f5563570fb2', '我的任务表单', '/modules/bpm/task/form/FormModule', 'modules/bpm/task/form/FormModule', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-03-08 16:49:05', 'admin', '2019-03-08 18:37:56', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('9fe26464838de2ea5e90f2367e35efa0', 'e41b69c57a941a3bbcce45032fe57605', 'AUTO在线报表', '/online/cgreport/:code', 'modules/online/cgreport/auto/OnlCgreportAutoList', 'onlineAutoList', NULL, 1, NULL, NULL, 9.00, 0, NULL, 1, 1, NULL, 1, NULL, 'admin', '2019-03-12 11:06:48', 'admin', '2019-04-30 18:19:10', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('a400e4f4d54f79bf5ce160ae432231af', '2a470fc0c3954d9dbb61de6d80846549', '百度', 'http://www.baidu.com', 'layouts/IframePageView', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-01-29 19:44:06', 'admin', '2019-02-15 16:25:02', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('ae4fed059f67086fd52a73d913cf473d', '540a2936940846cb98114ffb0d145cb8', '内联编辑表格', '/list/edit-table', 'examples/list/TableInnerEditList', NULL, NULL, 1, NULL, NULL, 2.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('aedbf679b5773c1f25e9f7b10111da73', '08e6b9dc3c04489c8e1ff2ce6f105aa4', 'SQL监控', '{{ window._CONFIG[\'domianURL\'] }}/druid/', 'layouts/IframePageView', NULL, NULL, 1, NULL, NULL, 3.00, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-01-30 09:43:22', 'admin', '2020-09-09 14:48:38', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('b1cb0a3fedf7ed0e4653cb5a229837ee', '08e6b9dc3c04489c8e1ff2ce6f105aa4', '定时任务', '/isystem/QuartzJobList', 'system/QuartzJobList', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, 0, 0, NULL, NULL, '2019-01-03 09:38:52', 'admin', '2020-09-09 14:48:16', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('b3c824fc22bd953e2eb16ae6914ac8f9', '4875ebe289344e14844d8e3ea1edd73f', '高级详情页', '/profile/advanced', 'examples/profile/advanced/Advanced', NULL, NULL, 1, NULL, NULL, 2.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('b4dfc7d5dd9e8d5b6dd6d4579b1aa559', 'c65321e57b7949b7a975313220de0422', '500', '/exception/500', 'exception/500', NULL, NULL, 1, NULL, NULL, 3.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('b6bcee2ccc854052d3cc3e9c96d90197', '71102b3b87fb07e5527bbd2c530dd90a', '加班申请', '/modules/extbpm/joa/JoaOvertimeList', 'modules/extbpm/joa/JoaOvertimeList', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-03 15:33:10', 'admin', '2019-04-03 15:34:48', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('c431130c0bc0ec71b0a5be37747bb36a', '2a470fc0c3954d9dbb61de6d80846549', '一对多JEditable', '/jeecg/JeecgOrderMainListForJEditableTable', 'jeecg/JeecgOrderMainListForJEditableTable', NULL, NULL, 1, NULL, NULL, 3.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-03-29 10:51:59', 'admin', '2019-04-04 20:09:39', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('c65321e57b7949b7a975313220de0422', NULL, '异常页', '/exception', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 8.00, NULL, 'warning', 1, 0, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('c6cf95444d80435eb37b2f9db3971ae6', '2a470fc0c3954d9dbb61de6d80846549', '数据回执模拟', '/jeecg/InterfaceTest', 'jeecg/InterfaceTest', NULL, NULL, 1, NULL, NULL, 6.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-02-19 16:02:23', 'admin', '2019-02-21 16:25:45', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('cc50656cf9ca528e6f2150eba4714ad2', '4875ebe289344e14844d8e3ea1edd73f', '基础详情页', '/profile/basic', 'examples/profile/basic/Index', NULL, NULL, 1, NULL, NULL, 1.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('d07a2c87a451434c99ab06296727ec4f', '700b7f95165c46cc7a78bf227aa8fed3', 'JVM信息', '/monitor/JvmInfo', 'modules/monitor/JvmInfo', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-01 23:07:48', 'admin', '2019-04-02 11:37:16', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('d2bbf9ebca5a8fa2e227af97d2da7548', 'c65321e57b7949b7a975313220de0422', '404', '/exception/404', 'exception/404', NULL, NULL, 1, NULL, NULL, 2.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('d7d6e2e4e2934f2c9385a623fd98c6f3', '', '系统管理', '/isystem', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 4.00, 0, 'setting', 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-03-31 22:19:52', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('d86f58e7ab516d3bc6bfb1fe10585f97', '717f6bee46f44a3897eca9abd6e2ec44', '个人中心', '/account/center', 'account/center/Index', NULL, NULL, 1, NULL, NULL, 1.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('de13e0f6328c069748de7399fcc1dbbd', 'fb07ca05a3e13674dbf6d3245956da2e', '搜索列表(项目)', '/list/search/project', 'examples/list/TableList', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-02-12 14:01:40', 'admin', '2019-02-12 14:14:18', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('e08cb190ef230d5d4f03824198773950', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '系统通告', '/isystem/annountCement', 'system/SysAnnouncementList', NULL, NULL, 1, 'annountCement', NULL, 6.00, NULL, '', 1, 1, NULL, NULL, NULL, NULL, '2019-01-02 17:23:01', NULL, '2019-01-02 17:31:23', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('e1979bb53e9ea51cecc74d86fd9d2f64', '2a470fc0c3954d9dbb61de6d80846549', 'PDF预览', '/jeecg/jeecgPdfView', 'jeecg/JeecgPdfView', NULL, NULL, 1, NULL, NULL, 3.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-25 10:39:35', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('e3c13679c73a4f829bcff2aba8fd68b1', '', '表单页', '/form', 'layouts/PageView', NULL, NULL, 0, NULL, NULL, 9.00, 0, 'form', 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-03-31 22:20:14', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('e41b69c57a941a3bbcce45032fe57605', '', '在线开发', '/online', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 5.00, 0, 'cloud', 1, 0, NULL, 0, NULL, 'admin', '2019-03-08 10:43:10', 'admin', '2019-05-11 10:36:01', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('e5973686ed495c379d829ea8b2881fc6', 'e3c13679c73a4f829bcff2aba8fd68b1', '高级表单', '/form/advanced-form', 'examples/form/advancedForm/AdvancedForm', NULL, NULL, 1, NULL, NULL, 3.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('e6bfd1fcabfd7942fdd05f076d1dad38', '2a470fc0c3954d9dbb61de6d80846549', '打印测试', '/jeecg/PrintDemo', 'jeecg/PrintDemo', NULL, NULL, 1, NULL, NULL, 3.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-02-19 15:58:48', 'admin', '2019-05-07 20:14:39', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('ebb9d82ea16ad864071158e0c449d186', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '分类字典', '/isys/category', 'system/SysCategoryList', NULL, NULL, 1, NULL, '1', 5.20, 0, NULL, 1, 1, 0, 0, NULL, 'admin', '2019-05-29 18:48:07', 'admin', '2020-02-23 22:45:33', 0, 0, '1', 0); +INSERT INTO `sys_permission` VALUES ('ec8d607d0156e198b11853760319c646', '6e73eb3c26099c191bf03852ee1310a1', '安全设置', '/account/settings/security', 'account/settings/Security', NULL, NULL, 1, 'SecuritySettings', NULL, NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-26 18:59:52', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('f0675b52d89100ee88472b6800754a08', '', '统计报表', '/report', 'layouts/RouteView', NULL, NULL, 0, NULL, NULL, 1.00, 0, 'bar-chart', 1, 0, NULL, 0, NULL, 'admin', '2019-04-03 18:32:02', 'admin', '2019-05-19 18:34:13', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('f1cb187abf927c88b89470d08615f5ac', 'd7d6e2e4e2934f2c9385a623fd98c6f3', '数据字典', '/isystem/dict', 'system/DictList', NULL, NULL, 1, NULL, NULL, 5.00, 0, NULL, 1, 1, 0, 0, NULL, NULL, '2018-12-28 13:54:43', 'admin', '2020-02-23 22:45:25', 0, 0, NULL, 0); +INSERT INTO `sys_permission` VALUES ('f23d9bfff4d9aa6b68569ba2cff38415', '540a2936940846cb98114ffb0d145cb8', '标准列表', '/list/basic-list', 'examples/list/StandardList', NULL, NULL, 1, NULL, NULL, 6.00, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, '2018-12-25 20:34:38', NULL, NULL, 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('f2849d3814fc97993bfc519ae6bbf049', 'e41b69c57a941a3bbcce45032fe57605', 'AUTO复制表单', '/online/copyform/:code', 'modules/online/cgform/OnlCgformCopyList', NULL, NULL, 1, NULL, '1', 1.00, 0, NULL, 1, 1, 0, 1, NULL, 'admin', '2019-08-29 16:05:37', NULL, NULL, 0, 0, '1', NULL); +INSERT INTO `sys_permission` VALUES ('f780d0d3083d849ccbdb1b1baee4911d', '5c8042bd6c601270b2bbd9b20bccc68b', '模板管理', '/modules/message/sysMessageTemplateList', 'modules/message/SysMessageTemplateList', NULL, NULL, 1, NULL, NULL, 1.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-09 11:50:31', 'admin', '2019-04-12 10:16:34', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('fb07ca05a3e13674dbf6d3245956da2e', '540a2936940846cb98114ffb0d145cb8', '搜索列表', '/list/search', 'examples/list/search/SearchLayout', NULL, '/list/search/article', 1, NULL, NULL, 8.00, 0, NULL, 1, 0, NULL, 0, NULL, NULL, '2018-12-25 20:34:38', 'admin', '2019-02-12 15:09:13', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('fb367426764077dcf94640c843733985', '2a470fc0c3954d9dbb61de6d80846549', '一对多示例', '/jeecg/JeecgOrderMainList', 'jeecg/JeecgOrderMainList', NULL, NULL, 1, NULL, NULL, 2.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-02-15 16:24:11', 'admin', '2019-02-18 10:50:14', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('fba41089766888023411a978d13c0aa4', 'e41b69c57a941a3bbcce45032fe57605', 'AUTO树表单列表', '/online/cgformTreeList/:code', 'modules/online/cgform/auto/OnlCgformTreeList', NULL, NULL, 1, NULL, '1', 9.00, 0, NULL, 1, 1, NULL, 1, NULL, 'admin', '2019-05-21 14:46:50', 'admin', '2019-06-11 13:52:52', 0, 0, '1', NULL); +INSERT INTO `sys_permission` VALUES ('fc810a2267dd183e4ef7c71cc60f4670', '700b7f95165c46cc7a78bf227aa8fed3', '请求追踪', '/monitor/HttpTrace', 'modules/monitor/HttpTrace', NULL, NULL, 1, NULL, NULL, 4.00, 0, NULL, 1, 1, NULL, 0, NULL, 'admin', '2019-04-02 09:46:19', 'admin', '2019-04-02 11:37:27', 0, 0, NULL, NULL); +INSERT INTO `sys_permission` VALUES ('fedfbf4420536cacc0218557d263dfea', '6e73eb3c26099c191bf03852ee1310a1', '新消息通知', '/account/settings/notification', 'account/settings/Notification', NULL, NULL, 1, 'NotificationSettings', NULL, NULL, NULL, '', 1, 1, NULL, NULL, NULL, NULL, '2018-12-26 19:02:05', NULL, NULL, 0, 0, NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_permission_data_rule +-- ---------------------------- +DROP TABLE IF EXISTS `sys_permission_data_rule`; +CREATE TABLE `sys_permission_data_rule` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', + `permission_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单ID', + `rule_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规则名称', + `rule_column` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段', + `rule_conditions` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '条件', + `rule_value` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规则值', + `status` varchar(3) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限有效状态1有0否', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_fucntionid`(`permission_id`) USING BTREE, + INDEX `idx_spdr_permission_id`(`permission_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_permission_data_rule +-- ---------------------------- +INSERT INTO `sys_permission_data_rule` VALUES ('1260935285157511170', '4148ec82b6acd69f470bea75fe41c357', 'createBy', 'createBy', '=', '#{sys_user_code}', '0', '2020-05-14 22:09:34', 'jeecg', '2020-05-14 22:13:52', 'admin'); +INSERT INTO `sys_permission_data_rule` VALUES ('1260936345293012993', '4148ec82b6acd69f470bea75fe41c357', '年龄', 'age', '>', '20', '1', '2020-05-14 22:13:46', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('1260937192290762754', '4148ec82b6acd69f470bea75fe41c357', 'sysOrgCode', 'sysOrgCode', 'RIGHT_LIKE', '#{sys_org_code}', '1', '2020-05-14 22:17:08', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('32b62cb04d6c788d9d92e3ff5e66854e', '8d4683aacaa997ab86b966b464360338', '000', '00', '!=', '00', '1', '2019-04-02 18:36:08', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('40283181614231d401614234fe670003', '40283181614231d401614232cd1c0001', 'createBy', 'createBy', '=', '#{sys_user_code}', '1', '2018-01-29 21:57:04', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('4028318161424e730161424fca6f0004', '4028318161424e730161424f61510002', 'createBy', 'createBy', '=', '#{sys_user_code}', '1', '2018-01-29 22:26:20', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402880e6487e661a01487e732c020005', '402889fb486e848101486e93a7c80014', 'SYS_ORG_CODE', 'SYS_ORG_CODE', 'LIKE', '010201%', '1', '2014-09-16 20:32:30', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402880e6487e661a01487e8153ee0007', '402889fb486e848101486e93a7c80014', 'create_by', 'create_by', '', '#{SYS_USER_CODE}', '1', '2014-09-16 20:47:57', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402880ec5ddec439015ddf9225060038', '40288088481d019401481d2fcebf000d', '复杂关系', '', 'USE_SQL_RULES', 'name like \'%张%\' or age > 10', '1', NULL, NULL, '2017-08-14 15:10:25', 'demo'); +INSERT INTO `sys_permission_data_rule` VALUES ('402880ec5ddfdd26015ddfe3e0570011', '4028ab775dca0d1b015dca3fccb60016', '复杂sql配置', '', 'USE_SQL_RULES', 'table_name like \'%test%\' or is_tree = \'Y\'', '1', NULL, NULL, '2017-08-14 16:38:55', 'demo'); +INSERT INTO `sys_permission_data_rule` VALUES ('402880f25b1e2ac7015b1e5fdebc0012', '402880f25b1e2ac7015b1e5cdc340010', '只能看自己数据', 'create_by', '=', '#{sys_user_code}', '1', '2017-03-30 16:40:51', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402881875b19f141015b19f8125e0014', '40288088481d019401481d2fcebf000d', '可看下属业务数据', 'sys_org_code', 'LIKE', '#{sys_org_code}', '1', NULL, NULL, '2017-08-14 15:04:32', 'demo'); +INSERT INTO `sys_permission_data_rule` VALUES ('402881e45394d66901539500a4450001', '402881e54df73c73014df75ab670000f', 'sysCompanyCode', 'sysCompanyCode', '=', '#{SYS_COMPANY_CODE}', '1', '2016-03-21 01:09:21', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402881e45394d6690153950177cb0003', '402881e54df73c73014df75ab670000f', 'sysOrgCode', 'sysOrgCode', '=', '#{SYS_ORG_CODE}', '1', '2016-03-21 01:10:15', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402881e56266f43101626727aff60067', '402881e56266f43101626724eb730065', '销售自己看自己的数据', 'createBy', '=', '#{sys_user_code}', '1', '2018-03-27 19:11:16', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402881e56266f4310162672fb1a70082', '402881e56266f43101626724eb730065', '销售经理看所有下级数据', 'sysOrgCode', 'LIKE', '#{sys_org_code}', '1', '2018-03-27 19:20:01', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402881e56266f431016267387c9f0088', '402881e56266f43101626724eb730065', '只看金额大于1000的数据', 'money', '>=', '1000', '1', '2018-03-27 19:29:37', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402881f3650de25101650dfb5a3a0010', '402881e56266f4310162671d62050044', '22', '', 'USE_SQL_RULES', '22', '1', '2018-08-06 14:45:01', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402889fb486e848101486e913cd6000b', '402889fb486e848101486e8e2e8b0007', 'userName', 'userName', '=', 'admin', '1', '2014-09-13 18:31:25', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('402889fb486e848101486e98d20d0016', '402889fb486e848101486e93a7c80014', 'title', 'title', '=', '12', '1', NULL, NULL, '2014-09-13 22:18:22', 'scott'); +INSERT INTO `sys_permission_data_rule` VALUES ('402889fe47fcb29c0147fcb6b6220001', '8a8ab0b246dc81120146dc8180fe002b', '12', '12', '>', '12', '1', '2014-08-22 15:55:38', '8a8ab0b246dc81120146dc8181950052', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('4028ab775dca0d1b015dca4183530018', '4028ab775dca0d1b015dca3fccb60016', '表名限制', 'isDbSynch', '=', 'Y', '1', NULL, NULL, '2017-08-14 16:43:45', 'demo'); +INSERT INTO `sys_permission_data_rule` VALUES ('4028ef815595a881015595b0ccb60001', '40288088481d019401481d2fcebf000d', '限只能看自己', 'create_by', '=', '#{sys_user_code}', '1', NULL, NULL, '2017-08-14 15:03:56', 'demo'); +INSERT INTO `sys_permission_data_rule` VALUES ('4028ef81574ae99701574aed26530005', '4028ef81574ae99701574aeb97bd0003', '用户名', 'userName', '!=', 'admin', '1', '2016-09-21 12:07:18', 'admin', NULL, NULL); +INSERT INTO `sys_permission_data_rule` VALUES ('f852d85d47f224990147f2284c0c0005', NULL, '小于', 'test', '<=', '11', '1', '2014-08-20 14:43:52', '8a8ab0b246dc81120146dc8181950052', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_position +-- ---------------------------- +DROP TABLE IF EXISTS `sys_position`; +CREATE TABLE `sys_position` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '职务编码', + `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '职务名称', + `post_rank` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '职级', + `company_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '公司id', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `sys_org_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组织机构编码', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uniq_code`(`code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_position +-- ---------------------------- +INSERT INTO `sys_position` VALUES ('1185040064792571906', 'devleader', '研发部经理', '2', NULL, 'admin', '2019-10-18 11:49:03', 'admin', '2020-02-23 22:55:42', 'A01'); +INSERT INTO `sys_position` VALUES ('1256485574212153345', '总经理', 'laozong', '5', NULL, 'admin', '2020-05-02 15:28:00', 'admin', '2020-05-02 15:28:03', '北京国炬公司'); + +-- ---------------------------- +-- Table structure for sys_quartz_job +-- ---------------------------- +DROP TABLE IF EXISTS `sys_quartz_job`; +CREATE TABLE `sys_quartz_job` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `del_flag` int(11) NULL DEFAULT NULL COMMENT '删除状态', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `job_class_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务类名', + `cron_expression` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'cron表达式', + `parameter` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数', + `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `status` int(11) NULL DEFAULT NULL COMMENT '状态 0正常 -1停止', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uniq_job_class_name`(`job_class_name`) USING BTREE +) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_quartz_job +-- ---------------------------- +INSERT INTO `sys_quartz_job` VALUES ('df26ecacf0f75d219d746750fe84bbee', NULL, NULL, 0, 'admin', '2020-05-02 15:40:35', 'org.jeecg.modules.quartz.job.SampleParamJob', '0/1 * * * * ?', 'scott', '带参测试 后台将每隔1秒执行输出日志', -1); +INSERT INTO `sys_quartz_job` VALUES ('a253cdfc811d69fa0efc70d052bc8128', 'admin', '2019-03-30 12:44:48', 0, 'admin', '2020-05-02 15:48:49', 'org.jeecg.modules.quartz.job.SampleJob', '0/1 * * * * ?', NULL, NULL, -1); +INSERT INTO `sys_quartz_job` VALUES ('5b3d2c087ad41aa755fc4f89697b01e7', 'admin', '2019-04-11 19:04:21', 0, 'admin', '2020-05-02 15:48:48', 'org.jeecg.modules.message.job.SendMsgJob', '0/50 * * * * ? *', NULL, NULL, -1); + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role`; +CREATE TABLE `sys_role` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id', + `role_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色名称', + `role_code` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色编码', + `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uniq_sys_role_role_code`(`role_code`) USING BTREE, + INDEX `idx_sr_role_code`(`role_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_role +-- ---------------------------- +INSERT INTO `sys_role` VALUES ('1169504891467464705', '第三方登录角色', 'third_role', '第三方登录角色', 'admin', '2019-09-05 14:57:49', 'admin', '2020-05-02 18:20:58'); +INSERT INTO `sys_role` VALUES ('1509464524584480770', '系统管理员', 'xtgly', '系统管理员', 'admin', '2022-03-31 17:36:02', NULL, NULL); +INSERT INTO `sys_role` VALUES ('f6817f48af4fb3af11b9e8bf182f618b', '管理员', 'admin', '管理员', NULL, '2018-12-21 18:03:39', 'admin', '2019-05-20 11:40:26'); + +-- ---------------------------- +-- Table structure for sys_role_permission +-- ---------------------------- +DROP TABLE IF EXISTS `sys_role_permission`; +CREATE TABLE `sys_role_permission` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色id', + `permission_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限id', + `data_rule_ids` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '数据权限ids', + `operate_date` datetime(0) NULL DEFAULT NULL COMMENT '操作时间', + `operate_ip` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作ip', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_group_role_per_id`(`role_id`, `permission_id`) USING BTREE, + INDEX `index_group_role_id`(`role_id`) USING BTREE, + INDEX `index_group_per_id`(`permission_id`) USING BTREE, + INDEX `idx_srp_role_per_id`(`role_id`, `permission_id`) USING BTREE, + INDEX `idx_srp_role_id`(`role_id`) USING BTREE, + INDEX `idx_srp_permission_id`(`permission_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '角色权限表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_role_permission +-- ---------------------------- +INSERT INTO `sys_role_permission` VALUES ('00b0748f04d3ea52c8cfa179c1c9d384', '52b0cf022ac4187b2a70dfa4f8b2d940', 'd7d6e2e4e2934f2c9385a623fd98c6f3', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('00b82058779cca5106fbb84783534c9b', 'f6817f48af4fb3af11b9e8bf182f618b', '4148ec82b6acd69f470bea75fe41c357', '', NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('0254c0b25694ad5479e6d6935bbc176e', 'f6817f48af4fb3af11b9e8bf182f618b', '944abf0a8fc22fe1f1154a389a574154', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('09bd4fc30ffe88c4a44ed3868f442719', 'f6817f48af4fb3af11b9e8bf182f618b', 'e6bfd1fcabfd7942fdd05f076d1dad38', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('0c2d2db76ee3aa81a4fe0925b0f31365', 'f6817f48af4fb3af11b9e8bf182f618b', '024f1fd1283dc632458976463d8984e1', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('0c6b8facbb1cc874964c87a8cf01e4b1', 'f6817f48af4fb3af11b9e8bf182f618b', '841057b8a1bef8f6b4b20f9a618a7fa6', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('0c6e1075e422972083c3e854d9af7851', 'f6817f48af4fb3af11b9e8bf182f618b', '08e6b9dc3c04489c8e1ff2ce6f105aa4', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('0e1469997af2d3b97fff56a59ee29eeb', 'f6817f48af4fb3af11b9e8bf182f618b', 'e41b69c57a941a3bbcce45032fe57605', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('0f861cb988fdc639bb1ab943471f3a72', 'f6817f48af4fb3af11b9e8bf182f618b', '97c8629abc7848eccdb6d77c24bb3ebb', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('115a6673ae6c0816d3f60de221520274', '21c5a3187763729408b40afb0d0fdfa8', '63b551e81c5956d5c861593d366d8c57', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1185039870491439105', 'f6817f48af4fb3af11b9e8bf182f618b', '1174506953255182338', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1185039870529187841', 'f6817f48af4fb3af11b9e8bf182f618b', '1174590283938041857', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1185039870537576450', 'f6817f48af4fb3af11b9e8bf182f618b', '1166535831146504193', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1197431682208206850', 'f6817f48af4fb3af11b9e8bf182f618b', '1192318987661234177', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1197795315916271617', 'f6817f48af4fb3af11b9e8bf182f618b', '109c78a583d4693ce2f16551b7786786', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1197795316268593154', 'f6817f48af4fb3af11b9e8bf182f618b', '9fe26464838de2ea5e90f2367e35efa0', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1209423530518761473', 'f6817f48af4fb3af11b9e8bf182f618b', '1205097455226462210', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1209423530594258945', 'f6817f48af4fb3af11b9e8bf182f618b', '1205098241075453953', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1209423530606841858', 'f6817f48af4fb3af11b9e8bf182f618b', '1205306106780364802', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1209423580355481602', 'f6817f48af4fb3af11b9e8bf182f618b', '190c2b43bec6a5f7a4194a85db67d96a', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1209654501558046722', 'f6817f48af4fb3af11b9e8bf182f618b', 'f2849d3814fc97993bfc519ae6bbf049', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1231590078632955905', 'f6817f48af4fb3af11b9e8bf182f618b', '1224641973866467330', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1231590078658121729', 'f6817f48af4fb3af11b9e8bf182f618b', '1209731624921534465', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1231590078662316033', 'f6817f48af4fb3af11b9e8bf182f618b', '1229674163694841857', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1232124727411150850', 'f6817f48af4fb3af11b9e8bf182f618b', '1232123780958064642', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1260923306820882434', 'f6817f48af4fb3af11b9e8bf182f618b', '1260923256208216065', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1260923306841853953', 'f6817f48af4fb3af11b9e8bf182f618b', '1260922988733255681', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1260928399955836929', 'f6817f48af4fb3af11b9e8bf182f618b', '1260928341675982849', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1269526122208522241', 'f6817f48af4fb3af11b9e8bf182f618b', '1267412134208319489', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('126ea9faebeec2b914d6d9bef957afb6', 'f6817f48af4fb3af11b9e8bf182f618b', 'f1cb187abf927c88b89470d08615f5ac', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1281494164924653569', 'f6817f48af4fb3af11b9e8bf182f618b', '1280350452934307841', NULL, '2020-07-10 15:43:13', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1281494164945625089', 'f6817f48af4fb3af11b9e8bf182f618b', '1280464606292099074', NULL, '2020-07-10 15:43:13', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1281494684632473602', 'f6817f48af4fb3af11b9e8bf182f618b', '1265162119913824258', NULL, '2020-07-10 15:45:16', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1303585080082485250', 'f6817f48af4fb3af11b9e8bf182f618b', '1287715272999944193', NULL, '2020-09-09 14:44:37', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1303585080103456769', 'f6817f48af4fb3af11b9e8bf182f618b', '1287715783966834689', NULL, '2020-09-09 14:44:37', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1303585080116039682', 'f6817f48af4fb3af11b9e8bf182f618b', '1287716451494510593', NULL, '2020-09-09 14:44:37', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1303585080124428290', 'f6817f48af4fb3af11b9e8bf182f618b', '1287718919049691137', NULL, '2020-09-09 14:44:37', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1303585080128622593', 'f6817f48af4fb3af11b9e8bf182f618b', '1287718938179911682', NULL, '2020-09-09 14:44:37', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1303585080141205506', 'f6817f48af4fb3af11b9e8bf182f618b', '1287718956957810689', NULL, '2020-09-09 14:44:37', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1506851163697152001', 'f6817f48af4fb3af11b9e8bf182f618b', '1506851094671491074', NULL, '2022-03-24 12:31:28', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1506851163697152002', 'f6817f48af4fb3af11b9e8bf182f618b', '1506850882536177665', NULL, '2022-03-24 12:31:28', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1507600056508497921', 'f6817f48af4fb3af11b9e8bf182f618b', '1507599354151321601', NULL, '2022-03-26 14:07:18', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1507600056525275138', 'f6817f48af4fb3af11b9e8bf182f618b', '1507599736818647042', NULL, '2022-03-26 14:07:18', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1507600056525275139', 'f6817f48af4fb3af11b9e8bf182f618b', '1507599887117336577', NULL, '2022-03-26 14:07:18', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1507600056525275140', 'f6817f48af4fb3af11b9e8bf182f618b', '1507600010484400130', NULL, '2022-03-26 14:07:18', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091474026497', '1509464524584480770', '1507599354151321601', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091482415105', '1509464524584480770', '1507599736818647042', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091482415106', '1509464524584480770', '1507599887117336577', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091486609410', '1509464524584480770', '1507600010484400130', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091486609411', '1509464524584480770', '9502685863ab87f0ad1134142788a385', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091486609412', '1509464524584480770', '3f915b2769fc80648e92d04e84ca059d', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091486609413', '1509464524584480770', '1260928341675982849', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091494998017', '1509464524584480770', '1260929666434318338', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091494998018', '1509464524584480770', '1260931366557696001', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091494998019', '1509464524584480770', '1260933542969458689', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091499192322', '1509464524584480770', '1a0811914300741f4e11838ff37a1d3a', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091499192323', '1509464524584480770', '45c966826eeff4c99b8f8ebfe74511fc', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465091499192324', '1509464524584480770', '1506851094671491074', NULL, '2022-03-31 17:38:17', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('1509465255316123650', '1509464524584480770', 'd7d6e2e4e2934f2c9385a623fd98c6f3', NULL, '2022-03-31 17:38:56', '127.0.0.1'); +INSERT INTO `sys_role_permission` VALUES ('154edd0599bd1dc2c7de220b489cd1e2', 'f6817f48af4fb3af11b9e8bf182f618b', '7ac9eb9ccbde2f7a033cd4944272bf1e', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('165acd6046a0eaf975099f46a3c898ea', 'f6817f48af4fb3af11b9e8bf182f618b', '4f66409ef3bbd69c1d80469d6e2a885e', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1664b92dff13e1575e3a929caa2fa14d', 'f6817f48af4fb3af11b9e8bf182f618b', 'd2bbf9ebca5a8fa2e227af97d2da7548', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('17ead5b7d97ed365398ab20009a69ea3', '52b0cf022ac4187b2a70dfa4f8b2d940', 'e08cb190ef230d5d4f03824198773950', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1ac1688ef8456f384091a03d88a89ab1', '52b0cf022ac4187b2a70dfa4f8b2d940', '693ce69af3432bd00be13c3971a57961', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1c1dbba68ef1817e7fb19c822d2854e8', 'f6817f48af4fb3af11b9e8bf182f618b', 'fb367426764077dcf94640c843733985', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1e47db875601fd97723254046b5bba90', 'f6817f48af4fb3af11b9e8bf182f618b', 'baf16b7174bd821b6bab23fa9abb200d', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('1fe4d408b85f19618c15bcb768f0ec22', '1750a8fb3e6d90cb7957c02de1dc8e59', '9502685863ab87f0ad1134142788a385', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('20e53c87a785688bdc0a5bb6de394ef1', 'f6817f48af4fb3af11b9e8bf182f618b', '540a2936940846cb98114ffb0d145cb8', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('248d288586c6ff3bd14381565df84163', '52b0cf022ac4187b2a70dfa4f8b2d940', '3f915b2769fc80648e92d04e84ca059d', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('25491ecbd5a9b34f09c8bc447a10ede1', 'f6817f48af4fb3af11b9e8bf182f618b', 'd07a2c87a451434c99ab06296727ec4f', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('27489816708b18859768dfed5945c405', 'a799c3b1b12dd3ed4bd046bfaef5fe6e', '9502685863ab87f0ad1134142788a385', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('2779cdea8367fff37db26a42c1a1f531', 'f6817f48af4fb3af11b9e8bf182f618b', 'fef097f3903caf3a3c3a6efa8de43fbb', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('296f9c75ca0e172ae5ce4c1022c996df', '646c628b2b8295fbdab2d34044de0354', '732d48f8e0abe99fe6a23d18a3171cd1', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('29fb6b0ad59a7e911c8d27e0bdc42d23', 'f6817f48af4fb3af11b9e8bf182f618b', '9a90363f216a6a08f32eecb3f0bf12a3', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('2ad37346c1b83ddeebc008f6987b2227', 'f6817f48af4fb3af11b9e8bf182f618b', '8d1ebd663688965f1fd86a2f0ead3416', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('2c462293cbb0eab7e8ae0a3600361b5f', '52b0cf022ac4187b2a70dfa4f8b2d940', '9502685863ab87f0ad1134142788a385', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('2fdaed22dfa4c8d4629e44ef81688c6a', '52b0cf022ac4187b2a70dfa4f8b2d940', 'aedbf679b5773c1f25e9f7b10111da73', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('300c462b7fec09e2ff32574ef8b3f0bd', '52b0cf022ac4187b2a70dfa4f8b2d940', '2a470fc0c3954d9dbb61de6d80846549', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('35ac7cae648de39eb56213ca1b649713', '52b0cf022ac4187b2a70dfa4f8b2d940', 'b1cb0a3fedf7ed0e4653cb5a229837ee', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('38a2e55db0960262800576e34b3af44c', 'f6817f48af4fb3af11b9e8bf182f618b', '5c2f42277948043026b7a14692456828', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('3b1886f727ac503c93fecdd06dcb9622', 'f6817f48af4fb3af11b9e8bf182f618b', 'c431130c0bc0ec71b0a5be37747bb36a', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('3de2a60c7e42a521fecf6fcc5cb54978', 'f6817f48af4fb3af11b9e8bf182f618b', '2d83d62bd2544b8994c8f38cf17b0ddf', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('3e4e38f748b8d87178dd62082e5b7b60', 'f6817f48af4fb3af11b9e8bf182f618b', '7960961b0063228937da5fa8dd73d371', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('3e563751942b0879c88ca4de19757b50', '1750a8fb3e6d90cb7957c02de1dc8e59', '58857ff846e61794c69208e9d3a85466', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('3f1d04075e3c3254666a4138106a4e51', 'f6817f48af4fb3af11b9e8bf182f618b', '3fac0d3c9cd40fa53ab70d4c583821f8', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('412e2de37a35b3442d68db8dd2f3c190', '52b0cf022ac4187b2a70dfa4f8b2d940', 'f1cb187abf927c88b89470d08615f5ac', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('4204f91fb61911ba8ce40afa7c02369f', 'f6817f48af4fb3af11b9e8bf182f618b', '3f915b2769fc80648e92d04e84ca059d', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('444126230885d5d38b8fa6072c9f43f8', 'f6817f48af4fb3af11b9e8bf182f618b', 'f780d0d3083d849ccbdb1b1baee4911d', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('445656dd187bd8a71605f4bbab1938a3', 'f6817f48af4fb3af11b9e8bf182f618b', '020b06793e4de2eee0007f603000c769', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('455cdb482457f529b79b479a2ff74427', 'f6817f48af4fb3af11b9e8bf182f618b', 'e1979bb53e9ea51cecc74d86fd9d2f64', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('45a358bb738782d1a0edbf7485e81459', 'f6817f48af4fb3af11b9e8bf182f618b', '0ac2ad938963b6c6d1af25477d5b8b51', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('4dab5a06acc8ef3297889872caa74747', 'f6817f48af4fb3af11b9e8bf182f618b', 'ffb423d25cc59dcd0532213c4a518261', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('4e0a37ed49524df5f08fc6593aee875c', 'f6817f48af4fb3af11b9e8bf182f618b', 'f23d9bfff4d9aa6b68569ba2cff38415', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('4ea403fc1d19feb871c8bdd9f94a4ecc', 'f6817f48af4fb3af11b9e8bf182f618b', '2e42e3835c2b44ec9f7bc26c146ee531', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('4f254549d9498f06f4cc9b23f3e2c070', 'f6817f48af4fb3af11b9e8bf182f618b', '93d5cfb4448f11e9916698e7f462b4b6', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('4faad8ff93cb2b5607cd3d07c1b624ee', 'a799c3b1b12dd3ed4bd046bfaef5fe6e', '70b8f33da5f39de1981bf89cf6c99792', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('504e326de3f03562cdd186748b48a8c7', 'f6817f48af4fb3af11b9e8bf182f618b', '027aee69baee98a0ed2e01806e89c891', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('520b5989e6fe4a302a573d4fee12a40a', 'f6817f48af4fb3af11b9e8bf182f618b', '6531cf3421b1265aeeeabaab5e176e6d', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('54fdf85e52807bdb32ce450814abc256', 'f6817f48af4fb3af11b9e8bf182f618b', 'cc50656cf9ca528e6f2150eba4714ad2', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('57c0b3a547b815ea3ec8e509b08948b3', '1750a8fb3e6d90cb7957c02de1dc8e59', '3f915b2769fc80648e92d04e84ca059d', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('593ee05c4fe4645c7826b7d5e14f23ec', '52b0cf022ac4187b2a70dfa4f8b2d940', '8fb8172747a78756c11916216b8b8066', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('5d230e6cd2935c4117f6cb9a7a749e39', 'f6817f48af4fb3af11b9e8bf182f618b', 'fc810a2267dd183e4ef7c71cc60f4670', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('5de6871fadb4fe1cdd28989da0126b07', 'f6817f48af4fb3af11b9e8bf182f618b', 'a400e4f4d54f79bf5ce160a3432231af', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('5e4015a9a641cbf3fb5d28d9f885d81a', 'f6817f48af4fb3af11b9e8bf182f618b', '2dbbafa22cda07fa5d169d741b81fe12', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('5fc194b709336d354640fe29fefd65a3', 'a799c3b1b12dd3ed4bd046bfaef5fe6e', '9ba60e626bf2882c31c488aba62b89f0', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('60eda4b4db138bdb47edbe8e10e71675', 'f6817f48af4fb3af11b9e8bf182f618b', 'fb07ca05a3e13674dbf6d3245956da2e', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('61835e48f3e675f7d3f5c9dd3a10dcf3', 'f6817f48af4fb3af11b9e8bf182f618b', 'f0675b52d89100ee88472b6800754a08', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('660fbc40bcb1044738f7cabdf1708c28', 'f6817f48af4fb3af11b9e8bf182f618b', 'b3c824fc22bd953e2eb16ae6914ac8f9', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('66b202f8f84fe766176b3f51071836ef', 'f6817f48af4fb3af11b9e8bf182f618b', '1367a93f2c410b169faa7abcbad2f77c', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('6b605c261ffbc8ac8a98ae33579c8c78', 'f6817f48af4fb3af11b9e8bf182f618b', 'fba41089766888023411a978d13c0aa4', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('6c74518eb6bb9a353f6a6c459c77e64b', 'f6817f48af4fb3af11b9e8bf182f618b', 'b4dfc7d5dd9e8d5b6dd6d4579b1aa559', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('6daddafacd7eccb91309530c17c5855d', 'f6817f48af4fb3af11b9e8bf182f618b', 'edfa74d66e8ea63ea432c2910837b150', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('6fb4c2142498dd6d5b6c014ef985cb66', 'f6817f48af4fb3af11b9e8bf182f618b', '6e73eb3c26099c191bf03852ee1310a1', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('7413acf23b56c906aedb5a36fb75bd3a', 'f6817f48af4fb3af11b9e8bf182f618b', 'a4fc7b64b01a224da066bb16230f9c5a', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('75002588591820806', '16457350655250432', '5129710648430592', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('75002588604403712', '16457350655250432', '5129710648430593', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('75002588612792320', '16457350655250432', '40238597734928384', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('75002588625375232', '16457350655250432', '57009744761589760', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('75002588633763840', '16457350655250432', '16392452747300864', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('75002588637958144', '16457350655250432', '16392767785668608', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('75002588650541056', '16457350655250432', '16439068543946752', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('76a54a8cc609754360bf9f57e7dbb2db', 'f6817f48af4fb3af11b9e8bf182f618b', 'c65321e57b7949b7a975313220de0422', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277779875336192', '496138616573952', '5129710648430592', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780043108352', '496138616573952', '5129710648430593', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780055691264', '496138616573952', '15701400130424832', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780064079872', '496138616573952', '16678126574637056', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780072468480', '496138616573952', '15701915807518720', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780076662784', '496138616573952', '15708892205944832', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780085051392', '496138616573952', '16678447719911424', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780089245696', '496138616573952', '25014528525733888', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780097634304', '496138616573952', '56898976661639168', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780135383040', '496138616573952', '40238597734928384', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780139577344', '496138616573952', '45235621697949696', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780147965952', '496138616573952', '45235787867885568', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780156354560', '496138616573952', '45235939278065664', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780164743168', '496138616573952', '43117268627886080', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780168937472', '496138616573952', '45236734832676864', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780181520384', '496138616573952', '45237010692050944', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780189908992', '496138616573952', '45237170029465600', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780198297600', '496138616573952', '57009544286441472', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780206686208', '496138616573952', '57009744761589760', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780215074816', '496138616573952', '57009981228060672', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780219269120', '496138616573952', '56309618086776832', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780227657728', '496138616573952', '57212882168844288', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780236046336', '496138616573952', '61560041605435392', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780244434944', '496138616573952', '61560275261722624', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780257017856', '496138616573952', '61560480518377472', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780265406464', '496138616573952', '44986029924421632', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780324126720', '496138616573952', '45235228800716800', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780332515328', '496138616573952', '45069342940860416', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780340903937', '496138616573952', '5129710648430594', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780349292544', '496138616573952', '16687383932047360', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780357681152', '496138616573952', '16689632049631232', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780366069760', '496138616573952', '16689745006432256', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780370264064', '496138616573952', '16689883993083904', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780374458369', '496138616573952', '16690313745666048', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780387041280', '496138616573952', '5129710648430595', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780395429888', '496138616573952', '16694861252005888', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780403818496', '496138616573952', '16695107491205120', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780412207104', '496138616573952', '16695243126607872', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780420595712', '496138616573952', '75002207560273920', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780428984320', '496138616573952', '76215889006956544', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780433178624', '496138616573952', '76216071333351424', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780441567232', '496138616573952', '76216264070008832', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780449955840', '496138616573952', '76216459709124608', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780458344448', '496138616573952', '76216594207870976', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780466733056', '496138616573952', '76216702639017984', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780475121664', '496138616573952', '58480609315524608', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780483510272', '496138616573952', '61394706252173312', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780491898880', '496138616573952', '61417744146370560', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780496093184', '496138616573952', '76606430504816640', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780504481792', '496138616573952', '76914082455752704', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780508676097', '496138616573952', '76607201262702592', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780517064704', '496138616573952', '39915540965232640', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780525453312', '496138616573952', '41370251991977984', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780538036224', '496138616573952', '45264987354042368', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780546424832', '496138616573952', '45265487029866496', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780554813440', '496138616573952', '45265762415284224', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780559007744', '496138616573952', '45265886315024384', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780567396352', '496138616573952', '45266070000373760', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780571590656', '496138616573952', '41363147411427328', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780579979264', '496138616573952', '41363537456533504', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780588367872', '496138616573952', '41364927394353152', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780596756480', '496138616573952', '41371711400054784', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780605145088', '496138616573952', '41469219249852416', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780613533696', '496138616573952', '39916171171991552', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780621922304', '496138616573952', '39918482854252544', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780630310912', '496138616573952', '41373430515240960', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780718391296', '496138616573952', '41375330996326400', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780722585600', '496138616573952', '63741744973352960', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780730974208', '496138616573952', '42082442672082944', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780739362816', '496138616573952', '41376192166629376', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780747751424', '496138616573952', '41377034236071936', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780756140032', '496138616573952', '56911328312299520', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780764528640', '496138616573952', '41378916912336896', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780768722944', '496138616573952', '63482475359244288', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780772917249', '496138616573952', '64290663792906240', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780785500160', '496138616573952', '66790433014943744', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780789694464', '496138616573952', '42087054753927168', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780798083072', '496138616573952', '67027338952445952', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780806471680', '496138616573952', '67027909637836800', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780810665985', '496138616573952', '67042515441684480', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780823248896', '496138616573952', '67082402312228864', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780827443200', '496138616573952', '16392452747300864', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780835831808', '496138616573952', '16392767785668608', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780840026112', '496138616573952', '16438800255291392', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780844220417', '496138616573952', '16438962738434048', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277780852609024', '496138616573952', '16439068543946752', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860062040064', '496138616573953', '5129710648430592', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860070428672', '496138616573953', '5129710648430593', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860078817280', '496138616573953', '40238597734928384', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860091400192', '496138616573953', '43117268627886080', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860099788800', '496138616573953', '57009744761589760', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860112371712', '496138616573953', '56309618086776832', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860120760320', '496138616573953', '44986029924421632', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860129148928', '496138616573953', '5129710648430594', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860141731840', '496138616573953', '5129710648430595', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860150120448', '496138616573953', '75002207560273920', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860158509056', '496138616573953', '58480609315524608', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860162703360', '496138616573953', '76606430504816640', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860171091968', '496138616573953', '76914082455752704', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860179480576', '496138616573953', '76607201262702592', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860187869184', '496138616573953', '39915540965232640', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860196257792', '496138616573953', '41370251991977984', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860204646400', '496138616573953', '41363147411427328', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860208840704', '496138616573953', '41371711400054784', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860213035009', '496138616573953', '39916171171991552', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860221423616', '496138616573953', '39918482854252544', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860225617920', '496138616573953', '41373430515240960', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860234006528', '496138616573953', '41375330996326400', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860242395136', '496138616573953', '63741744973352960', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860250783744', '496138616573953', '42082442672082944', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860254978048', '496138616573953', '41376192166629376', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860263366656', '496138616573953', '41377034236071936', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860271755264', '496138616573953', '56911328312299520', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860313698304', '496138616573953', '41378916912336896', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860322086912', '496138616573953', '63482475359244288', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860326281216', '496138616573953', '64290663792906240', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860334669824', '496138616573953', '66790433014943744', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860343058432', '496138616573953', '42087054753927168', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860347252736', '496138616573953', '67027338952445952', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860351447041', '496138616573953', '67027909637836800', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860359835648', '496138616573953', '67042515441684480', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860364029952', '496138616573953', '67082402312228864', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860368224256', '496138616573953', '16392452747300864', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860372418560', '496138616573953', '16392767785668608', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860376612865', '496138616573953', '16438800255291392', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860385001472', '496138616573953', '16438962738434048', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('77277860389195776', '496138616573953', '16439068543946752', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('7a5d31ba48fe3fb1266bf186dc5f7ba7', '52b0cf022ac4187b2a70dfa4f8b2d940', '58857ff846e61794c69208e9d3a85466', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('7a6bca9276c128309c80d21e795c66c6', 'f6817f48af4fb3af11b9e8bf182f618b', '54097c6a3cf50fad0793a34beff1efdf', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('7ca833caa5eac837b7200d8b6de8b2e3', 'f6817f48af4fb3af11b9e8bf182f618b', 'fedfbf4420536cacc0218557d263dfea', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('7de42bdc0b8c5446b7d428c66a7abc12', '52b0cf022ac4187b2a70dfa4f8b2d940', '54dd5457a3190740005c1bfec55b1c34', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('7e19d90cec0dd87aaef351b9ff8f4902', '646c628b2b8295fbdab2d34044de0354', 'f9d3f4f27653a71c52faa9fb8070fbe7', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('84eac2f113c23737128fb099d1d1da89', 'f6817f48af4fb3af11b9e8bf182f618b', '03dc3d93261dda19fc86dd7ca486c6cf', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('86060e2867a5049d8a80d9fe5d8bc28b', 'f6817f48af4fb3af11b9e8bf182f618b', '765dd244f37b804e3d00f475fd56149b', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('884f147c20e003cc80ed5b7efa598cbe', 'f6817f48af4fb3af11b9e8bf182f618b', 'e5973686ed495c379d829ea8b2881fc6', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('8a60df8d8b4c9ee5fa63f48aeee3ec00', '1750a8fb3e6d90cb7957c02de1dc8e59', 'd7d6e2e4e2934f2c9385a623fd98c6f3', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('8b09925bdc194ab7f3559cd3a7ea0507', 'f6817f48af4fb3af11b9e8bf182f618b', 'ebb9d82ea16ad864071158e0c449d186', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('8ce1022dac4e558ff9694600515cf510', '1750a8fb3e6d90cb7957c02de1dc8e59', '08e6b9dc3c04489c8e1ff2ce6f105aa4', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('8d154c2382a8ae5c8d1b84bd38df2a93', 'f6817f48af4fb3af11b9e8bf182f618b', 'd86f58e7ab516d3bc6bfb1fe10585f97', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('8d848ca7feec5b7ebb3ecb32b2c8857a', '52b0cf022ac4187b2a70dfa4f8b2d940', '4148ec82b6acd69f470bea75fe41c357', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('8dd64f65a1014196078d0882f767cd85', 'f6817f48af4fb3af11b9e8bf182f618b', 'e3c13679c73a4f829bcff2aba8fd68b1', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('8e3dc1671abad4f3c83883b194d2e05a', 'f6817f48af4fb3af11b9e8bf182f618b', 'b1cb0a3fedf7ed0e4653cb5a229837ee', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('905bf419332ebcb83863603b3ebe30f0', 'f6817f48af4fb3af11b9e8bf182f618b', '8fb8172747a78756c11916216b8b8066', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('9264104cee9b10c96241d527b2d0346d', '1750a8fb3e6d90cb7957c02de1dc8e59', '54dd5457a3190740005c1bfec55b1c34', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('9380121ca9cfee4b372194630fce150e', 'f6817f48af4fb3af11b9e8bf182f618b', '65a8f489f25a345836b7f44b1181197a', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('94911fef73a590f6824105ebf9b6cab3', 'f6817f48af4fb3af11b9e8bf182f618b', '8b3bff2eee6f1939147f5c68292a1642', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('9700d20dbc1ae3cbf7de1c810b521fe6', 'f6817f48af4fb3af11b9e8bf182f618b', 'ec8d607d0156e198b11853760319c646', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('980171fda43adfe24840959b1d048d4d', 'f6817f48af4fb3af11b9e8bf182f618b', 'd7d6e2e4e2934f2c9385a623fd98c6f3', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('987c23b70873bd1d6dca52f30aafd8c2', 'f6817f48af4fb3af11b9e8bf182f618b', '00a2a0ae65cdca5e93209cdbde97cbe6', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('9b2ad767f9861e64a20b097538feafd3', 'f6817f48af4fb3af11b9e8bf182f618b', '73678f9daa45ed17a3674131b03432fb', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('9d8772c310b675ae43eacdbc6c7fa04a', 'a799c3b1b12dd3ed4bd046bfaef5fe6e', '1663f3faba244d16c94552f849627d84', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('9d980ec0489040e631a9c24a6af42934', 'f6817f48af4fb3af11b9e8bf182f618b', '05b3c82ddb2536a4a5ee1a4c46b5abef', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('9f8311ecccd44e079723098cf2ffe1cc', '1750a8fb3e6d90cb7957c02de1dc8e59', '693ce69af3432bd00be13c3971a57961', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('a034ed7c38c996b880d3e78f586fe0ae', 'f6817f48af4fb3af11b9e8bf182f618b', 'c89018ea6286e852b424466fd92a2ffc', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('a307a9349ad64a2eff8ab69582fa9be4', 'f6817f48af4fb3af11b9e8bf182f618b', '0620e402857b8c5b605e1ad9f4b89350', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('a5d25fdb3c62904a8474182706ce11a0', 'f6817f48af4fb3af11b9e8bf182f618b', '418964ba087b90a84897b62474496b93', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('acacce4417e5d7f96a9c3be2ded5b4be', 'f6817f48af4fb3af11b9e8bf182f618b', 'f9d3f4f27653a71c52faa9fb8070fbe7', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('ae1852fb349d8513eb3fdc173da3ee56', 'f6817f48af4fb3af11b9e8bf182f618b', '8d4683aacaa997ab86b966b464360338', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('aefc8c22e061171806e59cd222f6b7e1', '52b0cf022ac4187b2a70dfa4f8b2d940', 'e8af452d8948ea49d37c934f5100ae6a', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('af60ac8fafd807ed6b6b354613b9ccbc', 'f6817f48af4fb3af11b9e8bf182f618b', '58857ff846e61794c69208e9d3a85466', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('b0c8a20800b8bf1ebdd7be473bceb44f', 'f6817f48af4fb3af11b9e8bf182f618b', '58b9204feaf07e47284ddb36cd2d8468', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('b128ebe78fa5abb54a3a82c6689bdca3', 'f6817f48af4fb3af11b9e8bf182f618b', 'aedbf679b5773c1f25e9f7b10111da73', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('b21b07951bb547b09cc85624a841aea0', 'f6817f48af4fb3af11b9e8bf182f618b', '4356a1a67b564f0988a484f5531fd4d9', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('b64c4ab9cd9a2ea8ac1e9db5fb7cf522', 'f6817f48af4fb3af11b9e8bf182f618b', '2aeddae571695cd6380f6d6d334d6e7d', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('bbec16ad016efec9ea2def38f4d3d9dc', 'f6817f48af4fb3af11b9e8bf182f618b', '13212d3416eb690c2e1d5033166ff47a', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('be8e5a9080569e59863f20c4c57a8e22', 'f6817f48af4fb3af11b9e8bf182f618b', '22d6a3d39a59dd7ea9a30acfa6bfb0a5', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('bea2986432079d89203da888d99b3f16', 'f6817f48af4fb3af11b9e8bf182f618b', '54dd5457a3190740005c1bfec55b1c34', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('c09373ebfc73fb5740db5ff02cba4f91', 'f6817f48af4fb3af11b9e8bf182f618b', '339329ed54cf255e1f9392e84f136901', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('c56fb1658ee5f7476380786bf5905399', 'f6817f48af4fb3af11b9e8bf182f618b', 'de13e0f6328c069748de7399fcc1dbbd', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('c6fee38d293b9d0596436a0cbd205070', 'f6817f48af4fb3af11b9e8bf182f618b', '4f84f9400e5e92c95f05b554724c2b58', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('c90b0b01c7ca454d2a1cb7408563e696', 'f6817f48af4fb3af11b9e8bf182f618b', '882a73768cfd7f78f3a37584f7299656', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('cf1feb1bf69eafc982295ad6c9c8d698', 'f6817f48af4fb3af11b9e8bf182f618b', 'a2b11669e98c5fe54a53c3e3c4f35d14', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('cf2ef620217673e4042f695743294f01', 'f6817f48af4fb3af11b9e8bf182f618b', '717f6bee46f44a3897eca9abd6e2ec44', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('cf43895aef7fc684669483ab00ef2257', 'f6817f48af4fb3af11b9e8bf182f618b', '700b7f95165c46cc7a78bf227aa8fed3', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('d281a95b8f293d0fa2a136f46c4e0b10', 'f6817f48af4fb3af11b9e8bf182f618b', '5c8042bd6c601270b2bbd9b20bccc68b', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('d37ad568e26f46ed0feca227aa9c2ffa', 'f6817f48af4fb3af11b9e8bf182f618b', '9502685863ab87f0ad1134142788a385', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('d3ddcacee1acdfaa0810618b74e38ef2', 'f6817f48af4fb3af11b9e8bf182f618b', 'c6cf95444d80435eb37b2f9db3971ae6', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('d3fe195d59811531c05d31d8436f5c8b', '1750a8fb3e6d90cb7957c02de1dc8e59', 'e8af452d8948ea49d37c934f5100ae6a', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('d83282192a69514cfe6161b3087ff962', 'f6817f48af4fb3af11b9e8bf182f618b', '53a9230444d33de28aa11cc108fb1dba', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('d8a5c9079df12090e108e21be94b4fd7', 'f6817f48af4fb3af11b9e8bf182f618b', '078f9558cdeab239aecb2bda1a8ed0d1', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('dbc5dd836d45c5bc7bc94b22596ab956', 'f6817f48af4fb3af11b9e8bf182f618b', '1939e035e803a99ceecb6f5563570fb2', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('dc83bb13c0e8c930e79d28b2db26f01f', 'f6817f48af4fb3af11b9e8bf182f618b', '63b551e81c5956d5c861593d366d8c57', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('dc8fd3f79bd85bd832608b42167a1c71', 'f6817f48af4fb3af11b9e8bf182f618b', '91c23960fab49335831cf43d820b0a61', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('de82e89b8b60a3ea99be5348f565c240', 'f6817f48af4fb3af11b9e8bf182f618b', '56ca78fe0f22d815fabc793461af67b8', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('de8f43229e351d34af3c95b1b9f0a15d', 'f6817f48af4fb3af11b9e8bf182f618b', 'a400e4f4d54f79bf5ce160ae432231af', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('e3e922673f4289b18366bb51b6200f17', '52b0cf022ac4187b2a70dfa4f8b2d940', '45c966826eeff4c99b8f8ebfe74511fc', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('e7467726ee72235baaeb47df04a35e73', 'f6817f48af4fb3af11b9e8bf182f618b', 'e08cb190ef230d5d4f03824198773950', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('eaef4486f1c9b0408580bbfa2037eb66', 'f6817f48af4fb3af11b9e8bf182f618b', '2a470fc0c3954d9dbb61de6d80846549', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('ec4bc97829ab56afd83f428b6dc37ff6', 'f6817f48af4fb3af11b9e8bf182f618b', '200006f0edf145a2b50eacca07585451', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('ec846a3f85fdb6813e515be71f11b331', 'f6817f48af4fb3af11b9e8bf182f618b', '732d48f8e0abe99fe6a23d18a3171cd1', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('ec93bb06f5be4c1f19522ca78180e2ef', 'f6817f48af4fb3af11b9e8bf182f618b', '265de841c58907954b8877fb85212622', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('ecdd72fe694e6bba9c1d9fc925ee79de', 'f6817f48af4fb3af11b9e8bf182f618b', '45c966826eeff4c99b8f8ebfe74511fc', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('edefd8d468f5727db465cf1b860af474', 'f6817f48af4fb3af11b9e8bf182f618b', '6ad53fd1b220989a8b71ff482d683a5a', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('ef8bdd20d29447681ec91d3603e80c7b', 'f6817f48af4fb3af11b9e8bf182f618b', 'ae4fed059f67086fd52a73d913cf473d', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('f177acac0276329dc66af0c9ad30558a', 'f6817f48af4fb3af11b9e8bf182f618b', 'c2c356bf4ddd29975347a7047a062440', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('f17ab8ad1e71341140857ef4914ef297', '21c5a3187763729408b40afb0d0fdfa8', '732d48f8e0abe99fe6a23d18a3171cd1', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('f99f99cc3bc27220cdd4f5aced33b7d7', 'f6817f48af4fb3af11b9e8bf182f618b', '655563cd64b75dcf52ef7bcdd4836953', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('fafe73c4448b977fe42880a6750c3ee8', 'f6817f48af4fb3af11b9e8bf182f618b', '9cb91b8851db0cf7b19d7ecc2a8193dd', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('fced905c7598973b970d42d833f73474', 'f6817f48af4fb3af11b9e8bf182f618b', '4875ebe289344e14844d8e3ea1edd73f', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('fd97963dc5f144d3aecfc7045a883427', 'f6817f48af4fb3af11b9e8bf182f618b', '043780fa095ff1b2bec4dc406d76f023', NULL, NULL, NULL); +INSERT INTO `sys_role_permission` VALUES ('fed41a4671285efb266cd404f24dd378', '52b0cf022ac4187b2a70dfa4f8b2d940', '00a2a0ae65cdca5e93209cdbde97cbe6', NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_sms +-- ---------------------------- +DROP TABLE IF EXISTS `sys_sms`; +CREATE TABLE `sys_sms` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'ID', + `es_title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '消息标题', + `es_type` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发送方式:1短信 2邮件 3微信', + `es_receiver` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '接收人', + `es_param` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发送所需参数Json格式', + `es_content` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '推送内容', + `es_send_time` datetime(0) NULL DEFAULT NULL COMMENT '推送时间', + `es_send_status` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '推送状态 0未推送 1推送成功 2推送失败 -1失败不再发送', + `es_send_num` int(11) NULL DEFAULT NULL COMMENT '发送次数 超过5次不再发送', + `es_result` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '推送失败原因', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人登录名称', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人登录名称', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_type`(`es_type`) USING BTREE, + INDEX `index_receiver`(`es_receiver`) USING BTREE, + INDEX `index_sendtime`(`es_send_time`) USING BTREE, + INDEX `index_status`(`es_send_status`) USING BTREE, + INDEX `idx_ss_es_type`(`es_type`) USING BTREE, + INDEX `idx_ss_es_receiver`(`es_receiver`) USING BTREE, + INDEX `idx_ss_es_send_time`(`es_send_time`) USING BTREE, + INDEX `idx_ss_es_send_status`(`es_send_status`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_sms +-- ---------------------------- +INSERT INTO `sys_sms` VALUES ('402880e74dc2f361014dc2f8411e0001', '消息推送测试333', '2', '411944058@qq.com', NULL, '张三你好,你的订单4028d881436d514601436d521ae80165已付款!', '2015-06-05 17:06:01', '3', NULL, NULL, '认证失败错误的用户名或者密码', 'admin', '2015-06-05 17:05:59', 'admin', '2015-11-19 22:30:39'); +INSERT INTO `sys_sms` VALUES ('402880ea533647b00153364e74770001', '发个问候', '3', 'admin', NULL, '你好', '2016-03-02 00:00:00', '2', NULL, NULL, NULL, 'admin', '2016-03-02 15:50:24', 'admin', '2018-07-05 19:53:01'); +INSERT INTO `sys_sms` VALUES ('402880ee5a17e711015a17f3188e013f', '消息推送测试333', '2', '411944058@qq.com', NULL, '张三你好,你的订单4028d881436d514601436d521ae80165已付款!', NULL, '2', NULL, NULL, NULL, 'admin', '2017-02-07 17:41:31', 'admin', '2017-03-10 11:37:05'); +INSERT INTO `sys_sms` VALUES ('402880f05ab649b4015ab64b9cd80012', '消息推送测试333', '2', '411944058@qq.com', NULL, '张三你好,你的订单4028d881436d514601436d521ae80165已付款!', '2017-11-16 15:58:15', '3', NULL, NULL, NULL, 'admin', '2017-03-10 11:38:13', 'admin', '2017-07-31 17:24:54'); +INSERT INTO `sys_sms` VALUES ('402880f05ab7b035015ab7c4462c0004', '消息推送测试333', '2', '411944058@qq.com', NULL, '张三你好,你的订单4028d881436d514601436d521ae80165已付款!', '2017-11-16 15:58:15', '3', NULL, NULL, NULL, 'admin', '2017-03-10 18:29:37', NULL, NULL); +INSERT INTO `sys_sms` VALUES ('402881f3646a472b01646a4a5af00001', '催办:HR审批', '3', 'admin', NULL, 'admin,您好!\r\n请前待办任务办理事项!HR审批\r\n\r\n\r\n===========================\r\n此消息由系统发出', '2018-07-05 19:53:35', '2', NULL, NULL, NULL, 'admin', '2018-07-05 19:53:35', 'admin', '2018-07-07 13:45:24'); +INSERT INTO `sys_sms` VALUES ('402881f3647da06c01647da43a940014', '催办:HR审批', '3', 'admin', NULL, 'admin,您好!\r\n请前待办任务办理事项!HR审批\r\n\r\n\r\n===========================\r\n此消息由系统发出', '2018-07-09 14:04:32', '2', NULL, NULL, NULL, 'admin', '2018-07-09 14:04:32', 'admin', '2018-07-09 18:51:30'); + +-- ---------------------------- +-- Table structure for sys_sms_template +-- ---------------------------- +DROP TABLE IF EXISTS `sys_sms_template`; +CREATE TABLE `sys_sms_template` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', + `template_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模板标题', + `template_code` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '模板CODE', + `template_type` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '模板类型:1短信 2邮件 3微信', + `template_content` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '模板内容', + `template_test_json` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模板测试json', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人登录名称', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人登录名称', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uniq_templatecode`(`template_code`) USING BTREE, + UNIQUE INDEX `uk_sst_template_code`(`template_code`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_sms_template +-- ---------------------------- +INSERT INTO `sys_sms_template` VALUES ('1199606397416775681', '系统消息通知', 'sys_ts_note', '4', '

    系统通知

\n', NULL, '2019-11-27 16:30:27', 'admin', '2019-11-27 19:36:50', 'admin'); +INSERT INTO `sys_sms_template` VALUES ('1199615897335095298', '流程催办', 'bpm_cuiban', '4', '

   流程催办提醒

\n', NULL, '2019-11-27 17:08:12', 'admin', '2019-11-27 19:36:45', 'admin'); +INSERT INTO `sys_sms_template` VALUES ('1199648914107625473', '流程办理超时提醒', 'bpm_chaoshi_tip', '4', '

   流程办理超时提醒

\n', NULL, '2019-11-27 19:19:24', 'admin', '2019-11-27 19:36:37', 'admin'); +INSERT INTO `sys_sms_template` VALUES ('4028608164691b000164693108140003', '催办:${taskName}', 'SYS001', '3', '${userName},您好!\r\n请前待办任务办理事项!${taskName}\r\n\r\n\r\n===========================\r\n此消息由系统发出', '{\r\n\"taskName\":\"HR审批\",\r\n\"userName\":\"admin\"\r\n}', '2018-07-05 14:46:18', 'admin', '2018-07-05 18:31:34', 'admin'); + +-- ---------------------------- +-- Table structure for sys_tenant +-- ---------------------------- +DROP TABLE IF EXISTS `sys_tenant`; +CREATE TABLE `sys_tenant` ( + `id` int(11) NOT NULL COMMENT '租户编码', + `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '租户名称', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `begin_date` datetime(0) NULL DEFAULT NULL COMMENT '开始时间', + `end_date` datetime(0) NULL DEFAULT NULL COMMENT '结束时间', + `status` int(11) NULL DEFAULT NULL COMMENT '状态 1正常 0冻结', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '多租户信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_tenant +-- ---------------------------- +INSERT INTO `sys_tenant` VALUES (1, '北京租户001', '2020-07-10 15:43:32', 'admin', NULL, NULL, 1); + +-- ---------------------------- +-- Table structure for sys_third_account +-- ---------------------------- +DROP TABLE IF EXISTS `sys_third_account`; +CREATE TABLE `sys_third_account` ( + `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '编号', + `sys_user_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方登录id', + `third_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录来源', + `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像', + `status` tinyint(1) NULL DEFAULT NULL COMMENT '状态(1-正常,2-冻结)', + `del_flag` tinyint(1) NULL DEFAULT NULL COMMENT '删除状态(0-正常,1-已删除)', + `realname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '真实姓名', + `third_user_uuid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '第三方账号', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user`; +CREATE TABLE `sys_user` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id', + `username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登录账号', + `realname` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '真实姓名', + `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码', + `salt` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'md5密码盐', + `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像', + `birthday` datetime(0) NULL DEFAULT NULL COMMENT '生日', + `sex` tinyint(1) NULL DEFAULT NULL COMMENT '性别(0-默认未知,1-男,2-女)', + `email` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电子邮件', + `phone` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电话', + `org_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '机构编码', + `status` tinyint(1) NULL DEFAULT NULL COMMENT '性别(1-正常,2-冻结)', + `del_flag` tinyint(1) NULL DEFAULT NULL COMMENT '删除状态(0-正常,1-已删除)', + `third_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '第三方登录的唯一标识', + `third_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '第三方类型', + `activiti_sync` tinyint(1) NULL DEFAULT NULL COMMENT '同步工作流引擎(1-同步,0-不同步)', + `work_no` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '工号,唯一键', + `post` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '职务,关联职务表', + `telephone` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '座机号', + `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `user_identity` tinyint(1) NULL DEFAULT NULL COMMENT '身份(1普通成员 2上级)', + `depart_ids` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '负责部门', + `rel_tenant_ids` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '多租户标识', + `client_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '设备ID', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `index_user_name`(`username`) USING BTREE, + UNIQUE INDEX `uniq_sys_user_work_no`(`work_no`) USING BTREE, + UNIQUE INDEX `uniq_sys_user_username`(`username`) USING BTREE, + UNIQUE INDEX `uniq_sys_user_phone`(`phone`) USING BTREE, + UNIQUE INDEX `uniq_sys_user_email`(`email`) USING BTREE, + INDEX `index_user_status`(`status`) USING BTREE, + INDEX `index_user_del_flag`(`del_flag`) USING BTREE, + INDEX `idx_su_username`(`username`) USING BTREE, + INDEX `idx_su_status`(`status`) USING BTREE, + INDEX `idx_su_del_flag`(`del_flag`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_user +-- ---------------------------- +INSERT INTO `sys_user` VALUES ('1509464454510243842', 'system', '管理员', '600eda1b26b602ea', 'bwbBGF8E', NULL, NULL, NULL, NULL, NULL, 'A01', 1, 0, NULL, NULL, 1, '0451', '', NULL, 'admin', '2022-03-31 17:35:45', 'admin', '2022-03-31 17:37:07', 1, '', '', NULL); +INSERT INTO `sys_user` VALUES ('3d464b4ea0d2491aab8a7bde74c57e95', 'zhangsan', '张三', '02ea098224c7d0d2077c14b9a3a1ed16', 'x5xRdeKB', 'https://static.jeecg.com/temp/jmlogo_1606575041993.png', NULL, NULL, NULL, NULL, '财务部', 1, 1, NULL, NULL, 1, '0005', '总经理', NULL, 'admin', '2020-05-14 21:26:24', 'admin', '2020-09-09 14:42:51', 1, '', '', NULL); +INSERT INTO `sys_user` VALUES ('a75d45a015c44384a04449ee80dc3503', 'jeecg', 'jeecg', '58a714412072f0b9', 'mIgiYJow', 'https://static.jeecg.com/temp/国炬软件logo_1606575029126.png', NULL, 1, NULL, NULL, 'A02A01', 1, 1, NULL, NULL, 1, '00002', 'devleader', NULL, 'admin', '2019-02-13 16:02:36', 'admin', '2020-11-26 15:16:05', 1, '', NULL, NULL); +INSERT INTO `sys_user` VALUES ('e9ca23d68d884d4ebb19d07889727dae', 'admin', '管理员', 'cb362cfeefbf3d8d', 'RCGTeGiH', 'https://static.jeecg.com/temp/国炬软件logo_1606575029126.png', '2018-12-05 00:00:00', 1, 'jeecg@163.com', '18611111111', 'A01', 1, 0, NULL, NULL, 1, '00001', '总经理', NULL, NULL, '2020-06-21 17:54:10', 'admin', '2020-07-10 15:27:10', 2, 'c6d7cb4deeac411cb3384b1b31278596', '', NULL); +INSERT INTO `sys_user` VALUES ('f0019fdebedb443c98dcb17d88222c38', 'zhagnxiao', '张小红', 'f898134e5e52ae11a2ffb2c3b57a4e90', 'go3jJ4zX', 'https://static.jeecg.com/temp/jmlogo_1606575041993.png', '2019-04-01 00:00:00', NULL, NULL, NULL, '研发部,财务部', 2, 1, NULL, NULL, 1, '00003', '', NULL, 'admin', '2020-10-01 19:34:10', 'admin', '2020-11-26 15:24:59', 1, '', '', NULL); + +-- ---------------------------- +-- Table structure for sys_user_agent +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_agent`; +CREATE TABLE `sys_user_agent` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '序号', + `user_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名', + `agent_user_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '代理人用户名', + `start_time` datetime(0) NULL DEFAULT NULL COMMENT '代理开始时间', + `end_time` datetime(0) NULL DEFAULT NULL COMMENT '代理结束时间', + `status` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '状态0无效1有效', + `create_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人名称', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人登录名称', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人名称', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人登录名称', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `sys_company_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '所属公司', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uniq_username`(`user_name`) USING BTREE, + UNIQUE INDEX `uk_sug_user_name`(`user_name`) USING BTREE, + INDEX `statux_index`(`status`) USING BTREE, + INDEX `begintime_index`(`start_time`) USING BTREE, + INDEX `endtime_index`(`end_time`) USING BTREE, + INDEX `idx_sug_status`(`status`) USING BTREE, + INDEX `idx_sug_start_time`(`start_time`) USING BTREE, + INDEX `idx_sug_end_time`(`end_time`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户代理人设置' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Table structure for sys_user_depart +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_depart`; +CREATE TABLE `sys_user_depart` ( + `ID` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'id', + `user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户id', + `dep_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部门id', + PRIMARY KEY (`ID`) USING BTREE, + INDEX `index_depart_groupk_userid`(`user_id`) USING BTREE, + INDEX `index_depart_groupkorgid`(`dep_id`) USING BTREE, + INDEX `index_depart_groupk_uidanddid`(`user_id`, `dep_id`) USING BTREE, + INDEX `idx_sud_user_id`(`user_id`) USING BTREE, + INDEX `idx_sud_dep_id`(`dep_id`) USING BTREE, + INDEX `idx_sud_user_dep_id`(`user_id`, `dep_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_user_depart +-- ---------------------------- +INSERT INTO `sys_user_depart` VALUES ('1509464799768571905', '1509464454510243842', 'c6d7cb4deeac411cb3384b1b31278596'); +INSERT INTO `sys_user_depart` VALUES ('1281490128540393474', 'e9ca23d68d884d4ebb19d07889727dae', 'c6d7cb4deeac411cb3384b1b31278596'); + +-- ---------------------------- +-- Table structure for sys_user_role +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_role`; +CREATE TABLE `sys_user_role` ( + `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键id', + `user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户id', + `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色id', + PRIMARY KEY (`id`) USING BTREE, + INDEX `index2_groupuu_user_id`(`user_id`) USING BTREE, + INDEX `index2_groupuu_ole_id`(`role_id`) USING BTREE, + INDEX `index2_groupuu_useridandroleid`(`user_id`, `role_id`) USING BTREE, + INDEX `idx_sur_user_id`(`user_id`) USING BTREE, + INDEX `idx_sur_role_id`(`role_id`) USING BTREE, + INDEX `idx_sur_user_role_id`(`user_id`, `role_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户角色表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_user_role +-- ---------------------------- +INSERT INTO `sys_user_role` VALUES ('b3ffd9311a1ca296c44e2409b547384f', '01b802058ea94b978a2c96f4807f6b48', '1'); +INSERT INTO `sys_user_role` VALUES ('1509464799659520002', '1509464454510243842', '1509464524584480770'); +INSERT INTO `sys_user_role` VALUES ('f2922a38ba24fb53749e45a0c459adb3', '439ae3e9bcf7418583fcd429cadb1d72', '1'); +INSERT INTO `sys_user_role` VALUES ('ee45d0343ecec894b6886effc92cb0b7', '4d8fef4667574b24a9ccfedaf257810c', 'f6817f48af4fb3af11b9e8bf182f618b'); +INSERT INTO `sys_user_role` VALUES ('1281490128242597889', 'e9ca23d68d884d4ebb19d07889727dae', 'f6817f48af4fb3af11b9e8bf182f618b'); + +-- ---------------------------- +-- Table structure for test_demo +-- ---------------------------- +DROP TABLE IF EXISTS `test_demo`; +CREATE TABLE `test_demo` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人登录名称', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人登录名称', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名', + `sex` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别', + `age` int(11) NULL DEFAULT NULL COMMENT '年龄', + `descc` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `birthday` datetime(0) NULL DEFAULT NULL COMMENT '生日', + `user_code` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户编码', + `file_kk` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '附件', + `top_pic` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像', + `chegnshi` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '城市', + `ceck` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'checkbox', + `xiamuti` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '下拉多选', + `search_sel` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '搜索下拉', + `pop` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '弹窗', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of test_demo +-- ---------------------------- +INSERT INTO `test_demo` VALUES ('1331884149004910593', 'admin', '2020-11-26 16:55:01', NULL, NULL, '张三', '1', NULL, NULL, NULL, NULL, '', '', '130304', NULL, NULL, NULL, NULL); +INSERT INTO `test_demo` VALUES ('1331901553776869377', 'admin', '2020-11-26 18:04:10', 'admin', '2020-11-26 18:04:24', '张三', '2', NULL, '', NULL, '', '', '', '', '1', '1,2', 'hr', ''); +INSERT INTO `test_demo` VALUES ('4028810c6aed99e1016aed9b31b40002', NULL, NULL, 'admin', '2019-10-19 15:37:27', 'jeecg', '2', 55, '5', '2019-05-15 00:00:00', NULL, '', '', NULL, NULL, NULL, NULL, NULL); +INSERT INTO `test_demo` VALUES ('4028810c6b02cba2016b02cba21f0000', 'admin', '2019-05-29 16:53:48', 'admin', '2019-08-23 23:45:21', '张小红', '1', 8222, '8', '2019-04-01 00:00:00', NULL, '', '', NULL, NULL, NULL, NULL, NULL); +INSERT INTO `test_demo` VALUES ('4028810c6b40244b016b4030a0e40001', 'admin', '2019-06-10 15:00:57', 'admin', '2020-05-03 01:28:34', '小芳', '2', 0, NULL, '2019-04-01 00:00:00', NULL, '', '11_1582482670686.jpg', NULL, NULL, NULL, NULL, NULL); +INSERT INTO `test_demo` VALUES ('fa1d1c249461498d90f405b94f60aae0', '', NULL, 'admin', '2019-05-15 12:30:28', '战三', '2', 222, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for test_enhance_select +-- ---------------------------- +DROP TABLE IF EXISTS `test_enhance_select`; +CREATE TABLE `test_enhance_select` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `province` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '省份', + `city` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '市', + `area` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '区', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of test_enhance_select +-- ---------------------------- +INSERT INTO `test_enhance_select` VALUES ('1256614575282958338', '1230769290609725441', '1230769470889299970', '1230769620021972993', '2020-05-03 00:00:36', 'admin'); +INSERT INTO `test_enhance_select` VALUES ('402880e570801ffe01708053743c002e', '1230769253267836929', '1230769769930592257', '1230769855347593217', '2020-02-26 15:08:37', 'admin'); +INSERT INTO `test_enhance_select` VALUES ('402880e570801ffe017080538b24002f', '1230769290609725441', '1230769470889299970', '1230769620021972993', '2020-02-26 15:08:43', 'admin'); +INSERT INTO `test_enhance_select` VALUES ('402880e570801ffe01708053b2b10030', '1230769253267836929', '1230769347157331969', '1230769407907631106', '2020-02-26 15:08:53', 'admin'); + +-- ---------------------------- +-- Table structure for test_note +-- ---------------------------- +DROP TABLE IF EXISTS `test_note`; +CREATE TABLE `test_note` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户名', + `age` int(11) NULL DEFAULT NULL COMMENT '年龄', + `sex` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '性别', + `birthday` datetime(0) NULL DEFAULT NULL COMMENT '生日', + `contents` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请假原因', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of test_note +-- ---------------------------- +INSERT INTO `test_note` VALUES ('1257876639515222017', 'admin', '2020-05-06 11:35:35', NULL, NULL, 'A01', '不同意', 20, '1', '2020-05-06 00:00:00', '999'); +INSERT INTO `test_note` VALUES ('1260208702503366657', 'admin', '2020-05-12 22:02:23', 'admin', '2020-07-11 11:40:24', 'A01', 'jeecg', 22233, '2', '2020-05-12 00:00:00', 'sss'); +INSERT INTO `test_note` VALUES ('1304309860578455553', 'admin', '2020-09-11 14:44:38', NULL, NULL, 'A01', 'zhangsan', 222, '1', '2020-09-11 00:00:00', '222'); + +-- ---------------------------- +-- Table structure for test_order_main +-- ---------------------------- +DROP TABLE IF EXISTS `test_order_main`; +CREATE TABLE `test_order_main` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `order_code` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '订单编码', + `order_date` datetime(0) NULL DEFAULT NULL COMMENT '下单时间', + `descc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of test_order_main +-- ---------------------------- +INSERT INTO `test_order_main` VALUES ('1256629667445714946', 'admin', '2020-05-03 01:00:34', 'admin', '2020-11-26 15:22:35', '鼠标', '2020-05-03 00:00:00', '15'); +INSERT INTO `test_order_main` VALUES ('1331861164286099457', 'admin', '2020-11-26 15:23:41', 'admin', '2020-11-26 19:49:56', '33', '2020-11-21 00:00:00', '44'); +INSERT INTO `test_order_main` VALUES ('1332354141651570690', 'admin', '2020-11-28 00:02:36', NULL, NULL, '11', '2020-11-28 00:00:00', '2'); +INSERT INTO `test_order_main` VALUES ('4028810c6b40244b016b40686dfb0003', 'admin', '2019-06-10 16:01:54', 'admin', '2020-02-24 02:31:59', 'B002', '2019-06-10 00:00:00', '123'); +INSERT INTO `test_order_main` VALUES ('4028810c6b40244b016b4068ef890006', 'admin', '2019-06-10 16:02:27', 'admin', '2020-05-03 01:00:17', '00001', '2019-06-10 00:00:00', '购买产品BOOT'); + +-- ---------------------------- +-- Table structure for test_order_product +-- ---------------------------- +DROP TABLE IF EXISTS `test_order_product`; +CREATE TABLE `test_order_product` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键', + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `product_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '产品名字', + `price` double(32, 0) NULL DEFAULT NULL COMMENT '价格', + `num` int(11) NULL DEFAULT NULL COMMENT '数量', + `descc` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述', + `order_fk_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '订单外键ID', + `pro_type` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '产品类型', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of test_order_product +-- ---------------------------- +INSERT INTO `test_order_product` VALUES ('1331860890813284353', 'admin', '2020-11-26 15:22:35', NULL, NULL, '44', 44, 44, '', '1256629667445714946', '1'); +INSERT INTO `test_order_product` VALUES ('1331861166739767297', 'admin', '2020-11-26 19:49:56', NULL, NULL, '44', 44, 4, '444', '1331861164286099457', '2'); +INSERT INTO `test_order_product` VALUES ('1331861166752350210', 'admin', '2020-11-26 15:23:41', NULL, NULL, '44', 44, 4, '44', '1331861164286099457', ''); +INSERT INTO `test_order_product` VALUES ('1331861166769127425', 'admin', '2020-11-26 15:23:41', NULL, NULL, '44', 44, 4, '44', '1331861164286099457', ''); +INSERT INTO `test_order_product` VALUES ('1331928171161427969', 'admin', '2020-11-26 19:49:56', NULL, NULL, '66', 66, 66, '666', '1331861164286099457', '2'); +INSERT INTO `test_order_product` VALUES ('1332354141873868802', 'admin', '2020-11-28 00:02:36', NULL, NULL, '2', 22, 2, '', '1332354141651570690', '2'); +INSERT INTO `test_order_product` VALUES ('1332354141940977665', 'admin', '2020-11-28 00:02:36', NULL, NULL, '2', 2, 2, '', '1332354141651570690', '2'); +INSERT INTO `test_order_product` VALUES ('1332354141961949186', 'admin', '2020-11-28 00:02:36', NULL, NULL, '2', 22, 2, '', '1332354141651570690', ''); +INSERT INTO `test_order_product` VALUES ('1332354141978726401', 'admin', '2020-11-28 00:02:36', NULL, NULL, '2', 2, 2, '', '1332354141651570690', '1'); +INSERT INTO `test_order_product` VALUES ('15665749852471', 'admin', '2020-05-03 01:00:17', NULL, NULL, '樱桃键盘', 200, 22, '', '4028810c6b40244b016b4068ef890006', '2'); +INSERT INTO `test_order_product` VALUES ('15665749948861', 'admin', '2020-02-24 02:05:38', NULL, NULL, '333', 33, NULL, '', '402831816a38e7fd016a38e825c90003', ''); +INSERT INTO `test_order_product` VALUES ('15884355700882143174', 'admin', '2020-05-03 01:00:17', NULL, NULL, '雷蛇鼠标', 100, NULL, '', '4028810c6b40244b016b4068ef890006', '1'); +INSERT INTO `test_order_product` VALUES ('15884355711373624689', 'admin', '2020-05-03 01:00:17', NULL, NULL, 'AOC显示器', 900, NULL, '', '4028810c6b40244b016b4068ef890006', '1'); +INSERT INTO `test_order_product` VALUES ('15884388229280883233', 'admin', '2020-11-26 15:22:35', NULL, NULL, '华为手机', 25, 35, '345', '1256629667445714946', '1'); +INSERT INTO `test_order_product` VALUES ('15884388231401967996', 'admin', '2020-07-11 11:36:36', NULL, NULL, '低代码平台', 25, 35, '445', '1256629667445714946', '1'); +INSERT INTO `test_order_product` VALUES ('15884388463052345317', 'admin', '2020-07-11 11:36:36', NULL, NULL, '表单设计器', 55, 55, '55', '1256629667445714946', '2'); +INSERT INTO `test_order_product` VALUES ('402831816a38e7fd016a38e7fdeb0001', 'admin', '2019-04-20 12:01:29', NULL, NULL, '笔记本', 100, 10, NULL, '402831816a38e7fd016a38e7fddf0000', NULL); +INSERT INTO `test_order_product` VALUES ('402831816a38e7fd016a38e7fdf10002', 'admin', '2019-04-20 12:01:29', NULL, NULL, '显示器', 300, 1, NULL, '402831816a38e7fd016a38e7fddf0000', NULL); +INSERT INTO `test_order_product` VALUES ('4028810c6b40244b016b40686e050004', 'admin', '2020-02-24 02:31:59', NULL, NULL, '笔记本', 2000, 2, '123', '4028810c6b40244b016b40686dfb0003', '2'); +INSERT INTO `test_order_product` VALUES ('4028810c6b40244b016b406884080005', 'admin', '2020-02-24 02:05:38', NULL, NULL, '333', NULL, 33, '', '402831816a38e7fd016a38e825c90003', ''); + +-- ---------------------------- +-- Table structure for test_person +-- ---------------------------- +DROP TABLE IF EXISTS `test_person`; +CREATE TABLE `test_person` ( + `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sex` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '性别', + `name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名', + `content` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '请假原因', + `be_date` datetime(0) NULL DEFAULT NULL COMMENT '请假时间', + `qj_days` int(11) NULL DEFAULT NULL COMMENT '请假天数', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of test_person +-- ---------------------------- +INSERT INTO `test_person` VALUES ('8ca668defdae47df8649a5477ae08b05', 'admin', '2019-04-12 09:51:37', NULL, NULL, '1', 'zhangdaiscott', 'dsdsd', '2019-04-12 00:00:00', 2); + +-- ---------------------------- +-- Table structure for test_shoptype_tree +-- ---------------------------- +DROP TABLE IF EXISTS `test_shoptype_tree`; +CREATE TABLE `test_shoptype_tree` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `type_name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品分类', + `pic` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类图片', + `pid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '父级节点', + `has_child` varchar(3) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否有子节点', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of test_shoptype_tree +-- ---------------------------- +INSERT INTO `test_shoptype_tree` VALUES ('1256628820489908225', 'admin', '2020-05-03 00:57:12', NULL, NULL, 'A01', '衣服', NULL, '0', '0'); +INSERT INTO `test_shoptype_tree` VALUES ('1256628843097206786', 'admin', '2020-05-03 00:57:17', NULL, NULL, 'A01', '电子产品', NULL, '0', '0'); +INSERT INTO `test_shoptype_tree` VALUES ('1256629035921944577', 'admin', '2020-05-03 00:58:03', NULL, NULL, 'A01', '三星显示器', 'gh_f28e66390fc9_344 (shop)_1588438682583.jpg', '1256628864848867329', '0'); +INSERT INTO `test_shoptype_tree` VALUES ('1256629093740425218', 'admin', '2020-05-03 00:58:17', 'admin', '2020-05-03 22:32:37', 'A01', '手机', '', '0', '1'); +INSERT INTO `test_shoptype_tree` VALUES ('1256629139206680578', 'admin', '2020-05-03 00:58:28', NULL, NULL, 'A01', 'iPhone', 'e1fe9925bc315c60addea1b98eb1cb1349547719_1588438707727.jpg', '1256629093740425218', '0'); +INSERT INTO `test_shoptype_tree` VALUES ('1256629188993069058', 'admin', '2020-05-03 00:58:40', 'admin', '2020-05-03 00:58:55', 'A01', '华为手机', 'jeewxshop测试号_1588438719823.jpg', '1256629093740425218', '0'); + +-- ---------------------------- +-- Table structure for tqc_gateway_common +-- ---------------------------- +DROP TABLE IF EXISTS `tqc_gateway_common`; +CREATE TABLE `tqc_gateway_common` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `heard_logo_url` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '门户头部logo', + `heard_logo_urlen` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '门户头部logo-英文版', + `footer_logo_url` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '门户尾部logo', + `footer_logo_urlen` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '门户尾部logo-英文版', + `copyright` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '版权所有', + `mailbox` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '版权所有-英文版', + `mailboxen` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱-英文版', + `copyrighten` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '版权所有-英文版', + `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址', + `addressen` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '地址-英文版', + `record_number` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备案号', + `record_numberen` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备案号-英文版', + `homepage_url` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '学校主页地址', + `homepage_urlen` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '学校主页地址-英文版', + `wechat_url` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '官方微信', + `wechat_urlen` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '官方微信-英文版', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '门户-基本配置' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tqc_gateway_common +-- ---------------------------- +INSERT INTO `tqc_gateway_common` VALUES ('1', 'admin', '2022-03-25 09:55:28', NULL, '2022-03-31 17:52:37', NULL, 'temp/logo_1648173259165.png', 'temp/logo_1648173259165.png', 'temp/logo2_1648173262212.png', 'temp/logo2_1648173262212.png', '吉林农业大学', 'webmaster@jlau.edu.cn', 'webmaster@jlau.edu.cn', 'Jilin Agricultural University', '吉林省长春市新城大街2888号(130118)', '吉林省长春市新城大街2888号(130118)(en)', '吉ICP备10001377号-1 吉公网安备22017202000217号', '吉ICP备10001377号-1 吉公网安备22017202000217号(en)', 'https://www.baidu.com/', 'http://www.jlau.edu.cn', 'temp/erweima_1648173302632.png', 'temp/erweima_1648173302632.png'); + +-- ---------------------------- +-- Table structure for tqc_i18n_config +-- ---------------------------- +DROP TABLE IF EXISTS `tqc_i18n_config`; +CREATE TABLE `tqc_i18n_config` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `identification` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '语言标识', + `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '显示名称', + `i18n_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '国际化JSON', + `is_enable` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否启用(Y:是,N:否),同一个标识只能有一个启用的', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '门户-国际化配置' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tqc_i18n_config +-- ---------------------------- +INSERT INTO `tqc_i18n_config` VALUES ('1506874219039563778', NULL, '2022-03-24 14:03:05', 'admin', '2022-04-08 14:50:05', NULL, 'cn', '中文', '{\n //公用部分\n common: {\n schoolHomePage: \'学校主页\',\n homePage: \'网站首页\',\n contactUs: \'联系我们\',\n searchPlaceholder: \'请输入要搜索的内容\',\n homeName: \'首页\',\n copyright: \'版权所有:\',\n mailbox: \'邮箱:\',\n address: \'地址:\',\n recordNumber: \'备案号:\',\n wechat: \'官方微信\',\n more: \'更多\',\n workDynamics: \'工作动态\',\n notice: \'通知公告\',\n fastGuid: \'快速导航\',\n link: \'友情链接\',\n currentLocation: \'当前位置:\',\n author: \'作者:\',\n source: \'来源:\',\n publishTime: \'发布日期:\',\n enclosure: \'附件:\',\n },\n //组件内容\n assembly:{\n datePicker: \'选择时间\'\n },\n }', 'Y'); +INSERT INTO `tqc_i18n_config` VALUES ('1506874335557328898', NULL, '2022-03-24 14:03:33', 'admin', '2022-04-08 14:49:52', NULL, 'en', 'English', '{\n //公用部分\n common: {\n schoolHomePage: \'school home page\',\n homePage: \'home page\',\n contactUs: \'countact us\',\n searchPlaceholder: \'Please enter the content to search\',\n homeName: \'home\',\n copyright: \'copyright:\',\n mailbox: \'mailbox:\',\n address: \'address:\',\n recordNumber: \'Record number:\',\n wechat: \'Official wechat\',\n more: \'more\',\n workDynamics: \'work Dynamics\',\n notice: \'notice\',\n fastGuid: \'fast Guid\',\n link: \'link\',\n currentLocation: \'current Location:\',\n author: \'author:\',\n source: \'source:\',\n publishTime: \'Release date:\',\n enclosure: \'enclosure:\',\n },\n //组件内容\n assembly:{\n datePicker: \'select time\'\n },\n }', 'Y'); + +-- ---------------------------- +-- Table structure for tqd_gateway_article +-- ---------------------------- +DROP TABLE IF EXISTS `tqd_gateway_article`; +CREATE TABLE `tqd_gateway_article` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'id', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `column_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分类-栏目表ID', + `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题', + `titleen` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题-英文版', + `cover` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '封面图url', + `coveren` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '封面图url--英文版', + `type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文章类型', + `author` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '作者', + `authoren` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '作者-英文版', + `source` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '来源', + `sourceen` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '来源-英文版', + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文章内容', + `contenten` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文章内容-英文版', + `files` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '附件', + `filesen` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '附件-英文版', + `is_release` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否发布(Y:是N:否)', + `content_file` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文章内容文件', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '门户-文章' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tqd_gateway_article +-- ---------------------------- +INSERT INTO `tqd_gateway_article` VALUES ('1508288564728627201', NULL, '2022-03-28 00:00:00', NULL, '2022-03-31 14:21:34', NULL, '1508282344655482882', '第一篇文章', 'one page article', 'temp/banner_1648438882079.png', 'temp/banner1_1648438886009.png', '首页轮播', '张三', 'zhangsan', 'xx网', 'xxwebsit', '

中文的内容

\n

加粗

\n

斜体

\n

右侧对齐

', '

英文的内容

\n

加粗

\n

斜体

\n

右侧对齐

', NULL, NULL, 'Y', NULL); +INSERT INTO `tqd_gateway_article` VALUES ('1508426390250094593', NULL, '2022-03-28 20:50:51', NULL, NULL, NULL, NULL, '轮播', NULL, 'temp/banner_1648471837761.png', NULL, '首页轮播', 'none', NULL, 'none', NULL, '

none

', '', NULL, NULL, 'Y', NULL); +INSERT INTO `tqd_gateway_article` VALUES ('1508426630185254913', NULL, '2022-03-28 00:00:00', NULL, '2022-04-08 14:23:03', NULL, '3', 'cscs', 'csccsc', 'temp/banner_1648471837761.png', NULL, NULL, 'cscs', NULL, 'cscsc', NULL, '

cscscscs

', '

啊实打实大三

', 'fujian/604d562fa40ee8e7a846b2b303c6b98b1f1d893a_1649398900692.jpg', 'fujianen/604d562fa40ee8e7a846b2b303c6b98b1f1d893a_1649398906385.jpg,fujianen/1f1e86dfff42ca428e79b5e13011d288349c2bf9_1649398915307.png,fujianen/604d562fa40ee8e7a846b2b303c6b98b1f1d893a_1649398974343.jpg', 'Y', NULL); +INSERT INTO `tqd_gateway_article` VALUES ('1508426630185254914', NULL, '2022-03-28 00:00:00', NULL, '2022-03-31 14:21:44', NULL, '2', 'cscs', 'csccsc', 'temp/banner_1648471837761.png', NULL, '首页轮播', 'cscs', NULL, 'cscsc', NULL, '

cscscscs

', NULL, NULL, NULL, 'Y', NULL); + +-- ---------------------------- +-- Table structure for tqd_gateway_column +-- ---------------------------- +DROP TABLE IF EXISTS `tqd_gateway_column`; +CREATE TABLE `tqd_gateway_column` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'id', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称', + `nameen` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称-英文版', + `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型', + `parent` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '上级ID 0为顶级', + `is_enable` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否启用', + `sort` int(11) NULL DEFAULT NULL COMMENT '排序', + `icon` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '门户-栏目' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tqd_gateway_column +-- ---------------------------- +INSERT INTO `tqd_gateway_column` VALUES ('1', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 14:06:37', NULL, '新闻中心', 'News Center', '隐藏在头部显示', NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508281679451451394', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 12:01:32', NULL, '部门简介', 'Departments', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508282344655482882', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 12:01:38', NULL, '部门职责', 'Responsibility', NULL, '1508281679451451394', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508293491119030274', NULL, '2022-03-28 12:02:46', NULL, NULL, NULL, '国际交流科', 'International Exchange', NULL, '1508281679451451394', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508293559830118401', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 12:03:06', NULL, '综合业务科', 'Integrated Business', NULL, '1508281679451451394', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508293703577305089', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 12:04:51', NULL, '海外学习', 'Study abroad', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508293863887798274', NULL, '2022-03-28 12:04:15', NULL, NULL, NULL, '项目介绍', 'Project introduction', NULL, '1508293703577305089', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508293905881169921', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 12:04:47', NULL, '规章制度', 'Regulation', NULL, '1508293703577305089', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508293987569434626', NULL, '2022-03-28 12:04:44', NULL, NULL, NULL, '合作办学', 'Cooperation', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508294063201124354', NULL, '2022-03-28 12:05:02', NULL, NULL, NULL, '外籍专家', 'Foreign Expert', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508294101805498369', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 12:05:14', NULL, '国际会议', 'Conference', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508294174937382913', NULL, '2022-03-28 12:05:29', NULL, NULL, NULL, '因公出访', 'Business Trip', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508294243073851393', NULL, '2022-03-28 12:05:45', NULL, NULL, NULL, '港澳台事务', 'HK,Macao,Taiwan', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508294281619505153', NULL, '2022-03-28 12:05:54', NULL, NULL, NULL, '党建工作', 'Party Building', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1508294315236851714', NULL, '2022-03-28 12:06:02', NULL, NULL, NULL, '下载专区', 'Download', NULL, NULL, 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807021152137217', NULL, '2022-04-01 16:16:59', NULL, NULL, NULL, '中意合作办学项目', 'China&Italy Project', NULL, '1508293987569434626', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807070959497217', NULL, '2022-04-01 00:00:00', NULL, '2022-04-01 16:17:30', NULL, '中美合作办学项目', 'China&U.S.A Project', NULL, '1508293987569434626', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807132049534978', NULL, '2022-04-01 16:17:26', NULL, NULL, NULL, '管理办法', 'Management measure', NULL, '1508294063201124354', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807215944003585', NULL, '2022-04-01 16:17:46', NULL, NULL, NULL, '引智项目', 'Conference,project', NULL, '1508294063201124354', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807287272337409', NULL, '2022-04-01 16:18:03', NULL, NULL, NULL, '管理办法', 'Management measure', NULL, '1508294174937382913', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807340200259585', NULL, '2022-04-01 16:18:15', NULL, NULL, NULL, '办理流程', 'Handling process', NULL, '1508294174937382913', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807560283779073', NULL, '2022-04-01 16:19:08', NULL, NULL, NULL, '国际会议', 'Conference', NULL, '1508294101805498369', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807620237160449', NULL, '2022-04-01 16:19:22', NULL, NULL, NULL, '港澳台事务', 'HK,Macao,Taiwan', NULL, '1508294243073851393', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807679662059522', NULL, '2022-04-01 16:19:36', NULL, NULL, NULL, '党建工作', 'Party Building', NULL, '1508294281619505153', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('1509807719482781698', NULL, '2022-04-01 16:19:46', NULL, NULL, NULL, '下载专区', 'Download', NULL, '1508294315236851714', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('2', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 14:06:26', NULL, '工作动态', 'Work dynamics', NULL, '1', 'Y', NULL, NULL); +INSERT INTO `tqd_gateway_column` VALUES ('3', NULL, '2022-03-28 14:06:20', NULL, NULL, NULL, '通知公告', 'Notice notice', NULL, '1', 'Y', NULL, NULL); + +-- ---------------------------- +-- Table structure for tqd_gateway_links +-- ---------------------------- +DROP TABLE IF EXISTS `tqd_gateway_links`; +CREATE TABLE `tqd_gateway_links` ( + `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'id', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', + `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期', + `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称', + `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型(显示在哪)', + `url` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '链接', + `urlen` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '链接-英文版', + `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题', + `titleen` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题-英文版', + `logo` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'logo url', + `logoen` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'logo url-英文版', + `is_enable` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '是否启用', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '门户-友情链接,快速导航' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of tqd_gateway_links +-- ---------------------------- +INSERT INTO `tqd_gateway_links` VALUES ('1508290886900842497', NULL, '2022-03-28 11:52:25', NULL, NULL, NULL, '百毒', '友情链接', 'https://www.baidu.com/', 'https://baidu.com/', '百毒', 'baidu', 'temp/yqlj_2_1648439538461.png', 'temp/yqlj_3_1648439542846.png', 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1508393941486960641', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 18:43:36', NULL, '学生留学申报系统', '快速导航', 'https://baidu.com', NULL, '学生留学申报系统', NULL, 'temp/tzgg_4_1648464077280.png', NULL, 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1508394122521509890', NULL, '2022-03-28 00:00:00', NULL, '2022-03-28 18:43:41', NULL, '因公出访管理系统', '快速导航', 'https://www.baidu.com', NULL, '因公出访管理系统', NULL, 'temp/tzgg_5_1648464156028.png', NULL, 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1509432193333161986', NULL, '2022-03-31 00:00:00', NULL, '2022-03-31 15:27:58', NULL, 'aaa', '友情链接', 'cascasc', NULL, ' ccaaac', '11231', 'temp/yqlj_3_1648711676770.png', NULL, 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1509432244394618882', NULL, '2022-03-31 00:00:00', NULL, '2022-03-31 15:29:00', NULL, 'sdsadasd', '友情链接', '123123', NULL, 'adasd', NULL, 'temp/yqlj_6_1648711664676.png', NULL, 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1509432358928478209', NULL, '2022-03-31 00:00:00', NULL, '2022-03-31 15:28:46', NULL, '12312', '友情链接', '123123', NULL, '123123', NULL, 'temp/yqlj_4_1648711685667.png', NULL, 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1509432644791267330', NULL, '2022-03-31 15:29:21', NULL, NULL, NULL, '1312', '友情链接', '123123', NULL, '321312', NULL, 'temp/yqlj_5_1648711759463.png', NULL, 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1509447057556467714', NULL, '2022-03-31 16:26:37', NULL, NULL, NULL, '123123', '友情链接', '123', NULL, '123', NULL, 'temp/yqlj_5_1648715189842.png', NULL, 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1509447100376117249', NULL, '2022-03-31 16:26:48', NULL, NULL, NULL, '123', '友情链接', '123213213', NULL, '123123', NULL, 'temp/yqlj_5_1648715206599.png', NULL, 'Y'); +INSERT INTO `tqd_gateway_links` VALUES ('1509447164691574786', NULL, '2022-03-31 16:27:03', NULL, NULL, NULL, '1231', '友情链接', '123123123', NULL, '123123', NULL, 'temp/yqlj_6_1648715220862.png', NULL, 'Y'); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..a16b543 --- /dev/null +++ b/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# https://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..c8d4337 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..664517b --- /dev/null +++ b/pom.xml @@ -0,0 +1,261 @@ + + + 4.0.0 + com.nyzy + nyzy + 0.0.1 + nyzy + 吉林省农业资源薪资平台 + + + org.springframework.boot + spring-boot-starter-parent + 2.3.5.RELEASE + + + + + + 2.4.0 + 1.8 + UTF-8 + Hoxton.SR8 + 2.2.3.RELEASE + 2.2.0 + 1.2.75 + 2.0.4 + 2.0.4 + 42.2.6 + 11.2.0.3 + 4.0 + 8.0.21 + 3.2.0 + 5.3.8 + 3.13.6 + 1.9.4 + 29.0-jre + 3.4.1 + 1.1.22 + 2.6 + 1.0.0 + 3.6.0 + 1.7.0 + 3.11.0 + 3.1.0 + 1.2.5 + 1.2.2 + 4.0.0 + 1.3.2 + 1.6.1 + 7.2.23 + 2.5.1 + 1.1.01 + + + + + local + jeecg Repository + http://maven.jeecg.org/nexus/content/repositories/jeecg + + + jeecg + 161 Snapshot Repository + http://maven.jeecg.org/nexus/content/repositories/jeecg + + + + + + aliyun + aliyun Repository + http://maven.aliyun.com/nexus/content/groups/public + + false + + + + jeecg + jeecg Repository + http://maven.jeecg.org/nexus/content/repositories/jeecg + + false + + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.projectlombok + lombok + + + + com.alibaba + fastjson + ${fastjson.version} + + + net.coobird + thumbnailator + 0.4.8 + + + com.sun + tools + ${java.version} + system + ${env.JAVA_HOME}/lib/tools.jar + + + + org.jeecgframework.boot + jeecg-system-local-api + ${jeecgboot.version} + + + + org.jeecgframework.boot + jeecg-boot-module-system + ${jeecgboot.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + org.apache.maven.plugins + maven-resources-plugin + + + woff + woff2 + eot + ttf + svg + + + + + + + src/main/resources + + true + + **/*.ttc + + + + src/main/resources + false + + **/*.ttc + + + + src/main/java + + **/*.xml + **/*.json + **/*.ftl + **/*.ttc + + + + + + + + + dev + + + true + + + + dev + + jeecg + + 127.0.0.1:8848 + + + + DEFAULT_GROUP + + 127.0.0.1:8848 + + + + + test + + + test + + jeecg + + 127.0.0.1:8848 + + + + DEFAULT_GROUP + + 127.0.0.1:8848 + + + + + prod + + + prod + + jeecg + + 127.0.0.1:8848 + + + + DEFAULT_GROUP + + 127.0.0.1:8848 + + + + + diff --git a/rebuild.bat b/rebuild.bat new file mode 100644 index 0000000..8465a1c --- /dev/null +++ b/rebuild.bat @@ -0,0 +1,3 @@ +@echo off +call mvn clean package +pause \ No newline at end of file diff --git a/run.bat b/run.bat new file mode 100644 index 0000000..db17330 --- /dev/null +++ b/run.bat @@ -0,0 +1,7 @@ +@echo off & title "СԵ" & color 17 +call mvn clean package +title "ɣ" & color B0 +rem java -jar jenkins.war ChttpPort=9999 +for /f "delims=" %%i in ('dir target\*.jar /b ') do @set jarPath=%%i +java -jar -Xms1024m -Xmx1536m -XX:PermSize=128M -XX:MaxPermSize=256M -Dspring.profiles.active=dev ./target/%jarPath% +pause \ No newline at end of file diff --git a/runWar.bat b/runWar.bat new file mode 100644 index 0000000..f8ca706 --- /dev/null +++ b/runWar.bat @@ -0,0 +1,9 @@ +@echo off & title "СԵ" & color 17 +run ǰ.bat +call mvn clean package +run .bat +title "ɣ" & color B0 +rem java -jar jenkins.war ChttpPort=9999 +for /f "delims=" %%i in ('dir target\*.war /b ') do @set jarPath=%%i +java -jar -Xms1024m -Xmx1536m -XX:PermSize=128M -XX:MaxPermSize=256M -Dspring.profiles.active=dev ./target/%jarPath% ChttpPort=8080 +pause \ No newline at end of file diff --git a/src/main/java/com/nd/ModuleApplication.java b/src/main/java/com/nd/ModuleApplication.java new file mode 100644 index 0000000..a28f0f6 --- /dev/null +++ b/src/main/java/com/nd/ModuleApplication.java @@ -0,0 +1,47 @@ +package com.nd; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.jeecg.common.util.oConvertUtils; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.core.env.Environment; + +import lombok.extern.slf4j.Slf4j; + +/** + * 单体启动类(采用此类启动项目为单体模式) + */ +@Slf4j +@SpringBootApplication +@ComponentScan(basePackages = {"org.jeecg","com.nd"}) +//@EnableAutoConfiguration(exclude={org.activiti.spring.boot.SecurityAutoConfiguration.class}) +public class ModuleApplication extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(ModuleApplication.class); + } + + public static void main(String[] args) throws UnknownHostException { + ConfigurableApplicationContext application = SpringApplication.run(ModuleApplication.class, args); + Environment env = application.getEnvironment(); + String ip = InetAddress.getLocalHost().getHostAddress(); + String port = env.getProperty("server.port"); + + String path = oConvertUtils.getString(env.getProperty("server.servlet.context-path")); + log.info("\n----------------------------------------------------------\n\t" + + "Application Jeecg-Boot is running! Access URLs:\n\t" + + "Local: \t\thttp://localhost:" + port + path + "/\n\t" + + "External: \thttp://" + ip + ":" + port + path + "/\n\t" + + "Swagger文档: \thttp://" + ip + ":" + port + path + "/doc.html\n" + + "----------------------------------------------------------"); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/nd/gateway/controller/GatewayArticleController.java b/src/main/java/com/nd/gateway/controller/GatewayArticleController.java new file mode 100644 index 0000000..4150df7 --- /dev/null +++ b/src/main/java/com/nd/gateway/controller/GatewayArticleController.java @@ -0,0 +1,216 @@ +package com.nd.gateway.controller; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.nd.gateway.entity.GatewayColumn; +import com.nd.gateway.service.IGatewayColumnService; +import org.apache.commons.lang.StringUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import com.nd.gateway.entity.GatewayArticle; +import com.nd.gateway.service.IGatewayArticleService; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: 门户-文章 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Api(tags="门户-文章") +@RestController +@RequestMapping("/gateway/gatewayArticle") +@Slf4j +public class GatewayArticleController extends JeecgController { + + @Autowired + private IGatewayArticleService gatewayArticleService; + + @Autowired + private IGatewayColumnService gatewayColumnService; + + /** + * 分页列表查询 + * + * @param gatewayArticle + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "门户-文章-分页列表查询") + @ApiOperation(value="门户-文章-分页列表查询", notes="门户-文章-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(GatewayArticle gatewayArticle, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(gatewayArticle, req.getParameterMap()); + Page page = new Page(pageNo, pageSize); + IPage pageList = gatewayArticleService.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param gatewayArticle + * @return + */ + @AutoLog(value = "门户-文章-添加") + @ApiOperation(value="门户-文章-添加", notes="门户-文章-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody GatewayArticle gatewayArticle) { + gatewayArticleService.save(gatewayArticle); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param gatewayArticle + * @return + */ + @AutoLog(value = "门户-文章-编辑") + @ApiOperation(value="门户-文章-编辑", notes="门户-文章-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody GatewayArticle gatewayArticle) { + gatewayArticleService.updateById(gatewayArticle); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "门户-文章-通过id删除") + @ApiOperation(value="门户-文章-通过id删除", notes="门户-文章-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + gatewayArticleService.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "门户-文章-批量删除") + @ApiOperation(value="门户-文章-批量删除", notes="门户-文章-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.gatewayArticleService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "门户-文章-通过id查询") + @ApiOperation(value="门户-文章-通过id查询", notes="门户-文章-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + GatewayArticle gatewayArticle = gatewayArticleService.getById(id); + if(gatewayArticle==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(gatewayArticle); + } + + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "门户-文章-通过id查询,带栏目") + @ApiOperation(value="门户-文章-通过id查询,带栏目", notes="门户-文章-通过id查询,带栏目") + @GetMapping(value = "/queryArticleById") + public Result queryArticleById(@RequestParam(name="id",required=true) String id) { + GatewayArticle gatewayArticle = gatewayArticleService.getById(id); + if(gatewayArticle != null && StringUtils.isNotBlank(gatewayArticle.getColumnId())){ + //如果有栏目ID,则反着查询出当前栏目和父级栏目和父级下的全部栏目列表 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("id",gatewayArticle.getColumnId()); + queryWrapper.eq("is_enable","Y"); + queryWrapper.last("limit 1"); + gatewayArticle.setCurrentGatewayColumn(gatewayColumnService.getOne(queryWrapper)); + if(gatewayArticle.getCurrentGatewayColumn() != null){ + queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("id",gatewayArticle.getCurrentGatewayColumn().getParent()); + queryWrapper.eq("is_enable","Y"); + queryWrapper.last("limit 1"); + gatewayArticle.setParentGatewayColumn(gatewayColumnService.getOne(queryWrapper)); + queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("parent",gatewayArticle.getCurrentGatewayColumn().getParent()); + queryWrapper.eq("is_enable","Y"); + gatewayArticle.setGatewayColumnList(gatewayColumnService.list(queryWrapper)); + } + } + if(gatewayArticle==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(gatewayArticle); + } + + /** + * 导出excel + * + * @param request + * @param gatewayArticle + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, GatewayArticle gatewayArticle) { + return super.exportXls(request, gatewayArticle, GatewayArticle.class, "门户-文章"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, GatewayArticle.class); + } + +} diff --git a/src/main/java/com/nd/gateway/controller/GatewayColumnController.java b/src/main/java/com/nd/gateway/controller/GatewayColumnController.java new file mode 100644 index 0000000..e5222b1 --- /dev/null +++ b/src/main/java/com/nd/gateway/controller/GatewayColumnController.java @@ -0,0 +1,192 @@ +package com.nd.gateway.controller; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import com.nd.gateway.entity.GatewayColumn; +import com.nd.gateway.service.IGatewayColumnService; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: 门户-栏目 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Api(tags="门户-栏目") +@RestController +@RequestMapping("/gateway/gatewayColumn") +@Slf4j +public class GatewayColumnController extends JeecgController { + @Autowired + private IGatewayColumnService gatewayColumnService; + + /** + * 分页列表查询 + * + * @param gatewayColumn + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "门户-栏目-分页列表查询") + @ApiOperation(value="门户-栏目-分页列表查询", notes="门户-栏目-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(GatewayColumn gatewayColumn, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(gatewayColumn, req.getParameterMap()); + + //有id,没有pid,查询pid等于次ID的和id等于次ID的 +// queryWrapper.and(StringUtils.isNotBlank(gatewayColumn.getFid())&&StringUtils.isBlank(gatewayColumn.getFpid()),x-> +// x.eq("parent",gatewayColumn.getFid()) +// .or() +// .eq("id",gatewayColumn.getFid()) +// ); + //没有id,有pid,查询pid等于次ID的和id等于次ID的 + queryWrapper.and(StringUtils.isBlank(gatewayColumn.getFid())&&StringUtils.isNotBlank(gatewayColumn.getFpid()),x-> + x.eq("parent",gatewayColumn.getFpid()) + .or() + .eq("id",gatewayColumn.getFpid()) + ); + +// queryWrapper.and(StringUtils.isNotBlank(gatewayColumn.getFid())&&StringUtils.isNotBlank(gatewayColumn.getFpid()), x-> +// x.eq("parent",gatewayColumn.getFpid()) +// .or() +// .eq("id",gatewayColumn.getFid()) +// ); + Page page = new Page(pageNo, pageSize); + IPage pageList = gatewayColumnService.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param gatewayColumn + * @return + */ + @AutoLog(value = "门户-栏目-添加") + @ApiOperation(value="门户-栏目-添加", notes="门户-栏目-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody GatewayColumn gatewayColumn) { + gatewayColumnService.save(gatewayColumn); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param gatewayColumn + * @return + */ + @AutoLog(value = "门户-栏目-编辑") + @ApiOperation(value="门户-栏目-编辑", notes="门户-栏目-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody GatewayColumn gatewayColumn) { + gatewayColumnService.updateById(gatewayColumn); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "门户-栏目-通过id删除") + @ApiOperation(value="门户-栏目-通过id删除", notes="门户-栏目-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + gatewayColumnService.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "门户-栏目-批量删除") + @ApiOperation(value="门户-栏目-批量删除", notes="门户-栏目-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.gatewayColumnService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "门户-栏目-通过id查询") + @ApiOperation(value="门户-栏目-通过id查询", notes="门户-栏目-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + GatewayColumn gatewayColumn = gatewayColumnService.getById(id); + if(gatewayColumn==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(gatewayColumn); + } + + /** + * 导出excel + * + * @param request + * @param gatewayColumn + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, GatewayColumn gatewayColumn) { + return super.exportXls(request, gatewayColumn, GatewayColumn.class, "门户-栏目"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, GatewayColumn.class); + } + +} diff --git a/src/main/java/com/nd/gateway/controller/GatewayLinksController.java b/src/main/java/com/nd/gateway/controller/GatewayLinksController.java new file mode 100644 index 0000000..ad5a11c --- /dev/null +++ b/src/main/java/com/nd/gateway/controller/GatewayLinksController.java @@ -0,0 +1,171 @@ +package com.nd.gateway.controller; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import com.nd.gateway.entity.GatewayLinks; +import com.nd.gateway.service.IGatewayLinksService; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: 门户-友情链接,快速导航 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Api(tags="门户-友情链接,快速导航") +@RestController +@RequestMapping("/gateway/gatewayLinks") +@Slf4j +public class GatewayLinksController extends JeecgController { + @Autowired + private IGatewayLinksService gatewayLinksService; + + /** + * 分页列表查询 + * + * @param gatewayLinks + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "门户-友情链接,快速导航-分页列表查询") + @ApiOperation(value="门户-友情链接,快速导航-分页列表查询", notes="门户-友情链接,快速导航-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(GatewayLinks gatewayLinks, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(gatewayLinks, req.getParameterMap()); + Page page = new Page(pageNo, pageSize); + IPage pageList = gatewayLinksService.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param gatewayLinks + * @return + */ + @AutoLog(value = "门户-友情链接,快速导航-添加") + @ApiOperation(value="门户-友情链接,快速导航-添加", notes="门户-友情链接,快速导航-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody GatewayLinks gatewayLinks) { + gatewayLinksService.save(gatewayLinks); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param gatewayLinks + * @return + */ + @AutoLog(value = "门户-友情链接,快速导航-编辑") + @ApiOperation(value="门户-友情链接,快速导航-编辑", notes="门户-友情链接,快速导航-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody GatewayLinks gatewayLinks) { + gatewayLinksService.updateById(gatewayLinks); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "门户-友情链接,快速导航-通过id删除") + @ApiOperation(value="门户-友情链接,快速导航-通过id删除", notes="门户-友情链接,快速导航-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + gatewayLinksService.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "门户-友情链接,快速导航-批量删除") + @ApiOperation(value="门户-友情链接,快速导航-批量删除", notes="门户-友情链接,快速导航-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.gatewayLinksService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "门户-友情链接,快速导航-通过id查询") + @ApiOperation(value="门户-友情链接,快速导航-通过id查询", notes="门户-友情链接,快速导航-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + GatewayLinks gatewayLinks = gatewayLinksService.getById(id); + if(gatewayLinks==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(gatewayLinks); + } + + /** + * 导出excel + * + * @param request + * @param gatewayLinks + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, GatewayLinks gatewayLinks) { + return super.exportXls(request, gatewayLinks, GatewayLinks.class, "门户-友情链接,快速导航"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, GatewayLinks.class); + } + +} diff --git a/src/main/java/com/nd/gateway/controller/I18nConfigController.java b/src/main/java/com/nd/gateway/controller/I18nConfigController.java new file mode 100644 index 0000000..2e3e523 --- /dev/null +++ b/src/main/java/com/nd/gateway/controller/I18nConfigController.java @@ -0,0 +1,156 @@ +package com.nd.gateway.controller; + +import java.util.Arrays; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import com.nd.gateway.entity.I18nConfig; +import com.nd.gateway.service.II18nConfigService; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; + +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: 国际化配置 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +@Api(tags="国际化配置") +@RestController +@RequestMapping("/gateway/i18nConfig") +@Slf4j +public class I18nConfigController extends JeecgController { + @Autowired + private II18nConfigService i18nConfigService; + + /** + * 分页列表查询 + * + * @param i18NConfig + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "国际化配置-分页列表查询") + @ApiOperation(value="国际化配置-分页列表查询", notes="国际化配置-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(I18nConfig i18NConfig, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(i18NConfig, req.getParameterMap()); + Page page = new Page(pageNo, pageSize); + IPage pageList = i18nConfigService.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param i18NConfig + * @return + */ + @AutoLog(value = "国际化配置-添加") + @ApiOperation(value="国际化配置-添加", notes="国际化配置-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody I18nConfig i18NConfig) { + i18nConfigService.save(i18NConfig); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param i18NConfig + * @return + */ + @AutoLog(value = "国际化配置-编辑") + @ApiOperation(value="国际化配置-编辑", notes="国际化配置-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody I18nConfig i18NConfig) { + i18nConfigService.updateById(i18NConfig); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "国际化配置-通过id删除") + @ApiOperation(value="国际化配置-通过id删除", notes="国际化配置-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + i18nConfigService.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "国际化配置-批量删除") + @ApiOperation(value="国际化配置-批量删除", notes="国际化配置-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.i18nConfigService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "国际化配置-通过id查询") + @ApiOperation(value="国际化配置-通过id查询", notes="国际化配置-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + I18nConfig i18NConfig = i18nConfigService.getById(id); + if(i18NConfig ==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(i18NConfig); + } + + /** + * 导出excel + * + * @param request + * @param i18NConfig + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, I18nConfig i18NConfig) { + return super.exportXls(request, i18NConfig, I18nConfig.class, "国际化配置"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, I18nConfig.class); + } + +} diff --git a/src/main/java/com/nd/gateway/controller/gatewayCommonController.java b/src/main/java/com/nd/gateway/controller/gatewayCommonController.java new file mode 100644 index 0000000..6dd7bb6 --- /dev/null +++ b/src/main/java/com/nd/gateway/controller/gatewayCommonController.java @@ -0,0 +1,171 @@ +package com.nd.gateway.controller; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import com.nd.gateway.entity.gatewayCommon; +import com.nd.gateway.service.IgatewayCommonService; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: 基本信息表 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +@Api(tags="基本信息表") +@RestController +@RequestMapping("/gateway/gatewayCommon") +@Slf4j +public class gatewayCommonController extends JeecgController { + @Autowired + private IgatewayCommonService gatewayCommonService; + + /** + * 分页列表查询 + * + * @param gatewayCommon + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "基本信息表-分页列表查询") + @ApiOperation(value="基本信息表-分页列表查询", notes="基本信息表-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(gatewayCommon gatewayCommon, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(gatewayCommon, req.getParameterMap()); + Page page = new Page(pageNo, pageSize); + IPage pageList = gatewayCommonService.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param gatewayCommon + * @return + */ + @AutoLog(value = "基本信息表-添加") + @ApiOperation(value="基本信息表-添加", notes="基本信息表-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody gatewayCommon gatewayCommon) { + gatewayCommonService.save(gatewayCommon); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param gatewayCommon + * @return + */ + @AutoLog(value = "基本信息表-编辑") + @ApiOperation(value="基本信息表-编辑", notes="基本信息表-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody gatewayCommon gatewayCommon) { + gatewayCommonService.updateById(gatewayCommon); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "基本信息表-通过id删除") + @ApiOperation(value="基本信息表-通过id删除", notes="基本信息表-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + gatewayCommonService.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "基本信息表-批量删除") + @ApiOperation(value="基本信息表-批量删除", notes="基本信息表-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.gatewayCommonService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "基本信息表-通过id查询") + @ApiOperation(value="基本信息表-通过id查询", notes="基本信息表-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + gatewayCommon gatewayCommon = gatewayCommonService.getById(id); + if(gatewayCommon==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(gatewayCommon); + } + + /** + * 导出excel + * + * @param request + * @param gatewayCommon + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, gatewayCommon gatewayCommon) { + return super.exportXls(request, gatewayCommon, gatewayCommon.class, "基本信息表"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, gatewayCommon.class); + } + +} diff --git a/src/main/java/com/nd/gateway/entity/GatewayArticle.java b/src/main/java/com/nd/gateway/entity/GatewayArticle.java new file mode 100644 index 0000000..e8d28be --- /dev/null +++ b/src/main/java/com/nd/gateway/entity/GatewayArticle.java @@ -0,0 +1,152 @@ +package com.nd.gateway.entity; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.math.BigDecimal; +import java.util.List; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * @Description: 门户-文章 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Data +@TableName("tqd_gateway_article") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="tqd_gateway_article对象", description="门户-文章") +public class GatewayArticle implements Serializable { + private static final long serialVersionUID = 1L; + + /**id*/ + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "id") + private java.lang.String id; + /**创建人*/ + @ApiModelProperty(value = "创建人") + private java.lang.String createBy; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "创建日期") + private java.util.Date createTime; + /**更新人*/ + @ApiModelProperty(value = "更新人") + private java.lang.String updateBy; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "更新日期") + private java.util.Date updateTime; + /**所属部门*/ + @ApiModelProperty(value = "所属部门") + private java.lang.String sysOrgCode; + /**标题*/ + @Excel(name = "标题", width = 15) + @ApiModelProperty(value = "标题") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String title; + /**标题-英文版*/ + @Excel(name = "标题-英文版", width = 15) + @ApiModelProperty(value = "标题-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String titleen; + /**文章类型*/ + @Excel(name = "文章类型", width = 15) + @ApiModelProperty(value = "文章类型") + @Dict(dicCode = "gateway_article_type") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String type; + /**分类-栏目表ID*/ + @Excel(name = "分类-栏目表ID", width = 15) + @ApiModelProperty(value = "分类-栏目表ID") + @Dict(dictTable = "tqd_gateway_column",dicCode = "id",dicText = "name") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String columnId; + /**封面图url*/ + @Excel(name = "封面图url", width = 15) + @ApiModelProperty(value = "封面图url") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String cover; + /**封面图url--英文版*/ + @Excel(name = "封面图url--英文版", width = 15) + @ApiModelProperty(value = "封面图url--英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String coveren; + /**作者*/ + @Excel(name = "作者", width = 15) + @ApiModelProperty(value = "作者") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String author; + /**作者-英文版*/ + @Excel(name = "作者-英文版", width = 15) + @ApiModelProperty(value = "作者-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String authoren; + /**来源*/ + @Excel(name = "来源", width = 15) + @ApiModelProperty(value = "来源") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String source; + /**来源-英文版*/ + @Excel(name = "来源-英文版", width = 15) + @ApiModelProperty(value = "来源-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String sourceen; + /**文章内容*/ + @Excel(name = "文章内容", width = 15) + @ApiModelProperty(value = "文章内容") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String content; + /**文章内容-英文版*/ + @Excel(name = "文章内容-英文版", width = 15) + @ApiModelProperty(value = "文章内容-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String contenten; + /**附件*/ + @Excel(name = "附件", width = 15) + @ApiModelProperty(value = "附件") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String files; + /**附件-英文版*/ + @Excel(name = "附件-英文版", width = 15) + @ApiModelProperty(value = "附件-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String filesen; + /**是否发布(Y:是N:否)*/ + @Excel(name = "是否发布(Y:是N:否)", width = 15) + @ApiModelProperty(value = "是否发布") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String isRelease; + + /** + * 父级栏目对象 + */ + @TableField(exist = false) + private GatewayColumn parentGatewayColumn; + + /** + * 当前栏目对象 + */ + @TableField(exist = false) + private GatewayColumn currentGatewayColumn; + + /** + * 当前父级栏目下的所有子栏目 + */ + @TableField(exist = false) + private List gatewayColumnList; +} diff --git a/src/main/java/com/nd/gateway/entity/GatewayColumn.java b/src/main/java/com/nd/gateway/entity/GatewayColumn.java new file mode 100644 index 0000000..f6708c2 --- /dev/null +++ b/src/main/java/com/nd/gateway/entity/GatewayColumn.java @@ -0,0 +1,99 @@ +package com.nd.gateway.entity; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * @Description: 门户-栏目 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Data +@TableName("tqd_gateway_column") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="tqd_gateway_column对象", description="门户-栏目") +public class GatewayColumn implements Serializable { + private static final long serialVersionUID = 1L; + + /**id*/ + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "id") + private java.lang.String id; + /**创建人*/ + @ApiModelProperty(value = "创建人") + private java.lang.String createBy; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "创建日期") + private java.util.Date createTime; + /**更新人*/ + @ApiModelProperty(value = "更新人") + private java.lang.String updateBy; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "更新日期") + private java.util.Date updateTime; + /**所属部门*/ + @ApiModelProperty(value = "所属部门") + private java.lang.String sysOrgCode; + /**名称*/ + @Excel(name = "名称", width = 15) + @ApiModelProperty(value = "名称") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String name; + /**名称-英文版*/ + @Excel(name = "名称-英文版", width = 15) + @ApiModelProperty(value = "名称-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String nameen; + /**类型*/ + @Excel(name = "类型", width = 15, dicCode = "gateway_column_type") + @Dict(dicCode = "gateway_column_type") + @ApiModelProperty(value = "类型") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String type; + /**上级ID 0为顶级*/ + @Excel(name = "上级ID 0为顶级", width = 15) + @ApiModelProperty(value = "上级ID 0为顶级") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String parent; + /**是否启用*/ + @Excel(name = "是否启用", width = 15) + @ApiModelProperty(value = "是否启用") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String isEnable; + /**排序*/ + @Excel(name = "排序", width = 15) + @ApiModelProperty(value = "排序") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String sort; + /**图标*/ + @Excel(name = "图标", width = 15) + @ApiModelProperty(value = "图标") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String icon; + + //查询父ID + @TableField(exist = false) + private String fpid; + //查询ID + @TableField(exist = false) + private String fid; +} diff --git a/src/main/java/com/nd/gateway/entity/GatewayLinks.java b/src/main/java/com/nd/gateway/entity/GatewayLinks.java new file mode 100644 index 0000000..b45f5d4 --- /dev/null +++ b/src/main/java/com/nd/gateway/entity/GatewayLinks.java @@ -0,0 +1,100 @@ +package com.nd.gateway.entity; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * @Description: 门户-友情链接,快速导航 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Data +@TableName("tqd_gateway_links") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="tqd_gateway_links对象", description="门户-友情链接,快速导航") +public class GatewayLinks implements Serializable { + private static final long serialVersionUID = 1L; + + /**id*/ + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "id") + private java.lang.String id; + /**创建人*/ + @ApiModelProperty(value = "创建人") + private java.lang.String createBy; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "创建日期") + private java.util.Date createTime; + /**更新人*/ + @ApiModelProperty(value = "更新人") + private java.lang.String updateBy; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + @ApiModelProperty(value = "更新日期") + private java.util.Date updateTime; + /**所属部门*/ + @ApiModelProperty(value = "所属部门") + private java.lang.String sysOrgCode; + /**名称*/ + @Excel(name = "名称", width = 15) + @ApiModelProperty(value = "名称") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String name; + /**类型(显示在哪)*/ + @Excel(name = "类型(显示在哪)", width = 15) + @ApiModelProperty(value = "类型(显示在哪)") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String type; + /**链接*/ + @Excel(name = "链接", width = 15) + @ApiModelProperty(value = "链接") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String url; + /**链接-英文版*/ + @Excel(name = "链接-英文版", width = 15) + @ApiModelProperty(value = "链接-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String urlen; + /**标题*/ + @Excel(name = "标题", width = 15) + @ApiModelProperty(value = "标题") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String title; + /**标题-英文版*/ + @Excel(name = "标题-英文版", width = 15) + @ApiModelProperty(value = "标题-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String titleen; + /**logo url*/ + @Excel(name = "logo url", width = 15) + @ApiModelProperty(value = "logo url") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String logo; + /**logo url-英文版*/ + @Excel(name = "logo url-英文版", width = 15) + @ApiModelProperty(value = "logo url-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String logoen; + /**是否启用*/ + @Excel(name = "是否启用", width = 15) + @ApiModelProperty(value = "是否启用") + private java.lang.String isEnable; +} diff --git a/src/main/java/com/nd/gateway/entity/I18nConfig.java b/src/main/java/com/nd/gateway/entity/I18nConfig.java new file mode 100644 index 0000000..4adea21 --- /dev/null +++ b/src/main/java/com/nd/gateway/entity/I18nConfig.java @@ -0,0 +1,71 @@ +package com.nd.gateway.entity; + +import java.io.Serializable; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * @Description: 国际化配置 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +@Data +@TableName("tqc_i18n_config") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="tqc_i18n_config对象", description="国际化配置") +public class I18nConfig implements Serializable { + private static final long serialVersionUID = 1L; + + /**主键*/ + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "主键") + private java.lang.String id; + /**创建人*/ + @ApiModelProperty(value = "创建人") + private java.lang.String createBy; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + private java.util.Date createTime; + /**更新人*/ + @ApiModelProperty(value = "更新人") + private java.lang.String updateBy; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + private java.util.Date updateTime; + /**所属部门*/ + @ApiModelProperty(value = "所属部门") + private java.lang.String sysOrgCode; + /**语言标识*/ + @Excel(name = "语言标识", width = 15) + @ApiModelProperty(value = "语言标识") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String identification; + /**显示名称*/ + @Excel(name = "显示名称", width = 15) + @ApiModelProperty(value = "显示名称") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String name; + /**国际化JSON*/ + @Excel(name = "国际化JSON", width = 15) + @ApiModelProperty(value = "国际化JSON") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String i18nJson; + /**是否启用(Y:是,N:否),同一个标识只能有一个启用的*/ + @Excel(name = "是否启用", width = 15) + @ApiModelProperty(value = "是否启用") + private java.lang.String isEnable; +} diff --git a/src/main/java/com/nd/gateway/entity/gatewayCommon.java b/src/main/java/com/nd/gateway/entity/gatewayCommon.java new file mode 100644 index 0000000..b6764d6 --- /dev/null +++ b/src/main/java/com/nd/gateway/entity/gatewayCommon.java @@ -0,0 +1,135 @@ +package com.nd.gateway.entity; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.math.BigDecimal; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * @Description: 基本信息表 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +@Data +@TableName("tqc_gateway_common") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="tqc_gateway_common对象", description="基本信息表") +public class gatewayCommon implements Serializable { + private static final long serialVersionUID = 1L; + + /**主键*/ + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "主键") + private java.lang.String id; + /**邮箱*/ + @Excel(name = "邮箱", width = 15) + @ApiModelProperty(value = "邮箱") + private java.lang.String mailbox; + /**创建人*/ + @ApiModelProperty(value = "创建人") + private java.lang.String createBy; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + private java.util.Date createTime; + /**更新人*/ + @ApiModelProperty(value = "更新人") + private java.lang.String updateBy; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + private java.util.Date updateTime; + /**所属部门*/ + @ApiModelProperty(value = "所属部门") + private java.lang.String sysOrgCode; + /**门户头部logo*/ + @Excel(name = "门户头部logo", width = 15) + @ApiModelProperty(value = "门户头部logo") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String heardLogoUrl; + /**门户头部logo-英文版*/ + @Excel(name = "门户头部logo-英文版", width = 15) + @ApiModelProperty(value = "门户头部logo-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String heardLogoUrlen; + /**门户尾部logo*/ + @Excel(name = "门户尾部logo", width = 15) + @ApiModelProperty(value = "门户尾部logo") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String footerLogoUrl; + /**门户尾部logo-英文版*/ + @Excel(name = "门户尾部logo-英文版", width = 15) + @ApiModelProperty(value = "门户尾部logo-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String footerLogoUrlen; + /**版权所有*/ + @Excel(name = "版权所有", width = 15) + @ApiModelProperty(value = "版权所有") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String copyright; + /**版权所有-英文版*/ + @Excel(name = "版权所有-英文版", width = 15) + @ApiModelProperty(value = "版权所有-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String copyrighten; + /**邮箱-英文版*/ + @Excel(name = "邮箱-英文版", width = 15) + @ApiModelProperty(value = "邮箱-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String mailboxen; + /**地址*/ + @Excel(name = "地址", width = 15) + @ApiModelProperty(value = "地址") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String address; + /**地址-英文版*/ + @Excel(name = "地址-英文版", width = 15) + @ApiModelProperty(value = "地址-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String addressen; + /**备案号*/ + @Excel(name = "备案号", width = 15) + @ApiModelProperty(value = "备案号") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String recordNumber; + /**备案号-英文版*/ + @Excel(name = "备案号-英文版", width = 15) + @ApiModelProperty(value = "备案号-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String recordNumberen; + /**官方微信*/ + @Excel(name = "官方微信", width = 15) + @ApiModelProperty(value = "官方微信") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String wechatUrl; + /**官方微信-英文版*/ + @Excel(name = "官方微信-英文版", width = 15) + @ApiModelProperty(value = "官方微信-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String wechatUrlen; + /**学校主页地址*/ + @Excel(name = "学校主页地址", width = 15) + @ApiModelProperty(value = "学校主页地址") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String homepageUrl; + /**学校主页地址-英文版*/ + @Excel(name = "学校主页地址-英文版", width = 15) + @ApiModelProperty(value = "学校主页地址-英文版") + @TableField(updateStrategy= FieldStrategy.IGNORED) + private java.lang.String homepageUrlen; +} diff --git a/src/main/java/com/nd/gateway/mapper/GatewayArticleMapper.java b/src/main/java/com/nd/gateway/mapper/GatewayArticleMapper.java new file mode 100644 index 0000000..0cffb05 --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/GatewayArticleMapper.java @@ -0,0 +1,17 @@ +package com.nd.gateway.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import com.nd.gateway.entity.GatewayArticle; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: 门户-文章 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +public interface GatewayArticleMapper extends BaseMapper { + +} diff --git a/src/main/java/com/nd/gateway/mapper/GatewayColumnMapper.java b/src/main/java/com/nd/gateway/mapper/GatewayColumnMapper.java new file mode 100644 index 0000000..eba45e9 --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/GatewayColumnMapper.java @@ -0,0 +1,17 @@ +package com.nd.gateway.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import com.nd.gateway.entity.GatewayColumn; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: 门户-栏目 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +public interface GatewayColumnMapper extends BaseMapper { + +} diff --git a/src/main/java/com/nd/gateway/mapper/GatewayLinksMapper.java b/src/main/java/com/nd/gateway/mapper/GatewayLinksMapper.java new file mode 100644 index 0000000..9dd240f --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/GatewayLinksMapper.java @@ -0,0 +1,17 @@ +package com.nd.gateway.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import com.nd.gateway.entity.GatewayLinks; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: 门户-友情链接,快速导航 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +public interface GatewayLinksMapper extends BaseMapper { + +} diff --git a/src/main/java/com/nd/gateway/mapper/I18nConfigMapper.java b/src/main/java/com/nd/gateway/mapper/I18nConfigMapper.java new file mode 100644 index 0000000..4025027 --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/I18nConfigMapper.java @@ -0,0 +1,14 @@ +package com.nd.gateway.mapper; + +import com.nd.gateway.entity.I18nConfig; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: 国际化配置 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +public interface I18nConfigMapper extends BaseMapper { + +} diff --git a/src/main/java/com/nd/gateway/mapper/gatewayCommonMapper.java b/src/main/java/com/nd/gateway/mapper/gatewayCommonMapper.java new file mode 100644 index 0000000..7c79b2c --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/gatewayCommonMapper.java @@ -0,0 +1,17 @@ +package com.nd.gateway.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import com.nd.gateway.entity.gatewayCommon; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: 基本信息表 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +public interface gatewayCommonMapper extends BaseMapper { + +} diff --git a/src/main/java/com/nd/gateway/mapper/xml/GatewayArticleMapper.xml b/src/main/java/com/nd/gateway/mapper/xml/GatewayArticleMapper.xml new file mode 100644 index 0000000..f4e1f9d --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/xml/GatewayArticleMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/nd/gateway/mapper/xml/GatewayColumnMapper.xml b/src/main/java/com/nd/gateway/mapper/xml/GatewayColumnMapper.xml new file mode 100644 index 0000000..b1d355c --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/xml/GatewayColumnMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/nd/gateway/mapper/xml/GatewayLinksMapper.xml b/src/main/java/com/nd/gateway/mapper/xml/GatewayLinksMapper.xml new file mode 100644 index 0000000..2da5c0b --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/xml/GatewayLinksMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/nd/gateway/mapper/xml/I18nConfigMapper.xml b/src/main/java/com/nd/gateway/mapper/xml/I18nConfigMapper.xml new file mode 100644 index 0000000..e47d207 --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/xml/I18nConfigMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/nd/gateway/mapper/xml/gatewayCommonMapper.xml b/src/main/java/com/nd/gateway/mapper/xml/gatewayCommonMapper.xml new file mode 100644 index 0000000..1694cde --- /dev/null +++ b/src/main/java/com/nd/gateway/mapper/xml/gatewayCommonMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/com/nd/gateway/service/IGatewayArticleService.java b/src/main/java/com/nd/gateway/service/IGatewayArticleService.java new file mode 100644 index 0000000..1813bad --- /dev/null +++ b/src/main/java/com/nd/gateway/service/IGatewayArticleService.java @@ -0,0 +1,14 @@ +package com.nd.gateway.service; + +import com.nd.gateway.entity.GatewayArticle; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @Description: 门户-文章 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +public interface IGatewayArticleService extends IService { + +} diff --git a/src/main/java/com/nd/gateway/service/IGatewayColumnService.java b/src/main/java/com/nd/gateway/service/IGatewayColumnService.java new file mode 100644 index 0000000..952547e --- /dev/null +++ b/src/main/java/com/nd/gateway/service/IGatewayColumnService.java @@ -0,0 +1,14 @@ +package com.nd.gateway.service; + +import com.nd.gateway.entity.GatewayColumn; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @Description: 门户-栏目 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +public interface IGatewayColumnService extends IService { + +} diff --git a/src/main/java/com/nd/gateway/service/IGatewayLinksService.java b/src/main/java/com/nd/gateway/service/IGatewayLinksService.java new file mode 100644 index 0000000..92dc4bf --- /dev/null +++ b/src/main/java/com/nd/gateway/service/IGatewayLinksService.java @@ -0,0 +1,14 @@ +package com.nd.gateway.service; + +import com.nd.gateway.entity.GatewayLinks; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @Description: 门户-友情链接,快速导航 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +public interface IGatewayLinksService extends IService { + +} diff --git a/src/main/java/com/nd/gateway/service/II18nConfigService.java b/src/main/java/com/nd/gateway/service/II18nConfigService.java new file mode 100644 index 0000000..489a67b --- /dev/null +++ b/src/main/java/com/nd/gateway/service/II18nConfigService.java @@ -0,0 +1,14 @@ +package com.nd.gateway.service; + +import com.nd.gateway.entity.I18nConfig; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @Description: 国际化配置 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +public interface II18nConfigService extends IService { + +} diff --git a/src/main/java/com/nd/gateway/service/IgatewayCommonService.java b/src/main/java/com/nd/gateway/service/IgatewayCommonService.java new file mode 100644 index 0000000..076d7ed --- /dev/null +++ b/src/main/java/com/nd/gateway/service/IgatewayCommonService.java @@ -0,0 +1,14 @@ +package com.nd.gateway.service; + +import com.nd.gateway.entity.gatewayCommon; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @Description: 基本信息表 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +public interface IgatewayCommonService extends IService { + +} diff --git a/src/main/java/com/nd/gateway/service/impl/GatewayArticleServiceImpl.java b/src/main/java/com/nd/gateway/service/impl/GatewayArticleServiceImpl.java new file mode 100644 index 0000000..da410a4 --- /dev/null +++ b/src/main/java/com/nd/gateway/service/impl/GatewayArticleServiceImpl.java @@ -0,0 +1,19 @@ +package com.nd.gateway.service.impl; + +import com.nd.gateway.entity.GatewayArticle; +import com.nd.gateway.mapper.GatewayArticleMapper; +import com.nd.gateway.service.IGatewayArticleService; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: 门户-文章 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Service +public class GatewayArticleServiceImpl extends ServiceImpl implements IGatewayArticleService { + +} diff --git a/src/main/java/com/nd/gateway/service/impl/GatewayColumnServiceImpl.java b/src/main/java/com/nd/gateway/service/impl/GatewayColumnServiceImpl.java new file mode 100644 index 0000000..db458ac --- /dev/null +++ b/src/main/java/com/nd/gateway/service/impl/GatewayColumnServiceImpl.java @@ -0,0 +1,19 @@ +package com.nd.gateway.service.impl; + +import com.nd.gateway.entity.GatewayColumn; +import com.nd.gateway.mapper.GatewayColumnMapper; +import com.nd.gateway.service.IGatewayColumnService; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: 门户-栏目 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Service +public class GatewayColumnServiceImpl extends ServiceImpl implements IGatewayColumnService { + +} diff --git a/src/main/java/com/nd/gateway/service/impl/GatewayLinksServiceImpl.java b/src/main/java/com/nd/gateway/service/impl/GatewayLinksServiceImpl.java new file mode 100644 index 0000000..315c3bc --- /dev/null +++ b/src/main/java/com/nd/gateway/service/impl/GatewayLinksServiceImpl.java @@ -0,0 +1,19 @@ +package com.nd.gateway.service.impl; + +import com.nd.gateway.entity.GatewayLinks; +import com.nd.gateway.mapper.GatewayLinksMapper; +import com.nd.gateway.service.IGatewayLinksService; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: 门户-友情链接,快速导航 + * @Author: jeecg-boot + * @Date: 2022-03-26 + * @Version: V1.0 + */ +@Service +public class GatewayLinksServiceImpl extends ServiceImpl implements IGatewayLinksService { + +} diff --git a/src/main/java/com/nd/gateway/service/impl/I18NConfigServiceImpl.java b/src/main/java/com/nd/gateway/service/impl/I18NConfigServiceImpl.java new file mode 100644 index 0000000..cf7af89 --- /dev/null +++ b/src/main/java/com/nd/gateway/service/impl/I18NConfigServiceImpl.java @@ -0,0 +1,19 @@ +package com.nd.gateway.service.impl; + +import com.nd.gateway.entity.I18nConfig; +import com.nd.gateway.mapper.I18nConfigMapper; +import com.nd.gateway.service.II18nConfigService; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: 国际化配置 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +@Service +public class I18NConfigServiceImpl extends ServiceImpl implements II18nConfigService { + +} diff --git a/src/main/java/com/nd/gateway/service/impl/gatewayCommonServiceImpl.java b/src/main/java/com/nd/gateway/service/impl/gatewayCommonServiceImpl.java new file mode 100644 index 0000000..d1ee3a8 --- /dev/null +++ b/src/main/java/com/nd/gateway/service/impl/gatewayCommonServiceImpl.java @@ -0,0 +1,19 @@ +package com.nd.gateway.service.impl; + +import com.nd.gateway.entity.gatewayCommon; +import com.nd.gateway.mapper.gatewayCommonMapper; +import com.nd.gateway.service.IgatewayCommonService; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: 基本信息表 + * @Author: jeecg-boot + * @Date: 2022-03-24 + * @Version: V1.0 + */ +@Service +public class gatewayCommonServiceImpl extends ServiceImpl implements IgatewayCommonService { + +} diff --git a/src/main/java/org/jeecg/JeecgOneGUI.java b/src/main/java/org/jeecg/JeecgOneGUI.java new file mode 100644 index 0000000..920808e --- /dev/null +++ b/src/main/java/org/jeecg/JeecgOneGUI.java @@ -0,0 +1,19 @@ +package org.jeecg; + +import org.jeecgframework.codegenerate.window.CodeWindow; + +/** + * @Title: 单表代码生成器入口 + * 【 GUI模式已弃用,请转移Online模式进行代码生成 】 + * @Author 张代浩 + * @site www.jeecg.com + * @Version:V1.0.1 + */ +public class JeecgOneGUI { + + /** 详细使用手册: http://doc.jeecg.com/2043919 */ + public static void main(String[] args) { + new CodeWindow().pack(); + } + +} \ No newline at end of file diff --git a/src/main/java/org/jeecg/JeecgOneToMainUtil.java b/src/main/java/org/jeecg/JeecgOneToMainUtil.java new file mode 100644 index 0000000..8a1ecd6 --- /dev/null +++ b/src/main/java/org/jeecg/JeecgOneToMainUtil.java @@ -0,0 +1,70 @@ +package org.jeecg; + +import java.util.ArrayList; +import java.util.List; + +import org.jeecgframework.codegenerate.generate.impl.CodeGenerateOneToMany; +import org.jeecgframework.codegenerate.generate.pojo.onetomany.MainTableVo; +import org.jeecgframework.codegenerate.generate.pojo.onetomany.SubTableVo; + +/** + * 代码生成器入口【一对多】 + * 【 GUI模式已弃用,请转移Online模式进行代码生成 】 + * @Author 张代浩 + * @site www.jeecg.org + * + */ +public class JeecgOneToMainUtil { + + /** + * 一对多(父子表)数据模型,生成方法 + * @param args + */ + public static void main(String[] args) { + //第一步:设置主表配置 + MainTableVo mainTable = new MainTableVo(); + mainTable.setTableName("jeecg_order_main");//表名 + mainTable.setEntityName("GuiTestOrderMain"); //实体名 + mainTable.setEntityPackage("gui"); //包名 + mainTable.setFtlDescription("GUI订单管理"); //描述 + + //第二步:设置子表集合配置 + List subTables = new ArrayList(); + //[1].子表一 + SubTableVo po = new SubTableVo(); + po.setTableName("jeecg_order_customer");//表名 + po.setEntityName("GuiTestOrderCustom"); //实体名 + po.setEntityPackage("gui"); //包名 + po.setFtlDescription("客户明细"); //描述 + //子表外键参数配置 + /*说明: + * a) 子表引用主表主键ID作为外键,外键字段必须以_ID结尾; + * b) 主表和子表的外键字段名字,必须相同(除主键ID外); + * c) 多个外键字段,采用逗号分隔; + */ + po.setForeignKeys(new String[]{"order_id"}); + subTables.add(po); + //[2].子表二 + SubTableVo po2 = new SubTableVo(); + po2.setTableName("jeecg_order_ticket"); //表名 + po2.setEntityName("GuiTestOrderTicket"); //实体名 + po2.setEntityPackage("gui"); //包名 + po2.setFtlDescription("产品明细"); //描述 + //子表外键参数配置 + /*说明: + * a) 子表引用主表主键ID作为外键,外键字段必须以_ID结尾; + * b) 主表和子表的外键字段名字,必须相同(除主键ID外); + * c) 多个外键字段,采用逗号分隔; + */ + po2.setForeignKeys(new String[]{"order_id"}); + subTables.add(po2); + mainTable.setSubTables(subTables); + + //第三步:一对多(父子表)数据模型,代码生成 + try { + new CodeGenerateOneToMany(mainTable,subTables).generateCodeFile(null); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/org/jeecg/common/aspect/DictAspect.java b/src/main/java/org/jeecg/common/aspect/DictAspect.java new file mode 100644 index 0000000..f6ebd5a --- /dev/null +++ b/src/main/java/org/jeecg/common/aspect/DictAspect.java @@ -0,0 +1,164 @@ +package org.jeecg.common.aspect; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.jeecg.common.api.CommonAPI; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.aspect.annotation.Dict; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.modules.base.service.BaseCommonService; +import org.jeecg.common.util.oConvertUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import java.lang.reflect.Field; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * @Description: 字典aop类 + * @Author: dangzhenghui + * @Date: 2019-3-17 21:50 + * @Version: 1.0 + */ +@Aspect +@Component +@Slf4j +public class DictAspect { + + @Autowired + private CommonAPI commonAPI; + + // 定义切点Pointcut + @Pointcut("execution(public * org.jeecg.modules..*.*Controller.*(..)) ||execution(public * com.qnsoft..*.*Controller.*(..))||execution(public * com.nd..*.*Controller.*(..))") + public void excudeService() { + } + + @Around("excudeService()") + public Object doAround(ProceedingJoinPoint pjp) throws Throwable { + long time1=System.currentTimeMillis(); + Object result = pjp.proceed(); + long time2=System.currentTimeMillis(); + log.debug("获取JSON数据 耗时:"+(time2-time1)+"ms"); + long start=System.currentTimeMillis(); + this.parseDictText(result); + long end=System.currentTimeMillis(); + log.debug("解析注入JSON数据 耗时"+(end-start)+"ms"); + return result; + } + + /** + * 本方法针对返回对象为Result 的IPage的分页列表数据进行动态字典注入 + * 字典注入实现 通过对实体类添加注解@dict 来标识需要的字典内容,字典分为单字典code即可 ,table字典 code table text配合使用与原来jeecg的用法相同 + * 示例为SysUser 字段为sex 添加了注解@Dict(dicCode = "sex") 会在字典服务立马查出来对应的text 然后在请求list的时候将这个字典text,已字段名称加_dictText形式返回到前端 + * 例输入当前返回值的就会多出一个sex_dictText字段 + * { + * sex:1, + * sex_dictText:"男" + * } + * 前端直接取值sext_dictText在table里面无需再进行前端的字典转换了 + * customRender:function (text) { + * if(text==1){ + * return "男"; + * }else if(text==2){ + * return "女"; + * }else{ + * return text; + * } + * } + * 目前vue是这么进行字典渲染到table上的多了就很麻烦了 这个直接在服务端渲染完成前端可以直接用 + * @param result + */ + private void parseDictText(Object result) { + if (result instanceof Result) { + if (((Result) result).getResult() instanceof IPage) { + List items = new ArrayList<>(); + for (Object record : ((IPage) ((Result) result).getResult()).getRecords()) { + ObjectMapper mapper = new ObjectMapper(); + String json="{}"; + try { + //解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat + json = mapper.writeValueAsString(record); + } catch (JsonProcessingException e) { + log.error("json解析失败"+e.getMessage(),e); + } + JSONObject item = JSONObject.parseObject(json); + //update-begin--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ + //for (Field field : record.getClass().getDeclaredFields()) { + for (Field field : oConvertUtils.getAllFields(record)) { + //update-end--Author:scott -- Date:20190603 ----for:解决继承实体字段无法翻译问题------ + if (field.getAnnotation(Dict.class) != null) { + String code = field.getAnnotation(Dict.class).dicCode(); + String text = field.getAnnotation(Dict.class).dicText(); + String table = field.getAnnotation(Dict.class).dictTable(); + String key = String.valueOf(item.get(field.getName())); + + //翻译字典值对应的txt + String textValue = translateDictValue(code, text, table, key); + + log.debug(" 字典Val : "+ textValue); + log.debug(" __翻译字典字段__ "+field.getName() + CommonConstant.DICT_TEXT_SUFFIX+": "+ textValue); + item.put(field.getName() + CommonConstant.DICT_TEXT_SUFFIX, textValue); + } + //date类型默认转换string格式化日期 + if (field.getType().getName().equals("java.util.Date")&&field.getAnnotation(JsonFormat.class)==null&&item.get(field.getName())!=null){ + SimpleDateFormat aDate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + item.put(field.getName(), aDate.format(new Date((Long) item.get(field.getName())))); + } + } + items.add(item); + } + ((IPage) ((Result) result).getResult()).setRecords(items); + } + + } + } + + /** + * 翻译字典文本 + * @param code + * @param text + * @param table + * @param key + * @return + */ + private String translateDictValue(String code, String text, String table, String key) { + if(oConvertUtils.isEmpty(key)) { + return null; + } + StringBuffer textValue=new StringBuffer(); + String[] keys = key.split(","); + for (String k : keys) { + String tmpValue = null; + log.debug(" 字典 key : "+ k); + if (k.trim().length() == 0) { + continue; //跳过循环 + } + if (!StringUtils.isEmpty(table)){ + log.debug("--DictAspect------dicTable="+ table+" ,dicText= "+text+" ,dicCode="+code); + tmpValue= commonAPI.translateDictFromTable(table,text,code,k.trim()); + }else { + tmpValue = commonAPI.translateDict(code, k.trim()); + } + if (tmpValue != null) { + if (!"".equals(textValue.toString())) { + textValue.append(","); + } + textValue.append(tmpValue); + } + + } + return textValue.toString(); + } + +} diff --git a/src/main/java/org/jeecg/common/system/query/QueryGenerator.java b/src/main/java/org/jeecg/common/system/query/QueryGenerator.java new file mode 100644 index 0000000..17a0690 --- /dev/null +++ b/src/main/java/org/jeecg/common/system/query/QueryGenerator.java @@ -0,0 +1,1080 @@ +package org.jeecg.common.system.query; + +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.beanutils.PropertyUtils; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.constant.DataBaseConstant; +import org.jeecg.common.system.util.JeecgDataAutorUtils; +import org.jeecg.common.system.util.JwtUtil; +import org.jeecg.common.system.vo.SysPermissionDataRuleModel; +import org.jeecg.common.util.CommonUtils; +import org.jeecg.common.util.DateUtils; +import org.jeecg.common.util.SqlInjectionUtil; +import org.jeecg.common.util.oConvertUtils; +import org.springframework.util.NumberUtils; + +import java.beans.PropertyDescriptor; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.net.URLDecoder; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@Slf4j +public class QueryGenerator { + public static final String SQL_RULES_COLUMN = "SQL_RULES_COLUMN"; + + private static final String BEGIN = "_begin"; + private static final String END = "_end"; + /** + * 数字类型字段,拼接此后缀 接受多值参数 + */ + private static final String MULTI = "_MultiString"; + private static final String STAR = "*"; + private static final String COMMA = ","; + private static final String NOT_EQUAL = "!"; + private static final String EQ_NULL = "!!null"; + private static final String NOT_NULL = "!!!null"; + private static final String EQ_EMPTY = "!!"; + private static final String NOT_EMPTY = "!!!"; + private static final String EQ_BLANK = "!!BLANK"; + private static final String NOT_BLANK = "!!!BLANK"; + + /**页面带有规则值查询,空格作为分隔符*/ + private static final String QUERY_SEPARATE_KEYWORD = " "; + /**高级查询前端传来的参数名*/ + private static final String SUPER_QUERY_PARAMS = "superQueryParams"; + /** 高级查询前端传来的拼接方式参数名 */ + private static final String SUPER_QUERY_MATCH_TYPE = "superQueryMatchType"; + /** 单引号 */ + public static final String SQL_SQ = "'"; + /**排序列*/ + private static final String ORDER_COLUMN = "column"; + /**排序方式*/ + private static final String ORDER_TYPE = "order"; + private static final String ORDER_TYPE_ASC = "ASC"; + + /**mysql 模糊查询之特殊字符下划线 (_、\)*/ + public static final String LIKE_MYSQL_SPECIAL_STRS = "_,%"; + + /**时间格式化 */ + private static final ThreadLocal local = new ThreadLocal(); + private static SimpleDateFormat getTime(){ + SimpleDateFormat time = local.get(); + if(time == null){ + time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + local.set(time); + } + return time; + } + + /** + * 获取查询条件构造器QueryWrapper实例 通用查询条件已被封装完成 + * @param searchObj 查询实体 + * @param parameterMap request.getParameterMap() + * @return QueryWrapper实例 + */ + public static QueryWrapper initQueryWrapper(T searchObj,Map parameterMap){ + return initQueryWrapper(null,searchObj,parameterMap); + } + + /** + * 获取查询条件构造器QueryWrapper实例 通用查询条件已被封装完成 + * @param searchObj 查询实体 + * @param parameterMap request.getParameterMap() + * @return QueryWrapper实例 + */ + public static QueryWrapper initQueryWrapper(String columnPrefix,T searchObj,Map parameterMap){ + long start = System.currentTimeMillis(); + QueryWrapper queryWrapper = new QueryWrapper(); + installMplus(queryWrapper, columnPrefix, searchObj, parameterMap); + log.debug("---查询条件构造器初始化完成,耗时:"+(System.currentTimeMillis()-start)+"毫秒----"); + return queryWrapper; + } + + /** + * 组装Mybatis Plus 查询条件 + *

使用此方法 需要有如下几点注意: + *
1.使用QueryWrapper 而非LambdaQueryWrapper; + *
2.实例化QueryWrapper时不可将实体传入参数 + *
错误示例:如QueryWrapper queryWrapper = new QueryWrapper(jeecgDemo); + *
正确示例:QueryWrapper queryWrapper = new QueryWrapper(); + *
3.也可以不使用这个方法直接调用 {@link #initQueryWrapper}直接获取实例 + */ + public static void installMplus(QueryWrapper queryWrapper,String columnPrefix,Object searchObj,Map parameterMap) { + + /* + * 注意:权限查询由前端配置数据规则 当一个人有多个所属部门时候 可以在规则配置包含条件 orgCode 包含 #{sys_org_code} + 但是不支持在自定义SQL中写orgCode in #{sys_org_code} + 当一个人只有一个部门 就直接配置等于条件: orgCode 等于 #{sys_org_code} 或者配置自定义SQL: orgCode = '#{sys_org_code}' + */ + + //区间条件组装 模糊查询 高级查询组装 简单排序 权限查询 + PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(searchObj); + Map ruleMap = getRuleMap(); + + //权限规则自定义SQL表达式 + for (String c : ruleMap.keySet()) { + if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){ + queryWrapper.and(i ->i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue()))); + } + } + + String name, type, column; + // update-begin--Author:taoyan Date:20200923 for:issues/1671 如果字段加注解了@TableField(exist = false),不走DB查询------- + //定义实体字段和数据库字段名称的映射 高级查询中 只能获取实体字段 如果设置TableField注解 那么查询条件会出问题 + Map fieldColumnMap = new HashMap(); + for (int i = 0; i < origDescriptors.length; i++) { + //aliasName = origDescriptors[i].getName(); mybatis 不存在实体属性 不用处理别名的情况 + name = origDescriptors[i].getName(); + type = origDescriptors[i].getPropertyType().toString(); + try { + if (judgedIsUselessField(name)|| !PropertyUtils.isReadable(searchObj, name)) { + continue; + } + + Object value = PropertyUtils.getSimpleProperty(searchObj, name); + column = getTableFieldName(searchObj.getClass(), name); + if(column==null){ + //column为null只有一种情况 那就是 添加了注解@TableField(exist = false) 后续都不用处理了 + continue; + } + //qn新增,为了支持多表,添加别名 + if(oConvertUtils.isNotEmpty(columnPrefix)){ + column = columnPrefix + "." + column; + } + fieldColumnMap.put(name,column); + //数据权限查询 + if(ruleMap.containsKey(name)) { + addRuleToQueryWrapper(ruleMap.get(name), column, origDescriptors[i].getPropertyType(), queryWrapper); + } + //区间查询 + doIntervalQuery(queryWrapper, parameterMap, type, name, column); + //判断单值 参数带不同标识字符串 走不同的查询 + //TODO 这种前后带逗号的支持分割后模糊查询需要否 使多选字段的查询生效 + if (null != value && value.toString().startsWith(COMMA) && value.toString().endsWith(COMMA)) { + String multiLikeval = value.toString().replace(",,", COMMA); + String[] vals = multiLikeval.substring(1, multiLikeval.length()).split(COMMA); + final String field = oConvertUtils.camelToUnderline(column); + if(vals.length>1) { + queryWrapper.and(j -> { + j = j.like(field,vals[0]); + for (int k=1;k j.like(field,vals[0])); + } + }else { + //根据参数值带什么关键字符串判断走什么类型的查询 + QueryRuleEnum rule = convert2Rule(value); + value = replaceValue(rule,value); + // add -begin 添加判断为字符串时设为全模糊查询 + //if( (rule==null || QueryRuleEnum.EQ.equals(rule)) && "class java.lang.String".equals(type)) { + // 可以设置左右模糊或全模糊,因人而异 + //rule = QueryRuleEnum.LIKE; + //} + // add -end 添加判断为字符串时设为全模糊查询 + addEasyQuery(queryWrapper, column, rule, value); + } + + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + // 排序逻辑 处理 + doMultiFieldsOrder(queryWrapper, parameterMap); + + //高级查询 + doSuperQuery(queryWrapper, parameterMap, fieldColumnMap); + // update-end--Author:taoyan Date:20200923 for:issues/1671 如果字段加注解了@TableField(exist = false),不走DB查询------- + + } + + + /** + * 区间查询 + * @param queryWrapper query对象 + * @param parameterMap 参数map + * @param type 字段类型 + * @param filedName 字段名称 + * @param columnName 列名称 + */ + private static void doIntervalQuery(QueryWrapper queryWrapper, Map parameterMap, String type, String filedName, String columnName) throws ParseException { + // 添加 判断是否有区间值 + String endValue = null,beginValue = null; + if (parameterMap != null && parameterMap.containsKey(filedName + BEGIN)) { + beginValue = parameterMap.get(filedName + BEGIN)[0].trim(); + addQueryByRule(queryWrapper, columnName, type, beginValue, QueryRuleEnum.GE); + + } + if (parameterMap != null && parameterMap.containsKey(filedName + END)) { + endValue = parameterMap.get(filedName + END)[0].trim(); + addQueryByRule(queryWrapper, columnName, type, endValue, QueryRuleEnum.LE); + } + //多值查询 + if (parameterMap != null && parameterMap.containsKey(filedName + MULTI)) { + endValue = parameterMap.get(filedName + MULTI)[0].trim(); + addQueryByRule(queryWrapper, columnName.replace(MULTI,""), type, endValue, QueryRuleEnum.IN); + } + } + + //多字段排序 TODO 需要修改前端 + public static void doMultiFieldsOrder(QueryWrapper queryWrapper,Map parameterMap) { + String column=null,order=null; + if(parameterMap!=null&& parameterMap.containsKey(ORDER_COLUMN)) { + column = parameterMap.get(ORDER_COLUMN)[0]; + } + if(parameterMap!=null&& parameterMap.containsKey(ORDER_TYPE)) { + order = parameterMap.get(ORDER_TYPE)[0]; + } + log.debug("排序规则>>列:"+column+",排序方式:"+order); + if (oConvertUtils.isNotEmpty(column) && oConvertUtils.isNotEmpty(order)) { + String[] columnList = column.split(","); + String[] orderList = order.split(","); + for (int i = 0;i=0) { + queryWrapper.orderByAsc(oConvertUtils.camelToUnderline(_column)); + } else { + queryWrapper.orderByDesc(oConvertUtils.camelToUnderline(_column)); + } + } + } + } + + /** + * 高级查询 + * @param queryWrapper 查询对象 + * @param parameterMap 参数对象 + * @param fieldColumnMap 实体字段和数据库列对应的map + */ + public static void doSuperQuery(QueryWrapper queryWrapper,Map parameterMap, Map fieldColumnMap) { + if(parameterMap!=null&& parameterMap.containsKey(SUPER_QUERY_PARAMS)){ + String superQueryParams = parameterMap.get(SUPER_QUERY_PARAMS)[0]; + String superQueryMatchType = parameterMap.get(SUPER_QUERY_MATCH_TYPE) != null ? parameterMap.get(SUPER_QUERY_MATCH_TYPE)[0] : MatchTypeEnum.AND.getValue(); + MatchTypeEnum matchType = MatchTypeEnum.getByValue(superQueryMatchType); + // update-begin--Author:sunjianlei Date:20200325 for:高级查询的条件要用括号括起来,防止和用户的其他条件冲突 ------- + try { + superQueryParams = URLDecoder.decode(superQueryParams, "UTF-8"); + List conditions = JSON.parseArray(superQueryParams, QueryCondition.class); + if (conditions == null || conditions.size() == 0) { + return; + } + log.info("---高级查询参数-->" + conditions.toString()); + queryWrapper.and(andWrapper -> { + for (int i = 0; i < conditions.size(); i++) { + QueryCondition rule = conditions.get(i); + if (oConvertUtils.isNotEmpty(rule.getField()) + && oConvertUtils.isNotEmpty(rule.getRule()) + && oConvertUtils.isNotEmpty(rule.getVal())) { + + log.debug("SuperQuery ==> " + rule.toString()); + addEasyQuery(andWrapper, fieldColumnMap.get(rule.getField()), QueryRuleEnum.getByValue(rule.getRule()), rule.getVal()); + + // 如果拼接方式是OR,就拼接OR + if (MatchTypeEnum.OR == matchType && i < (conditions.size() - 1)) { + andWrapper.or(); + } + } + } + //return andWrapper; + }); + } catch (UnsupportedEncodingException e) { + log.error("--高级查询参数转码失败:" + superQueryParams, e); + } catch (Exception e) { + log.error("--高级查询拼接失败:" + e.getMessage()); + e.printStackTrace(); + } + // update-end--Author:sunjianlei Date:20200325 for:高级查询的条件要用括号括起来,防止和用户的其他条件冲突 ------- + } + //log.info(" superQuery getCustomSqlSegment: "+ queryWrapper.getCustomSqlSegment()); + } + /** + * 根据所传的值 转化成对应的比较方式 + * 支持><= like in ! + * @param value + * @return + */ + private static QueryRuleEnum convert2Rule(Object value) { + // 避免空数据 + if (value == null) { + return null; + } + String val = (value + "").toString().trim(); + if (val.length() == 0) { + return null; + } + QueryRuleEnum rule =null; + + //update-begin--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284------------------- + //TODO 此处规则,只适用于 le lt ge gt + // step 2 .>= =< + if (rule == null && val.length() >= 3) { + if(QUERY_SEPARATE_KEYWORD.equals(val.substring(2, 3))){ + rule = QueryRuleEnum.getByValue(val.substring(0, 2)); + } + } + // step 1 .> < + if (rule == null && val.length() >= 2) { + if(QUERY_SEPARATE_KEYWORD.equals(val.substring(1, 2))){ + rule = QueryRuleEnum.getByValue(val.substring(0, 1)); + } + } + //update-end--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284--------------------- + + // step 3 like + if (rule == null && val.contains(STAR)) { + if (val.startsWith(STAR) && val.endsWith(STAR)) { + rule = QueryRuleEnum.LIKE; + } else if (val.startsWith(STAR)) { + rule = QueryRuleEnum.LEFT_LIKE; + } else if(val.endsWith(STAR)){ + rule = QueryRuleEnum.RIGHT_LIKE; + } + } + // step 4 in + if (rule == null && val.contains(COMMA)) { + //TODO in 查询这里应该有个bug 如果一字段本身就是多选 此时用in查询 未必能查询出来 + rule = QueryRuleEnum.IN; + } + // qn 补充,等于null的 + if(rule == null && val.equals(EQ_NULL)){ + rule = QueryRuleEnum.EQ_NULL; + } + // qn 补充,不等于null的 + if(rule == null && val.equals(NOT_NULL)){ + rule = QueryRuleEnum.NOT_NULL; + } + // qn 补充,等于空字符串的 + if(rule == null && val.equals(EQ_EMPTY)){ + rule = QueryRuleEnum.EQ_EMPTY; + } + // qn 补充,不等于空字符串的 + if(rule == null && val.equals(NOT_EMPTY)){ + rule = QueryRuleEnum.NOT_EMPTY; + } + // qn 补充,等于空的(包含null或空串) + if(rule == null && val.equals(EQ_BLANK)){ + rule = QueryRuleEnum.EQ_BLANK; + } + // qn 补充,不等于空的(不包含null和空串) + if(rule == null && val.equals(NOT_BLANK)){ + rule = QueryRuleEnum.NOT_BLANK; + } + // step 5 != + if(rule == null && val.startsWith(NOT_EQUAL)){ + rule = QueryRuleEnum.NE; + } + return rule != null ? rule : QueryRuleEnum.EQ; + } + + /** + * 替换掉关键字字符 + * + * @param rule + * @param value + * @return + */ + private static Object replaceValue(QueryRuleEnum rule, Object value) { + if (rule == null) { + return null; + } + if (! (value instanceof String)){ + return value; + } + String val = (value + "").toString().trim(); + if (rule == QueryRuleEnum.LIKE) { + value = val.substring(1, val.length() - 1); + //mysql 模糊查询之特殊字符下划线 (_、\) + value = specialStrConvert(value.toString()); + } else if (rule == QueryRuleEnum.LEFT_LIKE || rule == QueryRuleEnum.NE) { + value = val.substring(1); + //mysql 模糊查询之特殊字符下划线 (_、\) + value = specialStrConvert(value.toString()); + } else if (rule == QueryRuleEnum.RIGHT_LIKE) { + value = val.substring(0, val.length() - 1); + //mysql 模糊查询之特殊字符下划线 (_、\) + value = specialStrConvert(value.toString()); + } else if (rule == QueryRuleEnum.IN) { + value = val.split(","); + } else if (rule == QueryRuleEnum.EQ_NULL || rule == QueryRuleEnum.NOT_NULL + || rule == QueryRuleEnum.EQ_EMPTY || rule == QueryRuleEnum.NOT_EMPTY + || rule == QueryRuleEnum.EQ_BLANK || rule == QueryRuleEnum.NOT_BLANK) { + value = val; + } else { + //update-begin--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284------------------- + if(val.startsWith(rule.getValue())){ + //TODO 此处逻辑应该注释掉-> 如果查询内容中带有查询匹配规则符号,就会被截取的(比如:>=您好) + value = val.replaceFirst(rule.getValue(),""); + }else if(val.startsWith(rule.getCondition()+QUERY_SEPARATE_KEYWORD)){ + value = val.replaceFirst(rule.getCondition()+QUERY_SEPARATE_KEYWORD,"").trim(); + } + //update-end--Author:scott Date:20190724 for:initQueryWrapper组装sql查询条件错误 #284------------------- + } + return value; + } + + private static void addQueryByRule(QueryWrapper queryWrapper,String name,String type,String value,QueryRuleEnum rule) throws ParseException { + if(oConvertUtils.isNotEmpty(value)) { + Object temp; + // 针对数字类型字段,多值查询 + if(value.indexOf(COMMA)!=-1){ + temp = value; + addEasyQuery(queryWrapper, name, rule, temp); + return; + } + + switch (type) { + case "class java.lang.Integer": + temp = Integer.parseInt(value); + break; + case "class java.math.BigDecimal": + temp = new BigDecimal(value); + break; + case "class java.lang.Short": + temp = Short.parseShort(value); + break; + case "class java.lang.Long": + temp = Long.parseLong(value); + break; + case "class java.lang.Float": + temp = Float.parseFloat(value); + break; + case "class java.lang.Double": + temp = Double.parseDouble(value); + break; + case "class java.util.Date": + temp = getDateQueryByRule(value, rule); + break; + default: + temp = value; + break; + } + addEasyQuery(queryWrapper, name, rule, temp); + } + } + + /** + * 获取日期类型的值 + * @param value + * @param rule + * @return + * @throws ParseException + */ + private static Date getDateQueryByRule(String value,QueryRuleEnum rule) throws ParseException { + Date date = null; + if(value.length()==10) { + if(rule==QueryRuleEnum.GE) { + //比较大于 + date = getTime().parse(value + " 00:00:00"); + }else if(rule==QueryRuleEnum.LE) { + //比较小于 + date = getTime().parse(value + " 23:59:59"); + } + //TODO 日期类型比较特殊 可能oracle下不一定好使 + } + if(date==null) { + date = getTime().parse(value); + } + return date; + } + + /** + * 根据规则走不同的查询 + * @param queryWrapper QueryWrapper + * @param name 字段名字 + * @param rule 查询规则 + * @param value 查询条件值 + */ + private static void addEasyQuery(QueryWrapper queryWrapper, String name, QueryRuleEnum rule, Object value) { + if (value == null || rule == null || oConvertUtils.isEmpty(value)) { + return; + } + name = oConvertUtils.camelToUnderline(name); + String finalName = name; + log.info("--查询规则-->"+name+" "+rule.getValue()+" "+value); + switch (rule) { + case GT: + queryWrapper.gt(name, value); + break; + case GE: + queryWrapper.ge(name, value); + break; + case LT: + queryWrapper.lt(name, value); + break; + case LE: + queryWrapper.le(name, value); + break; + case EQ: + queryWrapper.eq(name, value); + break; + case NE: + queryWrapper.ne(name, value); + break; + case IN: + if(value instanceof String) { + queryWrapper.in(name, (Object[])value.toString().split(",")); + }else if(value instanceof String[]) { + queryWrapper.in(name, (Object[]) value); + } + //update-begin-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671 + else if(value.getClass().isArray()) { + queryWrapper.in(name, (Object[])value); + }else { + queryWrapper.in(name, value); + } + //update-end-author:taoyan date:20200909 for:【bug】in 类型多值查询 不适配postgresql #1671 + break; + case LIKE: + queryWrapper.like(name, value); + break; + case LEFT_LIKE: + queryWrapper.likeLeft(name, value); + break; + case RIGHT_LIKE: + queryWrapper.likeRight(name, value); + break; + //qn 新增多重查询 + case EQ_NULL: + queryWrapper.isNull(name); + break; + case NOT_NULL: + queryWrapper.isNotNull(name); + break; + case EQ_EMPTY: + queryWrapper.eq(name,""); + break; + case NOT_EMPTY: + queryWrapper.ne(name,""); + break; + case EQ_BLANK: + queryWrapper.and(x -> x.isNull(finalName).or().eq(finalName,"")); + break; + case NOT_BLANK: + queryWrapper.and(x -> x.isNotNull(finalName).or().ne(finalName,"")); + break; + default: + log.info("--查询规则未匹配到---"); + break; + } + } + /** + * + * @param name + * @return + */ + private static boolean judgedIsUselessField(String name) { + return "class".equals(name) || "ids".equals(name) + || "page".equals(name) || "rows".equals(name) + || "sort".equals(name) || "order".equals(name); + } + + + + /** + * 获取请求对应的数据权限规则 + * @return + */ + public static Map getRuleMap() { + Map ruleMap = new HashMap(); + List list =JeecgDataAutorUtils.loadDataSearchConditon(); + if(list != null&&list.size()>0){ + if(list.get(0)==null){ + return ruleMap; + } + for (SysPermissionDataRuleModel rule : list) { + String column = rule.getRuleColumn(); + if(QueryRuleEnum.SQL_RULES.getValue().equals(rule.getRuleConditions())) { + column = SQL_RULES_COLUMN+rule.getId(); + } + ruleMap.put(column, rule); + } + } + return ruleMap; + } + + /** + * 获取请求对应的数据权限规则 + * @return + */ + public static Map getRuleMap(List list) { + Map ruleMap = new HashMap(); + if(list==null){ + list =JeecgDataAutorUtils.loadDataSearchConditon(); + } + if(list != null&&list.size()>0){ + if(list.get(0)==null){ + return ruleMap; + } + for (SysPermissionDataRuleModel rule : list) { + String column = rule.getRuleColumn(); + if(QueryRuleEnum.SQL_RULES.getValue().equals(rule.getRuleConditions())) { + column = SQL_RULES_COLUMN+rule.getId(); + } + ruleMap.put(column, rule); + } + } + return ruleMap; + } + + private static void addRuleToQueryWrapper(SysPermissionDataRuleModel dataRule, String name, Class propertyType, QueryWrapper queryWrapper) { + QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions()); + if(rule.equals(QueryRuleEnum.IN) && ! propertyType.equals(String.class)) { + String[] values = dataRule.getRuleValue().split(","); + Object[] objs = new Object[values.length]; + for (int i = 0; i < values.length; i++) { + objs[i] = NumberUtils.parseNumber(values[i], propertyType); + } + addEasyQuery(queryWrapper, name, rule, objs); + }else { + if (propertyType.equals(String.class)) { + addEasyQuery(queryWrapper, name, rule, converRuleValue(dataRule.getRuleValue())); + }else if (propertyType.equals(Date.class)) { + String dateStr =converRuleValue(dataRule.getRuleValue()); + if(dateStr.length()==10){ + addEasyQuery(queryWrapper, name, rule, DateUtils.str2Date(dateStr,DateUtils.date_sdf.get())); + }else{ + addEasyQuery(queryWrapper, name, rule, DateUtils.str2Date(dateStr,DateUtils.datetimeFormat.get())); + } + }else { + addEasyQuery(queryWrapper, name, rule, NumberUtils.parseNumber(dataRule.getRuleValue(), propertyType)); + } + } + } + + public static String converRuleValue(String ruleValue) { + String value = JwtUtil.getUserSystemData(ruleValue,null); + return value!= null ? value : ruleValue; + } + + /** + * @author: scott + * @Description: 去掉值前后单引号 + * @date: 2020/3/19 21:26 + * @param ruleValue: + * @Return: java.lang.String + */ + public static String trimSingleQuote(String ruleValue) { + if (oConvertUtils.isEmpty(ruleValue)) { + return ""; + } + if (ruleValue.startsWith(QueryGenerator.SQL_SQ)) { + ruleValue = ruleValue.substring(1); + } + if (ruleValue.endsWith(QueryGenerator.SQL_SQ)) { + ruleValue = ruleValue.substring(0, ruleValue.length() - 1); + } + return ruleValue; + } + + public static String getSqlRuleValue(String sqlRule){ + try { + Set varParams = getSqlRuleParams(sqlRule); + for(String var:varParams){ + String tempValue = converRuleValue(var); + sqlRule = sqlRule.replace("#{"+var+"}",tempValue); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + } + return sqlRule; + } + + /** + * 获取sql中的#{key} 这个key组成的set + */ + public static Set getSqlRuleParams(String sql) { + if(oConvertUtils.isEmpty(sql)){ + return null; + } + Set varParams = new HashSet(); + String regex = "\\#\\{\\w+\\}"; + + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(sql); + while(m.find()){ + String var = m.group(); + varParams.add(var.substring(var.indexOf("{")+1,var.indexOf("}"))); + } + return varParams; + } + + /** + * 获取查询条件 + * @param field + * @param alias + * @param value + * @param isString + * @return + */ + public static String getSingleQueryConditionSql(String field,String alias,Object value,boolean isString) { + if (value == null) { + return ""; + } + field = alias+oConvertUtils.camelToUnderline(field); + QueryRuleEnum rule = QueryGenerator.convert2Rule(value); + return getSingleSqlByRule(rule, field, value, isString); + } + + public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString) { + String res = ""; + switch (rule) { + case GT: + res =field+rule.getValue()+getFieldConditionValue(value, isString); + break; + case GE: + res = field+rule.getValue()+getFieldConditionValue(value, isString); + break; + case LT: + res = field+rule.getValue()+getFieldConditionValue(value, isString); + break; + case LE: + res = field+rule.getValue()+getFieldConditionValue(value, isString); + break; + case EQ: + res = field+rule.getValue()+getFieldConditionValue(value, isString); + break; + case NE: + res = field+" <> "+getFieldConditionValue(value, isString); + break; + case IN: + res = field + " in "+getInConditionValue(value, isString); + break; + case LIKE: + res = field + " like "+getLikeConditionValue(value); + break; + case LEFT_LIKE: + res = field + " like "+getLikeConditionValue(value); + break; + case RIGHT_LIKE: + res = field + " like "+getLikeConditionValue(value); + break; + default: + res = field+" = "+getFieldConditionValue(value, isString); + break; + } + return res; + } + private static String getFieldConditionValue(Object value,boolean isString) { + String str = value.toString().trim(); + if(str.startsWith("!")) { + str = str.substring(1); + }else if(str.startsWith(">=")) { + str = str.substring(2); + }else if(str.startsWith("<=")) { + str = str.substring(2); + }else if(str.startsWith(">")) { + str = str.substring(1); + }else if(str.startsWith("<")) { + str = str.substring(1); + } + if(isString) { + if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ + return " N'"+str+"' "; + }else{ + return " '"+str+"' "; + } + }else { + // 如果不是字符串 有一种特殊情况 popup调用都走这个逻辑 参数传递的可能是“‘admin’”这种格式的 + if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType()) && str.endsWith("'") && str.startsWith("'")){ + return " N"+str; + } + return value.toString(); + } + } + + private static String getInConditionValue(Object value,boolean isString) { + if(isString) { + String temp[] = value.toString().split(","); + String res=""; + for (String string : temp) { + if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ + res+=",N'"+string+"'"; + }else{ + res+=",'"+string+"'"; + } + } + return "("+res.substring(1)+")"; + }else { + return "("+value.toString()+")"; + } + } + + private static String getLikeConditionValue(Object value) { + String str = value.toString().trim(); + if(str.startsWith("*") && str.endsWith("*")) { + if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ + return "N'%"+str.substring(1,str.length()-1)+"%'"; + }else{ + return "'%"+str.substring(1,str.length()-1)+"%'"; + } + }else if(str.startsWith("*")) { + if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ + return "N'%"+str.substring(1)+"'"; + }else{ + return "'%"+str.substring(1)+"'"; + } + }else if(str.endsWith("*")) { + if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ + return "N'"+str.substring(0,str.length()-1)+"%'"; + }else{ + return "'"+str.substring(0,str.length()-1)+"%'"; + } + }else { + if(str.indexOf("%")>=0) { + if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ + if(str.startsWith("'") && str.endsWith("'")){ + return "N"+str; + }else{ + return "N"+"'"+str+"'"; + } + }else{ + if(str.startsWith("'") && str.endsWith("'")){ + return str; + }else{ + return "'"+str+"'"; + } + } + }else { + if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ + return "N'%"+str+"%'"; + }else{ + return "'%"+str+"%'"; + } + } + } + } + + /** + * 根据权限相关配置生成相关的SQL 语句 + * @param clazz + * @return + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static String installAuthJdbc(Class clazz) { + StringBuffer sb = new StringBuffer(); + //权限查询 + Map ruleMap = getRuleMap(); + PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(clazz); + String sql_and = " and "; + for (String c : ruleMap.keySet()) { + if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){ + sb.append(sql_and+getSqlRuleValue(ruleMap.get(c).getRuleValue())); + } + } + String name, column; + for (int i = 0; i < origDescriptors.length; i++) { + name = origDescriptors[i].getName(); + if (judgedIsUselessField(name)) { + continue; + } + if(ruleMap.containsKey(name)) { + column = getTableFieldName(clazz, name); + if(column==null){ + continue; + } + SysPermissionDataRuleModel dataRule = ruleMap.get(name); + QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions()); + Class propType = origDescriptors[i].getPropertyType(); + boolean isString = propType.equals(String.class); + Object value; + if(isString) { + value = converRuleValue(dataRule.getRuleValue()); + }else { + value = NumberUtils.parseNumber(dataRule.getRuleValue(),propType); + } + String filedSql = getSingleSqlByRule(rule, oConvertUtils.camelToUnderline(column), value,isString); + sb.append(sql_and+filedSql); + } + } + log.info("query auth sql is:"+sb.toString()); + return sb.toString(); + } + + /** + * 根据权限相关配置 组装mp需要的权限 + * @param queryWrapper + * @param clazz + * @return + */ + public static void installAuthMplus(QueryWrapper queryWrapper,Class clazz) { + //权限查询 + Map ruleMap = getRuleMap(); + PropertyDescriptor origDescriptors[] = PropertyUtils.getPropertyDescriptors(clazz); + for (String c : ruleMap.keySet()) { + if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){ + queryWrapper.and(i ->i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue()))); + } + } + String name, column; + for (int i = 0; i < origDescriptors.length; i++) { + name = origDescriptors[i].getName(); + if (judgedIsUselessField(name)) { + continue; + } + column = getTableFieldName(clazz, name); + if(column==null){ + continue; + } + if(ruleMap.containsKey(name)) { + addRuleToQueryWrapper(ruleMap.get(name), column, origDescriptors[i].getPropertyType(), queryWrapper); + } + } + } + + /** + * 转换sql中的系统变量 + * @param sql + * @return + */ + public static String convertSystemVariables(String sql){ + return getSqlRuleValue(sql); + } + + /** + * 获取所有配置的权限 返回sql字符串 不受字段限制 配置什么就拿到什么 + * @return + */ + public static String getAllConfigAuth() { + StringBuffer sb = new StringBuffer(); + //权限查询 + Map ruleMap = getRuleMap(); + String sql_and = " and "; + for (String c : ruleMap.keySet()) { + SysPermissionDataRuleModel dataRule = ruleMap.get(c); + String ruleValue = dataRule.getRuleValue(); + if(oConvertUtils.isEmpty(ruleValue)){ + continue; + } + if(oConvertUtils.isNotEmpty(c) && c.startsWith(SQL_RULES_COLUMN)){ + sb.append(sql_and+getSqlRuleValue(ruleValue)); + }else{ + boolean isString = false; + ruleValue = ruleValue.trim(); + if(ruleValue.startsWith("'") && ruleValue.endsWith("'")){ + isString = true; + ruleValue = ruleValue.substring(1,ruleValue.length()-1); + } + QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions()); + String value = converRuleValue(ruleValue); + String filedSql = getSingleSqlByRule(rule, c, value,isString); + sb.append(sql_and+filedSql); + } + } + log.info("query auth sql is = "+sb.toString()); + return sb.toString(); + } + + + + /** 当前系统数据库类型 */ + private static String DB_TYPE; + /** + * 获取系统数据库类型 + */ + private static String getDbType(){ + return CommonUtils.getDatabaseType(); + } + + + /** + * 获取class的 包括父类的 + * @param clazz + * @return + */ + private static List getClassFields(Class clazz) { + List list = new ArrayList(); + Field[] fields; + do{ + fields = clazz.getDeclaredFields(); + for(int i = 0;i clazz, String name) { + try { + //如果字段加注解了@TableField(exist = false),不走DB查询 + Field field = null; + try { + field = clazz.getDeclaredField(name); + } catch (NoSuchFieldException e) { + //e.printStackTrace(); + } + + //如果为空,则去父类查找字段 + if (field == null) { + List allFields = getClassFields(clazz); + List searchFields = allFields.stream().filter(a -> a.getName().equals(name)).collect(Collectors.toList()); + if(searchFields!=null && searchFields.size()>0){ + field = searchFields.get(0); + } + } + + if (field != null) { + TableField tableField = field.getAnnotation(TableField.class); + if (tableField != null){ + if(tableField.exist() == false){ + //如果设置了TableField false 这个字段不需要处理 + return null; + }else{ + String column = tableField.value(); + //如果设置了TableField value 这个字段是实体字段 + if(!"".equals(column)){ + return column; + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return name; + } + + /** + * mysql 模糊查询之特殊字符下划线 (_、\) + * + * @param value: + * @Return: java.lang.String + */ + private static String specialStrConvert(String value) { + if (DataBaseConstant.DB_TYPE_MYSQL.equals(getDbType())) { + String[] special_str = QueryGenerator.LIKE_MYSQL_SPECIAL_STRS.split(","); + for (String str : special_str) { + if (value.indexOf(str) !=-1) { + value = value.replace(str, "\\" + str); + } + } + } + return value; + } +} diff --git a/src/main/java/org/jeecg/common/system/query/QueryRuleEnum.java b/src/main/java/org/jeecg/common/system/query/QueryRuleEnum.java new file mode 100644 index 0000000..5b5caa6 --- /dev/null +++ b/src/main/java/org/jeecg/common/system/query/QueryRuleEnum.java @@ -0,0 +1,88 @@ +package org.jeecg.common.system.query; + +import org.jeecg.common.util.oConvertUtils; + +/** + * Query 规则 常量 + * @Author Scott + * @Date 2019年02月14日 + */ +public enum QueryRuleEnum { + + GT(">","gt","大于"), + GE(">=","ge","大于等于"), + LT("<","lt","小于"), + LE("<=","le","小于等于"), + EQ("=","eq","等于"), + NE("!=","ne","不等于"), + IN("IN","in","包含"), + LIKE("LIKE","like","全模糊"), + LEFT_LIKE("LEFT_LIKE","left_like","左模糊"), + RIGHT_LIKE("RIGHT_LIKE","right_like","右模糊"), + SQL_RULES("USE_SQL_RULES","ext","自定义SQL片段"), + //qn补充 + EQ_NULL("EQ_NULL","eq_null","等于null"), + NOT_NULL("NOT_NULL","not_null","不等于null"), + EQ_EMPTY("EQ_EMPTY","eq_empty","等空串"), + NOT_EMPTY("NOT_EMPTY","not_empty","不等于空串"), + EQ_BLANK("EQ_BLANK","eq_blank","等于空串或null"), + NOT_BLANK("NOT_BLANK","not_blank","不等于空串和null"); + + +// private static final String EQ_NULL = "!!null"; +// private static final String NOT_NULL = "!!!null"; +// private static final String EQ_EMPTY = "!!"; +// private static final String NOT_EMPTY = "!!!"; +// private static final String EQ_BLANK = "!!BLANK"; +// private static final String NOT_BLANK = "!!!BLANK"; + + + + private String value; + + private String condition; + + private String msg; + + QueryRuleEnum(String value, String condition, String msg){ + this.value = value; + this.condition = condition; + this.msg = msg; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public String getCondition() { + return condition; + } + + public void setCondition(String condition) { + this.condition = condition; + } + + public static QueryRuleEnum getByValue(String value){ + if(oConvertUtils.isEmpty(value)) { + return null; + } + for(QueryRuleEnum val :values()){ + if (val.getValue().equals(value) || val.getCondition().equals(value)){ + return val; + } + } + return null; + } +} diff --git a/src/main/java/org/jeecg/common/system/util/JwtUtil.java b/src/main/java/org/jeecg/common/system/util/JwtUtil.java new file mode 100644 index 0000000..2bb3644 --- /dev/null +++ b/src/main/java/org/jeecg/common/system/util/JwtUtil.java @@ -0,0 +1,208 @@ +package org.jeecg.common.system.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTDecodeException; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.google.common.base.Joiner; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.constant.DataBaseConstant; +import org.jeecg.common.exception.JeecgBootException; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.common.system.vo.SysUserCacheInfo; +import org.jeecg.common.util.DateUtils; +import org.jeecg.common.util.SpringContextUtils; +import org.jeecg.common.util.oConvertUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.Date; + +/** + * @Author Scott + * @Date 2018-07-12 14:23 + * @Desc JWT工具类 + **/ +public class JwtUtil { + + // Token过期时间30分钟(用户登录过期时间是此时间的两倍,以token在reids缓存时间为准) +// public static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;//天*分钟*秒*毫秒 //24小时 + public static final long EXPIRE_TIME = 30 * 60 * 1000;;//分钟*秒*毫秒 //30分钟 + + /** + * 校验token是否正确 + * + * @param token 密钥 + * @param secret 用户的密码 + * @return 是否正确 + */ + public static boolean verify(String token, String username, String secret) { + try { + // 根据密码生成JWT效验器 + Algorithm algorithm = Algorithm.HMAC256(secret); + JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build(); + // 效验TOKEN + DecodedJWT jwt = verifier.verify(token); + return true; + } catch (Exception exception) { + return false; + } + } + + /** + * 获得token中的信息无需secret解密也能获得 + * + * @return token中包含的用户名 + */ + public static String getUsername(String token) { + try { + DecodedJWT jwt = JWT.decode(token); + return jwt.getClaim("username").asString(); + } catch (JWTDecodeException e) { + return null; + } + } + + /** + * 生成签名,5min后过期 + * + * @param username 用户名 + * @param secret 用户的密码 + * @return 加密的token + */ + public static String sign(String username, String secret) { + Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); + Algorithm algorithm = Algorithm.HMAC256(secret); + // 附带username信息 + return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm); + + } + + /** + * 根据request中的token获取用户账号 + * + * @param request + * @return + * @throws JeecgBootException + */ + public static String getUserNameByToken(HttpServletRequest request) throws JeecgBootException { + String accessToken = request.getHeader("X-Access-Token"); + String username = getUsername(accessToken); + if (oConvertUtils.isEmpty(username)) { + throw new JeecgBootException("未获取到用户"); + } + return username; + } + + /** + * 从session中获取变量 + * @param key + * @return + */ + public static String getSessionData(String key) { + //${myVar}% + //得到${} 后面的值 + String moshi = ""; + if(key.indexOf("}")!=-1){ + moshi = key.substring(key.indexOf("}")+1); + } + String returnValue = null; + if (key.contains("#{")) { + key = key.substring(2,key.indexOf("}")); + } + if (oConvertUtils.isNotEmpty(key)) { + HttpSession session = SpringContextUtils.getHttpServletRequest().getSession(); + returnValue = (String) session.getAttribute(key); + } + //结果加上${} 后面的值 + if(returnValue!=null){returnValue = returnValue + moshi;} + return returnValue; + } + + /** + * 从当前用户中获取变量 + * @param key + * @param user + * @return + */ + //TODO 急待改造 sckjkdsjsfjdk + public static String getUserSystemData(String key,SysUserCacheInfo user) { + if(user==null) { + user = JeecgDataAutorUtils.loadUserInfo(); + } + //#{sys_user_code}% + + // 获取登录用户信息 + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + String moshi = ""; + if(key.indexOf("}")!=-1){ + moshi = key.substring(key.indexOf("}")+1); + } + String returnValue = null; + //针对特殊标示处理#{sysOrgCode},判断替换 + if (key.contains("#{")) { + key = key.substring(2,key.indexOf("}")); + } else { + key = key; + } + //替换为系统登录用户帐号 + if (key.equals(DataBaseConstant.SYS_USER_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_CODE_TABLE)) { + if(user==null) { + returnValue = sysUser.getUsername(); + }else { + returnValue = user.getSysUserCode(); + } + } + //替换为系统登录用户真实名字 + else if (key.equals(DataBaseConstant.SYS_USER_NAME)|| key.toLowerCase().equals(DataBaseConstant.SYS_USER_NAME_TABLE)) { + if(user==null) { + returnValue = sysUser.getRealname(); + }else { + returnValue = user.getSysUserName(); + } + } + + //替换为系统用户登录所使用的机构编码 + else if (key.equals(DataBaseConstant.SYS_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_ORG_CODE_TABLE)) { + if(user==null) { + returnValue = sysUser.getOrgCode(); + }else { + returnValue = user.getSysOrgCode(); + } + } + //替换为系统用户所拥有的所有机构编码 + else if (key.equals(DataBaseConstant.SYS_MULTI_ORG_CODE)|| key.toLowerCase().equals(DataBaseConstant.SYS_MULTI_ORG_CODE_TABLE)) { + if(user==null){ + //TODO 暂时使用用户登录部门,存在逻辑缺陷,不是用户所拥有的部门 + returnValue = sysUser.getOrgCode(); + }else{ + if(user.isOneDepart()) { + returnValue = user.getSysMultiOrgCode().get(0); + }else { + returnValue = Joiner.on(",").join(user.getSysMultiOrgCode()); + } + } + } + //替换为当前系统时间(年月日) + else if (key.equals(DataBaseConstant.SYS_DATE)|| key.toLowerCase().equals(DataBaseConstant.SYS_DATE_TABLE)) { + returnValue = DateUtils.formatDate(); + } + //替换为当前系统时间(年月日时分秒) + else if (key.equals(DataBaseConstant.SYS_TIME)|| key.toLowerCase().equals(DataBaseConstant.SYS_TIME_TABLE)) { + returnValue = DateUtils.now(); + } + //流程状态默认值(默认未发起) + else if (key.equals(DataBaseConstant.BPM_STATUS)|| key.toLowerCase().equals(DataBaseConstant.BPM_STATUS_TABLE)) { + returnValue = "1"; + } + if(returnValue!=null){returnValue = returnValue + moshi;} + return returnValue; + } + +// public static void main(String[] args) { +// String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NjUzMzY1MTMsInVzZXJuYW1lIjoiYWRtaW4ifQ.xjhud_tWCNYBOg_aRlMgOdlZoWFFKB_givNElHNw3X0"; +// System.out.println(JwtUtil.getUsername(token)); +// } +} diff --git a/src/main/java/org/jeecg/config/WebSocketConfig.java b/src/main/java/org/jeecg/config/WebSocketConfig.java new file mode 100644 index 0000000..1a633e4 --- /dev/null +++ b/src/main/java/org/jeecg/config/WebSocketConfig.java @@ -0,0 +1,10 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by Fernflower decompiler) +// 禁止该类(打成war包必要的) +// + +package org.jeecg.config; + +public class WebSocketConfig { +} diff --git a/src/main/java/org/jeecg/config/mybatis/MybatisPlusSaasConfig.java b/src/main/java/org/jeecg/config/mybatis/MybatisPlusSaasConfig.java new file mode 100644 index 0000000..aef172b --- /dev/null +++ b/src/main/java/org/jeecg/config/mybatis/MybatisPlusSaasConfig.java @@ -0,0 +1,14 @@ +package org.jeecg.config.mybatis; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Configuration; + +/** + * 单数据源配置(jeecg.datasource.open = false时生效) + * @Author zhoujf + * + */ +@Configuration +@MapperScan(value={"org.jeecg.modules.**.mapper*","com.nd.**.mapper*"}) +public class MybatisPlusSaasConfig { +} diff --git a/src/main/java/org/jeecg/config/shiro/ShiroConfig.java b/src/main/java/org/jeecg/config/shiro/ShiroConfig.java new file mode 100644 index 0000000..5dc935c --- /dev/null +++ b/src/main/java/org/jeecg/config/shiro/ShiroConfig.java @@ -0,0 +1,262 @@ +package org.jeecg.config.shiro; + +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; +import org.apache.shiro.mgt.DefaultSubjectDAO; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.crazycake.shiro.IRedisManager; +import org.crazycake.shiro.RedisCacheManager; +import org.crazycake.shiro.RedisClusterManager; +import org.crazycake.shiro.RedisManager; +import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.config.shiro.ShiroRealm; +import org.jeecg.config.shiro.filters.JwtFilter; +import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.core.env.Environment; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.util.StringUtils; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisCluster; + +import javax.annotation.Resource; +import javax.servlet.Filter; +import java.util.*; + +/** + * @author: Scott + * @date: 2018/2/7 + * @description: shiro 配置类 + */ + +@Slf4j +@Configuration +public class ShiroConfig { + + @Value("${jeecg.shiro.excludeUrls}") + private String excludeUrls; + @Resource + LettuceConnectionFactory lettuceConnectionFactory; + @Autowired + private Environment env; + + + /** + * Filter Chain定义说明 + * + * 1、一个URL可以配置多个Filter,使用逗号分隔 + * 2、当设置多个过滤器时,全部验证通过,才视为通过 + * 3、部分过滤器可指定参数,如perms,roles + */ + @Bean("shiroFilter") + public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); + shiroFilterFactoryBean.setSecurityManager(securityManager); + // 拦截器 + Map filterChainDefinitionMap = new LinkedHashMap(); + if(oConvertUtils.isNotEmpty(excludeUrls)){ + String[] permissionUrl = excludeUrls.split(","); + for(String url : permissionUrl){ + filterChainDefinitionMap.put(url,"anon"); + } + } + // 配置不会被拦截的链接 顺序判断 + filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录 + filterChainDefinitionMap.put("/customer/**", "anon"); //婚恋网用户 + filterChainDefinitionMap.put("/hl/**", "anon"); //婚恋网用户 + filterChainDefinitionMap.put("/sys/common/upload", "anon"); //文件上传 + filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除 + filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除 + filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除 + filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除 + filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除 + filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录 + filterChainDefinitionMap.put("/sys/getEncryptedString", "anon"); //获取加密串 + filterChainDefinitionMap.put("/sys/sms", "anon");//短信验证码 + filterChainDefinitionMap.put("/sys/phoneLogin", "anon");//手机登录 + filterChainDefinitionMap.put("/sys/user/checkOnlyUser", "anon");//校验用户是否存在 + filterChainDefinitionMap.put("/sys/user/register", "anon");//用户注册 + filterChainDefinitionMap.put("/sys/user/querySysUser", "anon");//根据手机号获取用户信息 + filterChainDefinitionMap.put("/sys/user/phoneVerification", "anon");//用户忘记密码验证手机号 + filterChainDefinitionMap.put("/sys/user/passwordChange", "anon");//用户更改密码 + filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码 + filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token + filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览 + //filterChainDefinitionMap.put("/sys/common/view/**", "anon");//图片预览不限制token + //filterChainDefinitionMap.put("/sys/common/download/**", "anon");//文件下载不限制token + filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件 + filterChainDefinitionMap.put("/", "anon"); + filterChainDefinitionMap.put("/doc.html", "anon"); + filterChainDefinitionMap.put("/**/*.js", "anon"); + filterChainDefinitionMap.put("/**/*.css", "anon"); + filterChainDefinitionMap.put("/**/*.html", "anon"); + filterChainDefinitionMap.put("/**/*.svg", "anon"); + filterChainDefinitionMap.put("/**/*.pdf", "anon"); + filterChainDefinitionMap.put("/**/*.jpg", "anon"); + filterChainDefinitionMap.put("/**/*.png", "anon"); + filterChainDefinitionMap.put("/**/*.ico", "anon"); + + // update-begin--Author:sunjianlei Date:20190813 for:排除字体格式的后缀 + filterChainDefinitionMap.put("/**/*.ttf", "anon"); + filterChainDefinitionMap.put("/**/*.woff", "anon"); + filterChainDefinitionMap.put("/**/*.woff2", "anon"); + // update-begin--Author:sunjianlei Date:20190813 for:排除字体格式的后缀 + + filterChainDefinitionMap.put("/druid/**", "anon"); + filterChainDefinitionMap.put("/swagger-ui.html", "anon"); + filterChainDefinitionMap.put("/swagger**/**", "anon"); + filterChainDefinitionMap.put("/webjars/**", "anon"); + filterChainDefinitionMap.put("/v2/**", "anon"); + + //积木报表排除 + filterChainDefinitionMap.put("/jmreport/**", "anon"); + filterChainDefinitionMap.put("/**/*.js.map", "anon"); + filterChainDefinitionMap.put("/**/*.css.map", "anon"); + + //测试示例 + filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试 + filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); //大屏模板例子 + //filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面 + //filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试 + + //websocket排除 + filterChainDefinitionMap.put("/websocket/**", "anon");//系统通知和公告 + filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例 + + +// filterChainDefinitionMap.put("/gateway/**/list", "jwt"); + filterChainDefinitionMap.put("/gateway/**/add", "jwt");//禁止可修改的免登陆 + filterChainDefinitionMap.put("/gateway/**/edit", "jwt");//禁止可修改的免登陆 + filterChainDefinitionMap.put("/gateway/**/delete", "jwt");//禁止可修改的免登陆 + filterChainDefinitionMap.put("/gateway/**/deleteBatch", "jwt");//禁止可修改的免登陆 + //前台免登陆 + filterChainDefinitionMap.put("/gateway/**/", "anon");//前台免登陆 + + //性能监控 TODO 存在安全漏洞 + //filterChainDefinitionMap.put("/actuator/**", "anon"); + + // 添加自己的过滤器并且取名为jwt + Map filterMap = new HashMap(1); + //如果cloudServer为空 则说明是单体 需要加载跨域配置 + Object cloudServer = env.getProperty(CommonConstant.CLOUD_SERVER_KEY); + filterMap.put("jwt", new JwtFilter(cloudServer==null)); + shiroFilterFactoryBean.setFilters(filterMap); + // +<#-- freemarker 的一些工具方法 --> +<#----> +<#-- 驼峰转其他字符 --> +<#-- @param str 待转换的文本 --> +<#-- @param character 要转换成的字符 --> +<#-- @param case 转换大小写(normal 不转换,lower 小写,upper 大写) --> +<#function camelToChar(str, character, case='normal')> + <#assign text=str?replace("([a-z])([A-Z]+)","$1${character}$2","r")/> + <#if case=="upper"> + <#return text?upper_case> + <#elseif case=="lower"> + <#return text?lower_case> + <#else> + <#return text> + + +<#----> +<#-- 驼峰转下划线 --> +<#function camelToDashed(str, case='normal')> + <#return camelToChar(str, "_", case)> + +<#----> +<#-- 驼峰转横线 --> +<#function camelToHorizontal(str, case='normal')> + <#return camelToChar(str, "-", case)> + +<#----> +<#-- 获取 v-model 属性 --> +<#function getVModel po,suffix=""> + <#return "v-model=\"queryParam.${po.fieldName}${suffix}\""> + +<#-- 获取 placeholder 属性 --> +<#function getPlaceholder po,prefix,fillComment=true> + <#if fillComment> + <#return "placeholder=\"${prefix}${po.filedComment}\""> + <#else> + <#return "placeholder=\"${prefix}\""> + + +<#-- ** 判断某字段是否配置了校验 * --> +<#function poHasCheck po> + <#if (po.fieldValidType!'')?trim?length gt 0 || po.nullable == 'N'> + <#if po.fieldName != 'id'> + <#if po.nullable == 'N' + || po.fieldValidType == '*' + || po.fieldValidType == 'only' + || po.fieldValidType == 'n6-16' + || po.fieldValidType == '*6-16' + || po.fieldValidType == 's6-18' + || po.fieldValidType == 'url' + || po.fieldValidType == 'e' + || po.fieldValidType == 'm' + || po.fieldValidType == 'p' + || po.fieldValidType == 's' + || po.fieldValidType == 'n' + || po.fieldValidType == 'z' + || po.fieldValidType == 'money' + > + <#return true> + + + <#elseif po.defaultVal??> + <#return true> + + <#return false> + +<#-- ** 如果配置了校验就显示 validatorRules * --> +<#function autoWriteRules po> + <#if poHasCheck(po)> + <#return ", validatorRules.${po.fieldName}"> + <#else> + <#return ""> + + + +<#-- ** 高级查询生成 * --> +<#function superQueryFieldList po> + <#if po.classType=="popup"> + <#return "{type:'${po.classType}',value:'${po.fieldName}',text:'${po.filedComment}', popup:{code:'${po.dictTable}',field:'${po.dictField?split(',')[0]}',orgFields:'${po.dictField?split(',')[0]}',destFields:'${po.dictText?split(',')[0]}'}}"> + <#elseif po.classType=="sel_user" || po.classType=="sel_depart" || po.classType=="datetime" || po.classType=="date" || po.classType=="pca" || po.classType=="switch"> + <#return "{type:'${po.classType}',value:'${po.fieldName}',text:'${po.filedComment}'}"> + <#else> + <#if po.dictTable?? && po.dictTable!="" && po.classType!="sel_tree" && po.classType!="cat_tree" && po.classType!="link_down"> + <#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}',dictCode:'${po.dictTable},${po.dictText},${po.dictField}'}"> + <#elseif po.dictField?? && po.classType!="sel_tree" && po.classType!="cat_tree" && po.classType!="link_down"> + <#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}',dictCode:'${po.dictField}'}"> + <#elseif po.fieldDbType=="Text"> + <#return "{type:'string',value:'${po.fieldName}',text:'${po.filedComment}'}"> + <#elseif po.fieldDbType=="Blob"> + <#return "{type:'byte',value:'${po.fieldName}',text:'${po.filedComment}'}"> + <#elseif po.fieldDbType=="BigDecimal" || po.fieldDbType=="double"> + <#return "{type:'number',value:'${po.fieldName}',text:'${po.filedComment}'}"> + <#else> + <#return "{type:'${po.fieldDbType}',value:'${po.fieldName}',text:'${po.filedComment}'}"> + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/core.ftl b/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/core.ftl new file mode 100644 index 0000000..883f400 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/core.ftl @@ -0,0 +1,63 @@ +<#include "../utils.ftl"> +<#if po.isShow == 'Y' && poHasCheck(po)> + <#if po.fieldName != 'id'> + ${po.fieldName}: { + <#if po.defaultVal??> + <#if po.fieldDbType=="BigDecimal" || po.fieldDbType=="double" || po.fieldDbType=="int"> + initialValue:${po.defaultVal}, + <#else> + initialValue:"${po.defaultVal}", + + + rules: [ + <#assign fieldValidType = po.fieldValidType!''> + <#-- 非空校验 --> + <#if po.nullable == 'N' || fieldValidType == '*'> + { required: true, message: '请输入${po.filedComment}!'}, + <#elseif fieldValidType!=''> + { required: false}, + + <#-- 唯一校验 --> + <#if fieldValidType == 'only'> + { validator: (rule, value, callback) => validateDuplicateValue('${tableName}', '${po.fieldDbName}', value, this.model.id, callback)}, + <#-- 6到16位数字 --> + <#elseif fieldValidType == 'n6-16'> + { pattern: /\d{6,18}/, message: '请输入6到16位数字!'}, + <#-- 6到16位任意字符 --> + <#elseif fieldValidType == '*6-16'> + { pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'}, + <#-- 6到18位字符串 --> + <#elseif fieldValidType == 's6-18'> + { pattern: /^.{6,18}$/, message: '请输入6到18位任意字符!'}, + <#-- 网址 --> + <#elseif fieldValidType == 'url'> + { pattern: /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/, message: '请输入正确的网址!'}, + <#-- 电子邮件 --> + <#elseif fieldValidType == 'e'> + { pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'}, + <#-- 手机号码 --> + <#elseif fieldValidType == 'm'> + { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'}, + <#-- 邮政编码 --> + <#elseif fieldValidType == 'p'> + { pattern: /^[1-9]\d{5}$/, message: '请输入正确的邮政编码!'}, + <#-- 字母 --> + <#elseif fieldValidType == 's'> + { pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'}, + <#-- 数字 --> + <#elseif fieldValidType == 'n'> + { pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'}, + <#-- 整数 --> + <#elseif fieldValidType == 'z'> + { pattern: /^-?\d+$/, message: '请输入整数!'}, + <#-- 金额 --> + <#elseif fieldValidType == 'money'> + { pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'}, + <#-- 无校验 --> + <#else> + <#t> + + ] + }, + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/main.ftl b/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/main.ftl new file mode 100644 index 0000000..f86e068 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/main.ftl @@ -0,0 +1,5 @@ + validatorRules: { +<#list columns as po> + <#include "core.ftl"> + + }, diff --git a/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub.ftl b/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub.ftl new file mode 100644 index 0000000..a6e61c3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/common/validatorRulesTemplate/sub.ftl @@ -0,0 +1,5 @@ + validatorRules: { +<#list sub.colums as po> + <#include "core.ftl"> + + }, diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..d28024b --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,180 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; +<#assign bpm_flag=false> +<#list originalColumns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> + + + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service> { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName} ${entityName?uncap_first}) { + <#if bpm_flag> + ${entityName?uncap_first}.setBpmStatus("1"); + + ${entityName?uncap_first}Service.save(${entityName?uncap_first}); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.updateById(${entityName?uncap_first}); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + if(${entityName?uncap_first}==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(${entityName?uncap_first}); + } + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, ${entityName}.class); + } + +} diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..4f5ca2a --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,116 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${tableName}") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + <#-- <#if po.classType!='popup'> + <#if po.dictTable?default("")?trim?length gt 1> + @Dict(dicCode="${po.dictField}",dicText="${po.dictText}",dictTable="${po.dictTable}") + <#elseif po.dictField?default("")?trim?length gt 1> + @Dict(dicCode="${po.dictField}") + + --> + + <#if po.fieldDbType=='Blob'> + private transient java.lang.String ${po.fieldName}String; + + private byte[] ${po.fieldName}; + + public byte[] get${po.fieldName?cap_first}(){ + if(${po.fieldName}String==null){ + return null; + } + try { + return ${po.fieldName}String.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + public String get${po.fieldName?cap_first}String(){ + if(${po.fieldName}==null || ${po.fieldName}.length==0){ + return ""; + } + try { + return new String(${po.fieldName},"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return ""; + } + <#else> + @ApiModelProperty(value = "${po.filedComment}") + private ${po.fieldType} ${po.fieldName}; + + +} diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..f00240a --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,14 @@ +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..6326220 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,19 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + +} diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..104fc21 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,512 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei new file mode 100644 index 0000000..ad88de2 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei @@ -0,0 +1,343 @@ +<#--<#include "../../../../../../../common/utils.ftl">--> +<#include "/common/utils.ftl"> + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..9a707e0 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,70 @@ +<#--<#include "../../../../../../../common/utils.ftl">--> +<#include "/common/utils.ftl"> +<#assign modal_width = 800> +<#if tableVo.fieldRowNum==2> + <#assign modal_width = 896> +<#elseif tableVo.fieldRowNum==3> + <#assign modal_width = 1024> +<#elseif tableVo.fieldRowNum==4> + <#assign modal_width = 1280> + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal__Style#Drawer.vuei b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal__Style#Drawer.vuei new file mode 100644 index 0000000..c0a75f1 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal__Style#Drawer.vuei @@ -0,0 +1,92 @@ +<#include "/common/utils.ftl"> +<#assign modal_width = 800> +<#if tableVo.fieldRowNum==2> + <#assign modal_width = 896> +<#elseif tableVo.fieldRowNum==3> + <#assign modal_width = 1024> +<#elseif tableVo.fieldRowNum==4> + <#assign modal_width = 1280> + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..2772d2f --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,280 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.vo.LoginUser; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.vo.${entityName}Page; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; +<#assign bpm_flag=false> +<#list originalColumns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> + + + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + <#list subTables as sub> + @Autowired + private I${sub.entityName}Service ${sub.entityName?uncap_first}Service; + + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + <#if bpm_flag> + ${entityName?uncap_first}.setBpmStatus("1"); + + ${entityName?uncap_first}Service.saveMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName} ${entityName?uncap_first}Entity = ${entityName?uncap_first}Service.getById(${entityName?uncap_first}.getId()); + if(${entityName?uncap_first}Entity==null) { + return Result.error("未找到对应数据"); + } + ${entityName?uncap_first}Service.updateMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.delMain(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + if(${entityName?uncap_first}==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(${entityName?uncap_first}); + + } + + <#list subTables as sub> + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${sub.ftlDescription}通过主表ID查询") + @ApiOperation(value="${sub.ftlDescription}主表ID查询", notes="${sub.ftlDescription}-通主表ID查询") + @GetMapping(value = "/query${sub.entityName}ByMainId") + public Result query${sub.entityName}ListByMainId(@RequestParam(name="id",required=true) String id) { + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(id); + return Result.OK(${sub.entityName?uncap_first}List); + } + + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + // Step.1 组装查询条件查询数据 + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + //Step.2 获取导出数据 + List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper); + // 过滤选中数据 + String selections = request.getParameter("selections"); + List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>(); + if(oConvertUtils.isEmpty(selections)) { + ${entityName?uncap_first}List = queryList; + }else { + List selectionList = Arrays.asList(selections.split(",")); + ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); + } + + // Step.3 组装pageList + List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); + for (${entityName} main : ${entityName?uncap_first}List) { + ${entityName}Page vo = new ${entityName}Page(); + BeanUtils.copyProperties(main, vo); + <#list subTables as sub> + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(main.getId()); + vo.set${sub.entityName}List(${sub.entityName?uncap_first}List); + + pageList.add(vo); + } + + // Step.4 AutoPoi 导出Excel + ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); + mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}列表"); + mv.addObject(NormalExcelConstants.CLASS, ${entityName}Page.class); + mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}数据", "导出人:"+sysUser.getRealname(), "${tableVo.ftlDescription}")); + mv.addObject(NormalExcelConstants.DATA_LIST, pageList); + return mv; + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + ImportParams params = new ImportParams(); + params.setTitleRows(2); + params.setHeadRows(1); + params.setNeedSave(true); + try { + List<${entityName}Page> list = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}Page.class, params); + for (${entityName}Page page : list) { + ${entityName} po = new ${entityName}(); + BeanUtils.copyProperties(page, po); + ${entityName?uncap_first}Service.saveMain(po, <#list subTables as sub>page.get${sub.entityName}List()<#if sub_has_next>,); + } + return Result.OK("文件导入成功!数据行数:" + list.size()); + } catch (Exception e) { + log.error(e.getMessage(),e); + return Result.error("文件导入失败:"+e.getMessage()); + } finally { + try { + file.getInputStream().close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return Result.OK("文件导入失败!"); + } + +} diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..31f478c --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,103 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +@Data +@TableName("${tableName}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + <#if po.fieldDbType=='Blob'> + private transient java.lang.String ${po.fieldName}String; + + private byte[] ${po.fieldName}; + + public byte[] get${po.fieldName?cap_first}(){ + if(${po.fieldName}String==null){ + return null; + } + try { + return ${po.fieldName}String.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + public String get${po.fieldName?cap_first}String(){ + if(${po.fieldName}==null || ${po.fieldName}.length==0){ + return ""; + } + try { + return new String(${po.fieldName},"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return ""; + } + <#else> + @ApiModelProperty(value = "${po.filedComment}") + private ${po.fieldType} ${po.fieldName}; + + +} diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai new file mode 100644 index 0000000..1e559ab --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -0,0 +1,72 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}.java +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import java.util.Date; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +@Data +@TableName("${subTab.tableName}") +public class ${subTab.entityName} implements Serializable { + private static final long serialVersionUID = 1L; + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list subTab.originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#elseif !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai new file mode 100644 index 0000000..ad15bfd --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai @@ -0,0 +1,22 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}Mapper.java +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> { + + public boolean deleteByMainId(@Param("mainId") String mainId); + + public List<${subTab.entityName}> selectByMainId(@Param("mainId") String mainId); +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml new file mode 100644 index 0000000..117c9b6 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml @@ -0,0 +1,26 @@ +<#list subTables as subTab> +<#assign originalForeignKeys = subTab.originalForeignKeys> +#segment#${subTab.entityName}Mapper.xml + + + + + + DELETE + FROM ${subTab.tableName} + WHERE + <#list originalForeignKeys as key> + ${key} = ${r'#'}{mainId} <#rt/> + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..e7d9914 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,42 @@ +package ${bussiPackage}.${entityPackage}.service; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + + /** + * 添加一对多 + * + */ + public void saveMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) ; + + /** + * 修改一对多 + * + */ + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,); + + /** + * 删除一对多 + */ + public void delMain (String id); + + /** + * 批量删除一对多 + */ + public void delBatchMain (Collection idList); + +} diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai new file mode 100644 index 0000000..0f85cb3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai @@ -0,0 +1,19 @@ +<#list subTables as subTab> +#segment#I${subTab.entityName}Service.java +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> { + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..94bdfc9 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,105 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper; + +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import java.io.Serializable; +import java.util.List; +import java.util.Collection; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + + @Autowired + private ${entityName}Mapper ${entityName?uncap_first}Mapper; + <#list subTables as sub> + @Autowired + private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper; + + + @Override + @Transactional + public void saveMain(${entityName} ${entityName?uncap_first}, <#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.insert(${entityName?uncap_first}); + <#list subTables as sub> + if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) { + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + } + + } + + @Override + @Transactional + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.updateById(${entityName?uncap_first}); + + //1.先删除子表数据 + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(${entityName?uncap_first}.getId()); + + + //2.子表数据重新插入 + <#list subTables as sub> + if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) { + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + } + + } + + @Override + @Transactional + public void delMain(String id) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + + @Override + @Transactional + public void delBatchMain(Collection idList) { + for(Serializable id:idList) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString()); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + } + +} diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai new file mode 100644 index 0000000..0ce41d3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai @@ -0,0 +1,30 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}ServiceImpl.java +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service; +import org.springframework.stereotype.Service; +import java.util.List; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service { + + @Autowired + private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper; + + @Override + public List<${subTab.entityName}> selectByMainId(String mainId) { + return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId); + } +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai new file mode 100644 index 0000000..c4252bc --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai @@ -0,0 +1,80 @@ +package ${bussiPackage}.${entityPackage}.vo; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import lombok.Data; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecgframework.poi.excel.annotation.ExcelEntity; +import org.jeecgframework.poi.excel.annotation.ExcelCollection; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import java.util.Date; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@ApiModel(value="${tableName}Page对象", description="${tableVo.ftlDescription}") +public class ${entityName}Page { + + <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + + + <#list subTables as sub> + @ExcelCollection(name="${sub.ftlDescription}") + @ApiModelProperty(value = "${sub.ftlDescription}") + private List<${sub.entityName}> ${sub.entityName?uncap_first}List; + + +} diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..ea3d946 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,474 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei new file mode 100644 index 0000000..7672973 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei @@ -0,0 +1,598 @@ +<#include "/common/utils.ftl"> + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..8021bb8 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,65 @@ +<#include "/common/utils.ftl"> + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei new file mode 100644 index 0000000..aab5452 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei @@ -0,0 +1,306 @@ +<#include "/common/utils.ftl"> +<#list subTables as sub> +<#if sub.foreignRelationType=='1'> +#segment#${sub.entityName}Form.vue + + + + diff --git a/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..020d3f8 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,235 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +<#assign pidFieldName = ""> +<#list originalColumns as po> +<#if po.fieldDbName == tableVo.extendParams.pidField> +<#assign pidFieldName = po.fieldName> + + +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service>{ + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/rootList") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + String hasQuery = req.getParameter("hasQuery"); + if(hasQuery != null && "true".equals(hasQuery)){ + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + List<${entityName}> list = ${entityName?uncap_first}Service.queryTreeListNoPage(queryWrapper); + IPage<${entityName}> pageList = new Page<>(1, 10, list.size()); + pageList.setRecords(list); + return Result.OK(pageList); + }else{ + String parentId = ${entityName?uncap_first}.get${pidFieldName?cap_first}(); + if (oConvertUtils.isEmpty(parentId)) { + parentId = "0"; + } + ${entityName?uncap_first}.set${pidFieldName?cap_first}(null); + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + // 使用 eq 防止模糊查询 + queryWrapper.eq("${Format.humpToUnderline(pidFieldName)}", parentId); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + } + + /** + * 获取子数据 + * @param ${entityName?uncap_first} + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-获取子数据") + @ApiOperation(value="${tableVo.ftlDescription}-获取子数据", notes="${tableVo.ftlDescription}-获取子数据") + @GetMapping(value = "/childList") + public Result queryPageList(${entityName} ${entityName?uncap_first},HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + List<${entityName}> list = ${entityName?uncap_first}Service.list(queryWrapper); + IPage<${entityName}> pageList = new Page<>(1, 10, list.size()); + pageList.setRecords(list); + return Result.OK(pageList); + } + + /** + * 批量查询子节点 + * @param parentIds 父ID(多个采用半角逗号分割) + * @return 返回 IPage + * @param parentIds + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量获取子数据") + @ApiOperation(value="${tableVo.ftlDescription}-批量获取子数据", notes="${tableVo.ftlDescription}-批量获取子数据") + @GetMapping("/getChildListBatch") + public Result getChildListBatch(@RequestParam("parentIds") String parentIds) { + try { + QueryWrapper<${entityName}> queryWrapper = new QueryWrapper<>(); + List parentIdList = Arrays.asList(parentIds.split(",")); + queryWrapper.in("${Format.humpToUnderline(pidFieldName)}", parentIdList); + List<${entityName}> list = ${entityName?uncap_first}Service.list(queryWrapper); + IPage<${entityName}> pageList = new Page<>(1, 10, list.size()); + pageList.setRecords(list); + return Result.OK(pageList); + } catch (Exception e) { + log.error(e.getMessage(), e); + return Result.error("批量查询子节点失败:" + e.getMessage()); + } + } + + /** + * 添加 + * + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.add${entityName}(${entityName?uncap_first}); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.update${entityName}(${entityName?uncap_first}); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.delete${entityName}(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + if(${entityName?uncap_first}==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(${entityName?uncap_first}); + } + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, ${entityName}.class); + } + +} diff --git a/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..0d33483 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,81 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${tableName}") +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#-- <#if po.classType!='popup'> + <#if po.dictTable?default("")?trim?length gt 1> + @Dict(dicCode="${po.dictField}",dicText="${po.dictText}",dictTable="${po.dictTable}") + <#elseif po.dictField?default("")?trim?length gt 1> + @Dict(dicCode="${po.dictField}") + + --> + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} diff --git a/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..24a7f3e --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,22 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + + /** + * 编辑节点状态 + * @param id + * @param status + */ + void updateTreeNodeStatus(@Param("id") String id,@Param("status") String status); + +} diff --git a/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..273c582 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,15 @@ +<#assign hasChildrenField = ""> +<#list originalColumns as po> +<#if po.fieldDbName == tableVo.extendParams.hasChildren> +<#assign hasChildrenField = po.fieldName> + + + + + + + + update ${tableName} set ${Format.humpToUnderline(hasChildrenField)} = ${r'#'}{status} where id = ${r'#'}{id} + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..28490d4 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,38 @@ +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import org.jeecg.common.exception.JeecgBootException; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import java.util.List; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + + /**根节点父ID的值*/ + public static final String ROOT_PID_VALUE = "0"; + + /**树节点有子节点状态值*/ + public static final String HASCHILD = "1"; + + /**树节点无子节点状态值*/ + public static final String NOCHILD = "0"; + + /**新增节点*/ + void add${entityName}(${entityName} ${entityName?uncap_first}); + + /**修改节点*/ + void update${entityName}(${entityName} ${entityName?uncap_first}) throws JeecgBootException; + + /**删除节点*/ + void delete${entityName}(String id) throws JeecgBootException; + + /**查询所有数据,无分页*/ + List<${entityName}> queryTreeListNoPage(QueryWrapper<${entityName}> queryWrapper); + +} diff --git a/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..9b8dfca --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,199 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import org.jeecg.common.exception.JeecgBootException; +import org.jeecg.common.util.oConvertUtils; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +<#assign pidFieldName = ""> +<#assign hasChildrenField = ""> +<#list originalColumns as po> +<#if po.fieldDbName == tableVo.extendParams.pidField> +<#assign pidFieldName = po.fieldName> + +<#if po.fieldDbName == tableVo.extendParams.hasChildren> +<#assign hasChildrenField = po.fieldName> + + + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + + @Override + public void add${entityName}(${entityName} ${entityName?uncap_first}) { + if(oConvertUtils.isEmpty(${entityName?uncap_first}.get${pidFieldName?cap_first}())){ + ${entityName?uncap_first}.set${pidFieldName?cap_first}(I${entityName}Service.ROOT_PID_VALUE); + }else{ + //如果当前节点父ID不为空 则设置父节点的hasChildren 为1 + ${entityName} parent = baseMapper.selectById(${entityName?uncap_first}.get${pidFieldName?cap_first}()); + if(parent!=null && !"1".equals(parent.get${hasChildrenField?cap_first}())){ + parent.set${hasChildrenField?cap_first}("1"); + baseMapper.updateById(parent); + } + } + baseMapper.insert(${entityName?uncap_first}); + } + + @Override + public void update${entityName}(${entityName} ${entityName?uncap_first}) { + ${entityName} entity = this.getById(${entityName?uncap_first}.getId()); + if(entity==null) { + throw new JeecgBootException("未找到对应实体"); + } + String old_pid = entity.get${pidFieldName?cap_first}(); + String new_pid = ${entityName?uncap_first}.get${pidFieldName?cap_first}(); + if(!old_pid.equals(new_pid)) { + updateOldParentNode(old_pid); + if(oConvertUtils.isEmpty(new_pid)){ + ${entityName?uncap_first}.set${pidFieldName?cap_first}(I${entityName}Service.ROOT_PID_VALUE); + } + if(!I${entityName}Service.ROOT_PID_VALUE.equals(${entityName?uncap_first}.get${pidFieldName?cap_first}())) { + baseMapper.updateTreeNodeStatus(${entityName?uncap_first}.get${pidFieldName?cap_first}(), I${entityName}Service.HASCHILD); + } + } + baseMapper.updateById(${entityName?uncap_first}); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete${entityName}(String id) throws JeecgBootException { + //查询选中节点下所有子节点一并删除 + id = this.queryTreeChildIds(id); + if(id.indexOf(",")>0) { + StringBuffer sb = new StringBuffer(); + String[] idArr = id.split(","); + for (String idVal : idArr) { + if(idVal != null){ + ${entityName} ${entityName?uncap_first} = this.getById(idVal); + String pidVal = ${entityName?uncap_first}.get${pidFieldName?cap_first}(); + //查询此节点上一级是否还有其他子节点 + List<${entityName}> dataList = baseMapper.selectList(new QueryWrapper<${entityName}>().eq("${tableVo.extendParams.pidField}", pidVal).notIn("id",Arrays.asList(idArr))); + if((dataList == null || dataList.size()==0) && !Arrays.asList(idArr).contains(pidVal) + && !sb.toString().contains(pidVal)){ + //如果当前节点原本有子节点 现在木有了,更新状态 + sb.append(pidVal).append(","); + } + } + } + //批量删除节点 + baseMapper.deleteBatchIds(Arrays.asList(idArr)); + //修改已无子节点的标识 + String[] pidArr = sb.toString().split(","); + for(String pid : pidArr){ + this.updateOldParentNode(pid); + } + }else{ + ${entityName} ${entityName?uncap_first} = this.getById(id); + if(${entityName?uncap_first}==null) { + throw new JeecgBootException("未找到对应实体"); + } + updateOldParentNode(${entityName?uncap_first}.get${pidFieldName?cap_first}()); + baseMapper.deleteById(id); + } + } + + @Override + public List<${entityName}> queryTreeListNoPage(QueryWrapper<${entityName}> queryWrapper) { + List<${entityName}> dataList = baseMapper.selectList(queryWrapper); + List<${entityName}> mapList = new ArrayList<>(); + for(${entityName} data : dataList){ + String pidVal = data.get${pidFieldName?cap_first}(); + //递归查询子节点的根节点 + if(pidVal != null && !"0".equals(pidVal)){ + ${entityName} rootVal = this.getTreeRoot(pidVal); + if(rootVal != null && !mapList.contains(rootVal)){ + mapList.add(rootVal); + } + }else{ + if(!mapList.contains(data)){ + mapList.add(data); + } + } + } + return mapList; + } + + /** + * 根据所传pid查询旧的父级节点的子节点并修改相应状态值 + * @param pid + */ + private void updateOldParentNode(String pid) { + if(!I${entityName}Service.ROOT_PID_VALUE.equals(pid)) { + Integer count = baseMapper.selectCount(new QueryWrapper<${entityName}>().eq("${tableVo.extendParams.pidField}", pid)); + if(count==null || count<=1) { + baseMapper.updateTreeNodeStatus(pid, I${entityName}Service.NOCHILD); + } + } + } + + /** + * 递归查询节点的根节点 + * @param pidVal + * @return + */ + private ${entityName} getTreeRoot(String pidVal){ + ${entityName} data = baseMapper.selectById(pidVal); + if(data != null && !"0".equals(data.get${pidFieldName?cap_first}())){ + return this.getTreeRoot(data.get${pidFieldName?cap_first}()); + }else{ + return data; + } + } + + /** + * 根据id查询所有子节点id + * @param ids + * @return + */ + private String queryTreeChildIds(String ids) { + //获取id数组 + String[] idArr = ids.split(","); + StringBuffer sb = new StringBuffer(); + for (String pidVal : idArr) { + if(pidVal != null){ + if(!sb.toString().contains(pidVal)){ + if(sb.toString().length() > 0){ + sb.append(","); + } + sb.append(pidVal); + this.getTreeChildIds(pidVal,sb); + } + } + } + return sb.toString(); + } + + /** + * 递归查询所有子节点 + * @param pidVal + * @param sb + * @return + */ + private StringBuffer getTreeChildIds(String pidVal,StringBuffer sb){ + List<${entityName}> dataList = baseMapper.selectList(new QueryWrapper<${entityName}>().eq("${tableVo.extendParams.pidField}", pidVal)); + if(dataList != null && dataList.size()>0){ + for(${entityName} tree : dataList) { + if(!sb.toString().contains(tree.getId())){ + sb.append(",").append(tree.getId()); + } + this.getTreeChildIds(tree.getId(),sb); + } + } + return sb; + } + +} diff --git a/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..45bd1b7 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,599 @@ +<#assign pidFieldName = ""> +<#assign hasChildrenField = ""> +<#list originalColumns as po> +<#if po.fieldDbName == tableVo.extendParams.pidField> +<#assign pidFieldName = po.fieldName> + +<#if po.fieldDbName == tableVo.extendParams.hasChildren> +<#assign hasChildrenField = po.fieldName> + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..fdd708a --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,277 @@ +<#include "/common/utils.ftl"> + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..10fab4a --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,306 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import org.jeecg.common.system.query.QueryGenerator; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecg.common.api.vo.Result; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.web.servlet.ModelAndView; +import java.util.Arrays; +import org.jeecg.common.util.oConvertUtils; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service> { + + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + <#list subTables as sub> + + @Autowired + private I${sub.entityName}Service ${sub.entityName?uncap_first}Service; + + + + /*---------------------------------主表处理-begin-------------------------------------*/ + + /** + * 分页列表查询 + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.save(${entityName?uncap_first}); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.updateById(${entityName?uncap_first}); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.delMain(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 导出 + * @return + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}"); + } + + /** + * 导入 + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, ${entityName}.class); + } + /*---------------------------------主表处理-end-------------------------------------*/ + + <#list subTables as sub> + + /*--------------------------------子表处理-${sub.ftlDescription}-begin----------------------------------------------*/ + /** + * 通过主表ID查询 + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-通过主表ID查询") + @ApiOperation(value="${sub.ftlDescription}-通过主表ID查询", notes="${sub.ftlDescription}-通过主表ID查询") + @GetMapping(value = "/list${sub.entityName}ByMainId") + public Result list${sub.entityName}ByMainId(${sub.entityName} ${sub.entityName?uncap_first}, + @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${sub.entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${sub.entityName?uncap_first}, req.getParameterMap()); + Page<${sub.entityName}> page = new Page<${sub.entityName}>(pageNo, pageSize); + IPage<${sub.entityName}> pageList = ${sub.entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * @param ${sub.entityName?uncap_first} + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-添加") + @ApiOperation(value="${sub.ftlDescription}-添加", notes="${sub.ftlDescription}-添加") + @PostMapping(value = "/add${sub.entityName}") + public Result add${sub.entityName}(@RequestBody ${sub.entityName} ${sub.entityName?uncap_first}) { + ${sub.entityName?uncap_first}Service.save(${sub.entityName?uncap_first}); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * @param ${sub.entityName?uncap_first} + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-编辑") + @ApiOperation(value="${sub.ftlDescription}-编辑", notes="${sub.ftlDescription}-编辑") + @PutMapping(value = "/edit${sub.entityName}") + public Result edit${sub.entityName}(@RequestBody ${sub.entityName} ${sub.entityName?uncap_first}) { + ${sub.entityName?uncap_first}Service.updateById(${sub.entityName?uncap_first}); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * @param id + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-通过id删除") + @ApiOperation(value="${sub.ftlDescription}-通过id删除", notes="${sub.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete${sub.entityName}") + public Result delete${sub.entityName}(@RequestParam(name="id",required=true) String id) { + ${sub.entityName?uncap_first}Service.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * @param ids + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-批量删除") + @ApiOperation(value="${sub.ftlDescription}-批量删除", notes="${sub.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch${sub.entityName}") + public Result deleteBatch${sub.entityName}(@RequestParam(name="ids",required=true) String ids) { + this.${sub.entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 导出 + * @return + */ + @RequestMapping(value = "/export${sub.entityName}") + public ModelAndView export${sub.entityName}(HttpServletRequest request, ${sub.entityName} ${sub.entityName?uncap_first}) { + // Step.1 组装查询条件 + QueryWrapper<${sub.entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${sub.entityName?uncap_first}, request.getParameterMap()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + // Step.2 获取导出数据 + List<${sub.entityName}> pageList = ${sub.entityName?uncap_first}Service.list(queryWrapper); + List<${sub.entityName}> exportList = null; + + // 过滤选中数据 + String selections = request.getParameter("selections"); + if (oConvertUtils.isNotEmpty(selections)) { + List selectionList = Arrays.asList(selections.split(",")); + exportList = pageList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); + } else { + exportList = pageList; + } + + // Step.3 AutoPoi 导出Excel + ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); + mv.addObject(NormalExcelConstants.FILE_NAME, "${sub.ftlDescription}"); //此处设置的filename无效 ,前端会重更新设置一下 + mv.addObject(NormalExcelConstants.CLASS, ${sub.entityName}.class); + mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${sub.ftlDescription}报表", "导出人:" + sysUser.getRealname(), "${sub.ftlDescription}")); + mv.addObject(NormalExcelConstants.DATA_LIST, exportList); + return mv; + } + + /** + * 导入 + * @return + */ + @RequestMapping(value = "/import${sub.entityName}/{mainId}") + public Result import${sub.entityName}(HttpServletRequest request, HttpServletResponse response, @PathVariable("mainId") String mainId) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + ImportParams params = new ImportParams(); + params.setTitleRows(2); + params.setHeadRows(1); + params.setNeedSave(true); + try { + List<${sub.entityName}> list = ExcelImportUtil.importExcel(file.getInputStream(), ${sub.entityName}.class, params); + for (${sub.entityName} temp : list) { + <#list sub.foreignKeys as key> + temp.set${key?cap_first}(mainId); + + } + long start = System.currentTimeMillis(); + ${sub.entityName?uncap_first}Service.saveBatch(list); + log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒"); + return Result.OK("文件导入成功!数据行数:" + list.size()); + } catch (Exception e) { + log.error(e.getMessage(), e); + return Result.error("文件导入失败:" + e.getMessage()); + } finally { + try { + file.getInputStream().close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return Result.error("文件导入失败!"); + } + + /*--------------------------------子表处理-${sub.ftlDescription}-end----------------------------------------------*/ + + + + + +} diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..a3029b0 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,103 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import org.jeecgframework.poi.excel.annotation.Excel; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${tableName}") +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + <#if po.fieldDbType=='Blob'> + private transient java.lang.String ${po.fieldName}String; + + private byte[] ${po.fieldName}; + + public byte[] get${po.fieldName?cap_first}(){ + if(${po.fieldName}String==null){ + return null; + } + try { + return ${po.fieldName}String.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + public String get${po.fieldName?cap_first}String(){ + if(${po.fieldName}==null || ${po.fieldName}.length==0){ + return ""; + } + try { + return new String(${po.fieldName},"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return ""; + } + <#else> + @ApiModelProperty(value = "${po.filedComment}") + private ${po.fieldType} ${po.fieldName}; + + +} diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai new file mode 100644 index 0000000..7c1161f --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -0,0 +1,73 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}.java +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import org.jeecg.common.aspect.annotation.Dict; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import java.util.Date; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${subTab.tableName}") +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${subTab.entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> +<#list subTab.originalColumns as po> + /**${po.filedComment}*/ +<#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) +<#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#elseif !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15) + + + +<#if po.classType =='list' || po.classType =='radio' || po.classType =='list_multi' || po.classType =='checkbox' || po.classType =='sel_search'> + <#if po.dictTable?default("")?trim?length gt 1> + @Dict(dicCode = "${po.dictField}",dicText = "${po.dictText}",dictTable = "${po.dictTable}") + <#elseif po.dictField?default("")?trim?length gt 1> + @Dict(dicCode = "${po.dictField}") + + +<#if po.classType =='cat_tree'> + @Dict(dicCode = "id",dicText = "name",dictTable = "sys_category") + +<#if po.classType =='sel_depart'> + @Dict(dicCode = "id",dicText = "depart_name",dictTable = "sys_depart") + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai new file mode 100644 index 0000000..eccb8d6 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai @@ -0,0 +1,23 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}Mapper.java +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> { + + public boolean deleteByMainId(@Param("mainId") String mainId); + + public List<${subTab.entityName}> selectByMainId(@Param("mainId") String mainId); + +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml new file mode 100644 index 0000000..1dc5802 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml @@ -0,0 +1,28 @@ +<#list subTables as subTab> +<#assign originalForeignKeys = subTab.originalForeignKeys> +#segment#${subTab.entityName}Mapper.xml + + + + + + DELETE + FROM ${subTab.tableName} + WHERE + <#list originalForeignKeys as key> + ${key} = ${r'#'}{mainId} <#rt/> + + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..507143c --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,32 @@ +package ${bussiPackage}.${entityPackage}.service; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import org.springframework.beans.factory.annotation.Autowired; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + + /** + * 删除一对多 + */ + public void delMain (String id); + + /** + * 批量删除一对多 + */ + public void delBatchMain (Collection idList); + + +} diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai new file mode 100644 index 0000000..0f85cb3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai @@ -0,0 +1,19 @@ +<#list subTables as subTab> +#segment#I${subTab.entityName}Service.java +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> { + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..4484029 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,56 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper; + +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import java.io.Serializable; +import java.util.List; +import java.util.Collection; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + + @Autowired + private ${entityName}Mapper ${entityName?uncap_first}Mapper; + <#list subTables as sub> + @Autowired + private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper; + + + @Override + @Transactional + public void delMain(String id) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + + @Override + @Transactional + public void delBatchMain(Collection idList) { + for(Serializable id:idList) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString()); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + } + +} diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai new file mode 100644 index 0000000..0ce41d3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai @@ -0,0 +1,30 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}ServiceImpl.java +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service; +import org.springframework.stereotype.Service; +import java.util.List; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service { + + @Autowired + private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper; + + @Override + public List<${subTab.entityName}> selectByMainId(String mainId) { + return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId); + } +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..99d426e --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,522 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/[1-n]List.vuei b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/[1-n]List.vuei new file mode 100644 index 0000000..578ec41 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/[1-n]List.vuei @@ -0,0 +1,229 @@ +<#list subTables as sub> +#segment#${sub.entityName}List.vue + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..cbcec01 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,300 @@ +<#include "/common/utils.ftl"> + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei new file mode 100644 index 0000000..aed2c67 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/erp/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei @@ -0,0 +1,313 @@ +<#include "/common/utils.ftl"> +<#list subTables as sub> +#segment#${sub.entityName}Modal.vue + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..76a94ec --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,275 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.vo.LoginUser; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.vo.${entityName}Page; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + <#list subTables as sub> + @Autowired + private I${sub.entityName}Service ${sub.entityName?uncap_first}Service; + + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName?uncap_first}Service.saveMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName} ${entityName?uncap_first}Entity = ${entityName?uncap_first}Service.getById(${entityName?uncap_first}.getId()); + if(${entityName?uncap_first}Entity==null) { + return Result.error("未找到对应数据"); + } + ${entityName?uncap_first}Service.updateMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.delMain(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + if(${entityName?uncap_first}==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(${entityName?uncap_first}); + + } + + <#list subTables as sub> + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-通过主表ID查询") + @ApiOperation(value="${sub.ftlDescription}-通过主表ID查询", notes="${sub.ftlDescription}-通过主表ID查询") + @GetMapping(value = "/query${sub.entityName}ByMainId") + public Result query${sub.entityName}ListByMainId(@RequestParam(name="id",required=true) String id) { + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(id); + <#-- 包裹分页对象,用于翻译注解 --> + IPage <${sub.entityName}> page = new Page<>(); + page.setRecords(${sub.entityName?uncap_first}List); + page.setTotal(${sub.entityName?uncap_first}List.size()); + return Result.OK(page); + } + + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + // Step.1 组装查询条件查询数据 + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + //Step.2 获取导出数据 + List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper); + // 过滤选中数据 + String selections = request.getParameter("selections"); + List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>(); + if(oConvertUtils.isEmpty(selections)) { + ${entityName?uncap_first}List = queryList; + }else { + List selectionList = Arrays.asList(selections.split(",")); + ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); + } + + // Step.3 组装pageList + List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); + for (${entityName} main : ${entityName?uncap_first}List) { + ${entityName}Page vo = new ${entityName}Page(); + BeanUtils.copyProperties(main, vo); + <#list subTables as sub> + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(main.getId()); + vo.set${sub.entityName}List(${sub.entityName?uncap_first}List); + + pageList.add(vo); + } + + // Step.4 AutoPoi 导出Excel + ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); + mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}列表"); + mv.addObject(NormalExcelConstants.CLASS, ${entityName}Page.class); + mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}数据", "导出人:"+sysUser.getRealname(), "${tableVo.ftlDescription}")); + mv.addObject(NormalExcelConstants.DATA_LIST, pageList); + return mv; + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + ImportParams params = new ImportParams(); + params.setTitleRows(2); + params.setHeadRows(1); + params.setNeedSave(true); + try { + List<${entityName}Page> list = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}Page.class, params); + for (${entityName}Page page : list) { + ${entityName} po = new ${entityName}(); + BeanUtils.copyProperties(page, po); + ${entityName?uncap_first}Service.saveMain(po, <#list subTables as sub>page.get${sub.entityName}List()<#if sub_has_next>,); + } + return Result.OK("文件导入成功!数据行数:" + list.size()); + } catch (Exception e) { + log.error(e.getMessage(),e); + return Result.error("文件导入失败:"+e.getMessage()); + } finally { + try { + file.getInputStream().close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return Result.OK("文件导入失败!"); + } + +} diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..cb5ece7 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,103 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +@Data +@TableName("${tableName}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + <#if po.fieldDbType=='Blob'> + private transient java.lang.String ${po.fieldName}String; + + private byte[] ${po.fieldName}; + + public byte[] get${po.fieldName?cap_first}(){ + if(${po.fieldName}String==null){ + return null; + } + try { + return ${po.fieldName}String.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + public String get${po.fieldName?cap_first}String(){ + if(${po.fieldName}==null || ${po.fieldName}.length==0){ + return ""; + } + try { + return new String(${po.fieldName},"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return ""; + } + <#else> + @ApiModelProperty(value = "${po.filedComment}") + private ${po.fieldType} ${po.fieldName}; + + +} diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai new file mode 100644 index 0000000..c58a2a2 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -0,0 +1,76 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}.java +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import java.util.Date; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +@Data +@TableName("${subTab.tableName}") +public class ${subTab.entityName} implements Serializable { + private static final long serialVersionUID = 1L; + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list subTab.originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#elseif !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai new file mode 100644 index 0000000..ad15bfd --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai @@ -0,0 +1,22 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}Mapper.java +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> { + + public boolean deleteByMainId(@Param("mainId") String mainId); + + public List<${subTab.entityName}> selectByMainId(@Param("mainId") String mainId); +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml new file mode 100644 index 0000000..117c9b6 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml @@ -0,0 +1,26 @@ +<#list subTables as subTab> +<#assign originalForeignKeys = subTab.originalForeignKeys> +#segment#${subTab.entityName}Mapper.xml + + + + + + DELETE + FROM ${subTab.tableName} + WHERE + <#list originalForeignKeys as key> + ${key} = ${r'#'}{mainId} <#rt/> + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..e7d9914 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,42 @@ +package ${bussiPackage}.${entityPackage}.service; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + + /** + * 添加一对多 + * + */ + public void saveMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) ; + + /** + * 修改一对多 + * + */ + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,); + + /** + * 删除一对多 + */ + public void delMain (String id); + + /** + * 批量删除一对多 + */ + public void delBatchMain (Collection idList); + +} diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai new file mode 100644 index 0000000..0f85cb3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai @@ -0,0 +1,19 @@ +<#list subTables as subTab> +#segment#I${subTab.entityName}Service.java +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> { + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..94bdfc9 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,105 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper; + +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import java.io.Serializable; +import java.util.List; +import java.util.Collection; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + + @Autowired + private ${entityName}Mapper ${entityName?uncap_first}Mapper; + <#list subTables as sub> + @Autowired + private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper; + + + @Override + @Transactional + public void saveMain(${entityName} ${entityName?uncap_first}, <#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.insert(${entityName?uncap_first}); + <#list subTables as sub> + if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) { + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + } + + } + + @Override + @Transactional + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.updateById(${entityName?uncap_first}); + + //1.先删除子表数据 + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(${entityName?uncap_first}.getId()); + + + //2.子表数据重新插入 + <#list subTables as sub> + if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) { + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + } + + } + + @Override + @Transactional + public void delMain(String id) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + + @Override + @Transactional + public void delBatchMain(Collection idList) { + for(Serializable id:idList) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString()); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + } + +} diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai new file mode 100644 index 0000000..0ce41d3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai @@ -0,0 +1,30 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}ServiceImpl.java +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service; +import org.springframework.stereotype.Service; +import java.util.List; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service { + + @Autowired + private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper; + + @Override + public List<${subTab.entityName}> selectByMainId(String mainId) { + return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId); + } +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai new file mode 100644 index 0000000..b33758d --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai @@ -0,0 +1,80 @@ +package ${bussiPackage}.${entityPackage}.vo; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import lombok.Data; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecgframework.poi.excel.annotation.ExcelEntity; +import org.jeecgframework.poi.excel.annotation.ExcelCollection; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import java.util.Date; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@ApiModel(value="${tableName}Page对象", description="${tableVo.ftlDescription}") +public class ${entityName}Page { + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + + + <#list subTables as sub> + @ExcelCollection(name="${sub.ftlDescription}") + @ApiModelProperty(value = "${sub.ftlDescription}") + private List<${sub.entityName}> ${sub.entityName?uncap_first}List; + + +} diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..8b2cff1 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,480 @@ +<#-- noinspection JSDuplicatedDeclaration,RequiredAttributes,NpmUsedModulesInstalled --> +<#-- ** 引入全局工具方法 ** --> +<#--<#include "/common/utils.ftl">--> +<#include "../../../../../../common/utils.ftl"> +<#-- ** 定义全局使用的变量 ** --> +<#-- 是否有查询条件 --> +<#assign query_flag=false> +<#-- 是否有下拉查询条件 --> +<#assign query_field_select=false> +<#-- 是否有日期查询条件 --> +<#assign query_field_date=false> +<#-- 是否有字典 --> +<#assign list_need_dict=false> +<#-- 是否有分类字典 --> +<#assign list_need_category=false> +<#-- 是否有用户选择 --> +<#assign query_sel_user=false> +<#-- 是否有部门选择 --> +<#assign query_sel_dep=false> +<#-- 是否有下拉多选框 --> +<#assign query_sel_multi=false> +<#-- 是否有下拉搜索框 --> +<#assign query_sel_search=false> +<#-- 是否有省市区组件 --> +<#assign query_field_pca=false> +<#-- 是否有分类字典树 --> +<#assign query_sel_cat=false> + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..72fe228 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,523 @@ +<#include "/common/utils.ftl"> + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei new file mode 100644 index 0000000..012cad5 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei @@ -0,0 +1,223 @@ +<#include "/common/utils.ftl"> +<#list subTables as sub> +<#if sub.foreignRelationType=='1'> +#segment#${sub.entityName}Form.vue + + + + diff --git a/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/subTables/[1-n]SubTable.vuei b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/subTables/[1-n]SubTable.vuei new file mode 100644 index 0000000..4958da2 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/inner-table/onetomany/java/${bussiPackage}/${entityPackage}/vue/subTables/[1-n]SubTable.vuei @@ -0,0 +1,146 @@ +<#--noinspection JSDuplicatedDeclaration--> +<#list subTables as sub> +#segment#${sub.entityName}SubTable.vue + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..2772d2f --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,280 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.vo.LoginUser; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.vo.${entityName}Page; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; +<#assign bpm_flag=false> +<#list originalColumns as po> +<#if po.fieldDbName=='bpm_status'> + <#assign bpm_flag=true> + + + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + <#list subTables as sub> + @Autowired + private I${sub.entityName}Service ${sub.entityName?uncap_first}Service; + + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + <#if bpm_flag> + ${entityName?uncap_first}.setBpmStatus("1"); + + ${entityName?uncap_first}Service.saveMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName} ${entityName?uncap_first}Entity = ${entityName?uncap_first}Service.getById(${entityName?uncap_first}.getId()); + if(${entityName?uncap_first}Entity==null) { + return Result.error("未找到对应数据"); + } + ${entityName?uncap_first}Service.updateMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.delMain(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + if(${entityName?uncap_first}==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(${entityName?uncap_first}); + + } + + <#list subTables as sub> + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${sub.ftlDescription}通过主表ID查询") + @ApiOperation(value="${sub.ftlDescription}主表ID查询", notes="${sub.ftlDescription}-通主表ID查询") + @GetMapping(value = "/query${sub.entityName}ByMainId") + public Result query${sub.entityName}ListByMainId(@RequestParam(name="id",required=true) String id) { + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(id); + return Result.OK(${sub.entityName?uncap_first}List); + } + + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + // Step.1 组装查询条件查询数据 + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + //Step.2 获取导出数据 + List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper); + // 过滤选中数据 + String selections = request.getParameter("selections"); + List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>(); + if(oConvertUtils.isEmpty(selections)) { + ${entityName?uncap_first}List = queryList; + }else { + List selectionList = Arrays.asList(selections.split(",")); + ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); + } + + // Step.3 组装pageList + List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); + for (${entityName} main : ${entityName?uncap_first}List) { + ${entityName}Page vo = new ${entityName}Page(); + BeanUtils.copyProperties(main, vo); + <#list subTables as sub> + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(main.getId()); + vo.set${sub.entityName}List(${sub.entityName?uncap_first}List); + + pageList.add(vo); + } + + // Step.4 AutoPoi 导出Excel + ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); + mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}列表"); + mv.addObject(NormalExcelConstants.CLASS, ${entityName}Page.class); + mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}数据", "导出人:"+sysUser.getRealname(), "${tableVo.ftlDescription}")); + mv.addObject(NormalExcelConstants.DATA_LIST, pageList); + return mv; + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + ImportParams params = new ImportParams(); + params.setTitleRows(2); + params.setHeadRows(1); + params.setNeedSave(true); + try { + List<${entityName}Page> list = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}Page.class, params); + for (${entityName}Page page : list) { + ${entityName} po = new ${entityName}(); + BeanUtils.copyProperties(page, po); + ${entityName?uncap_first}Service.saveMain(po, <#list subTables as sub>page.get${sub.entityName}List()<#if sub_has_next>,); + } + return Result.OK("文件导入成功!数据行数:" + list.size()); + } catch (Exception e) { + log.error(e.getMessage(),e); + return Result.error("文件导入失败:"+e.getMessage()); + } finally { + try { + file.getInputStream().close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return Result.OK("文件导入失败!"); + } + +} diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..31f478c --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,103 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +@Data +@TableName("${tableName}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + <#if po.fieldDbType=='Blob'> + private transient java.lang.String ${po.fieldName}String; + + private byte[] ${po.fieldName}; + + public byte[] get${po.fieldName?cap_first}(){ + if(${po.fieldName}String==null){ + return null; + } + try { + return ${po.fieldName}String.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + public String get${po.fieldName?cap_first}String(){ + if(${po.fieldName}==null || ${po.fieldName}.length==0){ + return ""; + } + try { + return new String(${po.fieldName},"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return ""; + } + <#else> + @ApiModelProperty(value = "${po.filedComment}") + private ${po.fieldType} ${po.fieldName}; + + +} diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai new file mode 100644 index 0000000..1e559ab --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -0,0 +1,72 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}.java +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import java.util.Date; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +@Data +@TableName("${subTab.tableName}") +public class ${subTab.entityName} implements Serializable { + private static final long serialVersionUID = 1L; + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list subTab.originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#elseif !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai new file mode 100644 index 0000000..ad15bfd --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai @@ -0,0 +1,22 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}Mapper.java +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> { + + public boolean deleteByMainId(@Param("mainId") String mainId); + + public List<${subTab.entityName}> selectByMainId(@Param("mainId") String mainId); +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml new file mode 100644 index 0000000..117c9b6 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml @@ -0,0 +1,26 @@ +<#list subTables as subTab> +<#assign originalForeignKeys = subTab.originalForeignKeys> +#segment#${subTab.entityName}Mapper.xml + + + + + + DELETE + FROM ${subTab.tableName} + WHERE + <#list originalForeignKeys as key> + ${key} = ${r'#'}{mainId} <#rt/> + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..e7d9914 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,42 @@ +package ${bussiPackage}.${entityPackage}.service; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + + /** + * 添加一对多 + * + */ + public void saveMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) ; + + /** + * 修改一对多 + * + */ + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,); + + /** + * 删除一对多 + */ + public void delMain (String id); + + /** + * 批量删除一对多 + */ + public void delBatchMain (Collection idList); + +} diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai new file mode 100644 index 0000000..0f85cb3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai @@ -0,0 +1,19 @@ +<#list subTables as subTab> +#segment#I${subTab.entityName}Service.java +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> { + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..94bdfc9 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,105 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper; + +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import java.io.Serializable; +import java.util.List; +import java.util.Collection; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + + @Autowired + private ${entityName}Mapper ${entityName?uncap_first}Mapper; + <#list subTables as sub> + @Autowired + private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper; + + + @Override + @Transactional + public void saveMain(${entityName} ${entityName?uncap_first}, <#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.insert(${entityName?uncap_first}); + <#list subTables as sub> + if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) { + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + } + + } + + @Override + @Transactional + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.updateById(${entityName?uncap_first}); + + //1.先删除子表数据 + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(${entityName?uncap_first}.getId()); + + + //2.子表数据重新插入 + <#list subTables as sub> + if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) { + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + } + + } + + @Override + @Transactional + public void delMain(String id) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + + @Override + @Transactional + public void delBatchMain(Collection idList) { + for(Serializable id:idList) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString()); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + } + +} diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai new file mode 100644 index 0000000..0ce41d3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai @@ -0,0 +1,30 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}ServiceImpl.java +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service; +import org.springframework.stereotype.Service; +import java.util.List; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service { + + @Autowired + private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper; + + @Override + public List<${subTab.entityName}> selectByMainId(String mainId) { + return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId); + } +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai new file mode 100644 index 0000000..c4252bc --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai @@ -0,0 +1,80 @@ +package ${bussiPackage}.${entityPackage}.vo; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import lombok.Data; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecgframework.poi.excel.annotation.ExcelEntity; +import org.jeecgframework.poi.excel.annotation.ExcelCollection; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import java.util.Date; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@ApiModel(value="${tableName}Page对象", description="${tableVo.ftlDescription}") +public class ${entityName}Page { + + <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + + + <#list subTables as sub> + @ExcelCollection(name="${sub.ftlDescription}") + @ApiModelProperty(value = "${sub.ftlDescription}") + private List<${sub.entityName}> ${sub.entityName?uncap_first}List; + + +} diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..47dc502 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,474 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei new file mode 100644 index 0000000..59796ad --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Form.vuei @@ -0,0 +1,604 @@ +<#include "/common/utils.ftl"> + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..8021bb8 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,65 @@ +<#include "/common/utils.ftl"> + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei new file mode 100644 index 0000000..aab5452 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/jvxe/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Form.vuei @@ -0,0 +1,306 @@ +<#include "/common/utils.ftl"> +<#list subTables as sub> +<#if sub.foreignRelationType=='1'> +#segment#${sub.entityName}Form.vue + + + + diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..49dad0f --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,271 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.vo.LoginUser; +import org.apache.shiro.SecurityUtils; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.vo.${entityName}Page; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + <#list subTables as sub> + @Autowired + private I${sub.entityName}Service ${sub.entityName?uncap_first}Service; + + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName?uncap_first}Service.saveMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName} ${entityName?uncap_first}Entity = ${entityName?uncap_first}Service.getById(${entityName?uncap_first}.getId()); + if(${entityName?uncap_first}Entity==null) { + return Result.error("未找到对应数据"); + } + ${entityName?uncap_first}Service.updateMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.delMain(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + if(${entityName?uncap_first}==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(${entityName?uncap_first}); + + } + + <#list subTables as sub> + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${sub.ftlDescription}通过主表ID查询") + @ApiOperation(value="${sub.ftlDescription}主表ID查询", notes="${sub.ftlDescription}-通主表ID查询") + @GetMapping(value = "/query${sub.entityName}ByMainId") + public Result query${sub.entityName}ListByMainId(@RequestParam(name="id",required=true) String id) { + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(id); + return Result.OK(${sub.entityName?uncap_first}List); + } + + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + // Step.1 组装查询条件查询数据 + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + //Step.2 获取导出数据 + List<${entityName}> queryList = ${entityName?uncap_first}Service.list(queryWrapper); + // 过滤选中数据 + String selections = request.getParameter("selections"); + List<${entityName}> ${entityName?uncap_first}List = new ArrayList<${entityName}>(); + if(oConvertUtils.isEmpty(selections)) { + ${entityName?uncap_first}List = queryList; + }else { + List selectionList = Arrays.asList(selections.split(",")); + ${entityName?uncap_first}List = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList()); + } + + // Step.3 组装pageList + List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); + for (${entityName} main : ${entityName?uncap_first}List) { + ${entityName}Page vo = new ${entityName}Page(); + BeanUtils.copyProperties(main, vo); + <#list subTables as sub> + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(main.getId()); + vo.set${sub.entityName}List(${sub.entityName?uncap_first}List); + + pageList.add(vo); + } + + // Step.4 AutoPoi 导出Excel + ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); + mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}列表"); + mv.addObject(NormalExcelConstants.CLASS, ${entityName}Page.class); + mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}数据", "导出人:"+sysUser.getRealname(), "${tableVo.ftlDescription}")); + mv.addObject(NormalExcelConstants.DATA_LIST, pageList); + return mv; + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + ImportParams params = new ImportParams(); + params.setTitleRows(2); + params.setHeadRows(1); + params.setNeedSave(true); + try { + List<${entityName}Page> list = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}Page.class, params); + for (${entityName}Page page : list) { + ${entityName} po = new ${entityName}(); + BeanUtils.copyProperties(page, po); + ${entityName?uncap_first}Service.saveMain(po, <#list subTables as sub>page.get${sub.entityName}List()<#if sub_has_next>,); + } + return Result.OK("文件导入成功!数据行数:" + list.size()); + } catch (Exception e) { + log.error(e.getMessage(),e); + return Result.error("文件导入失败:"+e.getMessage()); + } finally { + try { + file.getInputStream().close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return Result.OK("文件导入失败!"); + } + +} diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..db93896 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,103 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +@Data +@TableName("${tableName}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ID_WORKER_STR) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + <#if po.fieldDbType=='Blob'> + private transient java.lang.String ${po.fieldName}String; + + private byte[] ${po.fieldName}; + + public byte[] get${po.fieldName?cap_first}(){ + if(${po.fieldName}String==null){ + return null; + } + try { + return ${po.fieldName}String.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + public String get${po.fieldName?cap_first}String(){ + if(${po.fieldName}==null || ${po.fieldName}.length==0){ + return ""; + } + try { + return new String(${po.fieldName},"UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return ""; + } + <#else> + @ApiModelProperty(value = "${po.filedComment}") + private ${po.fieldType} ${po.fieldName}; + + +} diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai new file mode 100644 index 0000000..8e59725 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -0,0 +1,72 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}.java +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import java.util.Date; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +@Data +@TableName("${subTab.tableName}") +public class ${subTab.entityName} implements Serializable { + private static final long serialVersionUID = 1L; + +<#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list subTab.originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ID_WORKER_STR) + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss"${list_field_dictCode}) + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#elseif !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai new file mode 100644 index 0000000..ad15bfd --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai @@ -0,0 +1,22 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}Mapper.java +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> { + + public boolean deleteByMainId(@Param("mainId") String mainId); + + public List<${subTab.entityName}> selectByMainId(@Param("mainId") String mainId); +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml new file mode 100644 index 0000000..117c9b6 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml @@ -0,0 +1,26 @@ +<#list subTables as subTab> +<#assign originalForeignKeys = subTab.originalForeignKeys> +#segment#${subTab.entityName}Mapper.xml + + + + + + DELETE + FROM ${subTab.tableName} + WHERE + <#list originalForeignKeys as key> + ${key} = ${r'#'}{mainId} <#rt/> + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..e7d9914 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,42 @@ +package ${bussiPackage}.${entityPackage}.service; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + + /** + * 添加一对多 + * + */ + public void saveMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) ; + + /** + * 修改一对多 + * + */ + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,); + + /** + * 删除一对多 + */ + public void delMain (String id); + + /** + * 批量删除一对多 + */ + public void delBatchMain (Collection idList); + +} diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai new file mode 100644 index 0000000..0f85cb3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai @@ -0,0 +1,19 @@ +<#list subTables as subTab> +#segment#I${subTab.entityName}Service.java +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> { + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..94bdfc9 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,105 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper; + +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import java.io.Serializable; +import java.util.List; +import java.util.Collection; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + + @Autowired + private ${entityName}Mapper ${entityName?uncap_first}Mapper; + <#list subTables as sub> + @Autowired + private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper; + + + @Override + @Transactional + public void saveMain(${entityName} ${entityName?uncap_first}, <#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.insert(${entityName?uncap_first}); + <#list subTables as sub> + if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) { + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + } + + } + + @Override + @Transactional + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.updateById(${entityName?uncap_first}); + + //1.先删除子表数据 + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(${entityName?uncap_first}.getId()); + + + //2.子表数据重新插入 + <#list subTables as sub> + if(${sub.entityName?uncap_first}List!=null && ${sub.entityName?uncap_first}List.size()>0) { + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + } + + } + + @Override + @Transactional + public void delMain(String id) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + + @Override + @Transactional + public void delBatchMain(Collection idList) { + for(Serializable id:idList) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString()); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + } + +} diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai new file mode 100644 index 0000000..0ce41d3 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai @@ -0,0 +1,30 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}ServiceImpl.java +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service; +import org.springframework.stereotype.Service; +import java.util.List; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service { + + @Autowired + private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper; + + @Override + public List<${subTab.entityName}> selectByMainId(String mainId) { + return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId); + } +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai new file mode 100644 index 0000000..c4252bc --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai @@ -0,0 +1,80 @@ +package ${bussiPackage}.${entityPackage}.vo; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import lombok.Data; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecgframework.poi.excel.annotation.ExcelEntity; +import org.jeecgframework.poi.excel.annotation.ExcelCollection; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import java.util.Date; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@ApiModel(value="${tableName}Page对象", description="${tableVo.ftlDescription}") +public class ${entityName}Page { + + <#assign excel_ignore_arr=['createBy','createTime','updateBy','updateTime','sysOrgCode']> + <#list originalColumns as po> + <#-- 生成字典Code --> + <#assign list_field_dictCode=""> + <#if po.classType='sel_user'> + <#assign list_field_dictCode=', dictTable = "sys_user", dicText = "realname", dicCode = "username"'> + <#elseif po.classType='sel_depart'> + <#assign list_field_dictCode=', dictTable = "sys_depart", dicText = "depart_name", dicCode = "id"'> + <#elseif po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox'> + <#if po.dictTable?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dictTable = "${po.dictTable}", dicText = "${po.dictText}", dicCode = "${po.dictField}"'> + <#elseif po.dictField?default("")?trim?length gt 1> + <#assign list_field_dictCode=', dicCode = "${po.dictField}"'> + + + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + <#else> + <#if po.fieldDbType =='Date'> + <#if po.classType=='date'> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !excel_ignore_arr?seq_contains("${po.fieldName}")> + @Excel(name = "${po.filedComment}", width = 15${list_field_dictCode}) + + + <#if list_field_dictCode?length gt 1> + @Dict(${list_field_dictCode?substring(2)}) + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + + + <#list subTables as sub> + @ExcelCollection(name="${sub.ftlDescription}") + @ApiModelProperty(value = "${sub.ftlDescription}") + private List<${sub.entityName}> ${sub.entityName?uncap_first}List; + + +} diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..8b10b70 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,428 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..f2fa600 --- /dev/null +++ b/src/main/resources/jeecg/code-template-online/tab/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,563 @@ +<#include "/common/utils.ftl"> + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..0319320 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,167 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.jeecg.common.util.oConvertUtils; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import java.util.Date; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.common.system.base.controller.JeecgController; +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Slf4j +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service> { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.save(${entityName?uncap_first}); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.updateById(${entityName?uncap_first}); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + return Result.OK(${entityName?uncap_first}); + } + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, ${entityName}.class); + } + +} diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..bf55735 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,53 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${tableName}") +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${entityName} { + + <#list originalColumns as po> + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldType =='java.util.Date'> + <#if po.fieldDbType =='date'> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#elseif po.fieldDbType =='datetime'> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + @Excel(name = "${po.filedComment}", width = 15) + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..f00240a --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,14 @@ +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..6326220 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,19 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + +} diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..23e3122 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,173 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..5a0d0c4 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,156 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal__Style#Drawer.vuei b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal__Style#Drawer.vuei new file mode 100644 index 0000000..4446ba6 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal__Style#Drawer.vuei @@ -0,0 +1,162 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/controller/${entityPackage}/${entityName}Controller.javai b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/controller/${entityPackage}/${entityName}Controller.javai new file mode 100644 index 0000000..87d5ed8 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/controller/${entityPackage}/${entityName}Controller.javai @@ -0,0 +1,170 @@ +package ${bussiPackage}.controller.${entityPackage}; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import ${bussiPackage}.entity.${entityPackage}.${entityName}; +import ${bussiPackage}.service.${entityPackage}.I${entityName}Service; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import lombok.extern.slf4j.Slf4j; + +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller extends JeecgController<${entityName}, I${entityName}Service> { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + + } + + /** + * 添加 + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.save(${entityName?uncap_first}); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first} + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName} ${entityName?uncap_first}) { + ${entityName?uncap_first}Service.updateById(${entityName?uncap_first}); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + return Result.OK(${entityName?uncap_first}); + } + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + return super.exportXls(request, ${entityName?uncap_first}, ${entityName}.class, "${tableVo.ftlDescription}"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, ${entityName}.class); + } + +} diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/entity/${entityPackage}/${entityName}.javai b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/entity/${entityPackage}/${entityName}.javai new file mode 100644 index 0000000..faf00a8 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/entity/${entityPackage}/${entityName}.javai @@ -0,0 +1,49 @@ +package ${bussiPackage}.entity.${entityPackage}; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${tableName}") +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#list originalColumns as po> + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldType =='java.util.Date'> + <#if po.fieldDbType =='date'> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#elseif po.fieldDbType =='datetime'> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + @Excel(name = "${po.filedComment}", width = 15) + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/mapper/${entityPackage}/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/mapper/${entityPackage}/${entityName}Mapper.javai new file mode 100644 index 0000000..4705b6c --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/mapper/${entityPackage}/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.mapper.${entityPackage}; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.entity.${entityPackage}.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/mapper/${entityPackage}/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/mapper/${entityPackage}/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..fb6f712 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/mapper/${entityPackage}/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/service/${entityPackage}/I${entityName}Service.javai b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/service/${entityPackage}/I${entityName}Service.javai new file mode 100644 index 0000000..8fdad41 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/service/${entityPackage}/I${entityName}Service.javai @@ -0,0 +1,14 @@ +package ${bussiPackage}.service.${entityPackage}; + +import ${bussiPackage}.entity.${entityPackage}.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/service/${entityPackage}/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/service/${entityPackage}/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..4b09157 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/service/${entityPackage}/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,19 @@ +package ${bussiPackage}.service.${entityPackage}.impl; + +import ${bussiPackage}.entity.${entityPackage}.${entityName}; +import ${bussiPackage}.mapper.${entityPackage}.${entityName}Mapper; +import ${bussiPackage}.service.${entityPackage}.I${entityName}Service; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + +} diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/${entityName}List.vuei b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/${entityName}List.vuei new file mode 100644 index 0000000..106943b --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/${entityName}List.vuei @@ -0,0 +1,173 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..ff934f1 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/modules/${entityName}Modal.vuei @@ -0,0 +1,156 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/modules/${entityName}Modal__Style#Drawer.vuei b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/modules/${entityName}Modal__Style#Drawer.vuei new file mode 100644 index 0000000..4446ba6 --- /dev/null +++ b/src/main/resources/jeecg/code-template/one2/java/${bussiPackage}/vue/${entityPackage}/modules/${entityName}Modal__Style#Drawer.vuei @@ -0,0 +1,162 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..dee2973 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,250 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jeecg.common.system.vo.LoginUser; +import org.apache.shiro.SecurityUtils; +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; + +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.vo.${entityName}Page; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + <#list subTables as sub> + @Autowired + private I${sub.entityName}Service ${sub.entityName?uncap_first}Service; + + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName?uncap_first}Service.saveMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-编辑", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName?uncap_first}Service.updateMain(${entityName?uncap_first}, <#list subTables as sub>${entityName?uncap_first}Page.get${sub.entityName}List()<#if sub_has_next>,); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.delMain(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.delBatchMain(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + return Result.OK(${entityName?uncap_first}); + } + + <#list subTables as sub> + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-通过主表ID查询") + @ApiOperation(value="${sub.ftlDescription}-通过主表ID查询", notes="${tableVo.ftlDescription}-通过主表ID查询") + @GetMapping(value = "/query${sub.entityName}ByMainId") + public Result query${sub.entityName}ListByMainId(@RequestParam(name="id",required=true) String id) { + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(id); + return Result.OK(${sub.entityName?uncap_first}List); + } + + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + // Step.1 组装查询条件 + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + //Step.2 获取导出数据 + List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper); + for (${entityName} temp : ${entityName?uncap_first}List) { + ${entityName}Page vo = new ${entityName}Page(); + BeanUtils.copyProperties(temp, vo); + <#list subTables as sub> + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(temp.getId()); + vo.set${sub.entityName}List(${sub.entityName?uncap_first}List); + + pageList.add(vo); + } + //Step.3 调用AutoPoi导出Excel + ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); + mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}"); + mv.addObject(NormalExcelConstants.CLASS, ${entityName}Page.class); + mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}数据", "导出人:"+sysUser.getRealname(), "${tableVo.ftlDescription}")); + mv.addObject(NormalExcelConstants.DATA_LIST, pageList); + return mv; + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + ImportParams params = new ImportParams(); + params.setTitleRows(2); + params.setHeadRows(1); + params.setNeedSave(true); + try { + List<${entityName}Page> list = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}Page.class, params); + for (${entityName}Page page : list) { + ${entityName} po = new ${entityName}(); + BeanUtils.copyProperties(page, po); + ${entityName?uncap_first}Service.saveMain(po, <#list subTables as sub>page.get${sub.entityName}List()<#if sub_has_next>,); + } + return Result.OK("文件导入成功!数据行数:" + list.size()); + } catch (Exception e) { + log.error(e.getMessage(),e); + return Result.error("文件导入失败:"+e.getMessage()); + } finally { + try { + file.getInputStream().close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return Result.OK("文件导入失败!"); + } + +} diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..3adee3a --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,43 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${tableName}") +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#list originalColumns as po> + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + + <#if po.fieldType =='java.util.Date'> + <#if po.fieldDbType =='date'> + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#elseif po.fieldDbType =='datetime'> + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai new file mode 100644 index 0000000..89c15b9 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -0,0 +1,54 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}.java +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import java.util.Date; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${subTab.tableName}") +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${subTab.entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#list subTab.originalColumns as po> + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldType =='java.util.Date'> + <#if po.fieldDbType =='date'> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#elseif po.fieldDbType =='datetime'> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)> + @Excel(name = "${po.filedComment}", width = 15) + + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai new file mode 100644 index 0000000..9585548 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai @@ -0,0 +1,21 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}Mapper.java +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> { + + public boolean deleteByMainId(String mainId); + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml new file mode 100644 index 0000000..708ae0b --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml @@ -0,0 +1,36 @@ +<#list subTables as subTab> +<#assign originalForeignKeys = subTab.originalForeignKeys> +#segment#${subTab.entityName}Mapper.xml + + + + + + DELETE + FROM ${subTab.tableName} + WHERE + <#list originalForeignKeys as key> + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + ${key} = ${r'#'}{${primaryKeyField}} <#rt/> + <#else> + ${key} = ${r'#'}{${key}} <#rt/> + + <#if key_has_next>AND + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..e7d9914 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,42 @@ +package ${bussiPackage}.${entityPackage}.service; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + + /** + * 添加一对多 + * + */ + public void saveMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) ; + + /** + * 修改一对多 + * + */ + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,); + + /** + * 删除一对多 + */ + public void delMain (String id); + + /** + * 批量删除一对多 + */ + public void delBatchMain (Collection idList); + +} diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai new file mode 100644 index 0000000..0f85cb3 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai @@ -0,0 +1,19 @@ +<#list subTables as subTab> +#segment#I${subTab.entityName}Service.java +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> { + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..fa8d61b --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,101 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper; + +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import java.io.Serializable; +import java.util.List; +import java.util.Collection; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + + @Autowired + private ${entityName}Mapper ${entityName?uncap_first}Mapper; + <#list subTables as sub> + @Autowired + private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper; + + + @Override + @Transactional + public void saveMain(${entityName} ${entityName?uncap_first}, <#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.insert(${entityName?uncap_first}); + <#list subTables as sub> + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + + } + + @Override + @Transactional + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.updateById(${entityName?uncap_first}); + + //1.先删除子表数据 + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(${entityName?uncap_first}.getId()); + + + //2.子表数据重新插入 + <#list subTables as sub> + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + + } + + @Override + @Transactional + public void delMain(String id) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + + @Override + @Transactional + public void delBatchMain(Collection idList) { + for(Serializable id:idList) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString()); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + } + +} diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai new file mode 100644 index 0000000..0ce41d3 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai @@ -0,0 +1,30 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}ServiceImpl.java +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service; +import org.springframework.stereotype.Service; +import java.util.List; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service { + + @Autowired + private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper; + + @Override + public List<${subTab.entityName}> selectByMainId(String mainId) { + return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId); + } +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai new file mode 100644 index 0000000..245e688 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai @@ -0,0 +1,54 @@ +package ${bussiPackage}.${entityPackage}.vo; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import lombok.Data; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecgframework.poi.excel.annotation.ExcelCollection; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import java.util.Date; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@ApiModel(value="${tableName}Page对象", description="${tableVo.ftlDescription}") +public class ${entityName}Page { + + <#list originalColumns as po> + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + <#else> + <#if po.fieldType =='java.util.Date'> + <#if po.fieldDbType =='date'> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#elseif po.fieldDbType =='datetime'> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + @Excel(name = "${po.filedComment}", width = 15) + + + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + + + <#list subTables as sub> + @ExcelCollection(name="${sub.ftlDescription}") + @ApiModelProperty(value = "${sub.ftlDescription}") + private List<${sub.entityName}> ${sub.entityName?uncap_first}List; + + +} diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..d6d1ea0 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,162 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..dba128e --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,185 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai new file mode 100644 index 0000000..93e7bb7 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai @@ -0,0 +1,337 @@ +package ${bussiPackage}.${entityPackage}.controller; + +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.SecurityUtils; +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.vo.LoginUser; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import ${bussiPackage}.${entityPackage}.vo.${entityName}Page; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; + + /** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Api(tags="${tableVo.ftlDescription}") +@RestController +@RequestMapping("/${entityPackage}/${entityName?uncap_first}") +@Slf4j +public class ${entityName}Controller { + @Autowired + private I${entityName}Service ${entityName?uncap_first}Service; + <#list subTables as sub> + @Autowired + private I${sub.entityName}Service ${sub.entityName?uncap_first}Service; + + + /** + * 分页列表查询 + * + * @param ${entityName?uncap_first} + * @param pageNo + * @param pageSize + * @param req + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-分页列表查询") + @ApiOperation(value="${tableVo.ftlDescription}-分页列表查询", notes="${tableVo.ftlDescription}-分页列表查询") + @GetMapping(value = "/list") + public Result queryPageList(${entityName} ${entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, req.getParameterMap()); + Page<${entityName}> page = new Page<${entityName}>(pageNo, pageSize); + IPage<${entityName}> pageList = ${entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-添加") + @ApiOperation(value="${tableVo.ftlDescription}-添加", notes="${tableVo.ftlDescription}-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName?uncap_first}Service.save(${entityName?uncap_first}); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param ${entityName?uncap_first}Page + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-编辑") + @ApiOperation(value="${tableVo.ftlDescription}-", notes="${tableVo.ftlDescription}-编辑") + @PutMapping(value = "/edit") + public Result edit(@RequestBody ${entityName}Page ${entityName?uncap_first}Page) { + ${entityName} ${entityName?uncap_first} = new ${entityName}(); + BeanUtils.copyProperties(${entityName?uncap_first}Page, ${entityName?uncap_first}); + ${entityName?uncap_first}Service.updateById(${entityName?uncap_first}); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id删除") + @ApiOperation(value="${tableVo.ftlDescription}-通过id删除", notes="${tableVo.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + ${entityName?uncap_first}Service.delMain(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-批量删除") + @ApiOperation(value="${tableVo.ftlDescription}-批量删除", notes="${tableVo.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.${entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + @AutoLog(value = "${tableVo.ftlDescription}-通过id查询") + @ApiOperation(value="${tableVo.ftlDescription}-通过id查询", notes="${tableVo.ftlDescription}-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + ${entityName} ${entityName?uncap_first} = ${entityName?uncap_first}Service.getById(id); + return Result.OK(${entityName?uncap_first}); + } + + //===========================以下是子表信息操作相关API==================================== + + <#list subTables as sub> + /** + * 通过主表id查询${sub.ftlDescription} + * + * @param ${sub.entityName?uncap_first} + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-通过主表id查询") + @ApiOperation(value="${sub.ftlDescription}-通过主表id查询", notes="${sub.ftlDescription}-通过主表id查询") + <#-- update-begin--Author:kangxiaolin Date:20190905 for:[442]主子表分开维护,生成的代码子表的分页改为真实的分页-------------------- --> + @GetMapping(value = "/list${sub.entityName}ByMainId") + public Result list${sub.entityName}ByMainId(${sub.entityName} ${sub.entityName?uncap_first}, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + if(<#list sub.foreignKeys as key><#rt/> + <#if key?lower_case?index_of("${primaryKeyField}")!=-1><#rt/> + <#if key_index == 0><#rt/> +${sub.entityName?uncap_first}.get${key?cap_first}()!=null<#rt/> + <#else><#rt/> +|| ${sub.entityName?uncap_first}.get${key?cap_first}()!=null<#rt/> + <#rt/> + <#else><#rt/> + <#if key_index == 0><#rt/> +${sub.entityName?uncap_first}.get${key}()!=null<#rt/> + <#else><#rt/> +|| ${sub.entityName?uncap_first}.get${key}()!=null<#rt/> + <#rt/> + + <#rt/> +) { + QueryWrapper<${sub.entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${sub.entityName?uncap_first}, req.getParameterMap()); + Page<${sub.entityName}> page = new Page<${sub.entityName}>(pageNo, pageSize); + IPage<${sub.entityName}> pageList = ${sub.entityName?uncap_first}Service.page(page, queryWrapper); + return Result.OK(pageList); + }else{ + return Result.OK(); + } + } + <#-- update-end--Author:kangxiaolin Date:20190905 for:[442]主子表分开维护,生成的代码子表的分页改为真实的分页-------------------- --> + + /** + * 添加${sub.ftlDescription} + * + * @param ${sub.entityName?uncap_first} + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-添加") + @ApiOperation(value="${sub.ftlDescription}-添加", notes="${sub.ftlDescription}-添加") + @PostMapping(value = "/add${sub.entityName}") + public Result add${sub.entityName}(@RequestBody ${sub.entityName} ${sub.entityName?uncap_first}) { + ${sub.entityName?uncap_first}Service.save(${sub.entityName?uncap_first}); + return Result.OK("添加${sub.ftlDescription}成功!"); + } + + /** + * 编辑${sub.ftlDescription} + * + * @param ${sub.entityName?uncap_first} + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-编辑") + @ApiOperation(value="${sub.ftlDescription}-编辑", notes="${sub.ftlDescription}-编辑") + @PutMapping("/edit${sub.entityName}") + public Result edit${sub.entityName}(@RequestBody ${sub.entityName} ${sub.entityName?uncap_first}) { + ${sub.entityName?uncap_first}Service.updateById(${sub.entityName?uncap_first}); + return Result.OK("编辑${sub.ftlDescription}成功!"); + } + + /** + * 通过id删除${sub.ftlDescription} + * + * @param id + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-通过id删除") + @ApiOperation(value="${sub.ftlDescription}-通过id删除", notes="${sub.ftlDescription}-通过id删除") + @DeleteMapping(value = "/delete${sub.entityName}") + public Result delete${sub.entityName}(@RequestParam(name = "id", required = true) String id) { + ${sub.entityName?uncap_first}Service.removeById(id); + return Result.OK("删除${sub.ftlDescription}成功!"); + } + + /** + * 批量删除${sub.ftlDescription} + * + * @param ids + * @return + */ + @AutoLog(value = "${sub.ftlDescription}-批量删除") + @ApiOperation(value="${sub.ftlDescription}-批量删除", notes="${sub.ftlDescription}-批量删除") + @DeleteMapping(value = "/deleteBatch${sub.entityName}") + public Result deleteBatch${sub.entityName}(@RequestParam(name = "ids", required = true) String ids) { + if (ids == null || "".equals(ids.trim())) { + return Result.error("参数不识别!"); + } + this.${sub.entityName?uncap_first}Service.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + + } + + + + /** + * 导出excel + * + * @param request + * @param ${entityName?uncap_first} + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, ${entityName} ${entityName?uncap_first}) { + // Step.1 组装查询条件 + QueryWrapper<${entityName}> queryWrapper = QueryGenerator.initQueryWrapper(${entityName?uncap_first}, request.getParameterMap()); + LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + + //Step.2 获取导出数据 + List<${entityName}Page> pageList = new ArrayList<${entityName}Page>(); + List<${entityName}> ${entityName?uncap_first}List = ${entityName?uncap_first}Service.list(queryWrapper); + for (${entityName} temp : ${entityName?uncap_first}List) { + ${entityName}Page vo = new ${entityName}Page(); + BeanUtils.copyProperties(temp, vo); + <#list subTables as sub> + List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(temp.getId()); + vo.set${sub.entityName}List(${sub.entityName?uncap_first}List); + + pageList.add(vo); + } + //Step.3 调用AutoPoi导出Excel + ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); + mv.addObject(NormalExcelConstants.FILE_NAME, "${tableVo.ftlDescription}"); + mv.addObject(NormalExcelConstants.CLASS, ${entityName}Page.class); + mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("${tableVo.ftlDescription}数据", "导出人:"+sysUser.getRealname(), "${tableVo.ftlDescription}")); + mv.addObject(NormalExcelConstants.DATA_LIST, pageList); + return mv; + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; + Map fileMap = multipartRequest.getFileMap(); + for (Map.Entry entity : fileMap.entrySet()) { + MultipartFile file = entity.getValue();// 获取上传文件对象 + ImportParams params = new ImportParams(); + params.setTitleRows(2); + params.setHeadRows(1); + params.setNeedSave(true); + try { + List<${entityName}Page> list = ExcelImportUtil.importExcel(file.getInputStream(), ${entityName}Page.class, params); + for (${entityName}Page page : list) { + ${entityName} po = new ${entityName}(); + BeanUtils.copyProperties(page, po); + ${entityName?uncap_first}Service.saveMain(po, <#list subTables as sub>page.get${sub.entityName}List()<#if sub_has_next>,); + } + return Result.OK("文件导入成功!数据行数:" + list.size()); + } catch (Exception e) { + log.error(e.getMessage(),e); + return Result.error("文件导入失败:"+e.getMessage()); + } finally { + try { + file.getInputStream().close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return Result.OK("文件导入失败!"); + } +} diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai new file mode 100644 index 0000000..3adee3a --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/entity/${entityName}.javai @@ -0,0 +1,43 @@ +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import java.util.Date; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${tableName}") +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#list originalColumns as po> + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + + <#if po.fieldType =='java.util.Date'> + <#if po.fieldDbType =='date'> + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#elseif po.fieldDbType =='datetime'> + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai new file mode 100644 index 0000000..54f3e9a --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/entity/[1-n]Entity.javai @@ -0,0 +1,53 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}.java +package ${bussiPackage}.${entityPackage}.entity; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@TableName("${subTab.tableName}") +@ApiModel(value="${tableName}对象", description="${tableVo.ftlDescription}") +public class ${subTab.entityName} implements Serializable { + private static final long serialVersionUID = 1L; + + <#list subTab.originalColumns as po> + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + @TableId(type = IdType.ASSIGN_ID) + <#else> + <#if po.fieldType =='java.util.Date'> + <#if po.fieldDbType =='date'> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#elseif po.fieldDbType =='datetime'> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + <#if !subTab.foreignKeys?seq_contains(po.fieldName?cap_first)> + @Excel(name = "${po.filedComment}", width = 15) + + + + @ApiModelProperty(value = "${po.filedComment}") + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai new file mode 100644 index 0000000..c31b9bf --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/${entityName}Mapper.javai @@ -0,0 +1,17 @@ +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${entityName}Mapper extends BaseMapper<${entityName}> { + +} diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai new file mode 100644 index 0000000..9585548 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/[1-n]Mapper.javai @@ -0,0 +1,21 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}Mapper.java +package ${bussiPackage}.${entityPackage}.mapper; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface ${subTab.entityName}Mapper extends BaseMapper<${subTab.entityName}> { + + public boolean deleteByMainId(String mainId); + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml new file mode 100644 index 0000000..16f3d65 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/xml/${entityName}Mapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml new file mode 100644 index 0000000..708ae0b --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/mapper/xml/[1-n]Mapper.xml @@ -0,0 +1,36 @@ +<#list subTables as subTab> +<#assign originalForeignKeys = subTab.originalForeignKeys> +#segment#${subTab.entityName}Mapper.xml + + + + + + DELETE + FROM ${subTab.tableName} + WHERE + <#list originalForeignKeys as key> + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + ${key} = ${r'#'}{${primaryKeyField}} <#rt/> + <#else> + ${key} = ${r'#'}{${key}} <#rt/> + + <#if key_has_next>AND + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai new file mode 100644 index 0000000..e7d9914 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/I${entityName}Service.javai @@ -0,0 +1,42 @@ +package ${bussiPackage}.${entityPackage}.service; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${entityName}Service extends IService<${entityName}> { + + /** + * 添加一对多 + * + */ + public void saveMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) ; + + /** + * 修改一对多 + * + */ + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,); + + /** + * 删除一对多 + */ + public void delMain (String id); + + /** + * 批量删除一对多 + */ + public void delBatchMain (Collection idList); + +} diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai new file mode 100644 index 0000000..0f85cb3 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/[1-n]Service.javai @@ -0,0 +1,19 @@ +<#list subTables as subTab> +#segment#I${subTab.entityName}Service.java +package ${bussiPackage}.${entityPackage}.service; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import com.baomidou.mybatisplus.extension.service.IService; +import java.util.List; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +public interface I${subTab.entityName}Service extends IService<${subTab.entityName}> { + + public List<${subTab.entityName}> selectByMainId(String mainId); +} + diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai new file mode 100644 index 0000000..fa8d61b --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/impl/${entityName}ServiceImpl.javai @@ -0,0 +1,101 @@ +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.mapper.${sub.entityName}Mapper; + +import ${bussiPackage}.${entityPackage}.mapper.${entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${entityName}Service; +import org.springframework.stereotype.Service; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import java.io.Serializable; +import java.util.List; +import java.util.Collection; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements I${entityName}Service { + + @Autowired + private ${entityName}Mapper ${entityName?uncap_first}Mapper; + <#list subTables as sub> + @Autowired + private ${sub.entityName}Mapper ${sub.entityName?uncap_first}Mapper; + + + @Override + @Transactional + public void saveMain(${entityName} ${entityName?uncap_first}, <#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.insert(${entityName?uncap_first}); + <#list subTables as sub> + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + + } + + @Override + @Transactional + public void updateMain(${entityName} ${entityName?uncap_first},<#list subTables as sub>List<${sub.entityName}> ${sub.entityName?uncap_first}List<#if sub_has_next>,) { + ${entityName?uncap_first}Mapper.updateById(${entityName?uncap_first}); + + //1.先删除子表数据 + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(${entityName?uncap_first}.getId()); + + + //2.子表数据重新插入 + <#list subTables as sub> + for(${sub.entityName} entity:${sub.entityName?uncap_first}List) { + <#list sub.foreignKeys as key> + //外键设置 + <#if key?lower_case?index_of("${primaryKeyField}")!=-1> + entity.set${key?cap_first}(${entityName?uncap_first}.get${primaryKeyField?cap_first}()); + <#else> + entity.set${key?cap_first}(${entityName?uncap_first}.get${key}()); + + + ${sub.entityName?uncap_first}Mapper.insert(entity); + } + + } + + @Override + @Transactional + public void delMain(String id) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + + @Override + @Transactional + public void delBatchMain(Collection idList) { + for(Serializable id:idList) { + <#list subTables as sub> + ${sub.entityName?uncap_first}Mapper.deleteByMainId(id.toString()); + + ${entityName?uncap_first}Mapper.deleteById(id); + } + } + +} diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai new file mode 100644 index 0000000..0ce41d3 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/service/impl/[1-n]ServiceImpl.javai @@ -0,0 +1,30 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}ServiceImpl.java +package ${bussiPackage}.${entityPackage}.service.impl; + +import ${bussiPackage}.${entityPackage}.entity.${subTab.entityName}; +import ${bussiPackage}.${entityPackage}.mapper.${subTab.entityName}Mapper; +import ${bussiPackage}.${entityPackage}.service.I${subTab.entityName}Service; +import org.springframework.stereotype.Service; +import java.util.List; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @Description: ${subTab.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Service +public class ${subTab.entityName}ServiceImpl extends ServiceImpl<${subTab.entityName}Mapper, ${subTab.entityName}> implements I${subTab.entityName}Service { + + @Autowired + private ${subTab.entityName}Mapper ${subTab.entityName?uncap_first}Mapper; + + @Override + public List<${subTab.entityName}> selectByMainId(String mainId) { + return ${subTab.entityName?uncap_first}Mapper.selectByMainId(mainId); + } +} + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai new file mode 100644 index 0000000..496d9d3 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vo/${entityName}Page.javai @@ -0,0 +1,53 @@ +package ${bussiPackage}.${entityPackage}.vo; + +import java.util.List; +import ${bussiPackage}.${entityPackage}.entity.${entityName}; +<#list subTables as sub> +import ${bussiPackage}.${entityPackage}.entity.${sub.entityName}; + +import lombok.Data; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecgframework.poi.excel.annotation.ExcelCollection; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * @Description: ${tableVo.ftlDescription} + * @Author: jeecg-boot + * @Date: ${.now?string["yyyy-MM-dd"]} + * @Version: V1.0 + */ +@Data +@ApiModel(value="${tableName}Page对象", description="${tableVo.ftlDescription}") +public class ${entityName}Page { + + <#list originalColumns as po> + /**${po.filedComment}*/ + <#if po.fieldName == primaryKeyField> + <#else> + <#if po.fieldType =='java.util.Date'> + <#if po.fieldDbType =='date'> + @Excel(name = "${po.filedComment}", width = 15, format = "yyyy-MM-dd") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern="yyyy-MM-dd") + <#elseif po.fieldDbType =='datetime'> + @Excel(name = "${po.filedComment}", width = 20, format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + + <#else> + @Excel(name = "${po.filedComment}", width = 15) + + + private <#if po.fieldType=='java.sql.Blob'>byte[]<#else>${po.fieldType} ${po.fieldName}; + + + <#list subTables as sub> + @ExcelCollection(name="${sub.ftlDescription}") + @ApiModelProperty(value = "${sub.ftlDescription}") + private List<${sub.entityName}> ${sub.entityName?uncap_first}List; + + +} diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei new file mode 100644 index 0000000..a07b236 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/${entityName}List.vuei @@ -0,0 +1,225 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/[1-n]List.vuei b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/[1-n]List.vuei new file mode 100644 index 0000000..f4b829c --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/[1-n]List.vuei @@ -0,0 +1,144 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}List.vue + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei new file mode 100644 index 0000000..1069111 --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/modules/${entityName}Modal.vuei @@ -0,0 +1,168 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei new file mode 100644 index 0000000..6d89afe --- /dev/null +++ b/src/main/resources/jeecg/code-template/onetomany2/java/${bussiPackage}/${entityPackage}/vue/modules/[1-n]Modal.vuei @@ -0,0 +1,184 @@ +<#list subTables as subTab> +#segment#${subTab.entityName}Modal.vue + + + + + + \ No newline at end of file diff --git a/src/main/resources/jeecg/jeecg_config.properties b/src/main/resources/jeecg/jeecg_config.properties new file mode 100644 index 0000000..0cd9a79 --- /dev/null +++ b/src/main/resources/jeecg/jeecg_config.properties @@ -0,0 +1,30 @@ +#code_generate_project_path +project_path=d:\\code +#bussi_package[User defined] +bussi_package=com.nd + + +#default code path +#source_root_package=src +#webroot_package=WebRoot + +#maven code path +source_root_package=src.main.java +webroot_package=src.main.webapp + +#ftl resource url +templatepath=/jeecg/code-template +system_encoding=utf-8 + +#db Table id [User defined] +db_table_id=id + +#db convert flag[true/false] +db_filed_convert=true + +#page Search Field num [User defined] +page_search_filed_num=1 +#page_filter_fields +page_filter_fields=create_time,create_by,update_time,update_by +#exclude table prefix +exclude_table=act_,ext_act_,design_,onl_,sys_,qrtz_,jmreport_,jimu_ diff --git a/src/main/resources/jeecg/jeecg_database.properties b/src/main/resources/jeecg/jeecg_database.properties new file mode 100644 index 0000000..8fc8db3 --- /dev/null +++ b/src/main/resources/jeecg/jeecg_database.properties @@ -0,0 +1,27 @@ +#mysql +diver_name=com.mysql.cj.jdbc.Driver +url=jdbc:mysql://127.0.0.1:3307/ndgjc_jeecg_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai +username=root +password=root +database_name=ndgjc_jeecg_db + +#oracle +#diver_name=oracle.jdbc.driver.OracleDriver +#url=jdbc:oracle:thin:@192.168.1.200:1521:ORCL +#username=scott +#password=tiger +#database_name=ORCL + +#postgre +#diver_name=org.postgresql.Driver +#url=jdbc:postgresql://localhost:5432/jeecg +#username=postgres +#password=postgres +#database_name=jeecg + +#SQLServer2005\u4ee5\u4e0a +#diver_name=org.hibernate.dialect.SQLServerDialect +#url=jdbc:sqlserver://192.168.1.200:1433;DatabaseName=jeecg +#username=sa +#password=SA +#database_name=jeecg \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..acad24b --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n + + + + + + + + ${LOG_HOME}/jeecgboot-%d{yyyy-MM-dd}.%i.log + + 30 + 10MB + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n + + + + + + + + ERROR + + + + %p%d%msg%M%F{32}%L + + + ${LOG_HOME}/error-log.html + + + + + + + + ${LOG_HOME}/jeecgboot-%d{yyyy-MM-dd}.%i.html + + 30 + 10MB + + + + %p%d%msg%M%F{32}%L + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/static/demo1.html b/src/main/resources/static/demo1.html new file mode 100644 index 0000000..f984869 --- /dev/null +++ b/src/main/resources/static/demo1.html @@ -0,0 +1 @@ +demo1 \ No newline at end of file diff --git a/src/main/resources/static/generic/LICENSE b/src/main/resources/static/generic/LICENSE new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/src/main/resources/static/generic/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/src/main/resources/static/generic/build/pdf.js b/src/main/resources/static/generic/build/pdf.js new file mode 100644 index 0000000..c94df53 --- /dev/null +++ b/src/main/resources/static/generic/build/pdf.js @@ -0,0 +1,8021 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * 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. + */ +/*jshint globalstrict: false */ +/* globals PDFJS */ + +// Initializing PDFJS global object (if still undefined) +if (typeof PDFJS === 'undefined') { + (typeof window !== 'undefined' ? window : this).PDFJS = {}; +} + +PDFJS.version = '1.1.159'; +PDFJS.build = '82536f8'; + +(function pdfjsWrapper() { + // Use strict in our context only - users might not want it + 'use strict'; + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * 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. + */ +/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL, + Promise */ + +'use strict'; + +var globalScope = (typeof window === 'undefined') ? this : window; + +var isWorker = (typeof window === 'undefined'); + +var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; + +var TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; + +var ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 +}; + +var AnnotationType = { + WIDGET: 1, + TEXT: 2, + LINK: 3 +}; + +var StreamType = { + UNKNOWN: 0, + FLATE: 1, + LZW: 2, + DCT: 3, + JPX: 4, + JBIG: 5, + A85: 6, + AHX: 7, + CCF: 8, + RL: 9 +}; + +var FontType = { + UNKNOWN: 0, + TYPE1: 1, + TYPE1C: 2, + CIDFONTTYPE0: 3, + CIDFONTTYPE0C: 4, + TRUETYPE: 5, + CIDFONTTYPE2: 6, + TYPE3: 7, + OPENTYPE: 8, + TYPE0: 9, + MMTYPE1: 10 +}; + +// The global PDFJS object exposes the API +// In production, it will be declared outside a global wrapper +// In development, it will be declared here +if (!globalScope.PDFJS) { + globalScope.PDFJS = {}; +} + +globalScope.PDFJS.pdfBug = false; + +PDFJS.VERBOSITY_LEVELS = { + errors: 0, + warnings: 1, + infos: 5 +}; + +// All the possible operations for an operator list. +var OPS = PDFJS.OPS = { + // Intentionally start from 1 so it is easy to spot bad operators that will be + // 0's. + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotations: 78, + endAnnotations: 79, + beginAnnotation: 80, + endAnnotation: 81, + paintJpegXObject: 82, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91 +}; + +// A notice for devs. These are good for things that are helpful to devs, such +// as warning that Workers were disabled, which is important to devs but not +// end users. +function info(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) { + console.log('Info: ' + msg); + } +} + +// Non-fatal warnings. +function warn(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) { + console.log('Warning: ' + msg); + } +} + +// Fatal errors that should trigger the fallback UI and halt execution by +// throwing an exception. +function error(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.errors) { + console.log('Error: ' + msg); + console.log(backtrace()); + } + UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown); + throw new Error(msg); +} + +function backtrace() { + try { + throw new Error(); + } catch (e) { + return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; + } +} + +function assert(cond, msg) { + if (!cond) { + error(msg); + } +} + +var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; + +var UnsupportedManager = PDFJS.UnsupportedManager = + (function UnsupportedManagerClosure() { + var listeners = []; + return { + listen: function (cb) { + listeners.push(cb); + }, + notify: function (featureId) { + warn('Unsupported feature "' + featureId + '"'); + for (var i = 0, ii = listeners.length; i < ii; i++) { + listeners[i](featureId); + } + } + }; +})(); + +// Combines two URLs. The baseUrl shall be absolute URL. If the url is an +// absolute URL, it will be returned as is. +function combineUrl(baseUrl, url) { + if (!url) { + return baseUrl; + } + if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) { + return url; + } + var i; + if (url.charAt(0) === '/') { + // absolute path + i = baseUrl.indexOf('://'); + if (url.charAt(1) === '/') { + ++i; + } else { + i = baseUrl.indexOf('/', i + 3); + } + return baseUrl.substring(0, i) + url; + } else { + // relative path + var pathLength = baseUrl.length; + i = baseUrl.lastIndexOf('#'); + pathLength = i >= 0 ? i : pathLength; + i = baseUrl.lastIndexOf('?', pathLength); + pathLength = i >= 0 ? i : pathLength; + var prefixLength = baseUrl.lastIndexOf('/', pathLength); + return baseUrl.substring(0, prefixLength + 1) + url; + } +} + +// Validates if URL is safe and allowed, e.g. to avoid XSS. +function isValidUrl(url, allowRelative) { + if (!url) { + return false; + } + // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1) + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url); + if (!protocol) { + return allowRelative; + } + protocol = protocol[0].toLowerCase(); + switch (protocol) { + case 'http': + case 'https': + case 'ftp': + case 'mailto': + case 'tel': + return true; + default: + return false; + } +} +PDFJS.isValidUrl = isValidUrl; + +function shadow(obj, prop, value) { + Object.defineProperty(obj, prop, { value: value, + enumerable: true, + configurable: true, + writable: false }); + return value; +} +PDFJS.shadow = shadow; + +var PasswordResponses = PDFJS.PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; + +var PasswordException = (function PasswordExceptionClosure() { + function PasswordException(msg, code) { + this.name = 'PasswordException'; + this.message = msg; + this.code = code; + } + + PasswordException.prototype = new Error(); + PasswordException.constructor = PasswordException; + + return PasswordException; +})(); +PDFJS.PasswordException = PasswordException; + +var UnknownErrorException = (function UnknownErrorExceptionClosure() { + function UnknownErrorException(msg, details) { + this.name = 'UnknownErrorException'; + this.message = msg; + this.details = details; + } + + UnknownErrorException.prototype = new Error(); + UnknownErrorException.constructor = UnknownErrorException; + + return UnknownErrorException; +})(); +PDFJS.UnknownErrorException = UnknownErrorException; + +var InvalidPDFException = (function InvalidPDFExceptionClosure() { + function InvalidPDFException(msg) { + this.name = 'InvalidPDFException'; + this.message = msg; + } + + InvalidPDFException.prototype = new Error(); + InvalidPDFException.constructor = InvalidPDFException; + + return InvalidPDFException; +})(); +PDFJS.InvalidPDFException = InvalidPDFException; + +var MissingPDFException = (function MissingPDFExceptionClosure() { + function MissingPDFException(msg) { + this.name = 'MissingPDFException'; + this.message = msg; + } + + MissingPDFException.prototype = new Error(); + MissingPDFException.constructor = MissingPDFException; + + return MissingPDFException; +})(); +PDFJS.MissingPDFException = MissingPDFException; + +var UnexpectedResponseException = + (function UnexpectedResponseExceptionClosure() { + function UnexpectedResponseException(msg, status) { + this.name = 'UnexpectedResponseException'; + this.message = msg; + this.status = status; + } + + UnexpectedResponseException.prototype = new Error(); + UnexpectedResponseException.constructor = UnexpectedResponseException; + + return UnexpectedResponseException; +})(); +PDFJS.UnexpectedResponseException = UnexpectedResponseException; + +var NotImplementedException = (function NotImplementedExceptionClosure() { + function NotImplementedException(msg) { + this.message = msg; + } + + NotImplementedException.prototype = new Error(); + NotImplementedException.prototype.name = 'NotImplementedException'; + NotImplementedException.constructor = NotImplementedException; + + return NotImplementedException; +})(); + +var MissingDataException = (function MissingDataExceptionClosure() { + function MissingDataException(begin, end) { + this.begin = begin; + this.end = end; + this.message = 'Missing data [' + begin + ', ' + end + ')'; + } + + MissingDataException.prototype = new Error(); + MissingDataException.prototype.name = 'MissingDataException'; + MissingDataException.constructor = MissingDataException; + + return MissingDataException; +})(); + +var XRefParseException = (function XRefParseExceptionClosure() { + function XRefParseException(msg) { + this.message = msg; + } + + XRefParseException.prototype = new Error(); + XRefParseException.prototype.name = 'XRefParseException'; + XRefParseException.constructor = XRefParseException; + + return XRefParseException; +})(); + + +function bytesToString(bytes) { + assert(bytes !== null && typeof bytes === 'object' && + bytes.length !== undefined, 'Invalid argument for bytesToString'); + var length = bytes.length; + var MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + var strBuf = []; + for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + var chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + return strBuf.join(''); +} + +function stringToBytes(str) { + assert(typeof str === 'string', 'Invalid argument for stringToBytes'); + var length = str.length; + var bytes = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 0xFF; + } + return bytes; +} + +function string32(value) { + return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff, + (value >> 8) & 0xff, value & 0xff); +} + +function log2(x) { + var n = 1, i = 0; + while (x > n) { + n <<= 1; + i++; + } + return i; +} + +function readInt8(data, start) { + return (data[start] << 24) >> 24; +} + +function readUint16(data, offset) { + return (data[offset] << 8) | data[offset + 1]; +} + +function readUint32(data, offset) { + return ((data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]) >>> 0; +} + +// Lazy test the endianness of the platform +// NOTE: This will be 'true' for simulated TypedArrays +function isLittleEndian() { + var buffer8 = new Uint8Array(2); + buffer8[0] = 1; + var buffer16 = new Uint16Array(buffer8.buffer); + return (buffer16[0] === 1); +} + +Object.defineProperty(PDFJS, 'isLittleEndian', { + configurable: true, + get: function PDFJS_isLittleEndian() { + return shadow(PDFJS, 'isLittleEndian', isLittleEndian()); + } +}); + + // Lazy test if the userAgant support CanvasTypedArrays +function hasCanvasTypedArrays() { + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + var ctx = canvas.getContext('2d'); + var imageData = ctx.createImageData(1, 1); + return (typeof imageData.data.buffer !== 'undefined'); +} + +Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', { + configurable: true, + get: function PDFJS_hasCanvasTypedArrays() { + return shadow(PDFJS, 'hasCanvasTypedArrays', hasCanvasTypedArrays()); + } +}); + +var Uint32ArrayView = (function Uint32ArrayViewClosure() { + + function Uint32ArrayView(buffer, length) { + this.buffer = buffer; + this.byteLength = buffer.length; + this.length = length === undefined ? (this.byteLength >> 2) : length; + ensureUint32ArrayViewProps(this.length); + } + Uint32ArrayView.prototype = Object.create(null); + + var uint32ArrayViewSetters = 0; + function createUint32ArrayProp(index) { + return { + get: function () { + var buffer = this.buffer, offset = index << 2; + return (buffer[offset] | (buffer[offset + 1] << 8) | + (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0; + }, + set: function (value) { + var buffer = this.buffer, offset = index << 2; + buffer[offset] = value & 255; + buffer[offset + 1] = (value >> 8) & 255; + buffer[offset + 2] = (value >> 16) & 255; + buffer[offset + 3] = (value >>> 24) & 255; + } + }; + } + + function ensureUint32ArrayViewProps(length) { + while (uint32ArrayViewSetters < length) { + Object.defineProperty(Uint32ArrayView.prototype, + uint32ArrayViewSetters, + createUint32ArrayProp(uint32ArrayViewSetters)); + uint32ArrayViewSetters++; + } + } + + return Uint32ArrayView; +})(); + +var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; + +var Util = PDFJS.Util = (function UtilClosure() { + function Util() {} + + var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')']; + + // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids + // creating many intermediate strings. + Util.makeCssRgb = function Util_makeCssRgb(r, g, b) { + rgbBuf[1] = r; + rgbBuf[3] = g; + rgbBuf[5] = b; + return rgbBuf.join(''); + }; + + // Concatenates two transformation matrices together and returns the result. + Util.transform = function Util_transform(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; + }; + + // For 2d affine transforms + Util.applyTransform = function Util_applyTransform(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + }; + + Util.applyInverseTransform = function Util_applyInverseTransform(p, m) { + var d = m[0] * m[3] - m[1] * m[2]; + var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + return [xt, yt]; + }; + + // Applies the transform to the rectangle and finds the minimum axially + // aligned bounding box. + Util.getAxialAlignedBoundingBox = + function Util_getAxialAlignedBoundingBox(r, m) { + + var p1 = Util.applyTransform(r, m); + var p2 = Util.applyTransform(r.slice(2, 4), m); + var p3 = Util.applyTransform([r[0], r[3]], m); + var p4 = Util.applyTransform([r[2], r[1]], m); + return [ + Math.min(p1[0], p2[0], p3[0], p4[0]), + Math.min(p1[1], p2[1], p3[1], p4[1]), + Math.max(p1[0], p2[0], p3[0], p4[0]), + Math.max(p1[1], p2[1], p3[1], p4[1]) + ]; + }; + + Util.inverseTransform = function Util_inverseTransform(m) { + var d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, + (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + }; + + // Apply a generic 3d matrix M on a 3-vector v: + // | a b c | | X | + // | d e f | x | Y | + // | g h i | | Z | + // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i], + // with v as [X,Y,Z] + Util.apply3dTransform = function Util_apply3dTransform(m, v) { + return [ + m[0] * v[0] + m[1] * v[1] + m[2] * v[2], + m[3] * v[0] + m[4] * v[1] + m[5] * v[2], + m[6] * v[0] + m[7] * v[1] + m[8] * v[2] + ]; + }; + + // This calculation uses Singular Value Decomposition. + // The SVD can be represented with formula A = USV. We are interested in the + // matrix S here because it represents the scale values. + Util.singularValueDecompose2dScale = + function Util_singularValueDecompose2dScale(m) { + + var transpose = [m[0], m[2], m[1], m[3]]; + + // Multiply matrix m with its transpose. + var a = m[0] * transpose[0] + m[1] * transpose[2]; + var b = m[0] * transpose[1] + m[1] * transpose[3]; + var c = m[2] * transpose[0] + m[3] * transpose[2]; + var d = m[2] * transpose[1] + m[3] * transpose[3]; + + // Solve the second degree polynomial to get roots. + var first = (a + d) / 2; + var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2; + var sx = first + second || 1; + var sy = first - second || 1; + + // Scale values are the square roots of the eigenvalues. + return [Math.sqrt(sx), Math.sqrt(sy)]; + }; + + // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) + // For coordinate systems whose origin lies in the bottom-left, this + // means normalization to (BL,TR) ordering. For systems with origin in the + // top-left, this means (TL,BR) ordering. + Util.normalizeRect = function Util_normalizeRect(rect) { + var r = rect.slice(0); // clone rect + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + }; + + // Returns a rectangle [x1, y1, x2, y2] corresponding to the + // intersection of rect1 and rect2. If no intersection, returns 'false' + // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] + Util.intersect = function Util_intersect(rect1, rect2) { + function compare(a, b) { + return a - b; + } + + // Order points along the axes + var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare), + orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare), + result = []; + + rect1 = Util.normalizeRect(rect1); + rect2 = Util.normalizeRect(rect2); + + // X: first and second points belong to different rectangles? + if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) || + (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) { + // Intersection must be between second and third points + result[0] = orderedX[1]; + result[2] = orderedX[2]; + } else { + return false; + } + + // Y: first and second points belong to different rectangles? + if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) || + (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) { + // Intersection must be between second and third points + result[1] = orderedY[1]; + result[3] = orderedY[2]; + } else { + return false; + } + + return result; + }; + + Util.sign = function Util_sign(num) { + return num < 0 ? -1 : 1; + }; + + Util.appendToArray = function Util_appendToArray(arr1, arr2) { + Array.prototype.push.apply(arr1, arr2); + }; + + Util.prependToArray = function Util_prependToArray(arr1, arr2) { + Array.prototype.unshift.apply(arr1, arr2); + }; + + Util.extendObj = function extendObj(obj1, obj2) { + for (var key in obj2) { + obj1[key] = obj2[key]; + } + }; + + Util.getInheritableProperty = function Util_getInheritableProperty(dict, + name) { + while (dict && !dict.has(name)) { + dict = dict.get('Parent'); + } + if (!dict) { + return null; + } + return dict.get(name); + }; + + Util.inherit = function Util_inherit(sub, base, prototype) { + sub.prototype = Object.create(base.prototype); + sub.prototype.constructor = sub; + for (var prop in prototype) { + sub.prototype[prop] = prototype[prop]; + } + }; + + Util.loadScript = function Util_loadScript(src, callback) { + var script = document.createElement('script'); + var loaded = false; + script.setAttribute('src', src); + if (callback) { + script.onload = function() { + if (!loaded) { + callback(); + } + loaded = true; + }; + } + document.getElementsByTagName('head')[0].appendChild(script); + }; + + return Util; +})(); + +/** + * PDF page viewport created based on scale, rotation and offset. + * @class + * @alias PDFJS.PageViewport + */ +var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() { + /** + * @constructor + * @private + * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates. + * @param scale {number} scale of the viewport. + * @param rotation {number} rotations of the viewport in degrees. + * @param offsetX {number} offset X + * @param offsetY {number} offset Y + * @param dontFlip {boolean} if true, axis Y will not be flipped. + */ + function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) { + this.viewBox = viewBox; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + + // creating transform to convert pdf coordinate system to the normal + // canvas like coordinates taking in account scale and rotation + var centerX = (viewBox[2] + viewBox[0]) / 2; + var centerY = (viewBox[3] + viewBox[1]) / 2; + var rotateA, rotateB, rotateC, rotateD; + rotation = rotation % 360; + rotation = rotation < 0 ? rotation + 360 : rotation; + switch (rotation) { + case 180: + rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1; + break; + case 90: + rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0; + break; + case 270: + rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0; + break; + //case 0: + default: + rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1; + break; + } + + if (dontFlip) { + rotateC = -rotateC; rotateD = -rotateD; + } + + var offsetCanvasX, offsetCanvasY; + var width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = Math.abs(viewBox[3] - viewBox[1]) * scale; + height = Math.abs(viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = Math.abs(viewBox[2] - viewBox[0]) * scale; + height = Math.abs(viewBox[3] - viewBox[1]) * scale; + } + // creating transform for the following operations: + // translate(-centerX, -centerY), rotate and flip vertically, + // scale, and translate(offsetCanvasX, offsetCanvasY) + this.transform = [ + rotateA * scale, + rotateB * scale, + rotateC * scale, + rotateD * scale, + offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, + offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY + ]; + + this.width = width; + this.height = height; + this.fontScale = scale; + } + PageViewport.prototype = /** @lends PDFJS.PageViewport.prototype */ { + /** + * Clones viewport with additional properties. + * @param args {Object} (optional) If specified, may contain the 'scale' or + * 'rotation' properties to override the corresponding properties in + * the cloned viewport. + * @returns {PDFJS.PageViewport} Cloned viewport. + */ + clone: function PageViewPort_clone(args) { + args = args || {}; + var scale = 'scale' in args ? args.scale : this.scale; + var rotation = 'rotation' in args ? args.rotation : this.rotation; + return new PageViewport(this.viewBox.slice(), scale, rotation, + this.offsetX, this.offsetY, args.dontFlip); + }, + /** + * Converts PDF point to the viewport coordinates. For examples, useful for + * converting PDF location into canvas pixel coordinates. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the viewport coordinate space. + * @see {@link convertToPdfPoint} + * @see {@link convertToViewportRectangle} + */ + convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) { + return Util.applyTransform([x, y], this.transform); + }, + /** + * Converts PDF rectangle to the viewport coordinates. + * @param rect {Array} xMin, yMin, xMax and yMax coordinates. + * @returns {Array} Contains corresponding coordinates of the rectangle + * in the viewport coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToViewportRectangle: + function PageViewport_convertToViewportRectangle(rect) { + var tl = Util.applyTransform([rect[0], rect[1]], this.transform); + var br = Util.applyTransform([rect[2], rect[3]], this.transform); + return [tl[0], tl[1], br[0], br[1]]; + }, + /** + * Converts viewport coordinates to the PDF location. For examples, useful + * for converting canvas pixel location into PDF one. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the PDF coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) { + return Util.applyInverseTransform([x, y], this.transform); + } + }; + return PageViewport; +})(); + +var PDFStringTranslateTable = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, + 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, + 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, + 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC +]; + +function stringToPDFString(str) { + var i, n = str.length, strBuf = []; + if (str[0] === '\xFE' && str[1] === '\xFF') { + // UTF16BE BOM + for (i = 2; i < n; i += 2) { + strBuf.push(String.fromCharCode( + (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1))); + } + } else { + for (i = 0; i < n; ++i) { + var code = PDFStringTranslateTable[str.charCodeAt(i)]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + } + return strBuf.join(''); +} + +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} + +function utf8StringToString(str) { + return unescape(encodeURIComponent(str)); +} + +function isEmptyObj(obj) { + for (var key in obj) { + return false; + } + return true; +} + +function isBool(v) { + return typeof v === 'boolean'; +} + +function isInt(v) { + return typeof v === 'number' && ((v | 0) === v); +} + +function isNum(v) { + return typeof v === 'number'; +} + +function isString(v) { + return typeof v === 'string'; +} + +function isName(v) { + return v instanceof Name; +} + +function isCmd(v, cmd) { + return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); +} + +function isDict(v, type) { + if (!(v instanceof Dict)) { + return false; + } + if (!type) { + return true; + } + var dictType = v.get('Type'); + return isName(dictType) && dictType.name === type; +} + +function isArray(v) { + return v instanceof Array; +} + +function isStream(v) { + return typeof v === 'object' && v !== null && v.getBytes !== undefined; +} + +function isArrayBuffer(v) { + return typeof v === 'object' && v !== null && v.byteLength !== undefined; +} + +function isRef(v) { + return v instanceof Ref; +} + +/** + * Promise Capability object. + * + * @typedef {Object} PromiseCapability + * @property {Promise} promise - A promise object. + * @property {function} resolve - Fullfills the promise. + * @property {function} reject - Rejects the promise. + */ + +/** + * Creates a promise capability object. + * @alias PDFJS.createPromiseCapability + * + * @return {PromiseCapability} A capability object contains: + * - a Promise, resolve and reject methods. + */ +function createPromiseCapability() { + var capability = {}; + capability.promise = new Promise(function (resolve, reject) { + capability.resolve = resolve; + capability.reject = reject; + }); + return capability; +} + +PDFJS.createPromiseCapability = createPromiseCapability; + +/** + * Polyfill for Promises: + * The following promise implementation tries to generally implement the + * Promise/A+ spec. Some notable differences from other promise libaries are: + * - There currently isn't a seperate deferred and promise object. + * - Unhandled rejections eventually show an error if they aren't handled. + * + * Based off of the work in: + * https://bugzilla.mozilla.org/show_bug.cgi?id=810490 + */ +(function PromiseClosure() { + if (globalScope.Promise) { + // Promises existing in the DOM/Worker, checking presence of all/resolve + if (typeof globalScope.Promise.all !== 'function') { + globalScope.Promise.all = function (iterable) { + var count = 0, results = [], resolve, reject; + var promise = new globalScope.Promise(function (resolve_, reject_) { + resolve = resolve_; + reject = reject_; + }); + iterable.forEach(function (p, i) { + count++; + p.then(function (result) { + results[i] = result; + count--; + if (count === 0) { + resolve(results); + } + }, reject); + }); + if (count === 0) { + resolve(results); + } + return promise; + }; + } + if (typeof globalScope.Promise.resolve !== 'function') { + globalScope.Promise.resolve = function (value) { + return new globalScope.Promise(function (resolve) { resolve(value); }); + }; + } + if (typeof globalScope.Promise.reject !== 'function') { + globalScope.Promise.reject = function (reason) { + return new globalScope.Promise(function (resolve, reject) { + reject(reason); + }); + }; + } + if (typeof globalScope.Promise.prototype.catch !== 'function') { + globalScope.Promise.prototype.catch = function (onReject) { + return globalScope.Promise.prototype.then(undefined, onReject); + }; + } + return; + } + var STATUS_PENDING = 0; + var STATUS_RESOLVED = 1; + var STATUS_REJECTED = 2; + + // In an attempt to avoid silent exceptions, unhandled rejections are + // tracked and if they aren't handled in a certain amount of time an + // error is logged. + var REJECTION_TIMEOUT = 500; + + var HandlerManager = { + handlers: [], + running: false, + unhandledRejections: [], + pendingRejectionCheck: false, + + scheduleHandlers: function scheduleHandlers(promise) { + if (promise._status === STATUS_PENDING) { + return; + } + + this.handlers = this.handlers.concat(promise._handlers); + promise._handlers = []; + + if (this.running) { + return; + } + this.running = true; + + setTimeout(this.runHandlers.bind(this), 0); + }, + + runHandlers: function runHandlers() { + var RUN_TIMEOUT = 1; // ms + var timeoutAt = Date.now() + RUN_TIMEOUT; + while (this.handlers.length > 0) { + var handler = this.handlers.shift(); + + var nextStatus = handler.thisPromise._status; + var nextValue = handler.thisPromise._value; + + try { + if (nextStatus === STATUS_RESOLVED) { + if (typeof handler.onResolve === 'function') { + nextValue = handler.onResolve(nextValue); + } + } else if (typeof handler.onReject === 'function') { + nextValue = handler.onReject(nextValue); + nextStatus = STATUS_RESOLVED; + + if (handler.thisPromise._unhandledRejection) { + this.removeUnhandeledRejection(handler.thisPromise); + } + } + } catch (ex) { + nextStatus = STATUS_REJECTED; + nextValue = ex; + } + + handler.nextPromise._updateStatus(nextStatus, nextValue); + if (Date.now() >= timeoutAt) { + break; + } + } + + if (this.handlers.length > 0) { + setTimeout(this.runHandlers.bind(this), 0); + return; + } + + this.running = false; + }, + + addUnhandledRejection: function addUnhandledRejection(promise) { + this.unhandledRejections.push({ + promise: promise, + time: Date.now() + }); + this.scheduleRejectionCheck(); + }, + + removeUnhandeledRejection: function removeUnhandeledRejection(promise) { + promise._unhandledRejection = false; + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (this.unhandledRejections[i].promise === promise) { + this.unhandledRejections.splice(i); + i--; + } + } + }, + + scheduleRejectionCheck: function scheduleRejectionCheck() { + if (this.pendingRejectionCheck) { + return; + } + this.pendingRejectionCheck = true; + setTimeout(function rejectionCheck() { + this.pendingRejectionCheck = false; + var now = Date.now(); + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) { + var unhandled = this.unhandledRejections[i].promise._value; + var msg = 'Unhandled rejection: ' + unhandled; + if (unhandled.stack) { + msg += '\n' + unhandled.stack; + } + warn(msg); + this.unhandledRejections.splice(i); + i--; + } + } + if (this.unhandledRejections.length) { + this.scheduleRejectionCheck(); + } + }.bind(this), REJECTION_TIMEOUT); + } + }; + + function Promise(resolver) { + this._status = STATUS_PENDING; + this._handlers = []; + try { + resolver.call(this, this._resolve.bind(this), this._reject.bind(this)); + } catch (e) { + this._reject(e); + } + } + /** + * Builds a promise that is resolved when all the passed in promises are + * resolved. + * @param {array} array of data and/or promises to wait for. + * @return {Promise} New dependant promise. + */ + Promise.all = function Promise_all(promises) { + var resolveAll, rejectAll; + var deferred = new Promise(function (resolve, reject) { + resolveAll = resolve; + rejectAll = reject; + }); + var unresolved = promises.length; + var results = []; + if (unresolved === 0) { + resolveAll(results); + return deferred; + } + function reject(reason) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results = []; + rejectAll(reason); + } + for (var i = 0, ii = promises.length; i < ii; ++i) { + var promise = promises[i]; + var resolve = (function(i) { + return function(value) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results[i] = value; + unresolved--; + if (unresolved === 0) { + resolveAll(results); + } + }; + })(i); + if (Promise.isPromise(promise)) { + promise.then(resolve, reject); + } else { + resolve(promise); + } + } + return deferred; + }; + + /** + * Checks if the value is likely a promise (has a 'then' function). + * @return {boolean} true if value is thenable + */ + Promise.isPromise = function Promise_isPromise(value) { + return value && typeof value.then === 'function'; + }; + + /** + * Creates resolved promise + * @param value resolve value + * @returns {Promise} + */ + Promise.resolve = function Promise_resolve(value) { + return new Promise(function (resolve) { resolve(value); }); + }; + + /** + * Creates rejected promise + * @param reason rejection value + * @returns {Promise} + */ + Promise.reject = function Promise_reject(reason) { + return new Promise(function (resolve, reject) { reject(reason); }); + }; + + Promise.prototype = { + _status: null, + _value: null, + _handlers: null, + _unhandledRejection: null, + + _updateStatus: function Promise__updateStatus(status, value) { + if (this._status === STATUS_RESOLVED || + this._status === STATUS_REJECTED) { + return; + } + + if (status === STATUS_RESOLVED && + Promise.isPromise(value)) { + value.then(this._updateStatus.bind(this, STATUS_RESOLVED), + this._updateStatus.bind(this, STATUS_REJECTED)); + return; + } + + this._status = status; + this._value = value; + + if (status === STATUS_REJECTED && this._handlers.length === 0) { + this._unhandledRejection = true; + HandlerManager.addUnhandledRejection(this); + } + + HandlerManager.scheduleHandlers(this); + }, + + _resolve: function Promise_resolve(value) { + this._updateStatus(STATUS_RESOLVED, value); + }, + + _reject: function Promise_reject(reason) { + this._updateStatus(STATUS_REJECTED, reason); + }, + + then: function Promise_then(onResolve, onReject) { + var nextPromise = new Promise(function (resolve, reject) { + this.resolve = resolve; + this.reject = reject; + }); + this._handlers.push({ + thisPromise: this, + onResolve: onResolve, + onReject: onReject, + nextPromise: nextPromise + }); + HandlerManager.scheduleHandlers(this); + return nextPromise; + }, + + catch: function Promise_catch(onReject) { + return this.then(undefined, onReject); + } + }; + + globalScope.Promise = Promise; +})(); + +var StatTimer = (function StatTimerClosure() { + function rpad(str, pad, length) { + while (str.length < length) { + str += pad; + } + return str; + } + function StatTimer() { + this.started = {}; + this.times = []; + this.enabled = true; + } + StatTimer.prototype = { + time: function StatTimer_time(name) { + if (!this.enabled) { + return; + } + if (name in this.started) { + warn('Timer is already running for ' + name); + } + this.started[name] = Date.now(); + }, + timeEnd: function StatTimer_timeEnd(name) { + if (!this.enabled) { + return; + } + if (!(name in this.started)) { + warn('Timer has not been started for ' + name); + } + this.times.push({ + 'name': name, + 'start': this.started[name], + 'end': Date.now() + }); + // Remove timer from started so it can be called again. + delete this.started[name]; + }, + toString: function StatTimer_toString() { + var i, ii; + var times = this.times; + var out = ''; + // Find the longest name for padding purposes. + var longest = 0; + for (i = 0, ii = times.length; i < ii; ++i) { + var name = times[i]['name']; + if (name.length > longest) { + longest = name.length; + } + } + for (i = 0, ii = times.length; i < ii; ++i) { + var span = times[i]; + var duration = span.end - span.start; + out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n'; + } + return out; + } + }; + return StatTimer; +})(); + +PDFJS.createBlob = function createBlob(data, contentType) { + if (typeof Blob !== 'undefined') { + return new Blob([data], { type: contentType }); + } + // Blob builder is deprecated in FF14 and removed in FF18. + var bb = new MozBlobBuilder(); + bb.append(data); + return bb.getBlob(contentType); +}; + +PDFJS.createObjectURL = (function createObjectURLClosure() { + // Blob/createObjectURL is not available, falling back to data schema. + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + return function createObjectURL(data, contentType) { + if (!PDFJS.disableCreateObjectURL && + typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = PDFJS.createBlob(data, contentType); + return URL.createObjectURL(blob); + } + + var buffer = 'data:' + contentType + ';base64,'; + for (var i = 0, ii = data.length; i < ii; i += 3) { + var b1 = data[i] & 0xFF; + var b2 = data[i + 1] & 0xFF; + var b3 = data[i + 2] & 0xFF; + var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < ii ? (b3 & 0x3F) : 64; + buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; + } + return buffer; + }; +})(); + +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + this.callbackIndex = 1; + this.postMessageTransfers = true; + var callbacksCapabilities = this.callbacksCapabilities = {}; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function ahConsoleLog(data) { + console.log.apply(console, data); + }]; + ah['console_error'] = [function ahConsoleError(data) { + console.error.apply(console, data); + }]; + ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) { + UnsupportedManager.notify(data); + }]; + + comObj.onmessage = function messageHandlerComObjOnMessage(event) { + var data = event.data; + if (data.isReply) { + var callbackId = data.callbackId; + if (data.callbackId in callbacksCapabilities) { + var callback = callbacksCapabilities[callbackId]; + delete callbacksCapabilities[callbackId]; + if ('error' in data) { + callback.reject(data.error); + } else { + callback.resolve(data.data); + } + } else { + error('Cannot resolve callback ' + callbackId); + } + } else if (data.action in ah) { + var action = ah[data.action]; + if (data.callbackId) { + Promise.resolve().then(function () { + return action[0].call(action[1], data.data); + }).then(function (result) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: result + }); + }, function (reason) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + error: reason + }); + }); + } else { + action[0].call(action[1], data.data); + } + } else { + error('Unknown action from worker: ' + data.action); + } + }; +} + +MessageHandler.prototype = { + on: function messageHandlerOn(actionName, handler, scope) { + var ah = this.actionHandler; + if (ah[actionName]) { + error('There is already an actionName called "' + actionName + '"'); + } + ah[actionName] = [handler, scope]; + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers + */ + send: function messageHandlerSend(actionName, data, transfers) { + var message = { + action: actionName, + data: data + }; + this.postMessage(message, transfers); + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * Expects that other side will callback with the response. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers. + * @returns {Promise} Promise to be resolved with response data. + */ + sendWithPromise: + function messageHandlerSendWithPromise(actionName, data, transfers) { + var callbackId = this.callbackIndex++; + var message = { + action: actionName, + data: data, + callbackId: callbackId + }; + var capability = createPromiseCapability(); + this.callbacksCapabilities[callbackId] = capability; + try { + this.postMessage(message, transfers); + } catch (e) { + capability.reject(e); + } + return capability.promise; + }, + /** + * Sends raw message to the comObj. + * @private + * @param message {Object} Raw message. + * @param transfers List of transfers/ArrayBuffers, or undefined. + */ + postMessage: function (message, transfers) { + if (transfers && this.postMessageTransfers) { + this.comObj.postMessage(message, transfers); + } else { + this.comObj.postMessage(message); + } + } +}; + +function loadJpegStream(id, imageUrl, objs) { + var img = new Image(); + img.onload = (function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }); + img.onerror = (function loadJpegStream_onerrorClosure() { + objs.resolve(id, null); + warn('Error during JPEG image loading'); + }); + img.src = imageUrl; +} + + +/** + * The maximum allowed image size in total pixels e.g. width * height. Images + * above this value will not be drawn. Use -1 for no limit. + * @var {number} + */ +PDFJS.maxImageSize = (PDFJS.maxImageSize === undefined ? + -1 : PDFJS.maxImageSize); + +/** + * The url of where the predefined Adobe CMaps are located. Include trailing + * slash. + * @var {string} + */ +PDFJS.cMapUrl = (PDFJS.cMapUrl === undefined ? null : PDFJS.cMapUrl); + +/** + * Specifies if CMaps are binary packed. + * @var {boolean} + */ +PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked; + +/** + * By default fonts are converted to OpenType fonts and loaded via font face + * rules. If disabled, the font will be rendered using a built in font renderer + * that constructs the glyphs with primitive path commands. + * @var {boolean} + */ +PDFJS.disableFontFace = (PDFJS.disableFontFace === undefined ? + false : PDFJS.disableFontFace); + +/** + * Path for image resources, mainly for annotation icons. Include trailing + * slash. + * @var {string} + */ +PDFJS.imageResourcesPath = (PDFJS.imageResourcesPath === undefined ? + '' : PDFJS.imageResourcesPath); + +/** + * Disable the web worker and run all code on the main thread. This will happen + * automatically if the browser doesn't support workers or sending typed arrays + * to workers. + * @var {boolean} + */ +PDFJS.disableWorker = (PDFJS.disableWorker === undefined ? + false : PDFJS.disableWorker); + +/** + * Path and filename of the worker file. Required when the worker is enabled in + * development mode. If unspecified in the production build, the worker will be + * loaded based on the location of the pdf.js file. + * @var {string} + */ +PDFJS.workerSrc = (PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc); + +/** + * Disable range request loading of PDF files. When enabled and if the server + * supports partial content requests then the PDF will be fetched in chunks. + * Enabled (false) by default. + * @var {boolean} + */ +PDFJS.disableRange = (PDFJS.disableRange === undefined ? + false : PDFJS.disableRange); + +/** + * Disable streaming of PDF file data. By default PDF.js attempts to load PDF + * in chunks. This default behavior can be disabled. + * @var {boolean} + */ +PDFJS.disableStream = (PDFJS.disableStream === undefined ? + false : PDFJS.disableStream); + +/** + * Disable pre-fetching of PDF file data. When range requests are enabled PDF.js + * will automatically keep fetching more data even if it isn't needed to display + * the current page. This default behavior can be disabled. + * + * NOTE: It is also necessary to disable streaming, see above, + * in order for disabling of pre-fetching to work correctly. + * @var {boolean} + */ +PDFJS.disableAutoFetch = (PDFJS.disableAutoFetch === undefined ? + false : PDFJS.disableAutoFetch); + +/** + * Enables special hooks for debugging PDF.js. + * @var {boolean} + */ +PDFJS.pdfBug = (PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug); + +/** + * Enables transfer usage in postMessage for ArrayBuffers. + * @var {boolean} + */ +PDFJS.postMessageTransfers = (PDFJS.postMessageTransfers === undefined ? + true : PDFJS.postMessageTransfers); + +/** + * Disables URL.createObjectURL usage. + * @var {boolean} + */ +PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ? + false : PDFJS.disableCreateObjectURL); + +/** + * Disables WebGL usage. + * @var {boolean} + */ +PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ? + true : PDFJS.disableWebGL); + +/** + * Disables fullscreen support, and by extension Presentation Mode, + * in browsers which support the fullscreen API. + * @var {boolean} + */ +PDFJS.disableFullscreen = (PDFJS.disableFullscreen === undefined ? + false : PDFJS.disableFullscreen); + +/** + * Enables CSS only zooming. + * @var {boolean} + */ +PDFJS.useOnlyCssZoom = (PDFJS.useOnlyCssZoom === undefined ? + false : PDFJS.useOnlyCssZoom); + +/** + * Controls the logging level. + * The constants from PDFJS.VERBOSITY_LEVELS should be used: + * - errors + * - warnings [default] + * - infos + * @var {number} + */ +PDFJS.verbosity = (PDFJS.verbosity === undefined ? + PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity); + +/** + * The maximum supported canvas size in total pixels e.g. width * height. + * The default value is 4096 * 4096. Use -1 for no limit. + * @var {number} + */ +PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ? + 16777216 : PDFJS.maxCanvasPixels); + +/** + * Opens external links in a new window if enabled. The default behavior opens + * external links in the PDF.js window. + * @var {boolean} + */ +PDFJS.openExternalLinksInNewWindow = ( + PDFJS.openExternalLinksInNewWindow === undefined ? + false : PDFJS.openExternalLinksInNewWindow); + +/** + * Document initialization / loading parameters object. + * + * @typedef {Object} DocumentInitParameters + * @property {string} url - The URL of the PDF. + * @property {TypedArray|Array|string} data - Binary PDF data. Use typed arrays + * (Uint8Array) to improve the memory usage. If PDF data is BASE64-encoded, + * use atob() to convert it to a binary string first. + * @property {Object} httpHeaders - Basic authentication headers. + * @property {boolean} withCredentials - Indicates whether or not cross-site + * Access-Control requests should be made using credentials such as cookies + * or authorization headers. The default is false. + * @property {string} password - For decrypting password-protected PDFs. + * @property {TypedArray} initialData - A typed array with the first portion or + * all of the pdf data. Used by the extension since some data is already + * loaded before the switch to range requests. + * @property {number} length - The PDF file length. It's used for progress + * reports and range requests operations. + * @property {PDFDataRangeTransport} range + */ + +/** + * @typedef {Object} PDFDocumentStats + * @property {Array} streamTypes - Used stream types in the document (an item + * is set to true if specific stream ID was used in the document). + * @property {Array} fontTypes - Used font type in the document (an item is set + * to true if specific font ID was used in the document). + */ + +/** + * This is the main entry point for loading a PDF and interacting with it. + * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR) + * is used, which means it must follow the same origin rules that any XHR does + * e.g. No cross domain requests without CORS. + * + * @param {string|TypedArray|DocumentInitParameters|PDFDataRangeTransport} src + * Can be a url to where a PDF is located, a typed array (Uint8Array) + * already populated with data or parameter object. + * + * @param {PDFDataRangeTransport} pdfDataRangeTransport (deprecated) It is used + * if you want to manually serve range requests for data in the PDF. + * + * @param {function} passwordCallback (deprecated) It is used to request a + * password if wrong or no password was provided. The callback receives two + * parameters: function that needs to be called with new password and reason + * (see {PasswordResponses}). + * + * @param {function} progressCallback (deprecated) It is used to be able to + * monitor the loading progress of the PDF file (necessary to implement e.g. + * a loading bar). The callback receives an {Object} with the properties: + * {number} loaded and {number} total. + * + * @return {PDFDocumentLoadingTask} + */ +PDFJS.getDocument = function getDocument(src, + pdfDataRangeTransport, + passwordCallback, + progressCallback) { + var task = new PDFDocumentLoadingTask(); + + // Support of the obsolete arguments (for compatibility with API v1.0) + if (pdfDataRangeTransport) { + if (!(pdfDataRangeTransport instanceof PDFDataRangeTransport)) { + // Not a PDFDataRangeTransport instance, trying to add missing properties. + pdfDataRangeTransport = Object.create(pdfDataRangeTransport); + pdfDataRangeTransport.length = src.length; + pdfDataRangeTransport.initialData = src.initialData; + } + src = Object.create(src); + src.range = pdfDataRangeTransport; + } + task.onPassword = passwordCallback || null; + task.onProgress = progressCallback || null; + + var workerInitializedCapability, transport; + var source; + if (typeof src === 'string') { + source = { url: src }; + } else if (isArrayBuffer(src)) { + source = { data: src }; + } else if (src instanceof PDFDataRangeTransport) { + source = { range: src }; + } else { + if (typeof src !== 'object') { + error('Invalid parameter in getDocument, need either Uint8Array, ' + + 'string or a parameter object'); + } + if (!src.url && !src.data && !src.range) { + error('Invalid parameter object: need either .data, .range or .url'); + } + + source = src; + } + + var params = {}; + for (var key in source) { + if (key === 'url' && typeof window !== 'undefined') { + // The full path is required in the 'url' field. + params[key] = combineUrl(window.location.href, source[key]); + continue; + } else if (key === 'range') { + continue; + } else if (key === 'data' && !(source[key] instanceof Uint8Array)) { + // Converting string or array-like data to Uint8Array. + var pdfBytes = source[key]; + if (typeof pdfBytes === 'string') { + params[key] = stringToBytes(pdfBytes); + } else if (typeof pdfBytes === 'object' && pdfBytes !== null && + !isNaN(pdfBytes.length)) { + params[key] = new Uint8Array(pdfBytes); + } else { + error('Invalid PDF binary data: either typed array, string or ' + + 'array-like object is expected in the data property.'); + } + continue; + } + params[key] = source[key]; + } + + workerInitializedCapability = createPromiseCapability(); + transport = new WorkerTransport(workerInitializedCapability, source.range); + workerInitializedCapability.promise.then(function transportInitialized() { + transport.fetchDocument(task, params); + }); + + return task; +}; + +/** + * PDF document loading operation. + * @class + */ +var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() { + /** @constructs PDFDocumentLoadingTask */ + function PDFDocumentLoadingTask() { + this._capability = createPromiseCapability(); + + /** + * Callback to request a password if wrong or no password was provided. + * The callback receives two parameters: function that needs to be called + * with new password and reason (see {PasswordResponses}). + */ + this.onPassword = null; + + /** + * Callback to be able to monitor the loading progress of the PDF file + * (necessary to implement e.g. a loading bar). The callback receives + * an {Object} with the properties: {number} loaded and {number} total. + */ + this.onProgress = null; + } + + PDFDocumentLoadingTask.prototype = + /** @lends PDFDocumentLoadingTask.prototype */ { + /** + * @return {Promise} + */ + get promise() { + return this._capability.promise; + }, + + // TODO add cancel or abort method + + /** + * Registers callbacks to indicate the document loading completion. + * + * @param {function} onFulfilled The callback for the loading completion. + * @param {function} onRejected The callback for the loading failure. + * @return {Promise} A promise that is resolved after the onFulfilled or + * onRejected callback. + */ + then: function PDFDocumentLoadingTask_then(onFulfilled, onRejected) { + return this.promise.then.apply(this.promise, arguments); + } + }; + + return PDFDocumentLoadingTask; +})(); + +/** + * Abstract class to support range requests file loading. + * @class + */ +var PDFDataRangeTransport = (function pdfDataRangeTransportClosure() { + /** + * @constructs PDFDataRangeTransport + * @param {number} length + * @param {Uint8Array} initialData + */ + function PDFDataRangeTransport(length, initialData) { + this.length = length; + this.initialData = initialData; + + this._rangeListeners = []; + this._progressListeners = []; + this._progressiveReadListeners = []; + this._readyCapability = createPromiseCapability(); + } + PDFDataRangeTransport.prototype = + /** @lends PDFDataRangeTransport.prototype */ { + addRangeListener: + function PDFDataRangeTransport_addRangeListener(listener) { + this._rangeListeners.push(listener); + }, + + addProgressListener: + function PDFDataRangeTransport_addProgressListener(listener) { + this._progressListeners.push(listener); + }, + + addProgressiveReadListener: + function PDFDataRangeTransport_addProgressiveReadListener(listener) { + this._progressiveReadListeners.push(listener); + }, + + onDataRange: function PDFDataRangeTransport_onDataRange(begin, chunk) { + var listeners = this._rangeListeners; + for (var i = 0, n = listeners.length; i < n; ++i) { + listeners[i](begin, chunk); + } + }, + + onDataProgress: function PDFDataRangeTransport_onDataProgress(loaded) { + this._readyCapability.promise.then(function () { + var listeners = this._progressListeners; + for (var i = 0, n = listeners.length; i < n; ++i) { + listeners[i](loaded); + } + }.bind(this)); + }, + + onDataProgressiveRead: + function PDFDataRangeTransport_onDataProgress(chunk) { + this._readyCapability.promise.then(function () { + var listeners = this._progressiveReadListeners; + for (var i = 0, n = listeners.length; i < n; ++i) { + listeners[i](chunk); + } + }.bind(this)); + }, + + transportReady: function PDFDataRangeTransport_transportReady() { + this._readyCapability.resolve(); + }, + + requestDataRange: + function PDFDataRangeTransport_requestDataRange(begin, end) { + throw new Error('Abstract method PDFDataRangeTransport.requestDataRange'); + } + }; + return PDFDataRangeTransport; +})(); + +PDFJS.PDFDataRangeTransport = PDFDataRangeTransport; + +/** + * Proxy to a PDFDocument in the worker thread. Also, contains commonly used + * properties that can be read synchronously. + * @class + */ +var PDFDocumentProxy = (function PDFDocumentProxyClosure() { + function PDFDocumentProxy(pdfInfo, transport) { + this.pdfInfo = pdfInfo; + this.transport = transport; + } + PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */ { + /** + * @return {number} Total number of pages the PDF contains. + */ + get numPages() { + return this.pdfInfo.numPages; + }, + /** + * @return {string} A unique ID to identify a PDF. Not guaranteed to be + * unique. + */ + get fingerprint() { + return this.pdfInfo.fingerprint; + }, + /** + * @param {number} pageNumber The page number to get. The first page is 1. + * @return {Promise} A promise that is resolved with a {@link PDFPageProxy} + * object. + */ + getPage: function PDFDocumentProxy_getPage(pageNumber) { + return this.transport.getPage(pageNumber); + }, + /** + * @param {{num: number, gen: number}} ref The page reference. Must have + * the 'num' and 'gen' properties. + * @return {Promise} A promise that is resolved with the page index that is + * associated with the reference. + */ + getPageIndex: function PDFDocumentProxy_getPageIndex(ref) { + return this.transport.getPageIndex(ref); + }, + /** + * @return {Promise} A promise that is resolved with a lookup table for + * mapping named destinations to reference numbers. + * + * This can be slow for large documents: use getDestination instead + */ + getDestinations: function PDFDocumentProxy_getDestinations() { + return this.transport.getDestinations(); + }, + /** + * @param {string} id The named destination to get. + * @return {Promise} A promise that is resolved with all information + * of the given named destination. + */ + getDestination: function PDFDocumentProxy_getDestination(id) { + return this.transport.getDestination(id); + }, + /** + * @return {Promise} A promise that is resolved with a lookup table for + * mapping named attachments to their content. + */ + getAttachments: function PDFDocumentProxy_getAttachments() { + return this.transport.getAttachments(); + }, + /** + * @return {Promise} A promise that is resolved with an array of all the + * JavaScript strings in the name tree. + */ + getJavaScript: function PDFDocumentProxy_getJavaScript() { + return this.transport.getJavaScript(); + }, + /** + * @return {Promise} A promise that is resolved with an {Array} that is a + * tree outline (if it has one) of the PDF. The tree is in the format of: + * [ + * { + * title: string, + * bold: boolean, + * italic: boolean, + * color: rgb array, + * dest: dest obj, + * items: array of more items like this + * }, + * ... + * ]. + */ + getOutline: function PDFDocumentProxy_getOutline() { + return this.transport.getOutline(); + }, + /** + * @return {Promise} A promise that is resolved with an {Object} that has + * info and metadata properties. Info is an {Object} filled with anything + * available in the information dictionary and similarly metadata is a + * {Metadata} object with information from the metadata section of the PDF. + */ + getMetadata: function PDFDocumentProxy_getMetadata() { + return this.transport.getMetadata(); + }, + /** + * @return {Promise} A promise that is resolved with a TypedArray that has + * the raw data from the PDF. + */ + getData: function PDFDocumentProxy_getData() { + return this.transport.getData(); + }, + /** + * @return {Promise} A promise that is resolved when the document's data + * is loaded. It is resolved with an {Object} that contains the length + * property that indicates size of the PDF data in bytes. + */ + getDownloadInfo: function PDFDocumentProxy_getDownloadInfo() { + return this.transport.downloadInfoCapability.promise; + }, + /** + * @return {Promise} A promise this is resolved with current stats about + * document structures (see {@link PDFDocumentStats}). + */ + getStats: function PDFDocumentProxy_getStats() { + return this.transport.getStats(); + }, + /** + * Cleans up resources allocated by the document, e.g. created @font-face. + */ + cleanup: function PDFDocumentProxy_cleanup() { + this.transport.startCleanup(); + }, + /** + * Destroys current document instance and terminates worker. + */ + destroy: function PDFDocumentProxy_destroy() { + this.transport.destroy(); + } + }; + return PDFDocumentProxy; +})(); + +/** + * Page text content. + * + * @typedef {Object} TextContent + * @property {array} items - array of {@link TextItem} + * @property {Object} styles - {@link TextStyles} objects, indexed by font + * name. + */ + +/** + * Page text content part. + * + * @typedef {Object} TextItem + * @property {string} str - text content. + * @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'. + * @property {array} transform - transformation matrix. + * @property {number} width - width in device space. + * @property {number} height - height in device space. + * @property {string} fontName - font name used by pdf.js for converted font. + */ + +/** + * Text style. + * + * @typedef {Object} TextStyle + * @property {number} ascent - font ascent. + * @property {number} descent - font descent. + * @property {boolean} vertical - text is in vertical mode. + * @property {string} fontFamily - possible font family + */ + +/** + * Page render parameters. + * + * @typedef {Object} RenderParameters + * @property {Object} canvasContext - A 2D context of a DOM Canvas object. + * @property {PDFJS.PageViewport} viewport - Rendering viewport obtained by + * calling of PDFPage.getViewport method. + * @property {string} intent - Rendering intent, can be 'display' or 'print' + * (default value is 'display'). + * @property {Object} imageLayer - (optional) An object that has beginLayout, + * endLayout and appendImage functions. + * @property {function} continueCallback - (deprecated) A function that will be + * called each time the rendering is paused. To continue + * rendering call the function that is the first argument + * to the callback. + */ + +/** + * PDF page operator list. + * + * @typedef {Object} PDFOperatorList + * @property {Array} fnArray - Array containing the operator functions. + * @property {Array} argsArray - Array containing the arguments of the + * functions. + */ + +/** + * Proxy to a PDFPage in the worker thread. + * @class + */ +var PDFPageProxy = (function PDFPageProxyClosure() { + function PDFPageProxy(pageIndex, pageInfo, transport) { + this.pageIndex = pageIndex; + this.pageInfo = pageInfo; + this.transport = transport; + this.stats = new StatTimer(); + this.stats.enabled = !!globalScope.PDFJS.enableStats; + this.commonObjs = transport.commonObjs; + this.objs = new PDFObjects(); + this.cleanupAfterRender = false; + this.pendingDestroy = false; + this.intentStates = {}; + } + PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ { + /** + * @return {number} Page number of the page. First page is 1. + */ + get pageNumber() { + return this.pageIndex + 1; + }, + /** + * @return {number} The number of degrees the page is rotated clockwise. + */ + get rotate() { + return this.pageInfo.rotate; + }, + /** + * @return {Object} The reference that points to this page. It has 'num' and + * 'gen' properties. + */ + get ref() { + return this.pageInfo.ref; + }, + /** + * @return {Array} An array of the visible portion of the PDF page in the + * user space units - [x1, y1, x2, y2]. + */ + get view() { + return this.pageInfo.view; + }, + /** + * @param {number} scale The desired scale of the viewport. + * @param {number} rotate Degrees to rotate the viewport. If omitted this + * defaults to the page rotation. + * @return {PDFJS.PageViewport} Contains 'width' and 'height' properties + * along with transforms required for rendering. + */ + getViewport: function PDFPageProxy_getViewport(scale, rotate) { + if (arguments.length < 2) { + rotate = this.rotate; + } + return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0); + }, + /** + * @return {Promise} A promise that is resolved with an {Array} of the + * annotation objects. + */ + getAnnotations: function PDFPageProxy_getAnnotations() { + if (this.annotationsPromise) { + return this.annotationsPromise; + } + + var promise = this.transport.getAnnotations(this.pageIndex); + this.annotationsPromise = promise; + return promise; + }, + /** + * Begins the process of rendering a page to the desired context. + * @param {RenderParameters} params Page render parameters. + * @return {RenderTask} An object that contains the promise, which + * is resolved when the page finishes rendering. + */ + render: function PDFPageProxy_render(params) { + var stats = this.stats; + stats.time('Overall'); + + // If there was a pending destroy cancel it so no cleanup happens during + // this call to render. + this.pendingDestroy = false; + + var renderingIntent = (params.intent === 'print' ? 'print' : 'display'); + + if (!this.intentStates[renderingIntent]) { + this.intentStates[renderingIntent] = {}; + } + var intentState = this.intentStates[renderingIntent]; + + // If there's no displayReadyCapability yet, then the operatorList + // was never requested before. Make the request and create the promise. + if (!intentState.displayReadyCapability) { + intentState.receivingOperatorList = true; + intentState.displayReadyCapability = createPromiseCapability(); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false + }; + + this.stats.time('Page Request'); + this.transport.messageHandler.send('RenderPageRequest', { + pageIndex: this.pageNumber - 1, + intent: renderingIntent + }); + } + + var internalRenderTask = new InternalRenderTask(complete, params, + this.objs, + this.commonObjs, + intentState.operatorList, + this.pageNumber); + internalRenderTask.useRequestAnimationFrame = renderingIntent !== 'print'; + if (!intentState.renderTasks) { + intentState.renderTasks = []; + } + intentState.renderTasks.push(internalRenderTask); + var renderTask = internalRenderTask.task; + + // Obsolete parameter support + if (params.continueCallback) { + renderTask.onContinue = params.continueCallback; + } + + var self = this; + intentState.displayReadyCapability.promise.then( + function pageDisplayReadyPromise(transparency) { + if (self.pendingDestroy) { + complete(); + return; + } + stats.time('Rendering'); + internalRenderTask.initalizeGraphics(transparency); + internalRenderTask.operatorListChanged(); + }, + function pageDisplayReadPromiseError(reason) { + complete(reason); + } + ); + + function complete(error) { + var i = intentState.renderTasks.indexOf(internalRenderTask); + if (i >= 0) { + intentState.renderTasks.splice(i, 1); + } + + if (self.cleanupAfterRender) { + self.pendingDestroy = true; + } + self._tryDestroy(); + + if (error) { + internalRenderTask.capability.reject(error); + } else { + internalRenderTask.capability.resolve(); + } + stats.timeEnd('Rendering'); + stats.timeEnd('Overall'); + } + + return renderTask; + }, + + /** + * @return {Promise} A promise resolved with an {@link PDFOperatorList} + * object that represents page's operator list. + */ + getOperatorList: function PDFPageProxy_getOperatorList() { + function operatorListChanged() { + if (intentState.operatorList.lastChunk) { + intentState.opListReadCapability.resolve(intentState.operatorList); + } + } + + var renderingIntent = 'oplist'; + if (!this.intentStates[renderingIntent]) { + this.intentStates[renderingIntent] = {}; + } + var intentState = this.intentStates[renderingIntent]; + + if (!intentState.opListReadCapability) { + var opListTask = {}; + opListTask.operatorListChanged = operatorListChanged; + intentState.receivingOperatorList = true; + intentState.opListReadCapability = createPromiseCapability(); + intentState.renderTasks = []; + intentState.renderTasks.push(opListTask); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false + }; + + this.transport.messageHandler.send('RenderPageRequest', { + pageIndex: this.pageIndex, + intent: renderingIntent + }); + } + return intentState.opListReadCapability.promise; + }, + + /** + * @return {Promise} That is resolved a {@link TextContent} + * object that represent the page text content. + */ + getTextContent: function PDFPageProxy_getTextContent() { + return this.transport.messageHandler.sendWithPromise('GetTextContent', { + pageIndex: this.pageNumber - 1 + }); + }, + /** + * Destroys resources allocated by the page. + */ + destroy: function PDFPageProxy_destroy() { + this.pendingDestroy = true; + this._tryDestroy(); + }, + /** + * For internal use only. Attempts to clean up if rendering is in a state + * where that's possible. + * @ignore + */ + _tryDestroy: function PDFPageProxy__destroy() { + if (!this.pendingDestroy || + Object.keys(this.intentStates).some(function(intent) { + var intentState = this.intentStates[intent]; + return (intentState.renderTasks.length !== 0 || + intentState.receivingOperatorList); + }, this)) { + return; + } + + Object.keys(this.intentStates).forEach(function(intent) { + delete this.intentStates[intent]; + }, this); + this.objs.clear(); + this.annotationsPromise = null; + this.pendingDestroy = false; + }, + /** + * For internal use only. + * @ignore + */ + _startRenderPage: function PDFPageProxy_startRenderPage(transparency, + intent) { + var intentState = this.intentStates[intent]; + // TODO Refactor RenderPageRequest to separate rendering + // and operator list logic + if (intentState.displayReadyCapability) { + intentState.displayReadyCapability.resolve(transparency); + } + }, + /** + * For internal use only. + * @ignore + */ + _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk, + intent) { + var intentState = this.intentStates[intent]; + var i, ii; + // Add the new chunk to the current operator list. + for (i = 0, ii = operatorListChunk.length; i < ii; i++) { + intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]); + intentState.operatorList.argsArray.push( + operatorListChunk.argsArray[i]); + } + intentState.operatorList.lastChunk = operatorListChunk.lastChunk; + + // Notify all the rendering tasks there are more operators to be consumed. + for (i = 0; i < intentState.renderTasks.length; i++) { + intentState.renderTasks[i].operatorListChanged(); + } + + if (operatorListChunk.lastChunk) { + intentState.receivingOperatorList = false; + this._tryDestroy(); + } + } + }; + return PDFPageProxy; +})(); + +/** + * For internal use only. + * @ignore + */ +var WorkerTransport = (function WorkerTransportClosure() { + function WorkerTransport(workerInitializedCapability, pdfDataRangeTransport) { + this.pdfDataRangeTransport = pdfDataRangeTransport; + this.workerInitializedCapability = workerInitializedCapability; + this.commonObjs = new PDFObjects(); + + this.loadingTask = null; + + this.pageCache = []; + this.pagePromises = []; + this.downloadInfoCapability = createPromiseCapability(); + + // If worker support isn't disabled explicit and the browser has worker + // support, create a new web worker and test if it/the browser fullfills + // all requirements to run parts of pdf.js in a web worker. + // Right now, the requirement is, that an Uint8Array is still an Uint8Array + // as it arrives on the worker. Chrome added this with version 15. + if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') { + var workerSrc = PDFJS.workerSrc; + if (!workerSrc) { + error('No PDFJS.workerSrc specified'); + } + + try { + // Some versions of FF can't create a worker on localhost, see: + // https://bugzilla.mozilla.org/show_bug.cgi?id=683280 + var worker = new Worker(workerSrc); + var messageHandler = new MessageHandler('main', worker); + this.messageHandler = messageHandler; + + messageHandler.on('test', function transportTest(data) { + var supportTypedArray = data && data.supportTypedArray; + if (supportTypedArray) { + this.worker = worker; + if (!data.supportTransfers) { + PDFJS.postMessageTransfers = false; + } + this.setupMessageHandler(messageHandler); + workerInitializedCapability.resolve(); + } else { + this.setupFakeWorker(); + } + }.bind(this)); + + var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]); + // Some versions of Opera throw a DATA_CLONE_ERR on serializing the + // typed array. Also, checking if we can use transfers. + try { + messageHandler.send('test', testObj, [testObj.buffer]); + } catch (ex) { + info('Cannot use postMessage transfers'); + testObj[0] = 0; + messageHandler.send('test', testObj); + } + return; + } catch (e) { + info('The worker has been disabled.'); + } + } + // Either workers are disabled, not supported or have thrown an exception. + // Thus, we fallback to a faked worker. + this.setupFakeWorker(); + } + WorkerTransport.prototype = { + destroy: function WorkerTransport_destroy() { + this.pageCache = []; + this.pagePromises = []; + var self = this; + this.messageHandler.sendWithPromise('Terminate', null).then(function () { + FontLoader.clear(); + if (self.worker) { + self.worker.terminate(); + } + }); + }, + + setupFakeWorker: function WorkerTransport_setupFakeWorker() { + globalScope.PDFJS.disableWorker = true; + + if (!PDFJS.fakeWorkerFilesLoadedCapability) { + PDFJS.fakeWorkerFilesLoadedCapability = createPromiseCapability(); + // In the developer build load worker_loader which in turn loads all the + // other files and resolves the promise. In production only the + // pdf.worker.js file is needed. + Util.loadScript(PDFJS.workerSrc, function() { + PDFJS.fakeWorkerFilesLoadedCapability.resolve(); + }); + } + PDFJS.fakeWorkerFilesLoadedCapability.promise.then(function () { + warn('Setting up fake worker.'); + // If we don't use a worker, just post/sendMessage to the main thread. + var fakeWorker = { + postMessage: function WorkerTransport_postMessage(obj) { + fakeWorker.onmessage({data: obj}); + }, + terminate: function WorkerTransport_terminate() {} + }; + + var messageHandler = new MessageHandler('main', fakeWorker); + this.setupMessageHandler(messageHandler); + + // If the main thread is our worker, setup the handling for the messages + // the main thread sends to it self. + PDFJS.WorkerMessageHandler.setup(messageHandler); + + this.workerInitializedCapability.resolve(); + }.bind(this)); + }, + + setupMessageHandler: + function WorkerTransport_setupMessageHandler(messageHandler) { + this.messageHandler = messageHandler; + + function updatePassword(password) { + messageHandler.send('UpdatePassword', password); + } + + var pdfDataRangeTransport = this.pdfDataRangeTransport; + if (pdfDataRangeTransport) { + pdfDataRangeTransport.addRangeListener(function(begin, chunk) { + messageHandler.send('OnDataRange', { + begin: begin, + chunk: chunk + }); + }); + + pdfDataRangeTransport.addProgressListener(function(loaded) { + messageHandler.send('OnDataProgress', { + loaded: loaded + }); + }); + + pdfDataRangeTransport.addProgressiveReadListener(function(chunk) { + messageHandler.send('OnDataRange', { + chunk: chunk + }); + }); + + messageHandler.on('RequestDataRange', + function transportDataRange(data) { + pdfDataRangeTransport.requestDataRange(data.begin, data.end); + }, this); + } + + messageHandler.on('GetDoc', function transportDoc(data) { + var pdfInfo = data.pdfInfo; + this.numPages = data.pdfInfo.numPages; + var pdfDocument = new PDFDocumentProxy(pdfInfo, this); + this.pdfDocument = pdfDocument; + this.loadingTask._capability.resolve(pdfDocument); + }, this); + + messageHandler.on('NeedPassword', + function transportNeedPassword(exception) { + var loadingTask = this.loadingTask; + if (loadingTask.onPassword) { + return loadingTask.onPassword(updatePassword, + PasswordResponses.NEED_PASSWORD); + } + loadingTask._capability.reject( + new PasswordException(exception.message, exception.code)); + }, this); + + messageHandler.on('IncorrectPassword', + function transportIncorrectPassword(exception) { + var loadingTask = this.loadingTask; + if (loadingTask.onPassword) { + return loadingTask.onPassword(updatePassword, + PasswordResponses.INCORRECT_PASSWORD); + } + loadingTask._capability.reject( + new PasswordException(exception.message, exception.code)); + }, this); + + messageHandler.on('InvalidPDF', function transportInvalidPDF(exception) { + this.loadingTask._capability.reject( + new InvalidPDFException(exception.message)); + }, this); + + messageHandler.on('MissingPDF', function transportMissingPDF(exception) { + this.loadingTask._capability.reject( + new MissingPDFException(exception.message)); + }, this); + + messageHandler.on('UnexpectedResponse', + function transportUnexpectedResponse(exception) { + this.loadingTask._capability.reject( + new UnexpectedResponseException(exception.message, exception.status)); + }, this); + + messageHandler.on('UnknownError', + function transportUnknownError(exception) { + this.loadingTask._capability.reject( + new UnknownErrorException(exception.message, exception.details)); + }, this); + + messageHandler.on('DataLoaded', function transportPage(data) { + this.downloadInfoCapability.resolve(data); + }, this); + + messageHandler.on('PDFManagerReady', function transportPage(data) { + if (this.pdfDataRangeTransport) { + this.pdfDataRangeTransport.transportReady(); + } + }, this); + + messageHandler.on('StartRenderPage', function transportRender(data) { + var page = this.pageCache[data.pageIndex]; + + page.stats.timeEnd('Page Request'); + page._startRenderPage(data.transparency, data.intent); + }, this); + + messageHandler.on('RenderPageChunk', function transportRender(data) { + var page = this.pageCache[data.pageIndex]; + + page._renderPageChunk(data.operatorList, data.intent); + }, this); + + messageHandler.on('commonobj', function transportObj(data) { + var id = data[0]; + var type = data[1]; + if (this.commonObjs.hasData(id)) { + return; + } + + switch (type) { + case 'Font': + var exportedData = data[2]; + + var font; + if ('error' in exportedData) { + var error = exportedData.error; + warn('Error during font loading: ' + error); + this.commonObjs.resolve(id, error); + break; + } else { + font = new FontFaceObject(exportedData); + } + + FontLoader.bind( + [font], + function fontReady(fontObjs) { + this.commonObjs.resolve(id, font); + }.bind(this) + ); + break; + case 'FontPath': + this.commonObjs.resolve(id, data[2]); + break; + default: + error('Got unknown common object type ' + type); + } + }, this); + + messageHandler.on('obj', function transportObj(data) { + var id = data[0]; + var pageIndex = data[1]; + var type = data[2]; + var pageProxy = this.pageCache[pageIndex]; + var imageData; + if (pageProxy.objs.hasData(id)) { + return; + } + + switch (type) { + case 'JpegStream': + imageData = data[3]; + loadJpegStream(id, imageData, pageProxy.objs); + break; + case 'Image': + imageData = data[3]; + pageProxy.objs.resolve(id, imageData); + + // heuristics that will allow not to store large data + var MAX_IMAGE_SIZE_TO_STORE = 8000000; + if (imageData && 'data' in imageData && + imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) { + pageProxy.cleanupAfterRender = true; + } + break; + default: + error('Got unknown object type ' + type); + } + }, this); + + messageHandler.on('DocProgress', function transportDocProgress(data) { + var loadingTask = this.loadingTask; + if (loadingTask.onProgress) { + loadingTask.onProgress({ + loaded: data.loaded, + total: data.total + }); + } + }, this); + + messageHandler.on('PageError', function transportError(data) { + var page = this.pageCache[data.pageNum - 1]; + var intentState = page.intentStates[data.intent]; + if (intentState.displayReadyCapability) { + intentState.displayReadyCapability.reject(data.error); + } else { + error(data.error); + } + }, this); + + messageHandler.on('JpegDecode', function(data) { + var imageUrl = data[0]; + var components = data[1]; + if (components !== 3 && components !== 1) { + return Promise.reject( + new Error('Only 3 components or 1 component can be returned')); + } + + return new Promise(function (resolve, reject) { + var img = new Image(); + img.onload = function () { + var width = img.width; + var height = img.height; + var size = width * height; + var rgbaLength = size * 4; + var buf = new Uint8Array(size * components); + var tmpCanvas = createScratchCanvas(width, height); + var tmpCtx = tmpCanvas.getContext('2d'); + tmpCtx.drawImage(img, 0, 0); + var data = tmpCtx.getImageData(0, 0, width, height).data; + var i, j; + + if (components === 3) { + for (i = 0, j = 0; i < rgbaLength; i += 4, j += 3) { + buf[j] = data[i]; + buf[j + 1] = data[i + 1]; + buf[j + 2] = data[i + 2]; + } + } else if (components === 1) { + for (i = 0, j = 0; i < rgbaLength; i += 4, j++) { + buf[j] = data[i]; + } + } + resolve({ data: buf, width: width, height: height}); + }; + img.onerror = function () { + reject(new Error('JpegDecode failed to load image')); + }; + img.src = imageUrl; + }); + }); + }, + + fetchDocument: function WorkerTransport_fetchDocument(loadingTask, source) { + this.loadingTask = loadingTask; + + source.disableAutoFetch = PDFJS.disableAutoFetch; + source.disableStream = PDFJS.disableStream; + source.chunkedViewerLoading = !!this.pdfDataRangeTransport; + if (this.pdfDataRangeTransport) { + source.length = this.pdfDataRangeTransport.length; + source.initialData = this.pdfDataRangeTransport.initialData; + } + this.messageHandler.send('GetDocRequest', { + source: source, + disableRange: PDFJS.disableRange, + maxImageSize: PDFJS.maxImageSize, + cMapUrl: PDFJS.cMapUrl, + cMapPacked: PDFJS.cMapPacked, + disableFontFace: PDFJS.disableFontFace, + disableCreateObjectURL: PDFJS.disableCreateObjectURL, + verbosity: PDFJS.verbosity + }); + }, + + getData: function WorkerTransport_getData() { + return this.messageHandler.sendWithPromise('GetData', null); + }, + + getPage: function WorkerTransport_getPage(pageNumber, capability) { + if (pageNumber <= 0 || pageNumber > this.numPages || + (pageNumber|0) !== pageNumber) { + return Promise.reject(new Error('Invalid page request')); + } + + var pageIndex = pageNumber - 1; + if (pageIndex in this.pagePromises) { + return this.pagePromises[pageIndex]; + } + var promise = this.messageHandler.sendWithPromise('GetPage', { + pageIndex: pageIndex + }).then(function (pageInfo) { + var page = new PDFPageProxy(pageIndex, pageInfo, this); + this.pageCache[pageIndex] = page; + return page; + }.bind(this)); + this.pagePromises[pageIndex] = promise; + return promise; + }, + + getPageIndex: function WorkerTransport_getPageIndexByRef(ref) { + return this.messageHandler.sendWithPromise('GetPageIndex', { ref: ref }); + }, + + getAnnotations: function WorkerTransport_getAnnotations(pageIndex) { + return this.messageHandler.sendWithPromise('GetAnnotations', + { pageIndex: pageIndex }); + }, + + getDestinations: function WorkerTransport_getDestinations() { + return this.messageHandler.sendWithPromise('GetDestinations', null); + }, + + getDestination: function WorkerTransport_getDestination(id) { + return this.messageHandler.sendWithPromise('GetDestination', { id: id } ); + }, + + getAttachments: function WorkerTransport_getAttachments() { + return this.messageHandler.sendWithPromise('GetAttachments', null); + }, + + getJavaScript: function WorkerTransport_getJavaScript() { + return this.messageHandler.sendWithPromise('GetJavaScript', null); + }, + + getOutline: function WorkerTransport_getOutline() { + return this.messageHandler.sendWithPromise('GetOutline', null); + }, + + getMetadata: function WorkerTransport_getMetadata() { + return this.messageHandler.sendWithPromise('GetMetadata', null). + then(function transportMetadata(results) { + return { + info: results[0], + metadata: (results[1] ? new PDFJS.Metadata(results[1]) : null) + }; + }); + }, + + getStats: function WorkerTransport_getStats() { + return this.messageHandler.sendWithPromise('GetStats', null); + }, + + startCleanup: function WorkerTransport_startCleanup() { + this.messageHandler.sendWithPromise('Cleanup', null). + then(function endCleanup() { + for (var i = 0, ii = this.pageCache.length; i < ii; i++) { + var page = this.pageCache[i]; + if (page) { + page.destroy(); + } + } + this.commonObjs.clear(); + FontLoader.clear(); + }.bind(this)); + } + }; + return WorkerTransport; + +})(); + +/** + * A PDF document and page is built of many objects. E.g. there are objects + * for fonts, images, rendering code and such. These objects might get processed + * inside of a worker. The `PDFObjects` implements some basic functions to + * manage these objects. + * @ignore + */ +var PDFObjects = (function PDFObjectsClosure() { + function PDFObjects() { + this.objs = {}; + } + + PDFObjects.prototype = { + /** + * Internal function. + * Ensures there is an object defined for `objId`. + */ + ensureObj: function PDFObjects_ensureObj(objId) { + if (this.objs[objId]) { + return this.objs[objId]; + } + + var obj = { + capability: createPromiseCapability(), + data: null, + resolved: false + }; + this.objs[objId] = obj; + + return obj; + }, + + /** + * If called *without* callback, this returns the data of `objId` but the + * object needs to be resolved. If it isn't, this function throws. + * + * If called *with* a callback, the callback is called with the data of the + * object once the object is resolved. That means, if you call this + * function and the object is already resolved, the callback gets called + * right away. + */ + get: function PDFObjects_get(objId, callback) { + // If there is a callback, then the get can be async and the object is + // not required to be resolved right now + if (callback) { + this.ensureObj(objId).capability.promise.then(callback); + return null; + } + + // If there isn't a callback, the user expects to get the resolved data + // directly. + var obj = this.objs[objId]; + + // If there isn't an object yet or the object isn't resolved, then the + // data isn't ready yet! + if (!obj || !obj.resolved) { + error('Requesting object that isn\'t resolved yet ' + objId); + } + + return obj.data; + }, + + /** + * Resolves the object `objId` with optional `data`. + */ + resolve: function PDFObjects_resolve(objId, data) { + var obj = this.ensureObj(objId); + + obj.resolved = true; + obj.data = data; + obj.capability.resolve(data); + }, + + isResolved: function PDFObjects_isResolved(objId) { + var objs = this.objs; + + if (!objs[objId]) { + return false; + } else { + return objs[objId].resolved; + } + }, + + hasData: function PDFObjects_hasData(objId) { + return this.isResolved(objId); + }, + + /** + * Returns the data of `objId` if object exists, null otherwise. + */ + getData: function PDFObjects_getData(objId) { + var objs = this.objs; + if (!objs[objId] || !objs[objId].resolved) { + return null; + } else { + return objs[objId].data; + } + }, + + clear: function PDFObjects_clear() { + this.objs = {}; + } + }; + return PDFObjects; +})(); + +/** + * Allows controlling of the rendering tasks. + * @class + */ +var RenderTask = (function RenderTaskClosure() { + function RenderTask(internalRenderTask) { + this._internalRenderTask = internalRenderTask; + + /** + * Callback for incremental rendering -- a function that will be called + * each time the rendering is paused. To continue rendering call the + * function that is the first argument to the callback. + * @type {function} + */ + this.onContinue = null; + } + + RenderTask.prototype = /** @lends RenderTask.prototype */ { + /** + * Promise for rendering task completion. + * @return {Promise} + */ + get promise() { + return this._internalRenderTask.capability.promise; + }, + + /** + * Cancels the rendering task. If the task is currently rendering it will + * not be cancelled until graphics pauses with a timeout. The promise that + * this object extends will resolved when cancelled. + */ + cancel: function RenderTask_cancel() { + this._internalRenderTask.cancel(); + }, + + /** + * Registers callbacks to indicate the rendering task completion. + * + * @param {function} onFulfilled The callback for the rendering completion. + * @param {function} onRejected The callback for the rendering failure. + * @return {Promise} A promise that is resolved after the onFulfilled or + * onRejected callback. + */ + then: function RenderTask_then(onFulfilled, onRejected) { + return this.promise.then.apply(this.promise, arguments); + } + }; + + return RenderTask; +})(); + +/** + * For internal use only. + * @ignore + */ +var InternalRenderTask = (function InternalRenderTaskClosure() { + + function InternalRenderTask(callback, params, objs, commonObjs, operatorList, + pageNumber) { + this.callback = callback; + this.params = params; + this.objs = objs; + this.commonObjs = commonObjs; + this.operatorListIdx = null; + this.operatorList = operatorList; + this.pageNumber = pageNumber; + this.running = false; + this.graphicsReadyCallback = null; + this.graphicsReady = false; + this.useRequestAnimationFrame = false; + this.cancelled = false; + this.capability = createPromiseCapability(); + this.task = new RenderTask(this); + // caching this-bound methods + this._continueBound = this._continue.bind(this); + this._scheduleNextBound = this._scheduleNext.bind(this); + this._nextBound = this._next.bind(this); + } + + InternalRenderTask.prototype = { + + initalizeGraphics: + function InternalRenderTask_initalizeGraphics(transparency) { + + if (this.cancelled) { + return; + } + if (PDFJS.pdfBug && 'StepperManager' in globalScope && + globalScope.StepperManager.enabled) { + this.stepper = globalScope.StepperManager.create(this.pageNumber - 1); + this.stepper.init(this.operatorList); + this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint(); + } + + var params = this.params; + this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs, + this.objs, params.imageLayer); + + this.gfx.beginDrawing(params.viewport, transparency); + this.operatorListIdx = 0; + this.graphicsReady = true; + if (this.graphicsReadyCallback) { + this.graphicsReadyCallback(); + } + }, + + cancel: function InternalRenderTask_cancel() { + this.running = false; + this.cancelled = true; + this.callback('cancelled'); + }, + + operatorListChanged: function InternalRenderTask_operatorListChanged() { + if (!this.graphicsReady) { + if (!this.graphicsReadyCallback) { + this.graphicsReadyCallback = this._continueBound; + } + return; + } + + if (this.stepper) { + this.stepper.updateOperatorList(this.operatorList); + } + + if (this.running) { + return; + } + this._continue(); + }, + + _continue: function InternalRenderTask__continue() { + this.running = true; + if (this.cancelled) { + return; + } + if (this.task.onContinue) { + this.task.onContinue.call(this.task, this._scheduleNextBound); + } else { + this._scheduleNext(); + } + }, + + _scheduleNext: function InternalRenderTask__scheduleNext() { + if (this.useRequestAnimationFrame) { + window.requestAnimationFrame(this._nextBound); + } else { + Promise.resolve(undefined).then(this._nextBound); + } + }, + + _next: function InternalRenderTask__next() { + if (this.cancelled) { + return; + } + this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, + this.operatorListIdx, + this._continueBound, + this.stepper); + if (this.operatorListIdx === this.operatorList.argsArray.length) { + this.running = false; + if (this.operatorList.lastChunk) { + this.gfx.endDrawing(); + this.callback(); + } + } + } + + }; + + return InternalRenderTask; +})(); + + +var Metadata = PDFJS.Metadata = (function MetadataClosure() { + function fixMetadata(meta) { + return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) { + var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, + function(code, d1, d2, d3) { + return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1); + }); + var chars = ''; + for (var i = 0; i < bytes.length; i += 2) { + var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1); + chars += code >= 32 && code < 127 && code !== 60 && code !== 62 && + code !== 38 && false ? String.fromCharCode(code) : + '&#x' + (0x10000 + code).toString(16).substring(1) + ';'; + } + return '>' + chars; + }); + } + + function Metadata(meta) { + if (typeof meta === 'string') { + // Ghostscript produces invalid metadata + meta = fixMetadata(meta); + + var parser = new DOMParser(); + meta = parser.parseFromString(meta, 'application/xml'); + } else if (!(meta instanceof Document)) { + error('Metadata: Invalid metadata object'); + } + + this.metaDocument = meta; + this.metadata = {}; + this.parse(); + } + + Metadata.prototype = { + parse: function Metadata_parse() { + var doc = this.metaDocument; + var rdf = doc.documentElement; + + if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in + rdf = rdf.firstChild; + while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') { + rdf = rdf.nextSibling; + } + } + + var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null; + if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) { + return; + } + + var children = rdf.childNodes, desc, entry, name, i, ii, length, iLength; + for (i = 0, length = children.length; i < length; i++) { + desc = children[i]; + if (desc.nodeName.toLowerCase() !== 'rdf:description') { + continue; + } + + for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) { + if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') { + entry = desc.childNodes[ii]; + name = entry.nodeName.toLowerCase(); + this.metadata[name] = entry.textContent.trim(); + } + } + } + }, + + get: function Metadata_get(name) { + return this.metadata[name] || null; + }, + + has: function Metadata_has(name) { + return typeof this.metadata[name] !== 'undefined'; + } + }; + + return Metadata; +})(); + + +// contexts store most of the state we need natively. +// However, PDF needs a bit more state, which we store here. + +// Minimal font size that would be used during canvas fillText operations. +var MIN_FONT_SIZE = 16; +// Maximum font size that would be used during canvas fillText operations. +var MAX_FONT_SIZE = 100; +var MAX_GROUP_SIZE = 4096; + +// Heuristic value used when enforcing minimum line widths. +var MIN_WIDTH_FACTOR = 0.65; + +var COMPILE_TYPE3_GLYPHS = true; +var MAX_SIZE_TO_COMPILE = 1000; + +var FULL_CHUNK_HEIGHT = 16; + +function createScratchCanvas(width, height) { + var canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + return canvas; +} + +function addContextCurrentTransform(ctx) { + // If the context doesn't expose a `mozCurrentTransform`, add a JS based one. + if (!ctx.mozCurrentTransform) { + ctx._originalSave = ctx.save; + ctx._originalRestore = ctx.restore; + ctx._originalRotate = ctx.rotate; + ctx._originalScale = ctx.scale; + ctx._originalTranslate = ctx.translate; + ctx._originalTransform = ctx.transform; + ctx._originalSetTransform = ctx.setTransform; + + ctx._transformMatrix = ctx._transformMatrix || [1, 0, 0, 1, 0, 0]; + ctx._transformStack = []; + + Object.defineProperty(ctx, 'mozCurrentTransform', { + get: function getCurrentTransform() { + return this._transformMatrix; + } + }); + + Object.defineProperty(ctx, 'mozCurrentTransformInverse', { + get: function getCurrentTransformInverse() { + // Calculation done using WolframAlpha: + // http://www.wolframalpha.com/input/? + // i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}} + + var m = this._transformMatrix; + var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5]; + + var ad_bc = a * d - b * c; + var bc_ad = b * c - a * d; + + return [ + d / ad_bc, + b / bc_ad, + c / bc_ad, + a / ad_bc, + (d * e - c * f) / bc_ad, + (b * e - a * f) / ad_bc + ]; + } + }); + + ctx.save = function ctxSave() { + var old = this._transformMatrix; + this._transformStack.push(old); + this._transformMatrix = old.slice(0, 6); + + this._originalSave(); + }; + + ctx.restore = function ctxRestore() { + var prev = this._transformStack.pop(); + if (prev) { + this._transformMatrix = prev; + this._originalRestore(); + } + }; + + ctx.translate = function ctxTranslate(x, y) { + var m = this._transformMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + + this._originalTranslate(x, y); + }; + + ctx.scale = function ctxScale(x, y) { + var m = this._transformMatrix; + m[0] = m[0] * x; + m[1] = m[1] * x; + m[2] = m[2] * y; + m[3] = m[3] * y; + + this._originalScale(x, y); + }; + + ctx.transform = function ctxTransform(a, b, c, d, e, f) { + var m = this._transformMatrix; + this._transformMatrix = [ + m[0] * a + m[2] * b, + m[1] * a + m[3] * b, + m[0] * c + m[2] * d, + m[1] * c + m[3] * d, + m[0] * e + m[2] * f + m[4], + m[1] * e + m[3] * f + m[5] + ]; + + ctx._originalTransform(a, b, c, d, e, f); + }; + + ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) { + this._transformMatrix = [a, b, c, d, e, f]; + + ctx._originalSetTransform(a, b, c, d, e, f); + }; + + ctx.rotate = function ctxRotate(angle) { + var cosValue = Math.cos(angle); + var sinValue = Math.sin(angle); + + var m = this._transformMatrix; + this._transformMatrix = [ + m[0] * cosValue + m[2] * sinValue, + m[1] * cosValue + m[3] * sinValue, + m[0] * (-sinValue) + m[2] * cosValue, + m[1] * (-sinValue) + m[3] * cosValue, + m[4], + m[5] + ]; + + this._originalRotate(angle); + }; + } +} + +var CachedCanvases = (function CachedCanvasesClosure() { + var cache = {}; + return { + getCanvas: function CachedCanvases_getCanvas(id, width, height, + trackTransform) { + var canvasEntry; + if (cache[id] !== undefined) { + canvasEntry = cache[id]; + canvasEntry.canvas.width = width; + canvasEntry.canvas.height = height; + // reset canvas transform for emulated mozCurrentTransform, if needed + canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0); + } else { + var canvas = createScratchCanvas(width, height); + var ctx = canvas.getContext('2d'); + if (trackTransform) { + addContextCurrentTransform(ctx); + } + cache[id] = canvasEntry = {canvas: canvas, context: ctx}; + } + return canvasEntry; + }, + clear: function () { + for (var id in cache) { + var canvasEntry = cache[id]; + // Zeroing the width and height causes Firefox to release graphics + // resources immediately, which can greatly reduce memory consumption. + canvasEntry.canvas.width = 0; + canvasEntry.canvas.height = 0; + delete cache[id]; + } + } + }; +})(); + +function compileType3Glyph(imgData) { + var POINT_TO_PROCESS_LIMIT = 1000; + + var width = imgData.width, height = imgData.height; + var i, j, j0, width1 = width + 1; + var points = new Uint8Array(width1 * (height + 1)); + var POINT_TYPES = + new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]); + + // decodes bit-packed mask data + var lineSize = (width + 7) & ~7, data0 = imgData.data; + var data = new Uint8Array(lineSize * height), pos = 0, ii; + for (i = 0, ii = data0.length; i < ii; i++) { + var mask = 128, elem = data0[i]; + while (mask > 0) { + data[pos++] = (elem & mask) ? 0 : 255; + mask >>= 1; + } + } + + // finding iteresting points: every point is located between mask pixels, + // so there will be points of the (width + 1)x(height + 1) grid. Every point + // will have flags assigned based on neighboring mask pixels: + // 4 | 8 + // --P-- + // 2 | 1 + // We are interested only in points with the flags: + // - outside corners: 1, 2, 4, 8; + // - inside corners: 7, 11, 13, 14; + // - and, intersections: 5, 10. + var count = 0; + pos = 0; + if (data[pos] !== 0) { + points[0] = 1; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j] = data[pos] ? 2 : 1; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j] = 2; + ++count; + } + for (i = 1; i < height; i++) { + pos = i * lineSize; + j0 = i * width1; + if (data[pos - lineSize] !== data[pos]) { + points[j0] = data[pos] ? 1 : 8; + ++count; + } + // 'sum' is the position of the current pixel configuration in the 'TYPES' + // array (in order 8-1-2-4, so we can use '>>2' to shift the column). + var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0); + for (j = 1; j < width; j++) { + sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + + (data[pos - lineSize + 1] ? 8 : 0); + if (POINT_TYPES[sum]) { + points[j0 + j] = POINT_TYPES[sum]; + ++count; + } + pos++; + } + if (data[pos - lineSize] !== data[pos]) { + points[j0 + j] = data[pos] ? 2 : 4; + ++count; + } + + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + } + + pos = lineSize * (height - 1); + j0 = i * width1; + if (data[pos] !== 0) { + points[j0] = 8; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j0 + j] = data[pos] ? 4 : 8; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j0 + j] = 4; + ++count; + } + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + + // building outlines + var steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]); + var outlines = []; + for (i = 0; count && i <= height; i++) { + var p = i * width1; + var end = p + width; + while (p < end && !points[p]) { + p++; + } + if (p === end) { + continue; + } + var coords = [p % width1, i]; + + var type = points[p], p0 = p, pp; + do { + var step = steps[type]; + do { + p += step; + } while (!points[p]); + + pp = points[p]; + if (pp !== 5 && pp !== 10) { + // set new direction + type = pp; + // delete mark + points[p] = 0; + } else { // type is 5 or 10, ie, a crossing + // set new direction + type = pp & ((0x33 * type) >> 4); + // set new type for "future hit" + points[p] &= (type >> 2 | type << 2); + } + + coords.push(p % width1); + coords.push((p / width1) | 0); + --count; + } while (p0 !== p); + outlines.push(coords); + --i; + } + + var drawOutline = function(c) { + c.save(); + // the path shall be painted in [0..1]x[0..1] space + c.scale(1 / width, -1 / height); + c.translate(0, -height); + c.beginPath(); + for (var i = 0, ii = outlines.length; i < ii; i++) { + var o = outlines[i]; + c.moveTo(o[0], o[1]); + for (var j = 2, jj = o.length; j < jj; j += 2) { + c.lineTo(o[j], o[j+1]); + } + } + c.fill(); + c.beginPath(); + c.restore(); + }; + + return drawOutline; +} + +var CanvasExtraState = (function CanvasExtraStateClosure() { + function CanvasExtraState(old) { + // Are soft masks and alpha values shapes or opacities? + this.alphaIsShape = false; + this.fontSize = 0; + this.fontSizeScale = 1; + this.textMatrix = IDENTITY_MATRIX; + this.textMatrixScale = 1; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.leading = 0; + // Current point (in user coordinates) + this.x = 0; + this.y = 0; + // Start of text line (in text coordinates) + this.lineX = 0; + this.lineY = 0; + // Character and word spacing + this.charSpacing = 0; + this.wordSpacing = 0; + this.textHScale = 1; + this.textRenderingMode = TextRenderingMode.FILL; + this.textRise = 0; + // Default fore and background colors + this.fillColor = '#000000'; + this.strokeColor = '#000000'; + this.patternFill = false; + // Note: fill alpha applies to all non-stroking operations + this.fillAlpha = 1; + this.strokeAlpha = 1; + this.lineWidth = 1; + this.activeSMask = null; // nonclonable field (see the save method below) + + this.old = old; + } + + CanvasExtraState.prototype = { + clone: function CanvasExtraState_clone() { + return Object.create(this); + }, + setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) { + this.x = x; + this.y = y; + } + }; + return CanvasExtraState; +})(); + +var CanvasGraphics = (function CanvasGraphicsClosure() { + // Defines the time the executeOperatorList is going to be executing + // before it stops and shedules a continue of execution. + var EXECUTION_TIME = 15; + // Defines the number of steps before checking the execution time + var EXECUTION_STEPS = 10; + + function CanvasGraphics(canvasCtx, commonObjs, objs, imageLayer) { + this.ctx = canvasCtx; + this.current = new CanvasExtraState(); + this.stateStack = []; + this.pendingClip = null; + this.pendingEOFill = false; + this.res = null; + this.xobjs = null; + this.commonObjs = commonObjs; + this.objs = objs; + this.imageLayer = imageLayer; + this.groupStack = []; + this.processingType3 = null; + // Patterns are painted relative to the initial page/form transform, see pdf + // spec 8.7.2 NOTE 1. + this.baseTransform = null; + this.baseTransformStack = []; + this.groupLevel = 0; + this.smaskStack = []; + this.smaskCounter = 0; + this.tempSMask = null; + if (canvasCtx) { + // NOTE: if mozCurrentTransform is polyfilled, then the current state of + // the transformation must already be set in canvasCtx._transformMatrix. + addContextCurrentTransform(canvasCtx); + } + this.cachedGetSinglePixelWidth = null; + } + + function putBinaryImageData(ctx, imgData) { + if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) { + ctx.putImageData(imgData, 0, 0); + return; + } + + // Put the image data to the canvas in chunks, rather than putting the + // whole image at once. This saves JS memory, because the ImageData object + // is smaller. It also possibly saves C++ memory within the implementation + // of putImageData(). (E.g. in Firefox we make two short-lived copies of + // the data passed to putImageData()). |n| shouldn't be too small, however, + // because too many putImageData() calls will slow things down. + // + // Note: as written, if the last chunk is partial, the putImageData() call + // will (conceptually) put pixels past the bounds of the canvas. But + // that's ok; any such pixels are ignored. + + var height = imgData.height, width = imgData.width; + var partialChunkHeight = height % FULL_CHUNK_HEIGHT; + var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + + var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + var srcPos = 0, destPos; + var src = imgData.data; + var dest = chunkImgData.data; + var i, j, thisChunkHeight, elemsInThisChunk; + + // There are multiple forms in which the pixel data can be passed, and + // imgData.kind tells us which one this is. + if (imgData.kind === ImageKind.GRAYSCALE_1BPP) { + // Grayscale, 1 bit per pixel (i.e. black-and-white). + var srcLength = src.byteLength; + var dest32 = PDFJS.hasCanvasTypedArrays ? new Uint32Array(dest.buffer) : + new Uint32ArrayView(dest); + var dest32DataLength = dest32.length; + var fullSrcDiff = (width + 7) >> 3; + var white = 0xFFFFFFFF; + var black = (PDFJS.isLittleEndian || !PDFJS.hasCanvasTypedArrays) ? + 0xFF000000 : 0x000000FF; + for (i = 0; i < totalChunks; i++) { + thisChunkHeight = + (i < fullChunks) ? FULL_CHUNK_HEIGHT : partialChunkHeight; + destPos = 0; + for (j = 0; j < thisChunkHeight; j++) { + var srcDiff = srcLength - srcPos; + var k = 0; + var kEnd = (srcDiff > fullSrcDiff) ? width : srcDiff * 8 - 7; + var kEndUnrolled = kEnd & ~7; + var mask = 0; + var srcByte = 0; + for (; k < kEndUnrolled; k += 8) { + srcByte = src[srcPos++]; + dest32[destPos++] = (srcByte & 128) ? white : black; + dest32[destPos++] = (srcByte & 64) ? white : black; + dest32[destPos++] = (srcByte & 32) ? white : black; + dest32[destPos++] = (srcByte & 16) ? white : black; + dest32[destPos++] = (srcByte & 8) ? white : black; + dest32[destPos++] = (srcByte & 4) ? white : black; + dest32[destPos++] = (srcByte & 2) ? white : black; + dest32[destPos++] = (srcByte & 1) ? white : black; + } + for (; k < kEnd; k++) { + if (mask === 0) { + srcByte = src[srcPos++]; + mask = 128; + } + + dest32[destPos++] = (srcByte & mask) ? white : black; + mask >>= 1; + } + } + // We ran out of input. Make all remaining pixels transparent. + while (destPos < dest32DataLength) { + dest32[destPos++] = 0; + } + + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else if (imgData.kind === ImageKind.RGBA_32BPP) { + // RGBA, 32-bits per pixel. + + j = 0; + elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4; + for (i = 0; i < fullChunks; i++) { + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + srcPos += elemsInThisChunk; + + ctx.putImageData(chunkImgData, 0, j); + j += FULL_CHUNK_HEIGHT; + } + if (i < totalChunks) { + elemsInThisChunk = width * partialChunkHeight * 4; + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + ctx.putImageData(chunkImgData, 0, j); + } + + } else if (imgData.kind === ImageKind.RGB_24BPP) { + // RGB, 24-bits per pixel. + thisChunkHeight = FULL_CHUNK_HEIGHT; + elemsInThisChunk = width * thisChunkHeight; + for (i = 0; i < totalChunks; i++) { + if (i >= fullChunks) { + thisChunkHeight = partialChunkHeight; + elemsInThisChunk = width * thisChunkHeight; + } + + destPos = 0; + for (j = elemsInThisChunk; j--;) { + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = 255; + } + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else { + error('bad image kind: ' + imgData.kind); + } + } + + function putBinaryImageMask(ctx, imgData) { + var height = imgData.height, width = imgData.width; + var partialChunkHeight = height % FULL_CHUNK_HEIGHT; + var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + + var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + var srcPos = 0; + var src = imgData.data; + var dest = chunkImgData.data; + + for (var i = 0; i < totalChunks; i++) { + var thisChunkHeight = + (i < fullChunks) ? FULL_CHUNK_HEIGHT : partialChunkHeight; + + // Expand the mask so it can be used by the canvas. Any required + // inversion has already been handled. + var destPos = 3; // alpha component offset + for (var j = 0; j < thisChunkHeight; j++) { + var mask = 0; + for (var k = 0; k < width; k++) { + if (!mask) { + var elem = src[srcPos++]; + mask = 128; + } + dest[destPos] = (elem & mask) ? 0 : 255; + destPos += 4; + mask >>= 1; + } + } + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } + + function copyCtxState(sourceCtx, destCtx) { + var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha', + 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit', + 'globalCompositeOperation', 'font']; + for (var i = 0, ii = properties.length; i < ii; i++) { + var property = properties[i]; + if (sourceCtx[property] !== undefined) { + destCtx[property] = sourceCtx[property]; + } + } + if (sourceCtx.setLineDash !== undefined) { + destCtx.setLineDash(sourceCtx.getLineDash()); + destCtx.lineDashOffset = sourceCtx.lineDashOffset; + } else if (sourceCtx.mozDashOffset !== undefined) { + destCtx.mozDash = sourceCtx.mozDash; + destCtx.mozDashOffset = sourceCtx.mozDashOffset; + } + } + + function composeSMaskBackdrop(bytes, r0, g0, b0) { + var length = bytes.length; + for (var i = 3; i < length; i += 4) { + var alpha = bytes[i]; + if (alpha === 0) { + bytes[i - 3] = r0; + bytes[i - 2] = g0; + bytes[i - 1] = b0; + } else if (alpha < 255) { + var alpha_ = 255 - alpha; + bytes[i - 3] = (bytes[i - 3] * alpha + r0 * alpha_) >> 8; + bytes[i - 2] = (bytes[i - 2] * alpha + g0 * alpha_) >> 8; + bytes[i - 1] = (bytes[i - 1] * alpha + b0 * alpha_) >> 8; + } + } + } + + function composeSMaskAlpha(maskData, layerData) { + var length = maskData.length; + var scale = 1 / 255; + for (var i = 3; i < length; i += 4) { + var alpha = maskData[i]; + layerData[i] = (layerData[i] * alpha * scale) | 0; + } + } + + function composeSMaskLuminosity(maskData, layerData) { + var length = maskData.length; + for (var i = 3; i < length; i += 4) { + var y = (maskData[i - 3] * 77) + // * 0.3 / 255 * 0x10000 + (maskData[i - 2] * 152) + // * 0.59 .... + (maskData[i - 1] * 28); // * 0.11 .... + layerData[i] = (layerData[i] * y) >> 16; + } + } + + function genericComposeSMask(maskCtx, layerCtx, width, height, + subtype, backdrop) { + var hasBackdrop = !!backdrop; + var r0 = hasBackdrop ? backdrop[0] : 0; + var g0 = hasBackdrop ? backdrop[1] : 0; + var b0 = hasBackdrop ? backdrop[2] : 0; + + var composeFn; + if (subtype === 'Luminosity') { + composeFn = composeSMaskLuminosity; + } else { + composeFn = composeSMaskAlpha; + } + + // processing image in chunks to save memory + var PIXELS_TO_PROCESS = 1048576; + var chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width)); + for (var row = 0; row < height; row += chunkSize) { + var chunkHeight = Math.min(chunkSize, height - row); + var maskData = maskCtx.getImageData(0, row, width, chunkHeight); + var layerData = layerCtx.getImageData(0, row, width, chunkHeight); + + if (hasBackdrop) { + composeSMaskBackdrop(maskData.data, r0, g0, b0); + } + composeFn(maskData.data, layerData.data); + + maskCtx.putImageData(layerData, 0, row); + } + } + + function composeSMask(ctx, smask, layerCtx) { + var mask = smask.canvas; + var maskCtx = smask.context; + + ctx.setTransform(smask.scaleX, 0, 0, smask.scaleY, + smask.offsetX, smask.offsetY); + + var backdrop = smask.backdrop || null; + if (WebGLUtils.isEnabled) { + var composed = WebGLUtils.composeSMask(layerCtx.canvas, mask, + {subtype: smask.subtype, backdrop: backdrop}); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(composed, smask.offsetX, smask.offsetY); + return; + } + genericComposeSMask(maskCtx, layerCtx, mask.width, mask.height, + smask.subtype, backdrop); + ctx.drawImage(mask, 0, 0); + } + + var LINE_CAP_STYLES = ['butt', 'round', 'square']; + var LINE_JOIN_STYLES = ['miter', 'round', 'bevel']; + var NORMAL_CLIP = {}; + var EO_CLIP = {}; + + CanvasGraphics.prototype = { + + beginDrawing: function CanvasGraphics_beginDrawing(viewport, transparency) { + // For pdfs that use blend modes we have to clear the canvas else certain + // blend modes can look wrong since we'd be blending with a white + // backdrop. The problem with a transparent backdrop though is we then + // don't get sub pixel anti aliasing on text, so we fill with white if + // we can. + var width = this.ctx.canvas.width; + var height = this.ctx.canvas.height; + if (transparency) { + this.ctx.clearRect(0, 0, width, height); + } else { + this.ctx.mozOpaque = true; + this.ctx.save(); + this.ctx.fillStyle = 'rgb(255, 255, 255)'; + this.ctx.fillRect(0, 0, width, height); + this.ctx.restore(); + } + + var transform = viewport.transform; + + this.ctx.save(); + this.ctx.transform.apply(this.ctx, transform); + + this.baseTransform = this.ctx.mozCurrentTransform.slice(); + + if (this.imageLayer) { + this.imageLayer.beginLayout(); + } + }, + + executeOperatorList: function CanvasGraphics_executeOperatorList( + operatorList, + executionStartIdx, continueCallback, + stepper) { + var argsArray = operatorList.argsArray; + var fnArray = operatorList.fnArray; + var i = executionStartIdx || 0; + var argsArrayLen = argsArray.length; + + // Sometimes the OperatorList to execute is empty. + if (argsArrayLen === i) { + return i; + } + + var chunkOperations = (argsArrayLen - i > EXECUTION_STEPS && + typeof continueCallback === 'function'); + var endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0; + var steps = 0; + + var commonObjs = this.commonObjs; + var objs = this.objs; + var fnId; + + while (true) { + if (stepper !== undefined && i === stepper.nextBreakPoint) { + stepper.breakIt(i, continueCallback); + return i; + } + + fnId = fnArray[i]; + + if (fnId !== OPS.dependency) { + this[fnId].apply(this, argsArray[i]); + } else { + var deps = argsArray[i]; + for (var n = 0, nn = deps.length; n < nn; n++) { + var depObjId = deps[n]; + var common = depObjId[0] === 'g' && depObjId[1] === '_'; + var objsPool = common ? commonObjs : objs; + + // If the promise isn't resolved yet, add the continueCallback + // to the promise and bail out. + if (!objsPool.isResolved(depObjId)) { + objsPool.get(depObjId, continueCallback); + return i; + } + } + } + + i++; + + // If the entire operatorList was executed, stop as were done. + if (i === argsArrayLen) { + return i; + } + + // If the execution took longer then a certain amount of time and + // `continueCallback` is specified, interrupt the execution. + if (chunkOperations && ++steps > EXECUTION_STEPS) { + if (Date.now() > endTime) { + continueCallback(); + return i; + } + steps = 0; + } + + // If the operatorList isn't executed completely yet OR the execution + // time was short enough, do another execution round. + } + }, + + endDrawing: function CanvasGraphics_endDrawing() { + this.ctx.restore(); + CachedCanvases.clear(); + WebGLUtils.clear(); + + if (this.imageLayer) { + this.imageLayer.endLayout(); + } + }, + + // Graphics state + setLineWidth: function CanvasGraphics_setLineWidth(width) { + this.current.lineWidth = width; + this.ctx.lineWidth = width; + }, + setLineCap: function CanvasGraphics_setLineCap(style) { + this.ctx.lineCap = LINE_CAP_STYLES[style]; + }, + setLineJoin: function CanvasGraphics_setLineJoin(style) { + this.ctx.lineJoin = LINE_JOIN_STYLES[style]; + }, + setMiterLimit: function CanvasGraphics_setMiterLimit(limit) { + this.ctx.miterLimit = limit; + }, + setDash: function CanvasGraphics_setDash(dashArray, dashPhase) { + var ctx = this.ctx; + if (ctx.setLineDash !== undefined) { + ctx.setLineDash(dashArray); + ctx.lineDashOffset = dashPhase; + } else { + ctx.mozDash = dashArray; + ctx.mozDashOffset = dashPhase; + } + }, + setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) { + // Maybe if we one day fully support color spaces this will be important + // for now we can ignore. + // TODO set rendering intent? + }, + setFlatness: function CanvasGraphics_setFlatness(flatness) { + // There's no way to control this with canvas, but we can safely ignore. + // TODO set flatness? + }, + setGState: function CanvasGraphics_setGState(states) { + for (var i = 0, ii = states.length; i < ii; i++) { + var state = states[i]; + var key = state[0]; + var value = state[1]; + + switch (key) { + case 'LW': + this.setLineWidth(value); + break; + case 'LC': + this.setLineCap(value); + break; + case 'LJ': + this.setLineJoin(value); + break; + case 'ML': + this.setMiterLimit(value); + break; + case 'D': + this.setDash(value[0], value[1]); + break; + case 'RI': + this.setRenderingIntent(value); + break; + case 'FL': + this.setFlatness(value); + break; + case 'Font': + this.setFont(value[0], value[1]); + break; + case 'CA': + this.current.strokeAlpha = state[1]; + break; + case 'ca': + this.current.fillAlpha = state[1]; + this.ctx.globalAlpha = state[1]; + break; + case 'BM': + if (value && value.name && (value.name !== 'Normal')) { + var mode = value.name.replace(/([A-Z])/g, + function(c) { + return '-' + c.toLowerCase(); + } + ).substring(1); + this.ctx.globalCompositeOperation = mode; + if (this.ctx.globalCompositeOperation !== mode) { + warn('globalCompositeOperation "' + mode + + '" is not supported'); + } + } else { + this.ctx.globalCompositeOperation = 'source-over'; + } + break; + case 'SMask': + if (this.current.activeSMask) { + this.endSMaskGroup(); + } + this.current.activeSMask = value ? this.tempSMask : null; + if (this.current.activeSMask) { + this.beginSMaskGroup(); + } + this.tempSMask = null; + break; + } + } + }, + beginSMaskGroup: function CanvasGraphics_beginSMaskGroup() { + + var activeSMask = this.current.activeSMask; + var drawnWidth = activeSMask.canvas.width; + var drawnHeight = activeSMask.canvas.height; + var cacheId = 'smaskGroupAt' + this.groupLevel; + var scratchCanvas = CachedCanvases.getCanvas( + cacheId, drawnWidth, drawnHeight, true); + + var currentCtx = this.ctx; + var currentTransform = currentCtx.mozCurrentTransform; + this.ctx.save(); + + var groupCtx = scratchCanvas.context; + groupCtx.scale(1 / activeSMask.scaleX, 1 / activeSMask.scaleY); + groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY); + groupCtx.transform.apply(groupCtx, currentTransform); + + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.setGState([ + ['BM', 'Normal'], + ['ca', 1], + ['CA', 1] + ]); + this.groupStack.push(currentCtx); + this.groupLevel++; + }, + endSMaskGroup: function CanvasGraphics_endSMaskGroup() { + var groupCtx = this.ctx; + this.groupLevel--; + this.ctx = this.groupStack.pop(); + + composeSMask(this.ctx, this.current.activeSMask, groupCtx); + this.ctx.restore(); + }, + save: function CanvasGraphics_save() { + this.ctx.save(); + var old = this.current; + this.stateStack.push(old); + this.current = old.clone(); + this.current.activeSMask = null; + }, + restore: function CanvasGraphics_restore() { + if (this.stateStack.length !== 0) { + if (this.current.activeSMask !== null) { + this.endSMaskGroup(); + } + + this.current = this.stateStack.pop(); + this.ctx.restore(); + + this.cachedGetSinglePixelWidth = null; + } + }, + transform: function CanvasGraphics_transform(a, b, c, d, e, f) { + this.ctx.transform(a, b, c, d, e, f); + + this.cachedGetSinglePixelWidth = null; + }, + + // Path + constructPath: function CanvasGraphics_constructPath(ops, args) { + var ctx = this.ctx; + var current = this.current; + var x = current.x, y = current.y; + for (var i = 0, j = 0, ii = ops.length; i < ii; i++) { + switch (ops[i] | 0) { + case OPS.rectangle: + x = args[j++]; + y = args[j++]; + var width = args[j++]; + var height = args[j++]; + if (width === 0) { + width = this.getSinglePixelWidth(); + } + if (height === 0) { + height = this.getSinglePixelWidth(); + } + var xw = x + width; + var yh = y + height; + this.ctx.moveTo(x, y); + this.ctx.lineTo(xw, y); + this.ctx.lineTo(xw, yh); + this.ctx.lineTo(x, yh); + this.ctx.lineTo(x, y); + this.ctx.closePath(); + break; + case OPS.moveTo: + x = args[j++]; + y = args[j++]; + ctx.moveTo(x, y); + break; + case OPS.lineTo: + x = args[j++]; + y = args[j++]; + ctx.lineTo(x, y); + break; + case OPS.curveTo: + x = args[j + 4]; + y = args[j + 5]; + ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], + x, y); + j += 6; + break; + case OPS.curveTo2: + ctx.bezierCurveTo(x, y, args[j], args[j + 1], + args[j + 2], args[j + 3]); + x = args[j + 2]; + y = args[j + 3]; + j += 4; + break; + case OPS.curveTo3: + x = args[j + 2]; + y = args[j + 3]; + ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y); + j += 4; + break; + case OPS.closePath: + ctx.closePath(); + break; + } + } + current.setCurrentPoint(x, y); + }, + closePath: function CanvasGraphics_closePath() { + this.ctx.closePath(); + }, + stroke: function CanvasGraphics_stroke(consumePath) { + consumePath = typeof consumePath !== 'undefined' ? consumePath : true; + var ctx = this.ctx; + var strokeColor = this.current.strokeColor; + // Prevent drawing too thin lines by enforcing a minimum line width. + ctx.lineWidth = Math.max(this.getSinglePixelWidth() * MIN_WIDTH_FACTOR, + this.current.lineWidth); + // For stroke we want to temporarily change the global alpha to the + // stroking alpha. + ctx.globalAlpha = this.current.strokeAlpha; + if (strokeColor && strokeColor.hasOwnProperty('type') && + strokeColor.type === 'Pattern') { + // for patterns, we transform to pattern space, calculate + // the pattern, call stroke, and restore to user space + ctx.save(); + ctx.strokeStyle = strokeColor.getPattern(ctx, this); + ctx.stroke(); + ctx.restore(); + } else { + ctx.stroke(); + } + if (consumePath) { + this.consumePath(); + } + // Restore the global alpha to the fill alpha + ctx.globalAlpha = this.current.fillAlpha; + }, + closeStroke: function CanvasGraphics_closeStroke() { + this.closePath(); + this.stroke(); + }, + fill: function CanvasGraphics_fill(consumePath) { + consumePath = typeof consumePath !== 'undefined' ? consumePath : true; + var ctx = this.ctx; + var fillColor = this.current.fillColor; + var isPatternFill = this.current.patternFill; + var needRestore = false; + + if (isPatternFill) { + ctx.save(); + ctx.fillStyle = fillColor.getPattern(ctx, this); + needRestore = true; + } + + if (this.pendingEOFill) { + if (ctx.mozFillRule !== undefined) { + ctx.mozFillRule = 'evenodd'; + ctx.fill(); + ctx.mozFillRule = 'nonzero'; + } else { + try { + ctx.fill('evenodd'); + } catch (ex) { + // shouldn't really happen, but browsers might think differently + ctx.fill(); + } + } + this.pendingEOFill = false; + } else { + ctx.fill(); + } + + if (needRestore) { + ctx.restore(); + } + if (consumePath) { + this.consumePath(); + } + }, + eoFill: function CanvasGraphics_eoFill() { + this.pendingEOFill = true; + this.fill(); + }, + fillStroke: function CanvasGraphics_fillStroke() { + this.fill(false); + this.stroke(false); + + this.consumePath(); + }, + eoFillStroke: function CanvasGraphics_eoFillStroke() { + this.pendingEOFill = true; + this.fillStroke(); + }, + closeFillStroke: function CanvasGraphics_closeFillStroke() { + this.closePath(); + this.fillStroke(); + }, + closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() { + this.pendingEOFill = true; + this.closePath(); + this.fillStroke(); + }, + endPath: function CanvasGraphics_endPath() { + this.consumePath(); + }, + + // Clipping + clip: function CanvasGraphics_clip() { + this.pendingClip = NORMAL_CLIP; + }, + eoClip: function CanvasGraphics_eoClip() { + this.pendingClip = EO_CLIP; + }, + + // Text + beginText: function CanvasGraphics_beginText() { + this.current.textMatrix = IDENTITY_MATRIX; + this.current.textMatrixScale = 1; + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + }, + endText: function CanvasGraphics_endText() { + var paths = this.pendingTextPaths; + var ctx = this.ctx; + if (paths === undefined) { + ctx.beginPath(); + return; + } + + ctx.save(); + ctx.beginPath(); + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + ctx.setTransform.apply(ctx, path.transform); + ctx.translate(path.x, path.y); + path.addToPath(ctx, path.fontSize); + } + ctx.restore(); + ctx.clip(); + ctx.beginPath(); + delete this.pendingTextPaths; + }, + setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) { + this.current.charSpacing = spacing; + }, + setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) { + this.current.wordSpacing = spacing; + }, + setHScale: function CanvasGraphics_setHScale(scale) { + this.current.textHScale = scale / 100; + }, + setLeading: function CanvasGraphics_setLeading(leading) { + this.current.leading = -leading; + }, + setFont: function CanvasGraphics_setFont(fontRefName, size) { + var fontObj = this.commonObjs.get(fontRefName); + var current = this.current; + + if (!fontObj) { + error('Can\'t find font for ' + fontRefName); + } + + current.fontMatrix = (fontObj.fontMatrix ? + fontObj.fontMatrix : FONT_IDENTITY_MATRIX); + + // A valid matrix needs all main diagonal elements to be non-zero + // This also ensures we bypass FF bugzilla bug #719844. + if (current.fontMatrix[0] === 0 || + current.fontMatrix[3] === 0) { + warn('Invalid font matrix for font ' + fontRefName); + } + + // The spec for Tf (setFont) says that 'size' specifies the font 'scale', + // and in some docs this can be negative (inverted x-y axes). + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + + this.current.font = fontObj; + this.current.fontSize = size; + + if (fontObj.isType3Font) { + return; // we don't need ctx.font for Type3 fonts + } + + var name = fontObj.loadedName || 'sans-serif'; + var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') : + (fontObj.bold ? 'bold' : 'normal'); + + var italic = fontObj.italic ? 'italic' : 'normal'; + var typeface = '"' + name + '", ' + fontObj.fallbackName; + + // Some font backends cannot handle fonts below certain size. + // Keeping the font at minimal size and using the fontSizeScale to change + // the current transformation matrix before the fillText/strokeText. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227 + var browserFontSize = size < MIN_FONT_SIZE ? MIN_FONT_SIZE : + size > MAX_FONT_SIZE ? MAX_FONT_SIZE : size; + this.current.fontSizeScale = size / browserFontSize; + + var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface; + this.ctx.font = rule; + }, + setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) { + this.current.textRenderingMode = mode; + }, + setTextRise: function CanvasGraphics_setTextRise(rise) { + this.current.textRise = rise; + }, + moveText: function CanvasGraphics_moveText(x, y) { + this.current.x = this.current.lineX += x; + this.current.y = this.current.lineY += y; + }, + setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) { + this.setLeading(-y); + this.moveText(x, y); + }, + setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) { + this.current.textMatrix = [a, b, c, d, e, f]; + this.current.textMatrixScale = Math.sqrt(a * a + b * b); + + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + }, + nextLine: function CanvasGraphics_nextLine() { + this.moveText(0, this.current.leading); + }, + + paintChar: function CanvasGraphics_paintChar(character, x, y) { + var ctx = this.ctx; + var current = this.current; + var font = current.font; + var textRenderingMode = current.textRenderingMode; + var fontSize = current.fontSize / current.fontSizeScale; + var fillStrokeMode = textRenderingMode & + TextRenderingMode.FILL_STROKE_MASK; + var isAddToPathSet = !!(textRenderingMode & + TextRenderingMode.ADD_TO_PATH_FLAG); + + var addToPath; + if (font.disableFontFace || isAddToPathSet) { + addToPath = font.getPathGenerator(this.commonObjs, character); + } + + if (font.disableFontFace) { + ctx.save(); + ctx.translate(x, y); + ctx.beginPath(); + addToPath(ctx, fontSize); + if (fillStrokeMode === TextRenderingMode.FILL || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.fill(); + } + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.stroke(); + } + ctx.restore(); + } else { + if (fillStrokeMode === TextRenderingMode.FILL || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.fillText(character, x, y); + } + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.strokeText(character, x, y); + } + } + + if (isAddToPathSet) { + var paths = this.pendingTextPaths || (this.pendingTextPaths = []); + paths.push({ + transform: ctx.mozCurrentTransform, + x: x, + y: y, + fontSize: fontSize, + addToPath: addToPath + }); + } + }, + + get isFontSubpixelAAEnabled() { + // Checks if anti-aliasing is enabled when scaled text is painted. + // On Windows GDI scaled fonts looks bad. + var ctx = document.createElement('canvas').getContext('2d'); + ctx.scale(1.5, 1); + ctx.fillText('I', 0, 10); + var data = ctx.getImageData(0, 0, 10, 10).data; + var enabled = false; + for (var i = 3; i < data.length; i += 4) { + if (data[i] > 0 && data[i] < 255) { + enabled = true; + break; + } + } + return shadow(this, 'isFontSubpixelAAEnabled', enabled); + }, + + showText: function CanvasGraphics_showText(glyphs) { + var current = this.current; + var font = current.font; + if (font.isType3Font) { + return this.showType3Text(glyphs); + } + + var fontSize = current.fontSize; + if (fontSize === 0) { + return; + } + + var ctx = this.ctx; + var fontSizeScale = current.fontSizeScale; + var charSpacing = current.charSpacing; + var wordSpacing = current.wordSpacing; + var fontDirection = current.fontDirection; + var textHScale = current.textHScale * fontDirection; + var glyphsLength = glyphs.length; + var vertical = font.vertical; + var defaultVMetrics = font.defaultVMetrics; + var widthAdvanceScale = fontSize * current.fontMatrix[0]; + + var simpleFillText = + current.textRenderingMode === TextRenderingMode.FILL && + !font.disableFontFace; + + ctx.save(); + ctx.transform.apply(ctx, current.textMatrix); + ctx.translate(current.x, current.y + current.textRise); + + if (fontDirection > 0) { + ctx.scale(textHScale, -1); + } else { + ctx.scale(textHScale, 1); + } + + var lineWidth = current.lineWidth; + var scale = current.textMatrixScale; + if (scale === 0 || lineWidth === 0) { + var fillStrokeMode = current.textRenderingMode & + TextRenderingMode.FILL_STROKE_MASK; + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + this.cachedGetSinglePixelWidth = null; + lineWidth = this.getSinglePixelWidth() * MIN_WIDTH_FACTOR; + } + } else { + lineWidth /= scale; + } + + if (fontSizeScale !== 1.0) { + ctx.scale(fontSizeScale, fontSizeScale); + lineWidth /= fontSizeScale; + } + + ctx.lineWidth = lineWidth; + + var x = 0, i; + for (i = 0; i < glyphsLength; ++i) { + var glyph = glyphs[i]; + if (glyph === null) { + // word break + x += fontDirection * wordSpacing; + continue; + } else if (isNum(glyph)) { + x += -glyph * fontSize * 0.001; + continue; + } + + var restoreNeeded = false; + var character = glyph.fontChar; + var accent = glyph.accent; + var scaledX, scaledY, scaledAccentX, scaledAccentY; + var width = glyph.width; + if (vertical) { + var vmetric, vx, vy; + vmetric = glyph.vmetric || defaultVMetrics; + vx = glyph.vmetric ? vmetric[1] : width * 0.5; + vx = -vx * widthAdvanceScale; + vy = vmetric[2] * widthAdvanceScale; + + width = vmetric ? -vmetric[0] : width; + scaledX = vx / fontSizeScale; + scaledY = (x + vy) / fontSizeScale; + } else { + scaledX = x / fontSizeScale; + scaledY = 0; + } + + if (font.remeasure && width > 0 && this.isFontSubpixelAAEnabled) { + // some standard fonts may not have the exact width, trying to + // rescale per character + var measuredWidth = ctx.measureText(character).width * 1000 / + fontSize * fontSizeScale; + var characterScaleX = width / measuredWidth; + restoreNeeded = true; + ctx.save(); + ctx.scale(characterScaleX, 1); + scaledX /= characterScaleX; + } + + if (simpleFillText && !accent) { + // common case + ctx.fillText(character, scaledX, scaledY); + } else { + this.paintChar(character, scaledX, scaledY); + if (accent) { + scaledAccentX = scaledX + accent.offset.x / fontSizeScale; + scaledAccentY = scaledY - accent.offset.y / fontSizeScale; + this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY); + } + } + + var charWidth = width * widthAdvanceScale + charSpacing * fontDirection; + x += charWidth; + + if (restoreNeeded) { + ctx.restore(); + } + } + if (vertical) { + current.y -= x * textHScale; + } else { + current.x += x * textHScale; + } + ctx.restore(); + }, + + showType3Text: function CanvasGraphics_showType3Text(glyphs) { + // Type3 fonts - each glyph is a "mini-PDF" + var ctx = this.ctx; + var current = this.current; + var font = current.font; + var fontSize = current.fontSize; + var fontDirection = current.fontDirection; + var charSpacing = current.charSpacing; + var wordSpacing = current.wordSpacing; + var textHScale = current.textHScale * fontDirection; + var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX; + var glyphsLength = glyphs.length; + var isTextInvisible = + current.textRenderingMode === TextRenderingMode.INVISIBLE; + var i, glyph, width; + + if (isTextInvisible || fontSize === 0) { + return; + } + + ctx.save(); + ctx.transform.apply(ctx, current.textMatrix); + ctx.translate(current.x, current.y); + + ctx.scale(textHScale, fontDirection); + + for (i = 0; i < glyphsLength; ++i) { + glyph = glyphs[i]; + if (glyph === null) { + // word break + this.ctx.translate(wordSpacing, 0); + current.x += wordSpacing * textHScale; + continue; + } else if (isNum(glyph)) { + var spacingLength = -glyph * 0.001 * fontSize; + this.ctx.translate(spacingLength, 0); + current.x += spacingLength * textHScale; + continue; + } + + var operatorList = font.charProcOperatorList[glyph.operatorListId]; + if (!operatorList) { + warn('Type3 character \"' + glyph.operatorListId + + '\" is not available'); + continue; + } + this.processingType3 = glyph; + this.save(); + ctx.scale(fontSize, fontSize); + ctx.transform.apply(ctx, fontMatrix); + this.executeOperatorList(operatorList); + this.restore(); + + var transformed = Util.applyTransform([glyph.width, 0], fontMatrix); + width = transformed[0] * fontSize + charSpacing; + + ctx.translate(width, 0); + current.x += width * textHScale; + } + ctx.restore(); + this.processingType3 = null; + }, + + // Type3 fonts + setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) { + // We can safely ignore this since the width should be the same + // as the width in the Widths array. + }, + setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth, + yWidth, + llx, + lly, + urx, + ury) { + // TODO According to the spec we're also suppose to ignore any operators + // that set color or include images while processing this type3 font. + this.ctx.rect(llx, lly, urx - llx, ury - lly); + this.clip(); + this.endPath(); + }, + + // Color + getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR) { + var pattern; + if (IR[0] === 'TilingPattern') { + var color = IR[1]; + pattern = new TilingPattern(IR, color, this.ctx, this.objs, + this.commonObjs, this.baseTransform); + } else { + pattern = getShadingPatternFromIR(IR); + } + return pattern; + }, + setStrokeColorN: function CanvasGraphics_setStrokeColorN(/*...*/) { + this.current.strokeColor = this.getColorN_Pattern(arguments); + }, + setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) { + this.current.fillColor = this.getColorN_Pattern(arguments); + this.current.patternFill = true; + }, + setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) { + var color = Util.makeCssRgb(r, g, b); + this.ctx.strokeStyle = color; + this.current.strokeColor = color; + }, + setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) { + var color = Util.makeCssRgb(r, g, b); + this.ctx.fillStyle = color; + this.current.fillColor = color; + this.current.patternFill = false; + }, + + shadingFill: function CanvasGraphics_shadingFill(patternIR) { + var ctx = this.ctx; + + this.save(); + var pattern = getShadingPatternFromIR(patternIR); + ctx.fillStyle = pattern.getPattern(ctx, this, true); + + var inv = ctx.mozCurrentTransformInverse; + if (inv) { + var canvas = ctx.canvas; + var width = canvas.width; + var height = canvas.height; + + var bl = Util.applyTransform([0, 0], inv); + var br = Util.applyTransform([0, height], inv); + var ul = Util.applyTransform([width, 0], inv); + var ur = Util.applyTransform([width, height], inv); + + var x0 = Math.min(bl[0], br[0], ul[0], ur[0]); + var y0 = Math.min(bl[1], br[1], ul[1], ur[1]); + var x1 = Math.max(bl[0], br[0], ul[0], ur[0]); + var y1 = Math.max(bl[1], br[1], ul[1], ur[1]); + + this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0); + } else { + // HACK to draw the gradient onto an infinite rectangle. + // PDF gradients are drawn across the entire image while + // Canvas only allows gradients to be drawn in a rectangle + // The following bug should allow us to remove this. + // https://bugzilla.mozilla.org/show_bug.cgi?id=664884 + + this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); + } + + this.restore(); + }, + + // Images + beginInlineImage: function CanvasGraphics_beginInlineImage() { + error('Should not call beginInlineImage'); + }, + beginImageData: function CanvasGraphics_beginImageData() { + error('Should not call beginImageData'); + }, + + paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix, + bbox) { + this.save(); + this.baseTransformStack.push(this.baseTransform); + + if (isArray(matrix) && 6 === matrix.length) { + this.transform.apply(this, matrix); + } + + this.baseTransform = this.ctx.mozCurrentTransform; + + if (isArray(bbox) && 4 === bbox.length) { + var width = bbox[2] - bbox[0]; + var height = bbox[3] - bbox[1]; + this.ctx.rect(bbox[0], bbox[1], width, height); + this.clip(); + this.endPath(); + } + }, + + paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() { + this.restore(); + this.baseTransform = this.baseTransformStack.pop(); + }, + + beginGroup: function CanvasGraphics_beginGroup(group) { + this.save(); + var currentCtx = this.ctx; + // TODO non-isolated groups - according to Rik at adobe non-isolated + // group results aren't usually that different and they even have tools + // that ignore this setting. Notes from Rik on implmenting: + // - When you encounter an transparency group, create a new canvas with + // the dimensions of the bbox + // - copy the content from the previous canvas to the new canvas + // - draw as usual + // - remove the backdrop alpha: + // alphaNew = 1 - (1 - alpha)/(1 - alphaBackdrop) with 'alpha' the alpha + // value of your transparency group and 'alphaBackdrop' the alpha of the + // backdrop + // - remove background color: + // colorNew = color - alphaNew *colorBackdrop /(1 - alphaNew) + if (!group.isolated) { + info('TODO: Support non-isolated groups.'); + } + + // TODO knockout - supposedly possible with the clever use of compositing + // modes. + if (group.knockout) { + warn('Knockout groups not supported.'); + } + + var currentTransform = currentCtx.mozCurrentTransform; + if (group.matrix) { + currentCtx.transform.apply(currentCtx, group.matrix); + } + assert(group.bbox, 'Bounding box is required.'); + + // Based on the current transform figure out how big the bounding box + // will actually be. + var bounds = Util.getAxialAlignedBoundingBox( + group.bbox, + currentCtx.mozCurrentTransform); + // Clip the bounding box to the current canvas. + var canvasBounds = [0, + 0, + currentCtx.canvas.width, + currentCtx.canvas.height]; + bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0]; + // Use ceil in case we're between sizes so we don't create canvas that is + // too small and make the canvas at least 1x1 pixels. + var offsetX = Math.floor(bounds[0]); + var offsetY = Math.floor(bounds[1]); + var drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1); + var drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1); + var scaleX = 1, scaleY = 1; + if (drawnWidth > MAX_GROUP_SIZE) { + scaleX = drawnWidth / MAX_GROUP_SIZE; + drawnWidth = MAX_GROUP_SIZE; + } + if (drawnHeight > MAX_GROUP_SIZE) { + scaleY = drawnHeight / MAX_GROUP_SIZE; + drawnHeight = MAX_GROUP_SIZE; + } + + var cacheId = 'groupAt' + this.groupLevel; + if (group.smask) { + // Using two cache entries is case if masks are used one after another. + cacheId += '_smask_' + ((this.smaskCounter++) % 2); + } + var scratchCanvas = CachedCanvases.getCanvas( + cacheId, drawnWidth, drawnHeight, true); + var groupCtx = scratchCanvas.context; + + // Since we created a new canvas that is just the size of the bounding box + // we have to translate the group ctx. + groupCtx.scale(1 / scaleX, 1 / scaleY); + groupCtx.translate(-offsetX, -offsetY); + groupCtx.transform.apply(groupCtx, currentTransform); + + if (group.smask) { + // Saving state and cached mask to be used in setGState. + this.smaskStack.push({ + canvas: scratchCanvas.canvas, + context: groupCtx, + offsetX: offsetX, + offsetY: offsetY, + scaleX: scaleX, + scaleY: scaleY, + subtype: group.smask.subtype, + backdrop: group.smask.backdrop + }); + } else { + // Setup the current ctx so when the group is popped we draw it at the + // right location. + currentCtx.setTransform(1, 0, 0, 1, 0, 0); + currentCtx.translate(offsetX, offsetY); + currentCtx.scale(scaleX, scaleY); + } + // The transparency group inherits all off the current graphics state + // except the blend mode, soft mask, and alpha constants. + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.setGState([ + ['BM', 'Normal'], + ['ca', 1], + ['CA', 1] + ]); + this.groupStack.push(currentCtx); + this.groupLevel++; + }, + + endGroup: function CanvasGraphics_endGroup(group) { + this.groupLevel--; + var groupCtx = this.ctx; + this.ctx = this.groupStack.pop(); + // Turn off image smoothing to avoid sub pixel interpolation which can + // look kind of blurry for some pdfs. + if (this.ctx.imageSmoothingEnabled !== undefined) { + this.ctx.imageSmoothingEnabled = false; + } else { + this.ctx.mozImageSmoothingEnabled = false; + } + if (group.smask) { + this.tempSMask = this.smaskStack.pop(); + } else { + this.ctx.drawImage(groupCtx.canvas, 0, 0); + } + this.restore(); + }, + + beginAnnotations: function CanvasGraphics_beginAnnotations() { + this.save(); + this.current = new CanvasExtraState(); + }, + + endAnnotations: function CanvasGraphics_endAnnotations() { + this.restore(); + }, + + beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform, + matrix) { + this.save(); + + if (isArray(rect) && 4 === rect.length) { + var width = rect[2] - rect[0]; + var height = rect[3] - rect[1]; + this.ctx.rect(rect[0], rect[1], width, height); + this.clip(); + this.endPath(); + } + + this.transform.apply(this, transform); + this.transform.apply(this, matrix); + }, + + endAnnotation: function CanvasGraphics_endAnnotation() { + this.restore(); + }, + + paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) { + var domImage = this.objs.get(objId); + if (!domImage) { + warn('Dependent image isn\'t ready yet'); + return; + } + + this.save(); + + var ctx = this.ctx; + // scale the image to the unit square + ctx.scale(1 / w, -1 / h); + + ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height, + 0, -h, w, h); + if (this.imageLayer) { + var currentTransform = ctx.mozCurrentTransformInverse; + var position = this.getCanvasPosition(0, 0); + this.imageLayer.appendImage({ + objId: objId, + left: position[0], + top: position[1], + width: w / currentTransform[0], + height: h / currentTransform[3] + }); + } + this.restore(); + }, + + paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) { + var ctx = this.ctx; + var width = img.width, height = img.height; + var fillColor = this.current.fillColor; + var isPatternFill = this.current.patternFill; + + var glyph = this.processingType3; + + if (COMPILE_TYPE3_GLYPHS && glyph && glyph.compiled === undefined) { + if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) { + glyph.compiled = + compileType3Glyph({data: img.data, width: width, height: height}); + } else { + glyph.compiled = null; + } + } + + if (glyph && glyph.compiled) { + glyph.compiled(ctx); + return; + } + + var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); + var maskCtx = maskCanvas.context; + maskCtx.save(); + + putBinaryImageMask(maskCtx, img); + + maskCtx.globalCompositeOperation = 'source-in'; + + maskCtx.fillStyle = isPatternFill ? + fillColor.getPattern(maskCtx, this) : fillColor; + maskCtx.fillRect(0, 0, width, height); + + maskCtx.restore(); + + this.paintInlineImageXObject(maskCanvas.canvas); + }, + + paintImageMaskXObjectRepeat: + function CanvasGraphics_paintImageMaskXObjectRepeat(imgData, scaleX, + scaleY, positions) { + var width = imgData.width; + var height = imgData.height; + var fillColor = this.current.fillColor; + var isPatternFill = this.current.patternFill; + + var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); + var maskCtx = maskCanvas.context; + maskCtx.save(); + + putBinaryImageMask(maskCtx, imgData); + + maskCtx.globalCompositeOperation = 'source-in'; + + maskCtx.fillStyle = isPatternFill ? + fillColor.getPattern(maskCtx, this) : fillColor; + maskCtx.fillRect(0, 0, width, height); + + maskCtx.restore(); + + var ctx = this.ctx; + for (var i = 0, ii = positions.length; i < ii; i += 2) { + ctx.save(); + ctx.transform(scaleX, 0, 0, scaleY, positions[i], positions[i + 1]); + ctx.scale(1, -1); + ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, + 0, -1, 1, 1); + ctx.restore(); + } + }, + + paintImageMaskXObjectGroup: + function CanvasGraphics_paintImageMaskXObjectGroup(images) { + var ctx = this.ctx; + + var fillColor = this.current.fillColor; + var isPatternFill = this.current.patternFill; + for (var i = 0, ii = images.length; i < ii; i++) { + var image = images[i]; + var width = image.width, height = image.height; + + var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); + var maskCtx = maskCanvas.context; + maskCtx.save(); + + putBinaryImageMask(maskCtx, image); + + maskCtx.globalCompositeOperation = 'source-in'; + + maskCtx.fillStyle = isPatternFill ? + fillColor.getPattern(maskCtx, this) : fillColor; + maskCtx.fillRect(0, 0, width, height); + + maskCtx.restore(); + + ctx.save(); + ctx.transform.apply(ctx, image.transform); + ctx.scale(1, -1); + ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, + 0, -1, 1, 1); + ctx.restore(); + } + }, + + paintImageXObject: function CanvasGraphics_paintImageXObject(objId) { + var imgData = this.objs.get(objId); + if (!imgData) { + warn('Dependent image isn\'t ready yet'); + return; + } + + this.paintInlineImageXObject(imgData); + }, + + paintImageXObjectRepeat: + function CanvasGraphics_paintImageXObjectRepeat(objId, scaleX, scaleY, + positions) { + var imgData = this.objs.get(objId); + if (!imgData) { + warn('Dependent image isn\'t ready yet'); + return; + } + + var width = imgData.width; + var height = imgData.height; + var map = []; + for (var i = 0, ii = positions.length; i < ii; i += 2) { + map.push({transform: [scaleX, 0, 0, scaleY, positions[i], + positions[i + 1]], x: 0, y: 0, w: width, h: height}); + } + this.paintInlineImageXObjectGroup(imgData, map); + }, + + paintInlineImageXObject: + function CanvasGraphics_paintInlineImageXObject(imgData) { + var width = imgData.width; + var height = imgData.height; + var ctx = this.ctx; + + this.save(); + // scale the image to the unit square + ctx.scale(1 / width, -1 / height); + + var currentTransform = ctx.mozCurrentTransformInverse; + var a = currentTransform[0], b = currentTransform[1]; + var widthScale = Math.max(Math.sqrt(a * a + b * b), 1); + var c = currentTransform[2], d = currentTransform[3]; + var heightScale = Math.max(Math.sqrt(c * c + d * d), 1); + + var imgToPaint, tmpCanvas; + // instanceof HTMLElement does not work in jsdom node.js module + if (imgData instanceof HTMLElement || !imgData.data) { + imgToPaint = imgData; + } else { + tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height); + var tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + imgToPaint = tmpCanvas.canvas; + } + + var paintWidth = width, paintHeight = height; + var tmpCanvasId = 'prescale1'; + // Vertial or horizontal scaling shall not be more than 2 to not loose the + // pixels during drawImage operation, painting on the temporary canvas(es) + // that are twice smaller in size + while ((widthScale > 2 && paintWidth > 1) || + (heightScale > 2 && paintHeight > 1)) { + var newWidth = paintWidth, newHeight = paintHeight; + if (widthScale > 2 && paintWidth > 1) { + newWidth = Math.ceil(paintWidth / 2); + widthScale /= paintWidth / newWidth; + } + if (heightScale > 2 && paintHeight > 1) { + newHeight = Math.ceil(paintHeight / 2); + heightScale /= paintHeight / newHeight; + } + tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight); + tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, newWidth, newHeight); + tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, + 0, 0, newWidth, newHeight); + imgToPaint = tmpCanvas.canvas; + paintWidth = newWidth; + paintHeight = newHeight; + tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1'; + } + ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, + 0, -height, width, height); + + if (this.imageLayer) { + var position = this.getCanvasPosition(0, -height); + this.imageLayer.appendImage({ + imgData: imgData, + left: position[0], + top: position[1], + width: width / currentTransform[0], + height: height / currentTransform[3] + }); + } + this.restore(); + }, + + paintInlineImageXObjectGroup: + function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) { + var ctx = this.ctx; + var w = imgData.width; + var h = imgData.height; + + var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h); + var tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + + for (var i = 0, ii = map.length; i < ii; i++) { + var entry = map[i]; + ctx.save(); + ctx.transform.apply(ctx, entry.transform); + ctx.scale(1, -1); + ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, + 0, -1, 1, 1); + if (this.imageLayer) { + var position = this.getCanvasPosition(entry.x, entry.y); + this.imageLayer.appendImage({ + imgData: imgData, + left: position[0], + top: position[1], + width: w, + height: h + }); + } + ctx.restore(); + } + }, + + paintSolidColorImageMask: + function CanvasGraphics_paintSolidColorImageMask() { + this.ctx.fillRect(0, 0, 1, 1); + }, + + // Marked content + + markPoint: function CanvasGraphics_markPoint(tag) { + // TODO Marked content. + }, + markPointProps: function CanvasGraphics_markPointProps(tag, properties) { + // TODO Marked content. + }, + beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) { + // TODO Marked content. + }, + beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps( + tag, properties) { + // TODO Marked content. + }, + endMarkedContent: function CanvasGraphics_endMarkedContent() { + // TODO Marked content. + }, + + // Compatibility + + beginCompat: function CanvasGraphics_beginCompat() { + // TODO ignore undefined operators (should we do that anyway?) + }, + endCompat: function CanvasGraphics_endCompat() { + // TODO stop ignoring undefined operators + }, + + // Helper functions + + consumePath: function CanvasGraphics_consumePath() { + var ctx = this.ctx; + if (this.pendingClip) { + if (this.pendingClip === EO_CLIP) { + if (ctx.mozFillRule !== undefined) { + ctx.mozFillRule = 'evenodd'; + ctx.clip(); + ctx.mozFillRule = 'nonzero'; + } else { + try { + ctx.clip('evenodd'); + } catch (ex) { + // shouldn't really happen, but browsers might think differently + ctx.clip(); + } + } + } else { + ctx.clip(); + } + this.pendingClip = null; + } + ctx.beginPath(); + }, + getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) { + if (this.cachedGetSinglePixelWidth === null) { + var inverse = this.ctx.mozCurrentTransformInverse; + // max of the current horizontal and vertical scale + this.cachedGetSinglePixelWidth = Math.sqrt(Math.max( + (inverse[0] * inverse[0] + inverse[1] * inverse[1]), + (inverse[2] * inverse[2] + inverse[3] * inverse[3]))); + } + return this.cachedGetSinglePixelWidth; + }, + getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) { + var transform = this.ctx.mozCurrentTransform; + return [ + transform[0] * x + transform[2] * y + transform[4], + transform[1] * x + transform[3] * y + transform[5] + ]; + } + }; + + for (var op in OPS) { + CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op]; + } + + return CanvasGraphics; +})(); + + +var WebGLUtils = (function WebGLUtilsClosure() { + function loadShader(gl, code, shaderType) { + var shader = gl.createShader(shaderType); + gl.shaderSource(shader, code); + gl.compileShader(shader); + var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); + if (!compiled) { + var errorMsg = gl.getShaderInfoLog(shader); + throw new Error('Error during shader compilation: ' + errorMsg); + } + return shader; + } + function createVertexShader(gl, code) { + return loadShader(gl, code, gl.VERTEX_SHADER); + } + function createFragmentShader(gl, code) { + return loadShader(gl, code, gl.FRAGMENT_SHADER); + } + function createProgram(gl, shaders) { + var program = gl.createProgram(); + for (var i = 0, ii = shaders.length; i < ii; ++i) { + gl.attachShader(program, shaders[i]); + } + gl.linkProgram(program); + var linked = gl.getProgramParameter(program, gl.LINK_STATUS); + if (!linked) { + var errorMsg = gl.getProgramInfoLog(program); + throw new Error('Error during program linking: ' + errorMsg); + } + return program; + } + function createTexture(gl, image, textureId) { + gl.activeTexture(textureId); + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + // Set the parameters so we can render any size image. + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + // Upload the image into the texture. + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + return texture; + } + + var currentGL, currentCanvas; + function generateGL() { + if (currentGL) { + return; + } + currentCanvas = document.createElement('canvas'); + currentGL = currentCanvas.getContext('webgl', + { premultipliedalpha: false }); + } + + var smaskVertexShaderCode = '\ + attribute vec2 a_position; \ + attribute vec2 a_texCoord; \ + \ + uniform vec2 u_resolution; \ + \ + varying vec2 v_texCoord; \ + \ + void main() { \ + vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0; \ + gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \ + \ + v_texCoord = a_texCoord; \ + } '; + + var smaskFragmentShaderCode = '\ + precision mediump float; \ + \ + uniform vec4 u_backdrop; \ + uniform int u_subtype; \ + uniform sampler2D u_image; \ + uniform sampler2D u_mask; \ + \ + varying vec2 v_texCoord; \ + \ + void main() { \ + vec4 imageColor = texture2D(u_image, v_texCoord); \ + vec4 maskColor = texture2D(u_mask, v_texCoord); \ + if (u_backdrop.a > 0.0) { \ + maskColor.rgb = maskColor.rgb * maskColor.a + \ + u_backdrop.rgb * (1.0 - maskColor.a); \ + } \ + float lum; \ + if (u_subtype == 0) { \ + lum = maskColor.a; \ + } else { \ + lum = maskColor.r * 0.3 + maskColor.g * 0.59 + \ + maskColor.b * 0.11; \ + } \ + imageColor.a *= lum; \ + imageColor.rgb *= imageColor.a; \ + gl_FragColor = imageColor; \ + } '; + + var smaskCache = null; + + function initSmaskGL() { + var canvas, gl; + + generateGL(); + canvas = currentCanvas; + currentCanvas = null; + gl = currentGL; + currentGL = null; + + // setup a GLSL program + var vertexShader = createVertexShader(gl, smaskVertexShaderCode); + var fragmentShader = createFragmentShader(gl, smaskFragmentShaderCode); + var program = createProgram(gl, [vertexShader, fragmentShader]); + gl.useProgram(program); + + var cache = {}; + cache.gl = gl; + cache.canvas = canvas; + cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution'); + cache.positionLocation = gl.getAttribLocation(program, 'a_position'); + cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop'); + cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype'); + + var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord'); + var texLayerLocation = gl.getUniformLocation(program, 'u_image'); + var texMaskLocation = gl.getUniformLocation(program, 'u_mask'); + + // provide texture coordinates for the rectangle. + var texCoordBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 1.0, 1.0]), gl.STATIC_DRAW); + gl.enableVertexAttribArray(texCoordLocation); + gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0); + + gl.uniform1i(texLayerLocation, 0); + gl.uniform1i(texMaskLocation, 1); + + smaskCache = cache; + } + + function composeSMask(layer, mask, properties) { + var width = layer.width, height = layer.height; + + if (!smaskCache) { + initSmaskGL(); + } + var cache = smaskCache,canvas = cache.canvas, gl = cache.gl; + canvas.width = width; + canvas.height = height; + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.uniform2f(cache.resolutionLocation, width, height); + + if (properties.backdrop) { + gl.uniform4f(cache.resolutionLocation, properties.backdrop[0], + properties.backdrop[1], properties.backdrop[2], 1); + } else { + gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0); + } + gl.uniform1i(cache.subtypeLocation, + properties.subtype === 'Luminosity' ? 1 : 0); + + // Create a textures + var texture = createTexture(gl, layer, gl.TEXTURE0); + var maskTexture = createTexture(gl, mask, gl.TEXTURE1); + + + // Create a buffer and put a single clipspace rectangle in + // it (2 triangles) + var buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + 0, 0, + width, 0, + 0, height, + 0, height, + width, 0, + width, height]), gl.STATIC_DRAW); + gl.enableVertexAttribArray(cache.positionLocation); + gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0); + + // draw + gl.clearColor(0, 0, 0, 0); + gl.enable(gl.BLEND); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.drawArrays(gl.TRIANGLES, 0, 6); + + gl.flush(); + + gl.deleteTexture(texture); + gl.deleteTexture(maskTexture); + gl.deleteBuffer(buffer); + + return canvas; + } + + var figuresVertexShaderCode = '\ + attribute vec2 a_position; \ + attribute vec3 a_color; \ + \ + uniform vec2 u_resolution; \ + uniform vec2 u_scale; \ + uniform vec2 u_offset; \ + \ + varying vec4 v_color; \ + \ + void main() { \ + vec2 position = (a_position + u_offset) * u_scale; \ + vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0; \ + gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \ + \ + v_color = vec4(a_color / 255.0, 1.0); \ + } '; + + var figuresFragmentShaderCode = '\ + precision mediump float; \ + \ + varying vec4 v_color; \ + \ + void main() { \ + gl_FragColor = v_color; \ + } '; + + var figuresCache = null; + + function initFiguresGL() { + var canvas, gl; + + generateGL(); + canvas = currentCanvas; + currentCanvas = null; + gl = currentGL; + currentGL = null; + + // setup a GLSL program + var vertexShader = createVertexShader(gl, figuresVertexShaderCode); + var fragmentShader = createFragmentShader(gl, figuresFragmentShaderCode); + var program = createProgram(gl, [vertexShader, fragmentShader]); + gl.useProgram(program); + + var cache = {}; + cache.gl = gl; + cache.canvas = canvas; + cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution'); + cache.scaleLocation = gl.getUniformLocation(program, 'u_scale'); + cache.offsetLocation = gl.getUniformLocation(program, 'u_offset'); + cache.positionLocation = gl.getAttribLocation(program, 'a_position'); + cache.colorLocation = gl.getAttribLocation(program, 'a_color'); + + figuresCache = cache; + } + + function drawFigures(width, height, backgroundColor, figures, context) { + if (!figuresCache) { + initFiguresGL(); + } + var cache = figuresCache, canvas = cache.canvas, gl = cache.gl; + + canvas.width = width; + canvas.height = height; + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.uniform2f(cache.resolutionLocation, width, height); + + // count triangle points + var count = 0; + var i, ii, rows; + for (i = 0, ii = figures.length; i < ii; i++) { + switch (figures[i].type) { + case 'lattice': + rows = (figures[i].coords.length / figures[i].verticesPerRow) | 0; + count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6; + break; + case 'triangles': + count += figures[i].coords.length; + break; + } + } + // transfer data + var coords = new Float32Array(count * 2); + var colors = new Uint8Array(count * 3); + var coordsMap = context.coords, colorsMap = context.colors; + var pIndex = 0, cIndex = 0; + for (i = 0, ii = figures.length; i < ii; i++) { + var figure = figures[i], ps = figure.coords, cs = figure.colors; + switch (figure.type) { + case 'lattice': + var cols = figure.verticesPerRow; + rows = (ps.length / cols) | 0; + for (var row = 1; row < rows; row++) { + var offset = row * cols + 1; + for (var col = 1; col < cols; col++, offset++) { + coords[pIndex] = coordsMap[ps[offset - cols - 1]]; + coords[pIndex + 1] = coordsMap[ps[offset - cols - 1] + 1]; + coords[pIndex + 2] = coordsMap[ps[offset - cols]]; + coords[pIndex + 3] = coordsMap[ps[offset - cols] + 1]; + coords[pIndex + 4] = coordsMap[ps[offset - 1]]; + coords[pIndex + 5] = coordsMap[ps[offset - 1] + 1]; + colors[cIndex] = colorsMap[cs[offset - cols - 1]]; + colors[cIndex + 1] = colorsMap[cs[offset - cols - 1] + 1]; + colors[cIndex + 2] = colorsMap[cs[offset - cols - 1] + 2]; + colors[cIndex + 3] = colorsMap[cs[offset - cols]]; + colors[cIndex + 4] = colorsMap[cs[offset - cols] + 1]; + colors[cIndex + 5] = colorsMap[cs[offset - cols] + 2]; + colors[cIndex + 6] = colorsMap[cs[offset - 1]]; + colors[cIndex + 7] = colorsMap[cs[offset - 1] + 1]; + colors[cIndex + 8] = colorsMap[cs[offset - 1] + 2]; + + coords[pIndex + 6] = coords[pIndex + 2]; + coords[pIndex + 7] = coords[pIndex + 3]; + coords[pIndex + 8] = coords[pIndex + 4]; + coords[pIndex + 9] = coords[pIndex + 5]; + coords[pIndex + 10] = coordsMap[ps[offset]]; + coords[pIndex + 11] = coordsMap[ps[offset] + 1]; + colors[cIndex + 9] = colors[cIndex + 3]; + colors[cIndex + 10] = colors[cIndex + 4]; + colors[cIndex + 11] = colors[cIndex + 5]; + colors[cIndex + 12] = colors[cIndex + 6]; + colors[cIndex + 13] = colors[cIndex + 7]; + colors[cIndex + 14] = colors[cIndex + 8]; + colors[cIndex + 15] = colorsMap[cs[offset]]; + colors[cIndex + 16] = colorsMap[cs[offset] + 1]; + colors[cIndex + 17] = colorsMap[cs[offset] + 2]; + pIndex += 12; + cIndex += 18; + } + } + break; + case 'triangles': + for (var j = 0, jj = ps.length; j < jj; j++) { + coords[pIndex] = coordsMap[ps[j]]; + coords[pIndex + 1] = coordsMap[ps[j] + 1]; + colors[cIndex] = colorsMap[cs[i]]; + colors[cIndex + 1] = colorsMap[cs[j] + 1]; + colors[cIndex + 2] = colorsMap[cs[j] + 2]; + pIndex += 2; + cIndex += 3; + } + break; + } + } + + // draw + if (backgroundColor) { + gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255, + backgroundColor[2] / 255, 1.0); + } else { + gl.clearColor(0, 0, 0, 0); + } + gl.clear(gl.COLOR_BUFFER_BIT); + + var coordsBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, coordsBuffer); + gl.bufferData(gl.ARRAY_BUFFER, coords, gl.STATIC_DRAW); + gl.enableVertexAttribArray(cache.positionLocation); + gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0); + + var colorsBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer); + gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW); + gl.enableVertexAttribArray(cache.colorLocation); + gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false, + 0, 0); + + gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY); + gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY); + + gl.drawArrays(gl.TRIANGLES, 0, count); + + gl.flush(); + + gl.deleteBuffer(coordsBuffer); + gl.deleteBuffer(colorsBuffer); + + return canvas; + } + + function cleanup() { + if (smaskCache && smaskCache.canvas) { + smaskCache.canvas.width = 0; + smaskCache.canvas.height = 0; + } + if (figuresCache && figuresCache.canvas) { + figuresCache.canvas.width = 0; + figuresCache.canvas.height = 0; + } + smaskCache = null; + figuresCache = null; + } + + return { + get isEnabled() { + if (PDFJS.disableWebGL) { + return false; + } + var enabled = false; + try { + generateGL(); + enabled = !!currentGL; + } catch (e) { } + return shadow(this, 'isEnabled', enabled); + }, + composeSMask: composeSMask, + drawFigures: drawFigures, + clear: cleanup + }; +})(); + + +var ShadingIRs = {}; + +ShadingIRs.RadialAxial = { + fromIR: function RadialAxial_fromIR(raw) { + var type = raw[1]; + var colorStops = raw[2]; + var p0 = raw[3]; + var p1 = raw[4]; + var r0 = raw[5]; + var r1 = raw[6]; + return { + type: 'Pattern', + getPattern: function RadialAxial_getPattern(ctx) { + var grad; + if (type === 'axial') { + grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]); + } else if (type === 'radial') { + grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1); + } + + for (var i = 0, ii = colorStops.length; i < ii; ++i) { + var c = colorStops[i]; + grad.addColorStop(c[0], c[1]); + } + return grad; + } + }; + } +}; + +var createMeshCanvas = (function createMeshCanvasClosure() { + function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) { + // Very basic Gouraud-shaded triangle rasterization algorithm. + var coords = context.coords, colors = context.colors; + var bytes = data.data, rowSize = data.width * 4; + var tmp; + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp; + } + if (coords[p2 + 1] > coords[p3 + 1]) { + tmp = p2; p2 = p3; p3 = tmp; tmp = c2; c2 = c3; c3 = tmp; + } + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp; + } + var x1 = (coords[p1] + context.offsetX) * context.scaleX; + var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY; + var x2 = (coords[p2] + context.offsetX) * context.scaleX; + var y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY; + var x3 = (coords[p3] + context.offsetX) * context.scaleX; + var y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY; + if (y1 >= y3) { + return; + } + var c1r = colors[c1], c1g = colors[c1 + 1], c1b = colors[c1 + 2]; + var c2r = colors[c2], c2g = colors[c2 + 1], c2b = colors[c2 + 2]; + var c3r = colors[c3], c3g = colors[c3 + 1], c3b = colors[c3 + 2]; + + var minY = Math.round(y1), maxY = Math.round(y3); + var xa, car, cag, cab; + var xb, cbr, cbg, cbb; + var k; + for (var y = minY; y <= maxY; y++) { + if (y < y2) { + k = y < y1 ? 0 : y1 === y2 ? 1 : (y1 - y) / (y1 - y2); + xa = x1 - (x1 - x2) * k; + car = c1r - (c1r - c2r) * k; + cag = c1g - (c1g - c2g) * k; + cab = c1b - (c1b - c2b) * k; + } else { + k = y > y3 ? 1 : y2 === y3 ? 0 : (y2 - y) / (y2 - y3); + xa = x2 - (x2 - x3) * k; + car = c2r - (c2r - c3r) * k; + cag = c2g - (c2g - c3g) * k; + cab = c2b - (c2b - c3b) * k; + } + k = y < y1 ? 0 : y > y3 ? 1 : (y1 - y) / (y1 - y3); + xb = x1 - (x1 - x3) * k; + cbr = c1r - (c1r - c3r) * k; + cbg = c1g - (c1g - c3g) * k; + cbb = c1b - (c1b - c3b) * k; + var x1_ = Math.round(Math.min(xa, xb)); + var x2_ = Math.round(Math.max(xa, xb)); + var j = rowSize * y + x1_ * 4; + for (var x = x1_; x <= x2_; x++) { + k = (xa - x) / (xa - xb); + k = k < 0 ? 0 : k > 1 ? 1 : k; + bytes[j++] = (car - (car - cbr) * k) | 0; + bytes[j++] = (cag - (cag - cbg) * k) | 0; + bytes[j++] = (cab - (cab - cbb) * k) | 0; + bytes[j++] = 255; + } + } + } + + function drawFigure(data, figure, context) { + var ps = figure.coords; + var cs = figure.colors; + var i, ii; + switch (figure.type) { + case 'lattice': + var verticesPerRow = figure.verticesPerRow; + var rows = Math.floor(ps.length / verticesPerRow) - 1; + var cols = verticesPerRow - 1; + for (i = 0; i < rows; i++) { + var q = i * verticesPerRow; + for (var j = 0; j < cols; j++, q++) { + drawTriangle(data, context, + ps[q], ps[q + 1], ps[q + verticesPerRow], + cs[q], cs[q + 1], cs[q + verticesPerRow]); + drawTriangle(data, context, + ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], + cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]); + } + } + break; + case 'triangles': + for (i = 0, ii = ps.length; i < ii; i += 3) { + drawTriangle(data, context, + ps[i], ps[i + 1], ps[i + 2], + cs[i], cs[i + 1], cs[i + 2]); + } + break; + default: + error('illigal figure'); + break; + } + } + + function createMeshCanvas(bounds, combinesScale, coords, colors, figures, + backgroundColor) { + // we will increase scale on some weird factor to let antialiasing take + // care of "rough" edges + var EXPECTED_SCALE = 1.1; + // MAX_PATTERN_SIZE is used to avoid OOM situation. + var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough + + var offsetX = Math.floor(bounds[0]); + var offsetY = Math.floor(bounds[1]); + var boundsWidth = Math.ceil(bounds[2]) - offsetX; + var boundsHeight = Math.ceil(bounds[3]) - offsetY; + + var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] * + EXPECTED_SCALE)), MAX_PATTERN_SIZE); + var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] * + EXPECTED_SCALE)), MAX_PATTERN_SIZE); + var scaleX = boundsWidth / width; + var scaleY = boundsHeight / height; + + var context = { + coords: coords, + colors: colors, + offsetX: -offsetX, + offsetY: -offsetY, + scaleX: 1 / scaleX, + scaleY: 1 / scaleY + }; + + var canvas, tmpCanvas, i, ii; + if (WebGLUtils.isEnabled) { + canvas = WebGLUtils.drawFigures(width, height, backgroundColor, + figures, context); + + // https://bugzilla.mozilla.org/show_bug.cgi?id=972126 + tmpCanvas = CachedCanvases.getCanvas('mesh', width, height, false); + tmpCanvas.context.drawImage(canvas, 0, 0); + canvas = tmpCanvas.canvas; + } else { + tmpCanvas = CachedCanvases.getCanvas('mesh', width, height, false); + var tmpCtx = tmpCanvas.context; + + var data = tmpCtx.createImageData(width, height); + if (backgroundColor) { + var bytes = data.data; + for (i = 0, ii = bytes.length; i < ii; i += 4) { + bytes[i] = backgroundColor[0]; + bytes[i + 1] = backgroundColor[1]; + bytes[i + 2] = backgroundColor[2]; + bytes[i + 3] = 255; + } + } + for (i = 0; i < figures.length; i++) { + drawFigure(data, figures[i], context); + } + tmpCtx.putImageData(data, 0, 0); + canvas = tmpCanvas.canvas; + } + + return {canvas: canvas, offsetX: offsetX, offsetY: offsetY, + scaleX: scaleX, scaleY: scaleY}; + } + return createMeshCanvas; +})(); + +ShadingIRs.Mesh = { + fromIR: function Mesh_fromIR(raw) { + //var type = raw[1]; + var coords = raw[2]; + var colors = raw[3]; + var figures = raw[4]; + var bounds = raw[5]; + var matrix = raw[6]; + //var bbox = raw[7]; + var background = raw[8]; + return { + type: 'Pattern', + getPattern: function Mesh_getPattern(ctx, owner, shadingFill) { + var scale; + if (shadingFill) { + scale = Util.singularValueDecompose2dScale(ctx.mozCurrentTransform); + } else { + // Obtain scale from matrix and current transformation matrix. + scale = Util.singularValueDecompose2dScale(owner.baseTransform); + if (matrix) { + var matrixScale = Util.singularValueDecompose2dScale(matrix); + scale = [scale[0] * matrixScale[0], + scale[1] * matrixScale[1]]; + } + } + + + // Rasterizing on the main thread since sending/queue large canvases + // might cause OOM. + var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords, + colors, figures, shadingFill ? null : background); + + if (!shadingFill) { + ctx.setTransform.apply(ctx, owner.baseTransform); + if (matrix) { + ctx.transform.apply(ctx, matrix); + } + } + + ctx.translate(temporaryPatternCanvas.offsetX, + temporaryPatternCanvas.offsetY); + ctx.scale(temporaryPatternCanvas.scaleX, + temporaryPatternCanvas.scaleY); + + return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat'); + } + }; + } +}; + +ShadingIRs.Dummy = { + fromIR: function Dummy_fromIR() { + return { + type: 'Pattern', + getPattern: function Dummy_fromIR_getPattern() { + return 'hotpink'; + } + }; + } +}; + +function getShadingPatternFromIR(raw) { + var shadingIR = ShadingIRs[raw[0]]; + if (!shadingIR) { + error('Unknown IR type: ' + raw[0]); + } + return shadingIR.fromIR(raw); +} + +var TilingPattern = (function TilingPatternClosure() { + var PaintType = { + COLORED: 1, + UNCOLORED: 2 + }; + + var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough + + function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) { + this.operatorList = IR[2]; + this.matrix = IR[3] || [1, 0, 0, 1, 0, 0]; + this.bbox = IR[4]; + this.xstep = IR[5]; + this.ystep = IR[6]; + this.paintType = IR[7]; + this.tilingType = IR[8]; + this.color = color; + this.objs = objs; + this.commonObjs = commonObjs; + this.baseTransform = baseTransform; + this.type = 'Pattern'; + this.ctx = ctx; + } + + TilingPattern.prototype = { + createPatternCanvas: function TilinPattern_createPatternCanvas(owner) { + var operatorList = this.operatorList; + var bbox = this.bbox; + var xstep = this.xstep; + var ystep = this.ystep; + var paintType = this.paintType; + var tilingType = this.tilingType; + var color = this.color; + var objs = this.objs; + var commonObjs = this.commonObjs; + + info('TilingType: ' + tilingType); + + var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3]; + + var topLeft = [x0, y0]; + // we want the canvas to be as large as the step size + var botRight = [x0 + xstep, y0 + ystep]; + + var width = botRight[0] - topLeft[0]; + var height = botRight[1] - topLeft[1]; + + // Obtain scale from matrix and current transformation matrix. + var matrixScale = Util.singularValueDecompose2dScale(this.matrix); + var curMatrixScale = Util.singularValueDecompose2dScale( + this.baseTransform); + var combinedScale = [matrixScale[0] * curMatrixScale[0], + matrixScale[1] * curMatrixScale[1]]; + + // MAX_PATTERN_SIZE is used to avoid OOM situation. + // Use width and height values that are as close as possible to the end + // result when the pattern is used. Too low value makes the pattern look + // blurry. Too large value makes it look too crispy. + width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])), + MAX_PATTERN_SIZE); + + height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])), + MAX_PATTERN_SIZE); + + var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true); + var tmpCtx = tmpCanvas.context; + var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs); + graphics.groupLevel = owner.groupLevel; + + this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color); + + this.setScale(width, height, xstep, ystep); + this.transformToScale(graphics); + + // transform coordinates to pattern space + var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]]; + graphics.transform.apply(graphics, tmpTranslate); + + this.clipBbox(graphics, bbox, x0, y0, x1, y1); + + graphics.executeOperatorList(operatorList); + return tmpCanvas.canvas; + }, + + setScale: function TilingPattern_setScale(width, height, xstep, ystep) { + this.scale = [width / xstep, height / ystep]; + }, + + transformToScale: function TilingPattern_transformToScale(graphics) { + var scale = this.scale; + var tmpScale = [scale[0], 0, 0, scale[1], 0, 0]; + graphics.transform.apply(graphics, tmpScale); + }, + + scaleToContext: function TilingPattern_scaleToContext() { + var scale = this.scale; + this.ctx.scale(1 / scale[0], 1 / scale[1]); + }, + + clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) { + if (bbox && isArray(bbox) && bbox.length === 4) { + var bboxWidth = x1 - x0; + var bboxHeight = y1 - y0; + graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight); + graphics.clip(); + graphics.endPath(); + } + }, + + setFillAndStrokeStyleToContext: + function setFillAndStrokeStyleToContext(context, paintType, color) { + switch (paintType) { + case PaintType.COLORED: + var ctx = this.ctx; + context.fillStyle = ctx.fillStyle; + context.strokeStyle = ctx.strokeStyle; + break; + case PaintType.UNCOLORED: + var cssColor = Util.makeCssRgb(color[0], color[1], color[2]); + context.fillStyle = cssColor; + context.strokeStyle = cssColor; + break; + default: + error('Unsupported paint type: ' + paintType); + } + }, + + getPattern: function TilingPattern_getPattern(ctx, owner) { + var temporaryPatternCanvas = this.createPatternCanvas(owner); + + ctx = this.ctx; + ctx.setTransform.apply(ctx, this.baseTransform); + ctx.transform.apply(ctx, this.matrix); + this.scaleToContext(); + + return ctx.createPattern(temporaryPatternCanvas, 'repeat'); + } + }; + + return TilingPattern; +})(); + + +PDFJS.disableFontFace = false; + +var FontLoader = { + insertRule: function fontLoaderInsertRule(rule) { + var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + if (!styleElement) { + styleElement = document.createElement('style'); + styleElement.id = 'PDFJS_FONT_STYLE_TAG'; + document.documentElement.getElementsByTagName('head')[0].appendChild( + styleElement); + } + + var styleSheet = styleElement.sheet; + styleSheet.insertRule(rule, styleSheet.cssRules.length); + }, + + clear: function fontLoaderClear() { + var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + if (styleElement) { + styleElement.parentNode.removeChild(styleElement); + } + this.nativeFontFaces.forEach(function(nativeFontFace) { + document.fonts.delete(nativeFontFace); + }); + this.nativeFontFaces.length = 0; + }, + get loadTestFont() { + // This is a CFF font with 1 glyph for '.' that fills its entire width and + // height. + return shadow(this, 'loadTestFont', atob( + 'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' + + 'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' + + 'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' + + 'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' + + 'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' + + 'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' + + 'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' + + 'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' + + 'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' + + 'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' + + 'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' + + 'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' + + 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' + + 'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' + + 'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' + + 'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' + + 'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' + + 'ABAAAAAAAAAAAD6AAAAAAAAA==' + )); + }, + + loadTestFontId: 0, + + loadingContext: { + requests: [], + nextRequestId: 0 + }, + + isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() { + if (isWorker) { + return false; + } + + // User agent string sniffing is bad, but there is no reliable way to tell + // if font is fully loaded and ready to be used with canvas. + var userAgent = window.navigator.userAgent; + var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent); + if (m && m[1] >= 14) { + return true; + } + // TODO other browsers + if (userAgent === 'node') { + return true; + } + return false; + })(), + + nativeFontFaces: [], + + isFontLoadingAPISupported: (!isWorker && typeof document !== 'undefined' && + !!document.fonts), + + addNativeFontFace: function fontLoader_addNativeFontFace(nativeFontFace) { + this.nativeFontFaces.push(nativeFontFace); + document.fonts.add(nativeFontFace); + }, + + bind: function fontLoaderBind(fonts, callback) { + assert(!isWorker, 'bind() shall be called from main thread'); + + var rules = []; + var fontsToLoad = []; + var fontLoadPromises = []; + for (var i = 0, ii = fonts.length; i < ii; i++) { + var font = fonts[i]; + + // Add the font to the DOM only once or skip if the font + // is already loaded. + if (font.attached || font.loading === false) { + continue; + } + font.attached = true; + + if (this.isFontLoadingAPISupported) { + var nativeFontFace = font.createNativeFontFace(); + if (nativeFontFace) { + fontLoadPromises.push(nativeFontFace.loaded); + } + } else { + var rule = font.bindDOM(); + if (rule) { + rules.push(rule); + fontsToLoad.push(font); + } + } + } + + var request = FontLoader.queueLoadingCallback(callback); + if (this.isFontLoadingAPISupported) { + Promise.all(fontsToLoad).then(function() { + request.complete(); + }); + } else if (rules.length > 0 && !this.isSyncFontLoadingSupported) { + FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request); + } else { + request.complete(); + } + }, + + queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) { + function LoadLoader_completeRequest() { + assert(!request.end, 'completeRequest() cannot be called twice'); + request.end = Date.now(); + + // sending all completed requests in order how they were queued + while (context.requests.length > 0 && context.requests[0].end) { + var otherRequest = context.requests.shift(); + setTimeout(otherRequest.callback, 0); + } + } + + var context = FontLoader.loadingContext; + var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++); + var request = { + id: requestId, + complete: LoadLoader_completeRequest, + callback: callback, + started: Date.now() + }; + context.requests.push(request); + return request; + }, + + prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, + fonts, + request) { + /** Hack begin */ + // There's currently no event when a font has finished downloading so the + // following code is a dirty hack to 'guess' when a font is + // ready. It's assumed fonts are loaded in order, so add a known test + // font after the desired fonts and then test for the loading of that + // test font. + + function int32(data, offset) { + return (data.charCodeAt(offset) << 24) | + (data.charCodeAt(offset + 1) << 16) | + (data.charCodeAt(offset + 2) << 8) | + (data.charCodeAt(offset + 3) & 0xff); + } + + function spliceString(s, offset, remove, insert) { + var chunk1 = s.substr(0, offset); + var chunk2 = s.substr(offset + remove); + return chunk1 + insert + chunk2; + } + + var i, ii; + + var canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + var ctx = canvas.getContext('2d'); + + var called = 0; + function isFontReady(name, callback) { + called++; + // With setTimeout clamping this gives the font ~100ms to load. + if(called > 30) { + warn('Load test font never loaded.'); + callback(); + return; + } + ctx.font = '30px ' + name; + ctx.fillText('.', 0, 20); + var imageData = ctx.getImageData(0, 0, 1, 1); + if (imageData.data[3] > 0) { + callback(); + return; + } + setTimeout(isFontReady.bind(null, name, callback)); + } + + var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++; + // Chromium seems to cache fonts based on a hash of the actual font data, + // so the font must be modified for each load test else it will appear to + // be loaded already. + // TODO: This could maybe be made faster by avoiding the btoa of the full + // font by splitting it in chunks before hand and padding the font id. + var data = this.loadTestFont; + var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum) + data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, + loadTestFontId); + // CFF checksum is important for IE, adjusting it + var CFF_CHECKSUM_OFFSET = 16; + var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X' + var checksum = int32(data, CFF_CHECKSUM_OFFSET); + for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) { + checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0; + } + if (i < loadTestFontId.length) { // align to 4 bytes boundary + checksum = (checksum - XXXX_VALUE + + int32(loadTestFontId + 'XXX', i)) | 0; + } + data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum)); + + var url = 'url(data:font/opentype;base64,' + btoa(data) + ');'; + var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' + + url + '}'; + FontLoader.insertRule(rule); + + var names = []; + for (i = 0, ii = fonts.length; i < ii; i++) { + names.push(fonts[i].loadedName); + } + names.push(loadTestFontId); + + var div = document.createElement('div'); + div.setAttribute('style', + 'visibility: hidden;' + + 'width: 10px; height: 10px;' + + 'position: absolute; top: 0px; left: 0px;'); + for (i = 0, ii = names.length; i < ii; ++i) { + var span = document.createElement('span'); + span.textContent = 'Hi'; + span.style.fontFamily = names[i]; + div.appendChild(span); + } + document.body.appendChild(div); + + isFontReady(loadTestFontId, function() { + document.body.removeChild(div); + request.complete(); + }); + /** Hack end */ + } +}; + +var FontFaceObject = (function FontFaceObjectClosure() { + function FontFaceObject(name, file, properties) { + this.compiledGlyphs = {}; + if (arguments.length === 1) { + // importing translated data + var data = arguments[0]; + for (var i in data) { + this[i] = data[i]; + } + + } + } + FontFaceObject.prototype = { + createNativeFontFace: function FontFaceObject_createNativeFontFace() { + if (!this.data) { + return null; + } + + if (PDFJS.disableFontFace) { + this.disableFontFace = true; + return null; + } + + var nativeFontFace = new FontFace(this.loadedName, this.data, {}); + + FontLoader.addNativeFontFace(nativeFontFace); + + if (PDFJS.pdfBug && 'FontInspector' in globalScope && + globalScope['FontInspector'].enabled) { + globalScope['FontInspector'].fontAdded(this); + } + return nativeFontFace; + }, + + bindDOM: function FontFaceObject_bindDOM() { + if (!this.data) { + return null; + } + + if (PDFJS.disableFontFace) { + this.disableFontFace = true; + return null; + } + + var data = bytesToString(new Uint8Array(this.data)); + var fontName = this.loadedName; + + // Add the font-face rule to the document + var url = ('url(data:' + this.mimetype + ';base64,' + + window.btoa(data) + ');'); + var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}'; + FontLoader.insertRule(rule); + + if (PDFJS.pdfBug && 'FontInspector' in globalScope && + globalScope['FontInspector'].enabled) { + globalScope['FontInspector'].fontAdded(this, url); + } + + return rule; + }, + + getPathGenerator: function FontLoader_getPathGenerator(objs, character) { + if (!(character in this.compiledGlyphs)) { + var js = objs.get(this.loadedName + '_path_' + character); + /*jshint -W054 */ + this.compiledGlyphs[character] = new Function('c', 'size', js); + } + return this.compiledGlyphs[character]; + } + }; + return FontFaceObject; +})(); + + +var ANNOT_MIN_SIZE = 10; // px + +var AnnotationUtils = (function AnnotationUtilsClosure() { + // TODO(mack): This dupes some of the logic in CanvasGraphics.setFont() + function setTextStyles(element, item, fontObj) { + + var style = element.style; + style.fontSize = item.fontSize + 'px'; + style.direction = item.fontDirection < 0 ? 'rtl': 'ltr'; + + if (!fontObj) { + return; + } + + style.fontWeight = fontObj.black ? + (fontObj.bold ? 'bolder' : 'bold') : + (fontObj.bold ? 'bold' : 'normal'); + style.fontStyle = fontObj.italic ? 'italic' : 'normal'; + + var fontName = fontObj.loadedName; + var fontFamily = fontName ? '"' + fontName + '", ' : ''; + // Use a reasonable default font if the font doesn't specify a fallback + var fallbackName = fontObj.fallbackName || 'Helvetica, sans-serif'; + style.fontFamily = fontFamily + fallbackName; + } + + function initContainer(item, drawBorder) { + var container = document.createElement('section'); + var cstyle = container.style; + var width = item.rect[2] - item.rect[0]; + var height = item.rect[3] - item.rect[1]; + + var bWidth = item.borderWidth || 0; + if (bWidth) { + width = width - 2 * bWidth; + height = height - 2 * bWidth; + cstyle.borderWidth = bWidth + 'px'; + var color = item.color; + if (drawBorder && color) { + cstyle.borderStyle = 'solid'; + cstyle.borderColor = Util.makeCssRgb(Math.round(color[0] * 255), + Math.round(color[1] * 255), + Math.round(color[2] * 255)); + } + } + cstyle.width = width + 'px'; + cstyle.height = height + 'px'; + return container; + } + + function getHtmlElementForTextWidgetAnnotation(item, commonObjs) { + var element = document.createElement('div'); + var width = item.rect[2] - item.rect[0]; + var height = item.rect[3] - item.rect[1]; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + element.style.display = 'table'; + + var content = document.createElement('div'); + content.textContent = item.fieldValue; + var textAlignment = item.textAlignment; + content.style.textAlign = ['left', 'center', 'right'][textAlignment]; + content.style.verticalAlign = 'middle'; + content.style.display = 'table-cell'; + + var fontObj = item.fontRefName ? + commonObjs.getData(item.fontRefName) : null; + setTextStyles(content, item, fontObj); + + element.appendChild(content); + + return element; + } + + function getHtmlElementForTextAnnotation(item) { + var rect = item.rect; + + // sanity check because of OOo-generated PDFs + if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) { + rect[3] = rect[1] + ANNOT_MIN_SIZE; + } + if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) { + rect[2] = rect[0] + (rect[3] - rect[1]); // make it square + } + + var container = initContainer(item, false); + container.className = 'annotText'; + + var image = document.createElement('img'); + image.style.height = container.style.height; + image.style.width = container.style.width; + var iconName = item.name; + image.src = PDFJS.imageResourcesPath + 'annotation-' + + iconName.toLowerCase() + '.svg'; + image.alt = '[{{type}} Annotation]'; + image.dataset.l10nId = 'text_annotation_type'; + image.dataset.l10nArgs = JSON.stringify({type: iconName}); + + var contentWrapper = document.createElement('div'); + contentWrapper.className = 'annotTextContentWrapper'; + contentWrapper.style.left = Math.floor(rect[2] - rect[0] + 5) + 'px'; + contentWrapper.style.top = '-10px'; + + var content = document.createElement('div'); + content.className = 'annotTextContent'; + content.setAttribute('hidden', true); + + var i, ii; + if (item.hasBgColor) { + var color = item.color; + + // Enlighten the color (70%) + var BACKGROUND_ENLIGHT = 0.7; + var r = BACKGROUND_ENLIGHT * (1.0 - color[0]) + color[0]; + var g = BACKGROUND_ENLIGHT * (1.0 - color[1]) + color[1]; + var b = BACKGROUND_ENLIGHT * (1.0 - color[2]) + color[2]; + content.style.backgroundColor = Util.makeCssRgb((r * 255) | 0, + (g * 255) | 0, + (b * 255) | 0); + } + + var title = document.createElement('h1'); + var text = document.createElement('p'); + title.textContent = item.title; + + if (!item.content && !item.title) { + content.setAttribute('hidden', true); + } else { + var e = document.createElement('span'); + var lines = item.content.split(/(?:\r\n?|\n)/); + for (i = 0, ii = lines.length; i < ii; ++i) { + var line = lines[i]; + e.appendChild(document.createTextNode(line)); + if (i < (ii - 1)) { + e.appendChild(document.createElement('br')); + } + } + text.appendChild(e); + + var pinned = false; + + var showAnnotation = function showAnnotation(pin) { + if (pin) { + pinned = true; + } + if (content.hasAttribute('hidden')) { + container.style.zIndex += 1; + content.removeAttribute('hidden'); + } + }; + + var hideAnnotation = function hideAnnotation(unpin) { + if (unpin) { + pinned = false; + } + if (!content.hasAttribute('hidden') && !pinned) { + container.style.zIndex -= 1; + content.setAttribute('hidden', true); + } + }; + + var toggleAnnotation = function toggleAnnotation() { + if (pinned) { + hideAnnotation(true); + } else { + showAnnotation(true); + } + }; + + image.addEventListener('click', function image_clickHandler() { + toggleAnnotation(); + }, false); + image.addEventListener('mouseover', function image_mouseOverHandler() { + showAnnotation(); + }, false); + image.addEventListener('mouseout', function image_mouseOutHandler() { + hideAnnotation(); + }, false); + + content.addEventListener('click', function content_clickHandler() { + hideAnnotation(true); + }, false); + } + + content.appendChild(title); + content.appendChild(text); + contentWrapper.appendChild(content); + container.appendChild(image); + container.appendChild(contentWrapper); + + return container; + } + + function getHtmlElementForLinkAnnotation(item) { + var container = initContainer(item, true); + container.className = 'annotLink'; + + var link = document.createElement('a'); + link.href = link.title = item.url || ''; + if (item.url && PDFJS.openExternalLinksInNewWindow) { + link.target = '_blank'; + } + + container.appendChild(link); + + return container; + } + + function getHtmlElement(data, objs) { + switch (data.annotationType) { + case AnnotationType.WIDGET: + return getHtmlElementForTextWidgetAnnotation(data, objs); + case AnnotationType.TEXT: + return getHtmlElementForTextAnnotation(data); + case AnnotationType.LINK: + return getHtmlElementForLinkAnnotation(data); + default: + throw new Error('Unsupported annotationType: ' + data.annotationType); + } + } + + return { + getHtmlElement: getHtmlElement + }; +})(); +PDFJS.AnnotationUtils = AnnotationUtils; + + +var SVG_DEFAULTS = { + fontStyle: 'normal', + fontWeight: 'normal', + fillColor: '#000000' +}; + +var convertImgDataToPng = (function convertImgDataToPngClosure() { + var PNG_HEADER = + new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); + + var CHUNK_WRAPPER_SIZE = 12; + + var crcTable = new Int32Array(256); + for (var i = 0; i < 256; i++) { + var c = i; + for (var h = 0; h < 8; h++) { + if (c & 1) { + c = 0xedB88320 ^ ((c >> 1) & 0x7fffffff); + } else { + c = (c >> 1) & 0x7fffffff; + } + } + crcTable[i] = c; + } + + function crc32(data, start, end) { + var crc = -1; + for (var i = start; i < end; i++) { + var a = (crc ^ data[i]) & 0xff; + var b = crcTable[a]; + crc = (crc >>> 8) ^ b; + } + return crc ^ -1; + } + + function writePngChunk(type, body, data, offset) { + var p = offset; + var len = body.length; + + data[p] = len >> 24 & 0xff; + data[p + 1] = len >> 16 & 0xff; + data[p + 2] = len >> 8 & 0xff; + data[p + 3] = len & 0xff; + p += 4; + + data[p] = type.charCodeAt(0) & 0xff; + data[p + 1] = type.charCodeAt(1) & 0xff; + data[p + 2] = type.charCodeAt(2) & 0xff; + data[p + 3] = type.charCodeAt(3) & 0xff; + p += 4; + + data.set(body, p); + p += body.length; + + var crc = crc32(data, offset + 4, p); + + data[p] = crc >> 24 & 0xff; + data[p + 1] = crc >> 16 & 0xff; + data[p + 2] = crc >> 8 & 0xff; + data[p + 3] = crc & 0xff; + } + + function adler32(data, start, end) { + var a = 1; + var b = 0; + for (var i = start; i < end; ++i) { + a = (a + (data[i] & 0xff)) % 65521; + b = (b + a) % 65521; + } + return (b << 16) | a; + } + + function encode(imgData, kind) { + var width = imgData.width; + var height = imgData.height; + var bitDepth, colorType, lineSize; + var bytes = imgData.data; + + switch (kind) { + case ImageKind.GRAYSCALE_1BPP: + colorType = 0; + bitDepth = 1; + lineSize = (width + 7) >> 3; + break; + case ImageKind.RGB_24BPP: + colorType = 2; + bitDepth = 8; + lineSize = width * 3; + break; + case ImageKind.RGBA_32BPP: + colorType = 6; + bitDepth = 8; + lineSize = width * 4; + break; + default: + throw new Error('invalid format'); + } + + // prefix every row with predictor 0 + var literals = new Uint8Array((1 + lineSize) * height); + var offsetLiterals = 0, offsetBytes = 0; + var y, i; + for (y = 0; y < height; ++y) { + literals[offsetLiterals++] = 0; // no prediction + literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize), + offsetLiterals); + offsetBytes += lineSize; + offsetLiterals += lineSize; + } + + if (kind === ImageKind.GRAYSCALE_1BPP) { + // inverting for B/W + offsetLiterals = 0; + for (y = 0; y < height; y++) { + offsetLiterals++; // skipping predictor + for (i = 0; i < lineSize; i++) { + literals[offsetLiterals++] ^= 0xFF; + } + } + } + + var ihdr = new Uint8Array([ + width >> 24 & 0xff, + width >> 16 & 0xff, + width >> 8 & 0xff, + width & 0xff, + height >> 24 & 0xff, + height >> 16 & 0xff, + height >> 8 & 0xff, + height & 0xff, + bitDepth, // bit depth + colorType, // color type + 0x00, // compression method + 0x00, // filter method + 0x00 // interlace method + ]); + + var len = literals.length; + var maxBlockLength = 0xFFFF; + + var deflateBlocks = Math.ceil(len / maxBlockLength); + var idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4); + var pi = 0; + idat[pi++] = 0x78; // compression method and flags + idat[pi++] = 0x9c; // flags + + var pos = 0; + while (len > maxBlockLength) { + // writing non-final DEFLATE blocks type 0 and length of 65535 + idat[pi++] = 0x00; + idat[pi++] = 0xff; + idat[pi++] = 0xff; + idat[pi++] = 0x00; + idat[pi++] = 0x00; + idat.set(literals.subarray(pos, pos + maxBlockLength), pi); + pi += maxBlockLength; + pos += maxBlockLength; + len -= maxBlockLength; + } + + // writing non-final DEFLATE blocks type 0 + idat[pi++] = 0x01; + idat[pi++] = len & 0xff; + idat[pi++] = len >> 8 & 0xff; + idat[pi++] = (~len & 0xffff) & 0xff; + idat[pi++] = (~len & 0xffff) >> 8 & 0xff; + idat.set(literals.subarray(pos), pi); + pi += literals.length - pos; + + var adler = adler32(literals, 0, literals.length); // checksum + idat[pi++] = adler >> 24 & 0xff; + idat[pi++] = adler >> 16 & 0xff; + idat[pi++] = adler >> 8 & 0xff; + idat[pi++] = adler & 0xff; + + // PNG will consists: header, IHDR+data, IDAT+data, and IEND. + var pngLength = PNG_HEADER.length + (CHUNK_WRAPPER_SIZE * 3) + + ihdr.length + idat.length; + var data = new Uint8Array(pngLength); + var offset = 0; + data.set(PNG_HEADER, offset); + offset += PNG_HEADER.length; + writePngChunk('IHDR', ihdr, data, offset); + offset += CHUNK_WRAPPER_SIZE + ihdr.length; + writePngChunk('IDATA', idat, data, offset); + offset += CHUNK_WRAPPER_SIZE + idat.length; + writePngChunk('IEND', new Uint8Array(0), data, offset); + + return PDFJS.createObjectURL(data, 'image/png'); + } + + return function convertImgDataToPng(imgData) { + var kind = (imgData.kind === undefined ? + ImageKind.GRAYSCALE_1BPP : imgData.kind); + return encode(imgData, kind); + }; +})(); + +var SVGExtraState = (function SVGExtraStateClosure() { + function SVGExtraState() { + this.fontSizeScale = 1; + this.fontWeight = SVG_DEFAULTS.fontWeight; + this.fontSize = 0; + + this.textMatrix = IDENTITY_MATRIX; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.leading = 0; + + // Current point (in user coordinates) + this.x = 0; + this.y = 0; + + // Start of text line (in text coordinates) + this.lineX = 0; + this.lineY = 0; + + // Character and word spacing + this.charSpacing = 0; + this.wordSpacing = 0; + this.textHScale = 1; + this.textRise = 0; + + // Default foreground and background colors + this.fillColor = SVG_DEFAULTS.fillColor; + this.strokeColor = '#000000'; + + this.fillAlpha = 1; + this.strokeAlpha = 1; + this.lineWidth = 1; + this.lineJoin = ''; + this.lineCap = ''; + this.miterLimit = 0; + + this.dashArray = []; + this.dashPhase = 0; + + this.dependencies = []; + + // Clipping + this.clipId = ''; + this.pendingClip = false; + + this.maskId = ''; + } + + SVGExtraState.prototype = { + clone: function SVGExtraState_clone() { + return Object.create(this); + }, + setCurrentPoint: function SVGExtraState_setCurrentPoint(x, y) { + this.x = x; + this.y = y; + } + }; + return SVGExtraState; +})(); + +var SVGGraphics = (function SVGGraphicsClosure() { + function createScratchSVG(width, height) { + var NS = 'http://www.w3.org/2000/svg'; + var svg = document.createElementNS(NS, 'svg:svg'); + svg.setAttributeNS(null, 'version', '1.1'); + svg.setAttributeNS(null, 'width', width + 'px'); + svg.setAttributeNS(null, 'height', height + 'px'); + svg.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height); + return svg; + } + + function opListToTree(opList) { + var opTree = []; + var tmp = []; + var opListLen = opList.length; + + for (var x = 0; x < opListLen; x++) { + if (opList[x].fn === 'save') { + opTree.push({'fnId': 92, 'fn': 'group', 'items': []}); + tmp.push(opTree); + opTree = opTree[opTree.length - 1].items; + continue; + } + + if(opList[x].fn === 'restore') { + opTree = tmp.pop(); + } else { + opTree.push(opList[x]); + } + } + return opTree; + } + + /** + * Formats float number. + * @param value {number} number to format. + * @returns {string} + */ + function pf(value) { + if (value === (value | 0)) { // integer number + return value.toString(); + } + var s = value.toFixed(10); + var i = s.length - 1; + if (s[i] !== '0') { + return s; + } + // removing trailing zeros + do { + i--; + } while (s[i] === '0'); + return s.substr(0, s[i] === '.' ? i : i + 1); + } + + /** + * Formats transform matrix. The standard rotation, scale and translate + * matrices are replaced by their shorter forms, and for identity matrix + * returns empty string to save the memory. + * @param m {Array} matrix to format. + * @returns {string} + */ + function pm(m) { + if (m[4] === 0 && m[5] === 0) { + if (m[1] === 0 && m[2] === 0) { + if (m[0] === 1 && m[3] === 1) { + return ''; + } + return 'scale(' + pf(m[0]) + ' ' + pf(m[3]) + ')'; + } + if (m[0] === m[3] && m[1] === -m[2]) { + var a = Math.acos(m[0]) * 180 / Math.PI; + return 'rotate(' + pf(a) + ')'; + } + } else { + if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) { + return 'translate(' + pf(m[4]) + ' ' + pf(m[5]) + ')'; + } + } + return 'matrix(' + pf(m[0]) + ' ' + pf(m[1]) + ' ' + pf(m[2]) + ' ' + + pf(m[3]) + ' ' + pf(m[4]) + ' ' + pf(m[5]) + ')'; + } + + function SVGGraphics(commonObjs, objs) { + this.current = new SVGExtraState(); + this.transformMatrix = IDENTITY_MATRIX; // Graphics state matrix + this.transformStack = []; + this.extraStack = []; + this.commonObjs = commonObjs; + this.objs = objs; + this.pendingEOFill = false; + + this.embedFonts = false; + this.embeddedFonts = {}; + this.cssStyle = null; + } + + var NS = 'http://www.w3.org/2000/svg'; + var XML_NS = 'http://www.w3.org/XML/1998/namespace'; + var XLINK_NS = 'http://www.w3.org/1999/xlink'; + var LINE_CAP_STYLES = ['butt', 'round', 'square']; + var LINE_JOIN_STYLES = ['miter', 'round', 'bevel']; + var clipCount = 0; + var maskCount = 0; + + SVGGraphics.prototype = { + save: function SVGGraphics_save() { + this.transformStack.push(this.transformMatrix); + var old = this.current; + this.extraStack.push(old); + this.current = old.clone(); + }, + + restore: function SVGGraphics_restore() { + this.transformMatrix = this.transformStack.pop(); + this.current = this.extraStack.pop(); + + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + this.pgrp.appendChild(this.tgrp); + }, + + group: function SVGGraphics_group(items) { + this.save(); + this.executeOpTree(items); + this.restore(); + }, + + loadDependencies: function SVGGraphics_loadDependencies(operatorList) { + var fnArray = operatorList.fnArray; + var fnArrayLen = fnArray.length; + var argsArray = operatorList.argsArray; + + var self = this; + for (var i = 0; i < fnArrayLen; i++) { + if (OPS.dependency === fnArray[i]) { + var deps = argsArray[i]; + for (var n = 0, nn = deps.length; n < nn; n++) { + var obj = deps[n]; + var common = obj.substring(0, 2) === 'g_'; + var promise; + if (common) { + promise = new Promise(function(resolve) { + self.commonObjs.get(obj, resolve); + }); + } else { + promise = new Promise(function(resolve) { + self.objs.get(obj, resolve); + }); + } + this.current.dependencies.push(promise); + } + } + } + return Promise.all(this.current.dependencies); + }, + + transform: function SVGGraphics_transform(a, b, c, d, e, f) { + var transformMatrix = [a, b, c, d, e, f]; + this.transformMatrix = PDFJS.Util.transform(this.transformMatrix, + transformMatrix); + + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + }, + + getSVG: function SVGGraphics_getSVG(operatorList, viewport) { + this.svg = createScratchSVG(viewport.width, viewport.height); + this.viewport = viewport; + + return this.loadDependencies(operatorList).then(function () { + this.transformMatrix = IDENTITY_MATRIX; + this.pgrp = document.createElementNS(NS, 'svg:g'); // Parent group + this.pgrp.setAttributeNS(null, 'transform', pm(viewport.transform)); + this.tgrp = document.createElementNS(NS, 'svg:g'); // Transform group + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + this.defs = document.createElementNS(NS, 'svg:defs'); + this.pgrp.appendChild(this.defs); + this.pgrp.appendChild(this.tgrp); + this.svg.appendChild(this.pgrp); + var opTree = this.convertOpList(operatorList); + this.executeOpTree(opTree); + return this.svg; + }.bind(this)); + }, + + convertOpList: function SVGGraphics_convertOpList(operatorList) { + var argsArray = operatorList.argsArray; + var fnArray = operatorList.fnArray; + var fnArrayLen = fnArray.length; + var REVOPS = []; + var opList = []; + + for (var op in OPS) { + REVOPS[OPS[op]] = op; + } + + for (var x = 0; x < fnArrayLen; x++) { + var fnId = fnArray[x]; + opList.push({'fnId' : fnId, 'fn': REVOPS[fnId], 'args': argsArray[x]}); + } + return opListToTree(opList); + }, + + executeOpTree: function SVGGraphics_executeOpTree(opTree) { + var opTreeLen = opTree.length; + for(var x = 0; x < opTreeLen; x++) { + var fn = opTree[x].fn; + var fnId = opTree[x].fnId; + var args = opTree[x].args; + + switch (fnId | 0) { + case OPS.beginText: + this.beginText(); + break; + case OPS.setLeading: + this.setLeading(args); + break; + case OPS.setLeadingMoveText: + this.setLeadingMoveText(args[0], args[1]); + break; + case OPS.setFont: + this.setFont(args); + break; + case OPS.showText: + this.showText(args[0]); + break; + case OPS.showSpacedText: + this.showText(args[0]); + break; + case OPS.endText: + this.endText(); + break; + case OPS.moveText: + this.moveText(args[0], args[1]); + break; + case OPS.setCharSpacing: + this.setCharSpacing(args[0]); + break; + case OPS.setWordSpacing: + this.setWordSpacing(args[0]); + break; + case OPS.setHScale: + this.setHScale(args[0]); + break; + case OPS.setTextMatrix: + this.setTextMatrix(args[0], args[1], args[2], + args[3], args[4], args[5]); + break; + case OPS.setLineWidth: + this.setLineWidth(args[0]); + break; + case OPS.setLineJoin: + this.setLineJoin(args[0]); + break; + case OPS.setLineCap: + this.setLineCap(args[0]); + break; + case OPS.setMiterLimit: + this.setMiterLimit(args[0]); + break; + case OPS.setFillRGBColor: + this.setFillRGBColor(args[0], args[1], args[2]); + break; + case OPS.setStrokeRGBColor: + this.setStrokeRGBColor(args[0], args[1], args[2]); + break; + case OPS.setDash: + this.setDash(args[0], args[1]); + break; + case OPS.setGState: + this.setGState(args[0]); + break; + case OPS.fill: + this.fill(); + break; + case OPS.eoFill: + this.eoFill(); + break; + case OPS.stroke: + this.stroke(); + break; + case OPS.fillStroke: + this.fillStroke(); + break; + case OPS.eoFillStroke: + this.eoFillStroke(); + break; + case OPS.clip: + this.clip('nonzero'); + break; + case OPS.eoClip: + this.clip('evenodd'); + break; + case OPS.paintSolidColorImageMask: + this.paintSolidColorImageMask(); + break; + case OPS.paintJpegXObject: + this.paintJpegXObject(args[0], args[1], args[2]); + break; + case OPS.paintImageXObject: + this.paintImageXObject(args[0]); + break; + case OPS.paintInlineImageXObject: + this.paintInlineImageXObject(args[0]); + break; + case OPS.paintImageMaskXObject: + this.paintImageMaskXObject(args[0]); + break; + case OPS.paintFormXObjectBegin: + this.paintFormXObjectBegin(args[0], args[1]); + break; + case OPS.paintFormXObjectEnd: + this.paintFormXObjectEnd(); + break; + case OPS.closePath: + this.closePath(); + break; + case OPS.closeStroke: + this.closeStroke(); + break; + case OPS.closeFillStroke: + this.closeFillStroke(); + break; + case OPS.nextLine: + this.nextLine(); + break; + case OPS.transform: + this.transform(args[0], args[1], args[2], args[3], + args[4], args[5]); + break; + case OPS.constructPath: + this.constructPath(args[0], args[1]); + break; + case OPS.endPath: + this.endPath(); + break; + case 92: + this.group(opTree[x].items); + break; + default: + warn('Unimplemented method '+ fn); + break; + } + } + }, + + setWordSpacing: function SVGGraphics_setWordSpacing(wordSpacing) { + this.current.wordSpacing = wordSpacing; + }, + + setCharSpacing: function SVGGraphics_setCharSpacing(charSpacing) { + this.current.charSpacing = charSpacing; + }, + + nextLine: function SVGGraphics_nextLine() { + this.moveText(0, this.current.leading); + }, + + setTextMatrix: function SVGGraphics_setTextMatrix(a, b, c, d, e, f) { + var current = this.current; + this.current.textMatrix = this.current.lineMatrix = [a, b, c, d, e, f]; + + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + + current.xcoords = []; + current.tspan = document.createElementNS(NS, 'svg:tspan'); + current.tspan.setAttributeNS(null, 'font-family', current.fontFamily); + current.tspan.setAttributeNS(null, 'font-size', + pf(current.fontSize) + 'px'); + current.tspan.setAttributeNS(null, 'y', pf(-current.y)); + + current.txtElement = document.createElementNS(NS, 'svg:text'); + current.txtElement.appendChild(current.tspan); + }, + + beginText: function SVGGraphics_beginText() { + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + this.current.textMatrix = IDENTITY_MATRIX; + this.current.lineMatrix = IDENTITY_MATRIX; + this.current.tspan = document.createElementNS(NS, 'svg:tspan'); + this.current.txtElement = document.createElementNS(NS, 'svg:text'); + this.current.txtgrp = document.createElementNS(NS, 'svg:g'); + this.current.xcoords = []; + }, + + moveText: function SVGGraphics_moveText(x, y) { + var current = this.current; + this.current.x = this.current.lineX += x; + this.current.y = this.current.lineY += y; + + current.xcoords = []; + current.tspan = document.createElementNS(NS, 'svg:tspan'); + current.tspan.setAttributeNS(null, 'font-family', current.fontFamily); + current.tspan.setAttributeNS(null, 'font-size', + pf(current.fontSize) + 'px'); + current.tspan.setAttributeNS(null, 'y', pf(-current.y)); + }, + + showText: function SVGGraphics_showText(glyphs) { + var current = this.current; + var font = current.font; + var fontSize = current.fontSize; + + if (fontSize === 0) { + return; + } + + var charSpacing = current.charSpacing; + var wordSpacing = current.wordSpacing; + var fontDirection = current.fontDirection; + var textHScale = current.textHScale * fontDirection; + var glyphsLength = glyphs.length; + var vertical = font.vertical; + var widthAdvanceScale = fontSize * current.fontMatrix[0]; + + var x = 0, i; + for (i = 0; i < glyphsLength; ++i) { + var glyph = glyphs[i]; + if (glyph === null) { + // word break + x += fontDirection * wordSpacing; + continue; + } else if (isNum(glyph)) { + x += -glyph * fontSize * 0.001; + continue; + } + current.xcoords.push(current.x + x * textHScale); + + var width = glyph.width; + var character = glyph.fontChar; + var charWidth = width * widthAdvanceScale + charSpacing * fontDirection; + x += charWidth; + + current.tspan.textContent += character; + } + if (vertical) { + current.y -= x * textHScale; + } else { + current.x += x * textHScale; + } + + current.tspan.setAttributeNS(null, 'x', + current.xcoords.map(pf).join(' ')); + current.tspan.setAttributeNS(null, 'y', pf(-current.y)); + current.tspan.setAttributeNS(null, 'font-family', current.fontFamily); + current.tspan.setAttributeNS(null, 'font-size', + pf(current.fontSize) + 'px'); + if (current.fontStyle !== SVG_DEFAULTS.fontStyle) { + current.tspan.setAttributeNS(null, 'font-style', current.fontStyle); + } + if (current.fontWeight !== SVG_DEFAULTS.fontWeight) { + current.tspan.setAttributeNS(null, 'font-weight', current.fontWeight); + } + if (current.fillColor !== SVG_DEFAULTS.fillColor) { + current.tspan.setAttributeNS(null, 'fill', current.fillColor); + } + + current.txtElement.setAttributeNS(null, 'transform', + pm(current.textMatrix) + + ' scale(1, -1)' ); + current.txtElement.setAttributeNS(XML_NS, 'xml:space', 'preserve'); + current.txtElement.appendChild(current.tspan); + current.txtgrp.appendChild(current.txtElement); + + this.tgrp.appendChild(current.txtElement); + + }, + + setLeadingMoveText: function SVGGraphics_setLeadingMoveText(x, y) { + this.setLeading(-y); + this.moveText(x, y); + }, + + addFontStyle: function SVGGraphics_addFontStyle(fontObj) { + if (!this.cssStyle) { + this.cssStyle = document.createElementNS(NS, 'svg:style'); + this.cssStyle.setAttributeNS(null, 'type', 'text/css'); + this.defs.appendChild(this.cssStyle); + } + + var url = PDFJS.createObjectURL(fontObj.data, fontObj.mimetype); + this.cssStyle.textContent += + '@font-face { font-family: "' + fontObj.loadedName + '";' + + ' src: url(' + url + '); }\n'; + }, + + setFont: function SVGGraphics_setFont(details) { + var current = this.current; + var fontObj = this.commonObjs.get(details[0]); + var size = details[1]; + this.current.font = fontObj; + + if (this.embedFonts && fontObj.data && + !this.embeddedFonts[fontObj.loadedName]) { + this.addFontStyle(fontObj); + this.embeddedFonts[fontObj.loadedName] = fontObj; + } + + current.fontMatrix = (fontObj.fontMatrix ? + fontObj.fontMatrix : FONT_IDENTITY_MATRIX); + + var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') : + (fontObj.bold ? 'bold' : 'normal'); + var italic = fontObj.italic ? 'italic' : 'normal'; + + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + current.fontSize = size; + current.fontFamily = fontObj.loadedName; + current.fontWeight = bold; + current.fontStyle = italic; + + current.tspan = document.createElementNS(NS, 'svg:tspan'); + current.tspan.setAttributeNS(null, 'y', pf(-current.y)); + current.xcoords = []; + }, + + endText: function SVGGraphics_endText() { + if (this.current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + }, + + // Path properties + setLineWidth: function SVGGraphics_setLineWidth(width) { + this.current.lineWidth = width; + }, + setLineCap: function SVGGraphics_setLineCap(style) { + this.current.lineCap = LINE_CAP_STYLES[style]; + }, + setLineJoin: function SVGGraphics_setLineJoin(style) { + this.current.lineJoin = LINE_JOIN_STYLES[style]; + }, + setMiterLimit: function SVGGraphics_setMiterLimit(limit) { + this.current.miterLimit = limit; + }, + setStrokeRGBColor: function SVGGraphics_setStrokeRGBColor(r, g, b) { + var color = Util.makeCssRgb(r, g, b); + this.current.strokeColor = color; + }, + setFillRGBColor: function SVGGraphics_setFillRGBColor(r, g, b) { + var color = Util.makeCssRgb(r, g, b); + this.current.fillColor = color; + this.current.tspan = document.createElementNS(NS, 'svg:tspan'); + this.current.xcoords = []; + }, + setDash: function SVGGraphics_setDash(dashArray, dashPhase) { + this.current.dashArray = dashArray; + this.current.dashPhase = dashPhase; + }, + + constructPath: function SVGGraphics_constructPath(ops, args) { + var current = this.current; + var x = current.x, y = current.y; + current.path = document.createElementNS(NS, 'svg:path'); + var d = []; + var opLength = ops.length; + + for (var i = 0, j = 0; i < opLength; i++) { + switch (ops[i] | 0) { + case OPS.rectangle: + x = args[j++]; + y = args[j++]; + var width = args[j++]; + var height = args[j++]; + var xw = x + width; + var yh = y + height; + d.push('M', pf(x), pf(y), 'L', pf(xw) , pf(y), 'L', pf(xw), pf(yh), + 'L', pf(x), pf(yh), 'Z'); + break; + case OPS.moveTo: + x = args[j++]; + y = args[j++]; + d.push('M', pf(x), pf(y)); + break; + case OPS.lineTo: + x = args[j++]; + y = args[j++]; + d.push('L', pf(x) , pf(y)); + break; + case OPS.curveTo: + x = args[j + 4]; + y = args[j + 5]; + d.push('C', pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), + pf(args[j + 3]), pf(x), pf(y)); + j += 6; + break; + case OPS.curveTo2: + x = args[j + 2]; + y = args[j + 3]; + d.push('C', pf(x), pf(y), pf(args[j]), pf(args[j + 1]), + pf(args[j + 2]), pf(args[j + 3])); + j += 4; + break; + case OPS.curveTo3: + x = args[j + 2]; + y = args[j + 3]; + d.push('C', pf(args[j]), pf(args[j + 1]), pf(x), pf(y), + pf(x), pf(y)); + j += 4; + break; + case OPS.closePath: + d.push('Z'); + break; + } + } + current.path.setAttributeNS(null, 'd', d.join(' ')); + current.path.setAttributeNS(null, 'stroke-miterlimit', + pf(current.miterLimit)); + current.path.setAttributeNS(null, 'stroke-linecap', current.lineCap); + current.path.setAttributeNS(null, 'stroke-linejoin', current.lineJoin); + current.path.setAttributeNS(null, 'stroke-width', + pf(current.lineWidth) + 'px'); + current.path.setAttributeNS(null, 'stroke-dasharray', + current.dashArray.map(pf).join(' ')); + current.path.setAttributeNS(null, 'stroke-dashoffset', + pf(current.dashPhase) + 'px'); + current.path.setAttributeNS(null, 'fill', 'none'); + + this.tgrp.appendChild(current.path); + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + // Saving a reference in current.element so that it can be addressed + // in 'fill' and 'stroke' + current.element = current.path; + current.setCurrentPoint(x, y); + }, + + endPath: function SVGGraphics_endPath() { + var current = this.current; + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + }, + + clip: function SVGGraphics_clip(type) { + var current = this.current; + // Add current path to clipping path + current.clipId = 'clippath' + clipCount; + clipCount++; + this.clippath = document.createElementNS(NS, 'svg:clipPath'); + this.clippath.setAttributeNS(null, 'id', current.clipId); + var clipElement = current.element.cloneNode(); + if (type === 'evenodd') { + clipElement.setAttributeNS(null, 'clip-rule', 'evenodd'); + } else { + clipElement.setAttributeNS(null, 'clip-rule', 'nonzero'); + } + this.clippath.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + this.clippath.appendChild(clipElement); + this.defs.appendChild(this.clippath); + + // Create a new group with that attribute + current.pendingClip = true; + this.cgrp = document.createElementNS(NS, 'svg:g'); + this.cgrp.setAttributeNS(null, 'clip-path', + 'url(#' + current.clipId + ')'); + this.pgrp.appendChild(this.cgrp); + }, + + closePath: function SVGGraphics_closePath() { + var current = this.current; + var d = current.path.getAttributeNS(null, 'd'); + d += 'Z'; + current.path.setAttributeNS(null, 'd', d); + }, + + setLeading: function SVGGraphics_setLeading(leading) { + this.current.leading = -leading; + }, + + setTextRise: function SVGGraphics_setTextRise(textRise) { + this.current.textRise = textRise; + }, + + setHScale: function SVGGraphics_setHScale(scale) { + this.current.textHScale = scale / 100; + }, + + setGState: function SVGGraphics_setGState(states) { + for (var i = 0, ii = states.length; i < ii; i++) { + var state = states[i]; + var key = state[0]; + var value = state[1]; + + switch (key) { + case 'LW': + this.setLineWidth(value); + break; + case 'LC': + this.setLineCap(value); + break; + case 'LJ': + this.setLineJoin(value); + break; + case 'ML': + this.setMiterLimit(value); + break; + case 'D': + this.setDash(value[0], value[1]); + break; + case 'RI': + break; + case 'FL': + break; + case 'Font': + this.setFont(value); + break; + case 'CA': + break; + case 'ca': + break; + case 'BM': + break; + case 'SMask': + break; + } + } + }, + + fill: function SVGGraphics_fill() { + var current = this.current; + current.element.setAttributeNS(null, 'fill', current.fillColor); + }, + + stroke: function SVGGraphics_stroke() { + var current = this.current; + current.element.setAttributeNS(null, 'stroke', current.strokeColor); + current.element.setAttributeNS(null, 'fill', 'none'); + }, + + eoFill: function SVGGraphics_eoFill() { + var current = this.current; + current.element.setAttributeNS(null, 'fill', current.fillColor); + current.element.setAttributeNS(null, 'fill-rule', 'evenodd'); + }, + + fillStroke: function SVGGraphics_fillStroke() { + // Order is important since stroke wants fill to be none. + // First stroke, then if fill needed, it will be overwritten. + this.stroke(); + this.fill(); + }, + + eoFillStroke: function SVGGraphics_eoFillStroke() { + this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd'); + this.fillStroke(); + }, + + closeStroke: function SVGGraphics_closeStroke() { + this.closePath(); + this.stroke(); + }, + + closeFillStroke: function SVGGraphics_closeFillStroke() { + this.closePath(); + this.fillStroke(); + }, + + paintSolidColorImageMask: + function SVGGraphics_paintSolidColorImageMask() { + var current = this.current; + var rect = document.createElementNS(NS, 'svg:rect'); + rect.setAttributeNS(null, 'x', '0'); + rect.setAttributeNS(null, 'y', '0'); + rect.setAttributeNS(null, 'width', '1px'); + rect.setAttributeNS(null, 'height', '1px'); + rect.setAttributeNS(null, 'fill', current.fillColor); + this.tgrp.appendChild(rect); + }, + + paintJpegXObject: function SVGGraphics_paintJpegXObject(objId, w, h) { + var current = this.current; + var imgObj = this.objs.get(objId); + var imgEl = document.createElementNS(NS, 'svg:image'); + imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgObj.src); + imgEl.setAttributeNS(null, 'width', imgObj.width + 'px'); + imgEl.setAttributeNS(null, 'height', imgObj.height + 'px'); + imgEl.setAttributeNS(null, 'x', '0'); + imgEl.setAttributeNS(null, 'y', pf(-h)); + imgEl.setAttributeNS(null, 'transform', + 'scale(' + pf(1 / w) + ' ' + pf(-1 / h) + ')'); + + this.tgrp.appendChild(imgEl); + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + }, + + paintImageXObject: function SVGGraphics_paintImageXObject(objId) { + var imgData = this.objs.get(objId); + if (!imgData) { + warn('Dependent image isn\'t ready yet'); + return; + } + this.paintInlineImageXObject(imgData); + }, + + paintInlineImageXObject: + function SVGGraphics_paintInlineImageXObject(imgData, mask) { + var current = this.current; + var width = imgData.width; + var height = imgData.height; + + var imgSrc = convertImgDataToPng(imgData); + var cliprect = document.createElementNS(NS, 'svg:rect'); + cliprect.setAttributeNS(null, 'x', '0'); + cliprect.setAttributeNS(null, 'y', '0'); + cliprect.setAttributeNS(null, 'width', pf(width)); + cliprect.setAttributeNS(null, 'height', pf(height)); + current.element = cliprect; + this.clip('nonzero'); + var imgEl = document.createElementNS(NS, 'svg:image'); + imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgSrc); + imgEl.setAttributeNS(null, 'x', '0'); + imgEl.setAttributeNS(null, 'y', pf(-height)); + imgEl.setAttributeNS(null, 'width', pf(width) + 'px'); + imgEl.setAttributeNS(null, 'height', pf(height) + 'px'); + imgEl.setAttributeNS(null, 'transform', + 'scale(' + pf(1 / width) + ' ' + + pf(-1 / height) + ')'); + if (mask) { + mask.appendChild(imgEl); + } else { + this.tgrp.appendChild(imgEl); + } + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + }, + + paintImageMaskXObject: + function SVGGraphics_paintImageMaskXObject(imgData) { + var current = this.current; + var width = imgData.width; + var height = imgData.height; + var fillColor = current.fillColor; + + current.maskId = 'mask' + maskCount++; + var mask = document.createElementNS(NS, 'svg:mask'); + mask.setAttributeNS(null, 'id', current.maskId); + + var rect = document.createElementNS(NS, 'svg:rect'); + rect.setAttributeNS(null, 'x', '0'); + rect.setAttributeNS(null, 'y', '0'); + rect.setAttributeNS(null, 'width', pf(width)); + rect.setAttributeNS(null, 'height', pf(height)); + rect.setAttributeNS(null, 'fill', fillColor); + rect.setAttributeNS(null, 'mask', 'url(#' + current.maskId +')'); + this.defs.appendChild(mask); + this.tgrp.appendChild(rect); + + this.paintInlineImageXObject(imgData, mask); + }, + + paintFormXObjectBegin: + function SVGGraphics_paintFormXObjectBegin(matrix, bbox) { + this.save(); + + if (isArray(matrix) && matrix.length === 6) { + this.transform(matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5]); + } + + if (isArray(bbox) && bbox.length === 4) { + var width = bbox[2] - bbox[0]; + var height = bbox[3] - bbox[1]; + + var cliprect = document.createElementNS(NS, 'svg:rect'); + cliprect.setAttributeNS(null, 'x', bbox[0]); + cliprect.setAttributeNS(null, 'y', bbox[1]); + cliprect.setAttributeNS(null, 'width', pf(width)); + cliprect.setAttributeNS(null, 'height', pf(height)); + this.current.element = cliprect; + this.clip('nonzero'); + this.endPath(); + } + }, + + paintFormXObjectEnd: + function SVGGraphics_paintFormXObjectEnd() { + this.restore(); + } + }; + return SVGGraphics; +})(); + +PDFJS.SVGGraphics = SVGGraphics; + + +}).call((typeof window === 'undefined') ? this : window); + +if (!PDFJS.workerSrc && typeof document !== 'undefined') { + // workerSrc is not set -- using last script url to define default location + PDFJS.workerSrc = (function () { + 'use strict'; + var scriptTagContainer = document.body || + document.getElementsByTagName('head')[0]; + var pdfjsSrc = scriptTagContainer.lastChild.src; + return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js'); + })(); +} + + diff --git a/src/main/resources/static/generic/build/pdf.worker.js b/src/main/resources/static/generic/build/pdf.worker.js new file mode 100644 index 0000000..06c6065 --- /dev/null +++ b/src/main/resources/static/generic/build/pdf.worker.js @@ -0,0 +1,39372 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * 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. + */ +/*jshint globalstrict: false */ +/* globals PDFJS */ + +// Initializing PDFJS global object (if still undefined) +if (typeof PDFJS === 'undefined') { + (typeof window !== 'undefined' ? window : this).PDFJS = {}; +} + +PDFJS.version = '1.1.159'; +PDFJS.build = '82536f8'; + +(function pdfjsWrapper() { + // Use strict in our context only - users might not want it + 'use strict'; + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * 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. + */ +/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL, + Promise */ + +'use strict'; + +var globalScope = (typeof window === 'undefined') ? this : window; + +var isWorker = (typeof window === 'undefined'); + +var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; + +var TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; + +var ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 +}; + +var AnnotationType = { + WIDGET: 1, + TEXT: 2, + LINK: 3 +}; + +var StreamType = { + UNKNOWN: 0, + FLATE: 1, + LZW: 2, + DCT: 3, + JPX: 4, + JBIG: 5, + A85: 6, + AHX: 7, + CCF: 8, + RL: 9 +}; + +var FontType = { + UNKNOWN: 0, + TYPE1: 1, + TYPE1C: 2, + CIDFONTTYPE0: 3, + CIDFONTTYPE0C: 4, + TRUETYPE: 5, + CIDFONTTYPE2: 6, + TYPE3: 7, + OPENTYPE: 8, + TYPE0: 9, + MMTYPE1: 10 +}; + +// The global PDFJS object exposes the API +// In production, it will be declared outside a global wrapper +// In development, it will be declared here +if (!globalScope.PDFJS) { + globalScope.PDFJS = {}; +} + +globalScope.PDFJS.pdfBug = false; + +PDFJS.VERBOSITY_LEVELS = { + errors: 0, + warnings: 1, + infos: 5 +}; + +// All the possible operations for an operator list. +var OPS = PDFJS.OPS = { + // Intentionally start from 1 so it is easy to spot bad operators that will be + // 0's. + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotations: 78, + endAnnotations: 79, + beginAnnotation: 80, + endAnnotation: 81, + paintJpegXObject: 82, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91 +}; + +// A notice for devs. These are good for things that are helpful to devs, such +// as warning that Workers were disabled, which is important to devs but not +// end users. +function info(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) { + console.log('Info: ' + msg); + } +} + +// Non-fatal warnings. +function warn(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) { + console.log('Warning: ' + msg); + } +} + +// Fatal errors that should trigger the fallback UI and halt execution by +// throwing an exception. +function error(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.errors) { + console.log('Error: ' + msg); + console.log(backtrace()); + } + UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown); + throw new Error(msg); +} + +function backtrace() { + try { + throw new Error(); + } catch (e) { + return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; + } +} + +function assert(cond, msg) { + if (!cond) { + error(msg); + } +} + +var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; + +var UnsupportedManager = PDFJS.UnsupportedManager = + (function UnsupportedManagerClosure() { + var listeners = []; + return { + listen: function (cb) { + listeners.push(cb); + }, + notify: function (featureId) { + warn('Unsupported feature "' + featureId + '"'); + for (var i = 0, ii = listeners.length; i < ii; i++) { + listeners[i](featureId); + } + } + }; +})(); + +// Combines two URLs. The baseUrl shall be absolute URL. If the url is an +// absolute URL, it will be returned as is. +function combineUrl(baseUrl, url) { + if (!url) { + return baseUrl; + } + if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) { + return url; + } + var i; + if (url.charAt(0) === '/') { + // absolute path + i = baseUrl.indexOf('://'); + if (url.charAt(1) === '/') { + ++i; + } else { + i = baseUrl.indexOf('/', i + 3); + } + return baseUrl.substring(0, i) + url; + } else { + // relative path + var pathLength = baseUrl.length; + i = baseUrl.lastIndexOf('#'); + pathLength = i >= 0 ? i : pathLength; + i = baseUrl.lastIndexOf('?', pathLength); + pathLength = i >= 0 ? i : pathLength; + var prefixLength = baseUrl.lastIndexOf('/', pathLength); + return baseUrl.substring(0, prefixLength + 1) + url; + } +} + +// Validates if URL is safe and allowed, e.g. to avoid XSS. +function isValidUrl(url, allowRelative) { + if (!url) { + return false; + } + // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1) + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url); + if (!protocol) { + return allowRelative; + } + protocol = protocol[0].toLowerCase(); + switch (protocol) { + case 'http': + case 'https': + case 'ftp': + case 'mailto': + case 'tel': + return true; + default: + return false; + } +} +PDFJS.isValidUrl = isValidUrl; + +function shadow(obj, prop, value) { + Object.defineProperty(obj, prop, { value: value, + enumerable: true, + configurable: true, + writable: false }); + return value; +} +PDFJS.shadow = shadow; + +var PasswordResponses = PDFJS.PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; + +var PasswordException = (function PasswordExceptionClosure() { + function PasswordException(msg, code) { + this.name = 'PasswordException'; + this.message = msg; + this.code = code; + } + + PasswordException.prototype = new Error(); + PasswordException.constructor = PasswordException; + + return PasswordException; +})(); +PDFJS.PasswordException = PasswordException; + +var UnknownErrorException = (function UnknownErrorExceptionClosure() { + function UnknownErrorException(msg, details) { + this.name = 'UnknownErrorException'; + this.message = msg; + this.details = details; + } + + UnknownErrorException.prototype = new Error(); + UnknownErrorException.constructor = UnknownErrorException; + + return UnknownErrorException; +})(); +PDFJS.UnknownErrorException = UnknownErrorException; + +var InvalidPDFException = (function InvalidPDFExceptionClosure() { + function InvalidPDFException(msg) { + this.name = 'InvalidPDFException'; + this.message = msg; + } + + InvalidPDFException.prototype = new Error(); + InvalidPDFException.constructor = InvalidPDFException; + + return InvalidPDFException; +})(); +PDFJS.InvalidPDFException = InvalidPDFException; + +var MissingPDFException = (function MissingPDFExceptionClosure() { + function MissingPDFException(msg) { + this.name = 'MissingPDFException'; + this.message = msg; + } + + MissingPDFException.prototype = new Error(); + MissingPDFException.constructor = MissingPDFException; + + return MissingPDFException; +})(); +PDFJS.MissingPDFException = MissingPDFException; + +var UnexpectedResponseException = + (function UnexpectedResponseExceptionClosure() { + function UnexpectedResponseException(msg, status) { + this.name = 'UnexpectedResponseException'; + this.message = msg; + this.status = status; + } + + UnexpectedResponseException.prototype = new Error(); + UnexpectedResponseException.constructor = UnexpectedResponseException; + + return UnexpectedResponseException; +})(); +PDFJS.UnexpectedResponseException = UnexpectedResponseException; + +var NotImplementedException = (function NotImplementedExceptionClosure() { + function NotImplementedException(msg) { + this.message = msg; + } + + NotImplementedException.prototype = new Error(); + NotImplementedException.prototype.name = 'NotImplementedException'; + NotImplementedException.constructor = NotImplementedException; + + return NotImplementedException; +})(); + +var MissingDataException = (function MissingDataExceptionClosure() { + function MissingDataException(begin, end) { + this.begin = begin; + this.end = end; + this.message = 'Missing data [' + begin + ', ' + end + ')'; + } + + MissingDataException.prototype = new Error(); + MissingDataException.prototype.name = 'MissingDataException'; + MissingDataException.constructor = MissingDataException; + + return MissingDataException; +})(); + +var XRefParseException = (function XRefParseExceptionClosure() { + function XRefParseException(msg) { + this.message = msg; + } + + XRefParseException.prototype = new Error(); + XRefParseException.prototype.name = 'XRefParseException'; + XRefParseException.constructor = XRefParseException; + + return XRefParseException; +})(); + + +function bytesToString(bytes) { + assert(bytes !== null && typeof bytes === 'object' && + bytes.length !== undefined, 'Invalid argument for bytesToString'); + var length = bytes.length; + var MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + var strBuf = []; + for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + var chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + return strBuf.join(''); +} + +function stringToBytes(str) { + assert(typeof str === 'string', 'Invalid argument for stringToBytes'); + var length = str.length; + var bytes = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 0xFF; + } + return bytes; +} + +function string32(value) { + return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff, + (value >> 8) & 0xff, value & 0xff); +} + +function log2(x) { + var n = 1, i = 0; + while (x > n) { + n <<= 1; + i++; + } + return i; +} + +function readInt8(data, start) { + return (data[start] << 24) >> 24; +} + +function readUint16(data, offset) { + return (data[offset] << 8) | data[offset + 1]; +} + +function readUint32(data, offset) { + return ((data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]) >>> 0; +} + +// Lazy test the endianness of the platform +// NOTE: This will be 'true' for simulated TypedArrays +function isLittleEndian() { + var buffer8 = new Uint8Array(2); + buffer8[0] = 1; + var buffer16 = new Uint16Array(buffer8.buffer); + return (buffer16[0] === 1); +} + +Object.defineProperty(PDFJS, 'isLittleEndian', { + configurable: true, + get: function PDFJS_isLittleEndian() { + return shadow(PDFJS, 'isLittleEndian', isLittleEndian()); + } +}); + + // Lazy test if the userAgant support CanvasTypedArrays +function hasCanvasTypedArrays() { + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + var ctx = canvas.getContext('2d'); + var imageData = ctx.createImageData(1, 1); + return (typeof imageData.data.buffer !== 'undefined'); +} + +Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', { + configurable: true, + get: function PDFJS_hasCanvasTypedArrays() { + return shadow(PDFJS, 'hasCanvasTypedArrays', hasCanvasTypedArrays()); + } +}); + +var Uint32ArrayView = (function Uint32ArrayViewClosure() { + + function Uint32ArrayView(buffer, length) { + this.buffer = buffer; + this.byteLength = buffer.length; + this.length = length === undefined ? (this.byteLength >> 2) : length; + ensureUint32ArrayViewProps(this.length); + } + Uint32ArrayView.prototype = Object.create(null); + + var uint32ArrayViewSetters = 0; + function createUint32ArrayProp(index) { + return { + get: function () { + var buffer = this.buffer, offset = index << 2; + return (buffer[offset] | (buffer[offset + 1] << 8) | + (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0; + }, + set: function (value) { + var buffer = this.buffer, offset = index << 2; + buffer[offset] = value & 255; + buffer[offset + 1] = (value >> 8) & 255; + buffer[offset + 2] = (value >> 16) & 255; + buffer[offset + 3] = (value >>> 24) & 255; + } + }; + } + + function ensureUint32ArrayViewProps(length) { + while (uint32ArrayViewSetters < length) { + Object.defineProperty(Uint32ArrayView.prototype, + uint32ArrayViewSetters, + createUint32ArrayProp(uint32ArrayViewSetters)); + uint32ArrayViewSetters++; + } + } + + return Uint32ArrayView; +})(); + +var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; + +var Util = PDFJS.Util = (function UtilClosure() { + function Util() {} + + var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')']; + + // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids + // creating many intermediate strings. + Util.makeCssRgb = function Util_makeCssRgb(r, g, b) { + rgbBuf[1] = r; + rgbBuf[3] = g; + rgbBuf[5] = b; + return rgbBuf.join(''); + }; + + // Concatenates two transformation matrices together and returns the result. + Util.transform = function Util_transform(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; + }; + + // For 2d affine transforms + Util.applyTransform = function Util_applyTransform(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + }; + + Util.applyInverseTransform = function Util_applyInverseTransform(p, m) { + var d = m[0] * m[3] - m[1] * m[2]; + var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + return [xt, yt]; + }; + + // Applies the transform to the rectangle and finds the minimum axially + // aligned bounding box. + Util.getAxialAlignedBoundingBox = + function Util_getAxialAlignedBoundingBox(r, m) { + + var p1 = Util.applyTransform(r, m); + var p2 = Util.applyTransform(r.slice(2, 4), m); + var p3 = Util.applyTransform([r[0], r[3]], m); + var p4 = Util.applyTransform([r[2], r[1]], m); + return [ + Math.min(p1[0], p2[0], p3[0], p4[0]), + Math.min(p1[1], p2[1], p3[1], p4[1]), + Math.max(p1[0], p2[0], p3[0], p4[0]), + Math.max(p1[1], p2[1], p3[1], p4[1]) + ]; + }; + + Util.inverseTransform = function Util_inverseTransform(m) { + var d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, + (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + }; + + // Apply a generic 3d matrix M on a 3-vector v: + // | a b c | | X | + // | d e f | x | Y | + // | g h i | | Z | + // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i], + // with v as [X,Y,Z] + Util.apply3dTransform = function Util_apply3dTransform(m, v) { + return [ + m[0] * v[0] + m[1] * v[1] + m[2] * v[2], + m[3] * v[0] + m[4] * v[1] + m[5] * v[2], + m[6] * v[0] + m[7] * v[1] + m[8] * v[2] + ]; + }; + + // This calculation uses Singular Value Decomposition. + // The SVD can be represented with formula A = USV. We are interested in the + // matrix S here because it represents the scale values. + Util.singularValueDecompose2dScale = + function Util_singularValueDecompose2dScale(m) { + + var transpose = [m[0], m[2], m[1], m[3]]; + + // Multiply matrix m with its transpose. + var a = m[0] * transpose[0] + m[1] * transpose[2]; + var b = m[0] * transpose[1] + m[1] * transpose[3]; + var c = m[2] * transpose[0] + m[3] * transpose[2]; + var d = m[2] * transpose[1] + m[3] * transpose[3]; + + // Solve the second degree polynomial to get roots. + var first = (a + d) / 2; + var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2; + var sx = first + second || 1; + var sy = first - second || 1; + + // Scale values are the square roots of the eigenvalues. + return [Math.sqrt(sx), Math.sqrt(sy)]; + }; + + // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) + // For coordinate systems whose origin lies in the bottom-left, this + // means normalization to (BL,TR) ordering. For systems with origin in the + // top-left, this means (TL,BR) ordering. + Util.normalizeRect = function Util_normalizeRect(rect) { + var r = rect.slice(0); // clone rect + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + }; + + // Returns a rectangle [x1, y1, x2, y2] corresponding to the + // intersection of rect1 and rect2. If no intersection, returns 'false' + // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] + Util.intersect = function Util_intersect(rect1, rect2) { + function compare(a, b) { + return a - b; + } + + // Order points along the axes + var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare), + orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare), + result = []; + + rect1 = Util.normalizeRect(rect1); + rect2 = Util.normalizeRect(rect2); + + // X: first and second points belong to different rectangles? + if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) || + (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) { + // Intersection must be between second and third points + result[0] = orderedX[1]; + result[2] = orderedX[2]; + } else { + return false; + } + + // Y: first and second points belong to different rectangles? + if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) || + (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) { + // Intersection must be between second and third points + result[1] = orderedY[1]; + result[3] = orderedY[2]; + } else { + return false; + } + + return result; + }; + + Util.sign = function Util_sign(num) { + return num < 0 ? -1 : 1; + }; + + Util.appendToArray = function Util_appendToArray(arr1, arr2) { + Array.prototype.push.apply(arr1, arr2); + }; + + Util.prependToArray = function Util_prependToArray(arr1, arr2) { + Array.prototype.unshift.apply(arr1, arr2); + }; + + Util.extendObj = function extendObj(obj1, obj2) { + for (var key in obj2) { + obj1[key] = obj2[key]; + } + }; + + Util.getInheritableProperty = function Util_getInheritableProperty(dict, + name) { + while (dict && !dict.has(name)) { + dict = dict.get('Parent'); + } + if (!dict) { + return null; + } + return dict.get(name); + }; + + Util.inherit = function Util_inherit(sub, base, prototype) { + sub.prototype = Object.create(base.prototype); + sub.prototype.constructor = sub; + for (var prop in prototype) { + sub.prototype[prop] = prototype[prop]; + } + }; + + Util.loadScript = function Util_loadScript(src, callback) { + var script = document.createElement('script'); + var loaded = false; + script.setAttribute('src', src); + if (callback) { + script.onload = function() { + if (!loaded) { + callback(); + } + loaded = true; + }; + } + document.getElementsByTagName('head')[0].appendChild(script); + }; + + return Util; +})(); + +/** + * PDF page viewport created based on scale, rotation and offset. + * @class + * @alias PDFJS.PageViewport + */ +var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() { + /** + * @constructor + * @private + * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates. + * @param scale {number} scale of the viewport. + * @param rotation {number} rotations of the viewport in degrees. + * @param offsetX {number} offset X + * @param offsetY {number} offset Y + * @param dontFlip {boolean} if true, axis Y will not be flipped. + */ + function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) { + this.viewBox = viewBox; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + + // creating transform to convert pdf coordinate system to the normal + // canvas like coordinates taking in account scale and rotation + var centerX = (viewBox[2] + viewBox[0]) / 2; + var centerY = (viewBox[3] + viewBox[1]) / 2; + var rotateA, rotateB, rotateC, rotateD; + rotation = rotation % 360; + rotation = rotation < 0 ? rotation + 360 : rotation; + switch (rotation) { + case 180: + rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1; + break; + case 90: + rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0; + break; + case 270: + rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0; + break; + //case 0: + default: + rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1; + break; + } + + if (dontFlip) { + rotateC = -rotateC; rotateD = -rotateD; + } + + var offsetCanvasX, offsetCanvasY; + var width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = Math.abs(viewBox[3] - viewBox[1]) * scale; + height = Math.abs(viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = Math.abs(viewBox[2] - viewBox[0]) * scale; + height = Math.abs(viewBox[3] - viewBox[1]) * scale; + } + // creating transform for the following operations: + // translate(-centerX, -centerY), rotate and flip vertically, + // scale, and translate(offsetCanvasX, offsetCanvasY) + this.transform = [ + rotateA * scale, + rotateB * scale, + rotateC * scale, + rotateD * scale, + offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, + offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY + ]; + + this.width = width; + this.height = height; + this.fontScale = scale; + } + PageViewport.prototype = /** @lends PDFJS.PageViewport.prototype */ { + /** + * Clones viewport with additional properties. + * @param args {Object} (optional) If specified, may contain the 'scale' or + * 'rotation' properties to override the corresponding properties in + * the cloned viewport. + * @returns {PDFJS.PageViewport} Cloned viewport. + */ + clone: function PageViewPort_clone(args) { + args = args || {}; + var scale = 'scale' in args ? args.scale : this.scale; + var rotation = 'rotation' in args ? args.rotation : this.rotation; + return new PageViewport(this.viewBox.slice(), scale, rotation, + this.offsetX, this.offsetY, args.dontFlip); + }, + /** + * Converts PDF point to the viewport coordinates. For examples, useful for + * converting PDF location into canvas pixel coordinates. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the viewport coordinate space. + * @see {@link convertToPdfPoint} + * @see {@link convertToViewportRectangle} + */ + convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) { + return Util.applyTransform([x, y], this.transform); + }, + /** + * Converts PDF rectangle to the viewport coordinates. + * @param rect {Array} xMin, yMin, xMax and yMax coordinates. + * @returns {Array} Contains corresponding coordinates of the rectangle + * in the viewport coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToViewportRectangle: + function PageViewport_convertToViewportRectangle(rect) { + var tl = Util.applyTransform([rect[0], rect[1]], this.transform); + var br = Util.applyTransform([rect[2], rect[3]], this.transform); + return [tl[0], tl[1], br[0], br[1]]; + }, + /** + * Converts viewport coordinates to the PDF location. For examples, useful + * for converting canvas pixel location into PDF one. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the PDF coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) { + return Util.applyInverseTransform([x, y], this.transform); + } + }; + return PageViewport; +})(); + +var PDFStringTranslateTable = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, + 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, + 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, + 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC +]; + +function stringToPDFString(str) { + var i, n = str.length, strBuf = []; + if (str[0] === '\xFE' && str[1] === '\xFF') { + // UTF16BE BOM + for (i = 2; i < n; i += 2) { + strBuf.push(String.fromCharCode( + (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1))); + } + } else { + for (i = 0; i < n; ++i) { + var code = PDFStringTranslateTable[str.charCodeAt(i)]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + } + return strBuf.join(''); +} + +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} + +function utf8StringToString(str) { + return unescape(encodeURIComponent(str)); +} + +function isEmptyObj(obj) { + for (var key in obj) { + return false; + } + return true; +} + +function isBool(v) { + return typeof v === 'boolean'; +} + +function isInt(v) { + return typeof v === 'number' && ((v | 0) === v); +} + +function isNum(v) { + return typeof v === 'number'; +} + +function isString(v) { + return typeof v === 'string'; +} + +function isName(v) { + return v instanceof Name; +} + +function isCmd(v, cmd) { + return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); +} + +function isDict(v, type) { + if (!(v instanceof Dict)) { + return false; + } + if (!type) { + return true; + } + var dictType = v.get('Type'); + return isName(dictType) && dictType.name === type; +} + +function isArray(v) { + return v instanceof Array; +} + +function isStream(v) { + return typeof v === 'object' && v !== null && v.getBytes !== undefined; +} + +function isArrayBuffer(v) { + return typeof v === 'object' && v !== null && v.byteLength !== undefined; +} + +function isRef(v) { + return v instanceof Ref; +} + +/** + * Promise Capability object. + * + * @typedef {Object} PromiseCapability + * @property {Promise} promise - A promise object. + * @property {function} resolve - Fullfills the promise. + * @property {function} reject - Rejects the promise. + */ + +/** + * Creates a promise capability object. + * @alias PDFJS.createPromiseCapability + * + * @return {PromiseCapability} A capability object contains: + * - a Promise, resolve and reject methods. + */ +function createPromiseCapability() { + var capability = {}; + capability.promise = new Promise(function (resolve, reject) { + capability.resolve = resolve; + capability.reject = reject; + }); + return capability; +} + +PDFJS.createPromiseCapability = createPromiseCapability; + +/** + * Polyfill for Promises: + * The following promise implementation tries to generally implement the + * Promise/A+ spec. Some notable differences from other promise libaries are: + * - There currently isn't a seperate deferred and promise object. + * - Unhandled rejections eventually show an error if they aren't handled. + * + * Based off of the work in: + * https://bugzilla.mozilla.org/show_bug.cgi?id=810490 + */ +(function PromiseClosure() { + if (globalScope.Promise) { + // Promises existing in the DOM/Worker, checking presence of all/resolve + if (typeof globalScope.Promise.all !== 'function') { + globalScope.Promise.all = function (iterable) { + var count = 0, results = [], resolve, reject; + var promise = new globalScope.Promise(function (resolve_, reject_) { + resolve = resolve_; + reject = reject_; + }); + iterable.forEach(function (p, i) { + count++; + p.then(function (result) { + results[i] = result; + count--; + if (count === 0) { + resolve(results); + } + }, reject); + }); + if (count === 0) { + resolve(results); + } + return promise; + }; + } + if (typeof globalScope.Promise.resolve !== 'function') { + globalScope.Promise.resolve = function (value) { + return new globalScope.Promise(function (resolve) { resolve(value); }); + }; + } + if (typeof globalScope.Promise.reject !== 'function') { + globalScope.Promise.reject = function (reason) { + return new globalScope.Promise(function (resolve, reject) { + reject(reason); + }); + }; + } + if (typeof globalScope.Promise.prototype.catch !== 'function') { + globalScope.Promise.prototype.catch = function (onReject) { + return globalScope.Promise.prototype.then(undefined, onReject); + }; + } + return; + } + var STATUS_PENDING = 0; + var STATUS_RESOLVED = 1; + var STATUS_REJECTED = 2; + + // In an attempt to avoid silent exceptions, unhandled rejections are + // tracked and if they aren't handled in a certain amount of time an + // error is logged. + var REJECTION_TIMEOUT = 500; + + var HandlerManager = { + handlers: [], + running: false, + unhandledRejections: [], + pendingRejectionCheck: false, + + scheduleHandlers: function scheduleHandlers(promise) { + if (promise._status === STATUS_PENDING) { + return; + } + + this.handlers = this.handlers.concat(promise._handlers); + promise._handlers = []; + + if (this.running) { + return; + } + this.running = true; + + setTimeout(this.runHandlers.bind(this), 0); + }, + + runHandlers: function runHandlers() { + var RUN_TIMEOUT = 1; // ms + var timeoutAt = Date.now() + RUN_TIMEOUT; + while (this.handlers.length > 0) { + var handler = this.handlers.shift(); + + var nextStatus = handler.thisPromise._status; + var nextValue = handler.thisPromise._value; + + try { + if (nextStatus === STATUS_RESOLVED) { + if (typeof handler.onResolve === 'function') { + nextValue = handler.onResolve(nextValue); + } + } else if (typeof handler.onReject === 'function') { + nextValue = handler.onReject(nextValue); + nextStatus = STATUS_RESOLVED; + + if (handler.thisPromise._unhandledRejection) { + this.removeUnhandeledRejection(handler.thisPromise); + } + } + } catch (ex) { + nextStatus = STATUS_REJECTED; + nextValue = ex; + } + + handler.nextPromise._updateStatus(nextStatus, nextValue); + if (Date.now() >= timeoutAt) { + break; + } + } + + if (this.handlers.length > 0) { + setTimeout(this.runHandlers.bind(this), 0); + return; + } + + this.running = false; + }, + + addUnhandledRejection: function addUnhandledRejection(promise) { + this.unhandledRejections.push({ + promise: promise, + time: Date.now() + }); + this.scheduleRejectionCheck(); + }, + + removeUnhandeledRejection: function removeUnhandeledRejection(promise) { + promise._unhandledRejection = false; + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (this.unhandledRejections[i].promise === promise) { + this.unhandledRejections.splice(i); + i--; + } + } + }, + + scheduleRejectionCheck: function scheduleRejectionCheck() { + if (this.pendingRejectionCheck) { + return; + } + this.pendingRejectionCheck = true; + setTimeout(function rejectionCheck() { + this.pendingRejectionCheck = false; + var now = Date.now(); + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) { + var unhandled = this.unhandledRejections[i].promise._value; + var msg = 'Unhandled rejection: ' + unhandled; + if (unhandled.stack) { + msg += '\n' + unhandled.stack; + } + warn(msg); + this.unhandledRejections.splice(i); + i--; + } + } + if (this.unhandledRejections.length) { + this.scheduleRejectionCheck(); + } + }.bind(this), REJECTION_TIMEOUT); + } + }; + + function Promise(resolver) { + this._status = STATUS_PENDING; + this._handlers = []; + try { + resolver.call(this, this._resolve.bind(this), this._reject.bind(this)); + } catch (e) { + this._reject(e); + } + } + /** + * Builds a promise that is resolved when all the passed in promises are + * resolved. + * @param {array} array of data and/or promises to wait for. + * @return {Promise} New dependant promise. + */ + Promise.all = function Promise_all(promises) { + var resolveAll, rejectAll; + var deferred = new Promise(function (resolve, reject) { + resolveAll = resolve; + rejectAll = reject; + }); + var unresolved = promises.length; + var results = []; + if (unresolved === 0) { + resolveAll(results); + return deferred; + } + function reject(reason) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results = []; + rejectAll(reason); + } + for (var i = 0, ii = promises.length; i < ii; ++i) { + var promise = promises[i]; + var resolve = (function(i) { + return function(value) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results[i] = value; + unresolved--; + if (unresolved === 0) { + resolveAll(results); + } + }; + })(i); + if (Promise.isPromise(promise)) { + promise.then(resolve, reject); + } else { + resolve(promise); + } + } + return deferred; + }; + + /** + * Checks if the value is likely a promise (has a 'then' function). + * @return {boolean} true if value is thenable + */ + Promise.isPromise = function Promise_isPromise(value) { + return value && typeof value.then === 'function'; + }; + + /** + * Creates resolved promise + * @param value resolve value + * @returns {Promise} + */ + Promise.resolve = function Promise_resolve(value) { + return new Promise(function (resolve) { resolve(value); }); + }; + + /** + * Creates rejected promise + * @param reason rejection value + * @returns {Promise} + */ + Promise.reject = function Promise_reject(reason) { + return new Promise(function (resolve, reject) { reject(reason); }); + }; + + Promise.prototype = { + _status: null, + _value: null, + _handlers: null, + _unhandledRejection: null, + + _updateStatus: function Promise__updateStatus(status, value) { + if (this._status === STATUS_RESOLVED || + this._status === STATUS_REJECTED) { + return; + } + + if (status === STATUS_RESOLVED && + Promise.isPromise(value)) { + value.then(this._updateStatus.bind(this, STATUS_RESOLVED), + this._updateStatus.bind(this, STATUS_REJECTED)); + return; + } + + this._status = status; + this._value = value; + + if (status === STATUS_REJECTED && this._handlers.length === 0) { + this._unhandledRejection = true; + HandlerManager.addUnhandledRejection(this); + } + + HandlerManager.scheduleHandlers(this); + }, + + _resolve: function Promise_resolve(value) { + this._updateStatus(STATUS_RESOLVED, value); + }, + + _reject: function Promise_reject(reason) { + this._updateStatus(STATUS_REJECTED, reason); + }, + + then: function Promise_then(onResolve, onReject) { + var nextPromise = new Promise(function (resolve, reject) { + this.resolve = resolve; + this.reject = reject; + }); + this._handlers.push({ + thisPromise: this, + onResolve: onResolve, + onReject: onReject, + nextPromise: nextPromise + }); + HandlerManager.scheduleHandlers(this); + return nextPromise; + }, + + catch: function Promise_catch(onReject) { + return this.then(undefined, onReject); + } + }; + + globalScope.Promise = Promise; +})(); + +var StatTimer = (function StatTimerClosure() { + function rpad(str, pad, length) { + while (str.length < length) { + str += pad; + } + return str; + } + function StatTimer() { + this.started = {}; + this.times = []; + this.enabled = true; + } + StatTimer.prototype = { + time: function StatTimer_time(name) { + if (!this.enabled) { + return; + } + if (name in this.started) { + warn('Timer is already running for ' + name); + } + this.started[name] = Date.now(); + }, + timeEnd: function StatTimer_timeEnd(name) { + if (!this.enabled) { + return; + } + if (!(name in this.started)) { + warn('Timer has not been started for ' + name); + } + this.times.push({ + 'name': name, + 'start': this.started[name], + 'end': Date.now() + }); + // Remove timer from started so it can be called again. + delete this.started[name]; + }, + toString: function StatTimer_toString() { + var i, ii; + var times = this.times; + var out = ''; + // Find the longest name for padding purposes. + var longest = 0; + for (i = 0, ii = times.length; i < ii; ++i) { + var name = times[i]['name']; + if (name.length > longest) { + longest = name.length; + } + } + for (i = 0, ii = times.length; i < ii; ++i) { + var span = times[i]; + var duration = span.end - span.start; + out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n'; + } + return out; + } + }; + return StatTimer; +})(); + +PDFJS.createBlob = function createBlob(data, contentType) { + if (typeof Blob !== 'undefined') { + return new Blob([data], { type: contentType }); + } + // Blob builder is deprecated in FF14 and removed in FF18. + var bb = new MozBlobBuilder(); + bb.append(data); + return bb.getBlob(contentType); +}; + +PDFJS.createObjectURL = (function createObjectURLClosure() { + // Blob/createObjectURL is not available, falling back to data schema. + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + return function createObjectURL(data, contentType) { + if (!PDFJS.disableCreateObjectURL && + typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = PDFJS.createBlob(data, contentType); + return URL.createObjectURL(blob); + } + + var buffer = 'data:' + contentType + ';base64,'; + for (var i = 0, ii = data.length; i < ii; i += 3) { + var b1 = data[i] & 0xFF; + var b2 = data[i + 1] & 0xFF; + var b3 = data[i + 2] & 0xFF; + var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < ii ? (b3 & 0x3F) : 64; + buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; + } + return buffer; + }; +})(); + +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + this.callbackIndex = 1; + this.postMessageTransfers = true; + var callbacksCapabilities = this.callbacksCapabilities = {}; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function ahConsoleLog(data) { + console.log.apply(console, data); + }]; + ah['console_error'] = [function ahConsoleError(data) { + console.error.apply(console, data); + }]; + ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) { + UnsupportedManager.notify(data); + }]; + + comObj.onmessage = function messageHandlerComObjOnMessage(event) { + var data = event.data; + if (data.isReply) { + var callbackId = data.callbackId; + if (data.callbackId in callbacksCapabilities) { + var callback = callbacksCapabilities[callbackId]; + delete callbacksCapabilities[callbackId]; + if ('error' in data) { + callback.reject(data.error); + } else { + callback.resolve(data.data); + } + } else { + error('Cannot resolve callback ' + callbackId); + } + } else if (data.action in ah) { + var action = ah[data.action]; + if (data.callbackId) { + Promise.resolve().then(function () { + return action[0].call(action[1], data.data); + }).then(function (result) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: result + }); + }, function (reason) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + error: reason + }); + }); + } else { + action[0].call(action[1], data.data); + } + } else { + error('Unknown action from worker: ' + data.action); + } + }; +} + +MessageHandler.prototype = { + on: function messageHandlerOn(actionName, handler, scope) { + var ah = this.actionHandler; + if (ah[actionName]) { + error('There is already an actionName called "' + actionName + '"'); + } + ah[actionName] = [handler, scope]; + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers + */ + send: function messageHandlerSend(actionName, data, transfers) { + var message = { + action: actionName, + data: data + }; + this.postMessage(message, transfers); + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * Expects that other side will callback with the response. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers. + * @returns {Promise} Promise to be resolved with response data. + */ + sendWithPromise: + function messageHandlerSendWithPromise(actionName, data, transfers) { + var callbackId = this.callbackIndex++; + var message = { + action: actionName, + data: data, + callbackId: callbackId + }; + var capability = createPromiseCapability(); + this.callbacksCapabilities[callbackId] = capability; + try { + this.postMessage(message, transfers); + } catch (e) { + capability.reject(e); + } + return capability.promise; + }, + /** + * Sends raw message to the comObj. + * @private + * @param message {Object} Raw message. + * @param transfers List of transfers/ArrayBuffers, or undefined. + */ + postMessage: function (message, transfers) { + if (transfers && this.postMessageTransfers) { + this.comObj.postMessage(message, transfers); + } else { + this.comObj.postMessage(message); + } + } +}; + +function loadJpegStream(id, imageUrl, objs) { + var img = new Image(); + img.onload = (function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }); + img.onerror = (function loadJpegStream_onerrorClosure() { + objs.resolve(id, null); + warn('Error during JPEG image loading'); + }); + img.src = imageUrl; +} + + + + +var NetworkManager = (function NetworkManagerClosure() { + + var OK_RESPONSE = 200; + var PARTIAL_CONTENT_RESPONSE = 206; + + function NetworkManager(url, args) { + this.url = url; + args = args || {}; + this.isHttp = /^https?:/i.test(url); + this.httpHeaders = (this.isHttp && args.httpHeaders) || {}; + this.withCredentials = args.withCredentials || false; + this.getXhr = args.getXhr || + function NetworkManager_getXhr() { + return new XMLHttpRequest(); + }; + + this.currXhrId = 0; + this.pendingRequests = {}; + this.loadedRequests = {}; + } + + function getArrayBuffer(xhr) { + var data = xhr.response; + if (typeof data !== 'string') { + return data; + } + var length = data.length; + var array = new Uint8Array(length); + for (var i = 0; i < length; i++) { + array[i] = data.charCodeAt(i) & 0xFF; + } + return array.buffer; + } + + NetworkManager.prototype = { + requestRange: function NetworkManager_requestRange(begin, end, listeners) { + var args = { + begin: begin, + end: end + }; + for (var prop in listeners) { + args[prop] = listeners[prop]; + } + return this.request(args); + }, + + requestFull: function NetworkManager_requestFull(listeners) { + return this.request(listeners); + }, + + request: function NetworkManager_request(args) { + var xhr = this.getXhr(); + var xhrId = this.currXhrId++; + var pendingRequest = this.pendingRequests[xhrId] = { + xhr: xhr + }; + + xhr.open('GET', this.url); + xhr.withCredentials = this.withCredentials; + for (var property in this.httpHeaders) { + var value = this.httpHeaders[property]; + if (typeof value === 'undefined') { + continue; + } + xhr.setRequestHeader(property, value); + } + if (this.isHttp && 'begin' in args && 'end' in args) { + var rangeStr = args.begin + '-' + (args.end - 1); + xhr.setRequestHeader('Range', 'bytes=' + rangeStr); + pendingRequest.expectedStatus = 206; + } else { + pendingRequest.expectedStatus = 200; + } + + if (args.onProgressiveData) { + // Some legacy browsers might throw an exception. + try { + xhr.responseType = 'moz-chunked-arraybuffer'; + } catch(e) {} + if (xhr.responseType === 'moz-chunked-arraybuffer') { + pendingRequest.onProgressiveData = args.onProgressiveData; + pendingRequest.mozChunked = true; + } else { + xhr.responseType = 'arraybuffer'; + } + } else { + xhr.responseType = 'arraybuffer'; + } + + if (args.onError) { + xhr.onerror = function(evt) { + args.onError(xhr.status); + }; + } + xhr.onreadystatechange = this.onStateChange.bind(this, xhrId); + xhr.onprogress = this.onProgress.bind(this, xhrId); + + pendingRequest.onHeadersReceived = args.onHeadersReceived; + pendingRequest.onDone = args.onDone; + pendingRequest.onError = args.onError; + pendingRequest.onProgress = args.onProgress; + + xhr.send(null); + + return xhrId; + }, + + onProgress: function NetworkManager_onProgress(xhrId, evt) { + var pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + // Maybe abortRequest was called... + return; + } + + if (pendingRequest.mozChunked) { + var chunk = getArrayBuffer(pendingRequest.xhr); + pendingRequest.onProgressiveData(chunk); + } + + var onProgress = pendingRequest.onProgress; + if (onProgress) { + onProgress(evt); + } + }, + + onStateChange: function NetworkManager_onStateChange(xhrId, evt) { + var pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + // Maybe abortRequest was called... + return; + } + + var xhr = pendingRequest.xhr; + if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { + pendingRequest.onHeadersReceived(); + delete pendingRequest.onHeadersReceived; + } + + if (xhr.readyState !== 4) { + return; + } + + if (!(xhrId in this.pendingRequests)) { + // The XHR request might have been aborted in onHeadersReceived() + // callback, in which case we should abort request + return; + } + + delete this.pendingRequests[xhrId]; + + // success status == 0 can be on ftp, file and other protocols + if (xhr.status === 0 && this.isHttp) { + if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + return; + } + var xhrStatus = xhr.status || OK_RESPONSE; + + // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2: + // "A server MAY ignore the Range header". This means it's possible to + // get a 200 rather than a 206 response from a range request. + var ok_response_on_range_request = + xhrStatus === OK_RESPONSE && + pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; + + if (!ok_response_on_range_request && + xhrStatus !== pendingRequest.expectedStatus) { + if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + return; + } + + this.loadedRequests[xhrId] = true; + + var chunk = getArrayBuffer(xhr); + if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { + var rangeHeader = xhr.getResponseHeader('Content-Range'); + var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); + var begin = parseInt(matches[1], 10); + pendingRequest.onDone({ + begin: begin, + chunk: chunk + }); + } else if (pendingRequest.onProgressiveData) { + pendingRequest.onDone(null); + } else { + pendingRequest.onDone({ + begin: 0, + chunk: chunk + }); + } + }, + + hasPendingRequests: function NetworkManager_hasPendingRequests() { + for (var xhrId in this.pendingRequests) { + return true; + } + return false; + }, + + getRequestXhr: function NetworkManager_getXhr(xhrId) { + return this.pendingRequests[xhrId].xhr; + }, + + isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) { + return !!(this.pendingRequests[xhrId].onProgressiveData); + }, + + isPendingRequest: function NetworkManager_isPendingRequest(xhrId) { + return xhrId in this.pendingRequests; + }, + + isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) { + return xhrId in this.loadedRequests; + }, + + abortAllRequests: function NetworkManager_abortAllRequests() { + for (var xhrId in this.pendingRequests) { + this.abortRequest(xhrId | 0); + } + }, + + abortRequest: function NetworkManager_abortRequest(xhrId) { + var xhr = this.pendingRequests[xhrId].xhr; + delete this.pendingRequests[xhrId]; + xhr.abort(); + } + }; + + return NetworkManager; +})(); + + +var ChunkedStream = (function ChunkedStreamClosure() { + function ChunkedStream(length, chunkSize, manager) { + this.bytes = new Uint8Array(length); + this.start = 0; + this.pos = 0; + this.end = length; + this.chunkSize = chunkSize; + this.loadedChunks = []; + this.numChunksLoaded = 0; + this.numChunks = Math.ceil(length / chunkSize); + this.manager = manager; + this.progressiveDataLength = 0; + this.lastSuccessfulEnsureByteChunk = -1; // a single-entry cache + } + + // required methods for a stream. if a particular stream does not + // implement these, an error should be thrown + ChunkedStream.prototype = { + + getMissingChunks: function ChunkedStream_getMissingChunks() { + var chunks = []; + for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) { + if (!this.loadedChunks[chunk]) { + chunks.push(chunk); + } + } + return chunks; + }, + + getBaseStreams: function ChunkedStream_getBaseStreams() { + return [this]; + }, + + allChunksLoaded: function ChunkedStream_allChunksLoaded() { + return this.numChunksLoaded === this.numChunks; + }, + + onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) { + var end = begin + chunk.byteLength; + + assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin); + // Using this.length is inaccurate here since this.start can be moved + // See ChunkedStream.moveStart() + var length = this.bytes.length; + assert(end % this.chunkSize === 0 || end === length, + 'Bad end offset: ' + end); + + this.bytes.set(new Uint8Array(chunk), begin); + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(begin / chunkSize); + var endChunk = Math.floor((end - 1) / chunkSize) + 1; + var curChunk; + + for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + if (!this.loadedChunks[curChunk]) { + this.loadedChunks[curChunk] = true; + ++this.numChunksLoaded; + } + } + }, + + onReceiveProgressiveData: + function ChunkedStream_onReceiveProgressiveData(data) { + var position = this.progressiveDataLength; + var beginChunk = Math.floor(position / this.chunkSize); + + this.bytes.set(new Uint8Array(data), position); + position += data.byteLength; + this.progressiveDataLength = position; + var endChunk = position >= this.end ? this.numChunks : + Math.floor(position / this.chunkSize); + var curChunk; + for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + if (!this.loadedChunks[curChunk]) { + this.loadedChunks[curChunk] = true; + ++this.numChunksLoaded; + } + } + }, + + ensureByte: function ChunkedStream_ensureByte(pos) { + var chunk = Math.floor(pos / this.chunkSize); + if (chunk === this.lastSuccessfulEnsureByteChunk) { + return; + } + + if (!this.loadedChunks[chunk]) { + throw new MissingDataException(pos, pos + 1); + } + this.lastSuccessfulEnsureByteChunk = chunk; + }, + + ensureRange: function ChunkedStream_ensureRange(begin, end) { + if (begin >= end) { + return; + } + + if (end <= this.progressiveDataLength) { + return; + } + + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(begin / chunkSize); + var endChunk = Math.floor((end - 1) / chunkSize) + 1; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!this.loadedChunks[chunk]) { + throw new MissingDataException(begin, end); + } + } + }, + + nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) { + var chunk, n; + for (chunk = beginChunk, n = this.numChunks; chunk < n; ++chunk) { + if (!this.loadedChunks[chunk]) { + return chunk; + } + } + // Wrap around to beginning + for (chunk = 0; chunk < beginChunk; ++chunk) { + if (!this.loadedChunks[chunk]) { + return chunk; + } + } + return null; + }, + + hasChunk: function ChunkedStream_hasChunk(chunk) { + return !!this.loadedChunks[chunk]; + }, + + get length() { + return this.end - this.start; + }, + + get isEmpty() { + return this.length === 0; + }, + + getByte: function ChunkedStream_getByte() { + var pos = this.pos; + if (pos >= this.end) { + return -1; + } + this.ensureByte(pos); + return this.bytes[this.pos++]; + }, + + getUint16: function ChunkedStream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + + getInt32: function ChunkedStream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + + // returns subarray of original buffer + // should only be read + getBytes: function ChunkedStream_getBytes(length) { + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + + if (!length) { + this.ensureRange(pos, strEnd); + return bytes.subarray(pos, strEnd); + } + + var end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.ensureRange(pos, end); + + this.pos = end; + return bytes.subarray(pos, end); + }, + + peekByte: function ChunkedStream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + + peekBytes: function ChunkedStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + + getByteRange: function ChunkedStream_getBytes(begin, end) { + this.ensureRange(begin, end); + return this.bytes.subarray(begin, end); + }, + + skip: function ChunkedStream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + + reset: function ChunkedStream_reset() { + this.pos = this.start; + }, + + moveStart: function ChunkedStream_moveStart() { + this.start = this.pos; + }, + + makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) { + this.ensureRange(start, start + length); + + function ChunkedStreamSubstream() {} + ChunkedStreamSubstream.prototype = Object.create(this); + ChunkedStreamSubstream.prototype.getMissingChunks = function() { + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(this.start / chunkSize); + var endChunk = Math.floor((this.end - 1) / chunkSize) + 1; + var missingChunks = []; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!this.loadedChunks[chunk]) { + missingChunks.push(chunk); + } + } + return missingChunks; + }; + var subStream = new ChunkedStreamSubstream(); + subStream.pos = subStream.start = start; + subStream.end = start + length || this.end; + subStream.dict = dict; + return subStream; + }, + + isStream: true + }; + + return ChunkedStream; +})(); + +var ChunkedStreamManager = (function ChunkedStreamManagerClosure() { + + function ChunkedStreamManager(length, chunkSize, url, args) { + this.stream = new ChunkedStream(length, chunkSize, this); + this.length = length; + this.chunkSize = chunkSize; + this.url = url; + this.disableAutoFetch = args.disableAutoFetch; + var msgHandler = this.msgHandler = args.msgHandler; + + if (args.chunkedViewerLoading) { + msgHandler.on('OnDataRange', this.onReceiveData.bind(this)); + msgHandler.on('OnDataProgress', this.onProgress.bind(this)); + this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) { + msgHandler.send('RequestDataRange', { begin: begin, end: end }); + }; + } else { + + var getXhr = function getXhr() { + return new XMLHttpRequest(); + }; + this.networkManager = new NetworkManager(this.url, { + getXhr: getXhr, + httpHeaders: args.httpHeaders, + withCredentials: args.withCredentials + }); + this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) { + this.networkManager.requestRange(begin, end, { + onDone: this.onReceiveData.bind(this), + onProgress: this.onProgress.bind(this) + }); + }; + } + + this.currRequestId = 0; + + this.chunksNeededByRequest = {}; + this.requestsByChunk = {}; + this.callbacksByRequest = {}; + this.progressiveDataLength = 0; + + this._loadedStreamCapability = createPromiseCapability(); + + if (args.initialData) { + this.onReceiveData({chunk: args.initialData}); + } + } + + ChunkedStreamManager.prototype = { + onLoadedStream: function ChunkedStreamManager_getLoadedStream() { + return this._loadedStreamCapability.promise; + }, + + // Get all the chunks that are not yet loaded and groups them into + // contiguous ranges to load in as few requests as possible + requestAllChunks: function ChunkedStreamManager_requestAllChunks() { + var missingChunks = this.stream.getMissingChunks(); + this.requestChunks(missingChunks); + return this._loadedStreamCapability.promise; + }, + + requestChunks: function ChunkedStreamManager_requestChunks(chunks, + callback) { + var requestId = this.currRequestId++; + + var chunksNeeded; + var i, ii; + this.chunksNeededByRequest[requestId] = chunksNeeded = {}; + for (i = 0, ii = chunks.length; i < ii; i++) { + if (!this.stream.hasChunk(chunks[i])) { + chunksNeeded[chunks[i]] = true; + } + } + + if (isEmptyObj(chunksNeeded)) { + if (callback) { + callback(); + } + return; + } + + this.callbacksByRequest[requestId] = callback; + + var chunksToRequest = []; + for (var chunk in chunksNeeded) { + chunk = chunk | 0; + if (!(chunk in this.requestsByChunk)) { + this.requestsByChunk[chunk] = []; + chunksToRequest.push(chunk); + } + this.requestsByChunk[chunk].push(requestId); + } + + if (!chunksToRequest.length) { + return; + } + + var groupedChunksToRequest = this.groupChunks(chunksToRequest); + + for (i = 0; i < groupedChunksToRequest.length; ++i) { + var groupedChunk = groupedChunksToRequest[i]; + var begin = groupedChunk.beginChunk * this.chunkSize; + var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length); + this.sendRequest(begin, end); + } + }, + + getStream: function ChunkedStreamManager_getStream() { + return this.stream; + }, + + // Loads any chunks in the requested range that are not yet loaded + requestRange: function ChunkedStreamManager_requestRange( + begin, end, callback) { + + end = Math.min(end, this.length); + + var beginChunk = this.getBeginChunk(begin); + var endChunk = this.getEndChunk(end); + + var chunks = []; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + chunks.push(chunk); + } + + this.requestChunks(chunks, callback); + }, + + requestRanges: function ChunkedStreamManager_requestRanges(ranges, + callback) { + ranges = ranges || []; + var chunksToRequest = []; + + for (var i = 0; i < ranges.length; i++) { + var beginChunk = this.getBeginChunk(ranges[i].begin); + var endChunk = this.getEndChunk(ranges[i].end); + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (chunksToRequest.indexOf(chunk) < 0) { + chunksToRequest.push(chunk); + } + } + } + + chunksToRequest.sort(function(a, b) { return a - b; }); + this.requestChunks(chunksToRequest, callback); + }, + + // Groups a sorted array of chunks into as few continguous larger + // chunks as possible + groupChunks: function ChunkedStreamManager_groupChunks(chunks) { + var groupedChunks = []; + var beginChunk = -1; + var prevChunk = -1; + for (var i = 0; i < chunks.length; ++i) { + var chunk = chunks[i]; + + if (beginChunk < 0) { + beginChunk = chunk; + } + + if (prevChunk >= 0 && prevChunk + 1 !== chunk) { + groupedChunks.push({ beginChunk: beginChunk, + endChunk: prevChunk + 1 }); + beginChunk = chunk; + } + if (i + 1 === chunks.length) { + groupedChunks.push({ beginChunk: beginChunk, + endChunk: chunk + 1 }); + } + + prevChunk = chunk; + } + return groupedChunks; + }, + + onProgress: function ChunkedStreamManager_onProgress(args) { + var bytesLoaded = (this.stream.numChunksLoaded * this.chunkSize + + args.loaded); + this.msgHandler.send('DocProgress', { + loaded: bytesLoaded, + total: this.length + }); + }, + + onReceiveData: function ChunkedStreamManager_onReceiveData(args) { + var chunk = args.chunk; + var isProgressive = args.begin === undefined; + var begin = isProgressive ? this.progressiveDataLength : args.begin; + var end = begin + chunk.byteLength; + + var beginChunk = Math.floor(begin / this.chunkSize); + var endChunk = end < this.length ? Math.floor(end / this.chunkSize) : + Math.ceil(end / this.chunkSize); + + if (isProgressive) { + this.stream.onReceiveProgressiveData(chunk); + this.progressiveDataLength = end; + } else { + this.stream.onReceiveData(begin, chunk); + } + + if (this.stream.allChunksLoaded()) { + this._loadedStreamCapability.resolve(this.stream); + } + + var loadedRequests = []; + var i, requestId; + for (chunk = beginChunk; chunk < endChunk; ++chunk) { + // The server might return more chunks than requested + var requestIds = this.requestsByChunk[chunk] || []; + delete this.requestsByChunk[chunk]; + + for (i = 0; i < requestIds.length; ++i) { + requestId = requestIds[i]; + var chunksNeeded = this.chunksNeededByRequest[requestId]; + if (chunk in chunksNeeded) { + delete chunksNeeded[chunk]; + } + + if (!isEmptyObj(chunksNeeded)) { + continue; + } + + loadedRequests.push(requestId); + } + } + + // If there are no pending requests, automatically fetch the next + // unfetched chunk of the PDF + if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) { + var nextEmptyChunk; + if (this.stream.numChunksLoaded === 1) { + // This is a special optimization so that after fetching the first + // chunk, rather than fetching the second chunk, we fetch the last + // chunk. + var lastChunk = this.stream.numChunks - 1; + if (!this.stream.hasChunk(lastChunk)) { + nextEmptyChunk = lastChunk; + } + } else { + nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); + } + if (isInt(nextEmptyChunk)) { + this.requestChunks([nextEmptyChunk]); + } + } + + for (i = 0; i < loadedRequests.length; ++i) { + requestId = loadedRequests[i]; + var callback = this.callbacksByRequest[requestId]; + delete this.callbacksByRequest[requestId]; + if (callback) { + callback(); + } + } + + this.msgHandler.send('DocProgress', { + loaded: this.stream.numChunksLoaded * this.chunkSize, + total: this.length + }); + }, + + onError: function ChunkedStreamManager_onError(err) { + this._loadedStreamCapability.reject(err); + }, + + getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) { + var chunk = Math.floor(begin / this.chunkSize); + return chunk; + }, + + getEndChunk: function ChunkedStreamManager_getEndChunk(end) { + if (end % this.chunkSize === 0) { + return end / this.chunkSize; + } + + // 0 -> 0 + // 1 -> 1 + // 99 -> 1 + // 100 -> 1 + // 101 -> 2 + var chunk = Math.floor((end - 1) / this.chunkSize) + 1; + return chunk; + } + }; + + return ChunkedStreamManager; +})(); + + +// The maximum number of bytes fetched per range request +var RANGE_CHUNK_SIZE = 65536; + +// TODO(mack): Make use of PDFJS.Util.inherit() when it becomes available +var BasePdfManager = (function BasePdfManagerClosure() { + function BasePdfManager() { + throw new Error('Cannot initialize BaseManagerManager'); + } + + BasePdfManager.prototype = { + onLoadedStream: function BasePdfManager_onLoadedStream() { + throw new NotImplementedException(); + }, + + ensureDoc: function BasePdfManager_ensureDoc(prop, args) { + return this.ensure(this.pdfDocument, prop, args); + }, + + ensureXRef: function BasePdfManager_ensureXRef(prop, args) { + return this.ensure(this.pdfDocument.xref, prop, args); + }, + + ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) { + return this.ensure(this.pdfDocument.catalog, prop, args); + }, + + getPage: function BasePdfManager_pagePage(pageIndex) { + return this.pdfDocument.getPage(pageIndex); + }, + + cleanup: function BasePdfManager_cleanup() { + return this.pdfDocument.cleanup(); + }, + + ensure: function BasePdfManager_ensure(obj, prop, args) { + return new NotImplementedException(); + }, + + requestRange: function BasePdfManager_ensure(begin, end) { + return new NotImplementedException(); + }, + + requestLoadedStream: function BasePdfManager_requestLoadedStream() { + return new NotImplementedException(); + }, + + sendProgressiveData: function BasePdfManager_sendProgressiveData(chunk) { + return new NotImplementedException(); + }, + + updatePassword: function BasePdfManager_updatePassword(password) { + this.pdfDocument.xref.password = this.password = password; + if (this._passwordChangedCapability) { + this._passwordChangedCapability.resolve(); + } + }, + + passwordChanged: function BasePdfManager_passwordChanged() { + this._passwordChangedCapability = createPromiseCapability(); + return this._passwordChangedCapability.promise; + }, + + terminate: function BasePdfManager_terminate() { + return new NotImplementedException(); + } + }; + + return BasePdfManager; +})(); + +var LocalPdfManager = (function LocalPdfManagerClosure() { + function LocalPdfManager(data, password) { + var stream = new Stream(data); + this.pdfDocument = new PDFDocument(this, stream, password); + this._loadedStreamCapability = createPromiseCapability(); + this._loadedStreamCapability.resolve(stream); + } + + LocalPdfManager.prototype = Object.create(BasePdfManager.prototype); + LocalPdfManager.prototype.constructor = LocalPdfManager; + + LocalPdfManager.prototype.ensure = + function LocalPdfManager_ensure(obj, prop, args) { + return new Promise(function (resolve, reject) { + try { + var value = obj[prop]; + var result; + if (typeof value === 'function') { + result = value.apply(obj, args); + } else { + result = value; + } + resolve(result); + } catch (e) { + reject(e); + } + }); + }; + + LocalPdfManager.prototype.requestRange = + function LocalPdfManager_requestRange(begin, end) { + return Promise.resolve(); + }; + + LocalPdfManager.prototype.requestLoadedStream = + function LocalPdfManager_requestLoadedStream() { + }; + + LocalPdfManager.prototype.onLoadedStream = + function LocalPdfManager_getLoadedStream() { + return this._loadedStreamCapability.promise; + }; + + LocalPdfManager.prototype.terminate = + function LocalPdfManager_terminate() { + + }; + + return LocalPdfManager; +})(); + +var NetworkPdfManager = (function NetworkPdfManagerClosure() { + function NetworkPdfManager(args, msgHandler) { + + this.msgHandler = msgHandler; + + var params = { + msgHandler: msgHandler, + httpHeaders: args.httpHeaders, + withCredentials: args.withCredentials, + chunkedViewerLoading: args.chunkedViewerLoading, + disableAutoFetch: args.disableAutoFetch, + initialData: args.initialData + }; + this.streamManager = new ChunkedStreamManager(args.length, RANGE_CHUNK_SIZE, + args.url, params); + + this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(), + args.password); + } + + NetworkPdfManager.prototype = Object.create(BasePdfManager.prototype); + NetworkPdfManager.prototype.constructor = NetworkPdfManager; + + NetworkPdfManager.prototype.ensure = + function NetworkPdfManager_ensure(obj, prop, args) { + var pdfManager = this; + + return new Promise(function (resolve, reject) { + function ensureHelper() { + try { + var result; + var value = obj[prop]; + if (typeof value === 'function') { + result = value.apply(obj, args); + } else { + result = value; + } + resolve(result); + } catch(e) { + if (!(e instanceof MissingDataException)) { + reject(e); + return; + } + pdfManager.streamManager.requestRange(e.begin, e.end, ensureHelper); + } + } + + ensureHelper(); + }); + }; + + NetworkPdfManager.prototype.requestRange = + function NetworkPdfManager_requestRange(begin, end) { + return new Promise(function (resolve) { + this.streamManager.requestRange(begin, end, function() { + resolve(); + }); + }.bind(this)); + }; + + NetworkPdfManager.prototype.requestLoadedStream = + function NetworkPdfManager_requestLoadedStream() { + this.streamManager.requestAllChunks(); + }; + + NetworkPdfManager.prototype.sendProgressiveData = + function NetworkPdfManager_sendProgressiveData(chunk) { + this.streamManager.onReceiveData({ chunk: chunk }); + }; + + NetworkPdfManager.prototype.onLoadedStream = + function NetworkPdfManager_getLoadedStream() { + return this.streamManager.onLoadedStream(); + }; + + NetworkPdfManager.prototype.terminate = + function NetworkPdfManager_terminate() { + this.streamManager.networkManager.abortAllRequests(); + }; + + return NetworkPdfManager; +})(); + + +var Page = (function PageClosure() { + + var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792]; + + function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) { + this.pdfManager = pdfManager; + this.pageIndex = pageIndex; + this.pageDict = pageDict; + this.xref = xref; + this.ref = ref; + this.fontCache = fontCache; + this.idCounters = { + obj: 0 + }; + this.resourcesPromise = null; + } + + Page.prototype = { + getPageProp: function Page_getPageProp(key) { + return this.pageDict.get(key); + }, + + getInheritedPageProp: function Page_inheritPageProp(key) { + var dict = this.pageDict; + var value = dict.get(key); + while (value === undefined) { + dict = dict.get('Parent'); + if (!dict) { + break; + } + value = dict.get(key); + } + return value; + }, + + get content() { + return this.getPageProp('Contents'); + }, + + get resources() { + var value = this.getInheritedPageProp('Resources'); + // For robustness: The spec states that a \Resources entry has to be + // present, but can be empty. Some document omit it still. In this case + // return an empty dictionary: + if (value === undefined) { + value = Dict.empty; + } + return shadow(this, 'resources', value); + }, + + get mediaBox() { + var obj = this.getInheritedPageProp('MediaBox'); + // Reset invalid media box to letter size. + if (!isArray(obj) || obj.length !== 4) { + obj = LETTER_SIZE_MEDIABOX; + } + return shadow(this, 'mediaBox', obj); + }, + + get view() { + var mediaBox = this.mediaBox; + var cropBox = this.getInheritedPageProp('CropBox'); + if (!isArray(cropBox) || cropBox.length !== 4) { + return shadow(this, 'view', mediaBox); + } + + // From the spec, 6th ed., p.963: + // "The crop, bleed, trim, and art boxes should not ordinarily + // extend beyond the boundaries of the media box. If they do, they are + // effectively reduced to their intersection with the media box." + cropBox = Util.intersect(cropBox, mediaBox); + if (!cropBox) { + return shadow(this, 'view', mediaBox); + } + return shadow(this, 'view', cropBox); + }, + + get annotationRefs() { + return shadow(this, 'annotationRefs', + this.getInheritedPageProp('Annots')); + }, + + get rotate() { + var rotate = this.getInheritedPageProp('Rotate') || 0; + // Normalize rotation so it's a multiple of 90 and between 0 and 270 + if (rotate % 90 !== 0) { + rotate = 0; + } else if (rotate >= 360) { + rotate = rotate % 360; + } else if (rotate < 0) { + // The spec doesn't cover negatives, assume its counterclockwise + // rotation. The following is the other implementation of modulo. + rotate = ((rotate % 360) + 360) % 360; + } + return shadow(this, 'rotate', rotate); + }, + + getContentStream: function Page_getContentStream() { + var content = this.content; + var stream; + if (isArray(content)) { + // fetching items + var xref = this.xref; + var i, n = content.length; + var streams = []; + for (i = 0; i < n; ++i) { + streams.push(xref.fetchIfRef(content[i])); + } + stream = new StreamsSequenceStream(streams); + } else if (isStream(content)) { + stream = content; + } else { + // replacing non-existent page content with empty one + stream = new NullStream(); + } + return stream; + }, + + loadResources: function Page_loadResources(keys) { + if (!this.resourcesPromise) { + // TODO: add async getInheritedPageProp and remove this. + this.resourcesPromise = this.pdfManager.ensure(this, 'resources'); + } + return this.resourcesPromise.then(function resourceSuccess() { + var objectLoader = new ObjectLoader(this.resources.map, + keys, + this.xref); + return objectLoader.load(); + }.bind(this)); + }, + + getOperatorList: function Page_getOperatorList(handler, intent) { + var self = this; + + var pdfManager = this.pdfManager; + var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', + []); + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'ColorSpace', + 'Pattern', + 'Shading', + 'XObject', + 'Font' + // ProcSet + // Properties + ]); + + var partialEvaluator = new PartialEvaluator(pdfManager, this.xref, + handler, this.pageIndex, + 'p' + this.pageIndex + '_', + this.idCounters, + this.fontCache); + + var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); + var pageListPromise = dataPromises.then(function(data) { + var contentStream = data[0]; + var opList = new OperatorList(intent, handler, self.pageIndex); + + handler.send('StartRenderPage', { + transparency: partialEvaluator.hasBlendModes(self.resources), + pageIndex: self.pageIndex, + intent: intent + }); + return partialEvaluator.getOperatorList(contentStream, self.resources, + opList).then(function () { + return opList; + }); + }); + + var annotationsPromise = pdfManager.ensure(this, 'annotations'); + return Promise.all([pageListPromise, annotationsPromise]).then( + function(datas) { + var pageOpList = datas[0]; + var annotations = datas[1]; + + if (annotations.length === 0) { + pageOpList.flush(true); + return pageOpList; + } + + var annotationsReadyPromise = Annotation.appendToOperatorList( + annotations, pageOpList, pdfManager, partialEvaluator, intent); + return annotationsReadyPromise.then(function () { + pageOpList.flush(true); + return pageOpList; + }); + }); + }, + + extractTextContent: function Page_extractTextContent() { + var handler = { + on: function nullHandlerOn() {}, + send: function nullHandlerSend() {} + }; + + var self = this; + + var pdfManager = this.pdfManager; + var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', + []); + + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'XObject', + 'Font' + ]); + + var dataPromises = Promise.all([contentStreamPromise, + resourcesPromise]); + return dataPromises.then(function(data) { + var contentStream = data[0]; + var partialEvaluator = new PartialEvaluator(pdfManager, self.xref, + handler, self.pageIndex, + 'p' + self.pageIndex + '_', + self.idCounters, + self.fontCache); + + return partialEvaluator.getTextContent(contentStream, + self.resources); + }); + }, + + getAnnotationsData: function Page_getAnnotationsData() { + var annotations = this.annotations; + var annotationsData = []; + for (var i = 0, n = annotations.length; i < n; ++i) { + annotationsData.push(annotations[i].getData()); + } + return annotationsData; + }, + + get annotations() { + var annotations = []; + var annotationRefs = (this.annotationRefs || []); + for (var i = 0, n = annotationRefs.length; i < n; ++i) { + var annotationRef = annotationRefs[i]; + var annotation = Annotation.fromRef(this.xref, annotationRef); + if (annotation) { + annotations.push(annotation); + } + } + return shadow(this, 'annotations', annotations); + } + }; + + return Page; +})(); + +/** + * The `PDFDocument` holds all the data of the PDF file. Compared to the + * `PDFDoc`, this one doesn't have any job management code. + * Right now there exists one PDFDocument on the main thread + one object + * for each worker. If there is no worker support enabled, there are two + * `PDFDocument` objects on the main thread created. + */ +var PDFDocument = (function PDFDocumentClosure() { + var FINGERPRINT_FIRST_BYTES = 1024; + var EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' + + '\x00\x00\x00\x00\x00\x00\x00\x00\x00'; + + function PDFDocument(pdfManager, arg, password) { + if (isStream(arg)) { + init.call(this, pdfManager, arg, password); + } else if (isArrayBuffer(arg)) { + init.call(this, pdfManager, new Stream(arg), password); + } else { + error('PDFDocument: Unknown argument type'); + } + } + + function init(pdfManager, stream, password) { + assert(stream.length > 0, 'stream must have data'); + this.pdfManager = pdfManager; + this.stream = stream; + var xref = new XRef(this.stream, password, pdfManager); + this.xref = xref; + } + + function find(stream, needle, limit, backwards) { + var pos = stream.pos; + var end = stream.end; + var strBuf = []; + if (pos + limit > end) { + limit = end - pos; + } + for (var n = 0; n < limit; ++n) { + strBuf.push(String.fromCharCode(stream.getByte())); + } + var str = strBuf.join(''); + stream.pos = pos; + var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle); + if (index === -1) { + return false; /* not found */ + } + stream.pos += index; + return true; /* found */ + } + + var DocumentInfoValidators = { + get entries() { + // Lazily build this since all the validation functions below are not + // defined until after this file loads. + return shadow(this, 'entries', { + Title: isString, + Author: isString, + Subject: isString, + Keywords: isString, + Creator: isString, + Producer: isString, + CreationDate: isString, + ModDate: isString, + Trapped: isName + }); + } + }; + + PDFDocument.prototype = { + parse: function PDFDocument_parse(recoveryMode) { + this.setup(recoveryMode); + try { + // checking if AcroForm is present + this.acroForm = this.catalog.catDict.get('AcroForm'); + if (this.acroForm) { + this.xfa = this.acroForm.get('XFA'); + var fields = this.acroForm.get('Fields'); + if ((!fields || !isArray(fields) || fields.length === 0) && + !this.xfa) { + // no fields and no XFA -- not a form (?) + this.acroForm = null; + } + } + } catch (ex) { + info('Something wrong with AcroForm entry'); + this.acroForm = null; + } + }, + + get linearization() { + var linearization = null; + if (this.stream.length) { + try { + linearization = Linearization.create(this.stream); + } catch (err) { + if (err instanceof MissingDataException) { + throw err; + } + info(err); + } + } + // shadow the prototype getter with a data property + return shadow(this, 'linearization', linearization); + }, + get startXRef() { + var stream = this.stream; + var startXRef = 0; + var linearization = this.linearization; + if (linearization) { + // Find end of first obj. + stream.reset(); + if (find(stream, 'endobj', 1024)) { + startXRef = stream.pos + 6; + } + } else { + // Find startxref by jumping backward from the end of the file. + var step = 1024; + var found = false, pos = stream.end; + while (!found && pos > 0) { + pos -= step - 'startxref'.length; + if (pos < 0) { + pos = 0; + } + stream.pos = pos; + found = find(stream, 'startxref', step, true); + } + if (found) { + stream.skip(9); + var ch; + do { + ch = stream.getByte(); + } while (Lexer.isSpace(ch)); + var str = ''; + while (ch >= 0x20 && ch <= 0x39) { // < '9' + str += String.fromCharCode(ch); + ch = stream.getByte(); + } + startXRef = parseInt(str, 10); + if (isNaN(startXRef)) { + startXRef = 0; + } + } + } + // shadow the prototype getter with a data property + return shadow(this, 'startXRef', startXRef); + }, + get mainXRefEntriesOffset() { + var mainXRefEntriesOffset = 0; + var linearization = this.linearization; + if (linearization) { + mainXRefEntriesOffset = linearization.mainXRefEntriesOffset; + } + // shadow the prototype getter with a data property + return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset); + }, + // Find the header, remove leading garbage and setup the stream + // starting from the header. + checkHeader: function PDFDocument_checkHeader() { + var stream = this.stream; + stream.reset(); + if (find(stream, '%PDF-', 1024)) { + // Found the header, trim off any garbage before it. + stream.moveStart(); + // Reading file format version + var MAX_VERSION_LENGTH = 12; + var version = '', ch; + while ((ch = stream.getByte()) > 0x20) { // SPACE + if (version.length >= MAX_VERSION_LENGTH) { + break; + } + version += String.fromCharCode(ch); + } + // removing "%PDF-"-prefix + this.pdfFormatVersion = version.substring(5); + + } + // May not be a PDF file, continue anyway. + }, + parseStartXRef: function PDFDocument_parseStartXRef() { + var startXRef = this.startXRef; + this.xref.setStartXRef(startXRef); + }, + setup: function PDFDocument_setup(recoveryMode) { + this.xref.parse(recoveryMode); + this.catalog = new Catalog(this.pdfManager, this.xref); + }, + get numPages() { + var linearization = this.linearization; + var num = linearization ? linearization.numPages : this.catalog.numPages; + // shadow the prototype getter + return shadow(this, 'numPages', num); + }, + get documentInfo() { + var docInfo = { + PDFFormatVersion: this.pdfFormatVersion, + IsAcroFormPresent: !!this.acroForm, + IsXFAPresent: !!this.xfa + }; + var infoDict; + try { + infoDict = this.xref.trailer.get('Info'); + } catch (err) { + info('The document information dictionary is invalid.'); + } + if (infoDict) { + var validEntries = DocumentInfoValidators.entries; + // Only fill the document info with valid entries from the spec. + for (var key in validEntries) { + if (infoDict.has(key)) { + var value = infoDict.get(key); + // Make sure the value conforms to the spec. + if (validEntries[key](value)) { + docInfo[key] = (typeof value !== 'string' ? + value : stringToPDFString(value)); + } else { + info('Bad value in document info for "' + key + '"'); + } + } + } + } + return shadow(this, 'documentInfo', docInfo); + }, + get fingerprint() { + var xref = this.xref, idArray, hash, fileID = ''; + + if (xref.trailer.has('ID')) { + idArray = xref.trailer.get('ID'); + } + if (idArray && isArray(idArray) && idArray[0] !== EMPTY_FINGERPRINT) { + hash = stringToBytes(idArray[0]); + } else { + if (this.stream.ensureRange) { + this.stream.ensureRange(0, + Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end)); + } + hash = calculateMD5(this.stream.bytes.subarray(0, + FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); + } + + for (var i = 0, n = hash.length; i < n; i++) { + var hex = hash[i].toString(16); + fileID += hex.length === 1 ? '0' + hex : hex; + } + + return shadow(this, 'fingerprint', fileID); + }, + + getPage: function PDFDocument_getPage(pageIndex) { + return this.catalog.getPage(pageIndex); + }, + + cleanup: function PDFDocument_cleanup() { + return this.catalog.cleanup(); + } + }; + + return PDFDocument; +})(); + + +var Name = (function NameClosure() { + function Name(name) { + this.name = name; + } + + Name.prototype = {}; + + var nameCache = {}; + + Name.get = function Name_get(name) { + var nameValue = nameCache[name]; + return (nameValue ? nameValue : (nameCache[name] = new Name(name))); + }; + + return Name; +})(); + +var Cmd = (function CmdClosure() { + function Cmd(cmd) { + this.cmd = cmd; + } + + Cmd.prototype = {}; + + var cmdCache = {}; + + Cmd.get = function Cmd_get(cmd) { + var cmdValue = cmdCache[cmd]; + return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd))); + }; + + return Cmd; +})(); + +var Dict = (function DictClosure() { + var nonSerializable = function nonSerializableClosure() { + return nonSerializable; // creating closure on some variable + }; + + var GETALL_DICTIONARY_TYPES_WHITELIST = { + 'Background': true, + 'ExtGState': true, + 'Halftone': true, + 'Layout': true, + 'Mask': true, + 'Pagination': true, + 'Printing': true + }; + + function isRecursionAllowedFor(dict) { + if (!isName(dict.Type)) { + return true; + } + var dictType = dict.Type.name; + return GETALL_DICTIONARY_TYPES_WHITELIST[dictType] === true; + } + + // xref is optional + function Dict(xref) { + // Map should only be used internally, use functions below to access. + this.map = Object.create(null); + this.xref = xref; + this.objId = null; + this.__nonSerializable__ = nonSerializable; // disable cloning of the Dict + } + + Dict.prototype = { + assignXref: function Dict_assignXref(newXref) { + this.xref = newXref; + }, + + // automatically dereferences Ref objects + get: function Dict_get(key1, key2, key3) { + var value; + var xref = this.xref; + if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || + typeof key2 === 'undefined') { + return xref ? xref.fetchIfRef(value) : value; + } + if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || + typeof key3 === 'undefined') { + return xref ? xref.fetchIfRef(value) : value; + } + value = this.map[key3] || null; + return xref ? xref.fetchIfRef(value) : value; + }, + + // Same as get(), but returns a promise and uses fetchIfRefAsync(). + getAsync: function Dict_getAsync(key1, key2, key3) { + var value; + var xref = this.xref; + if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || + typeof key2 === 'undefined') { + if (xref) { + return xref.fetchIfRefAsync(value); + } + return Promise.resolve(value); + } + if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || + typeof key3 === 'undefined') { + if (xref) { + return xref.fetchIfRefAsync(value); + } + return Promise.resolve(value); + } + value = this.map[key3] || null; + if (xref) { + return xref.fetchIfRefAsync(value); + } + return Promise.resolve(value); + }, + + // no dereferencing + getRaw: function Dict_getRaw(key) { + return this.map[key]; + }, + + // creates new map and dereferences all Refs + getAll: function Dict_getAll() { + var all = Object.create(null); + var queue = null; + var key, obj; + for (key in this.map) { + obj = this.get(key); + if (obj instanceof Dict) { + if (isRecursionAllowedFor(obj)) { + (queue || (queue = [])).push({target: all, key: key, obj: obj}); + } else { + all[key] = this.getRaw(key); + } + } else { + all[key] = obj; + } + } + if (!queue) { + return all; + } + + // trying to take cyclic references into the account + var processed = Object.create(null); + while (queue.length > 0) { + var item = queue.shift(); + var itemObj = item.obj; + var objId = itemObj.objId; + if (objId && objId in processed) { + item.target[item.key] = processed[objId]; + continue; + } + var dereferenced = Object.create(null); + for (key in itemObj.map) { + obj = itemObj.get(key); + if (obj instanceof Dict) { + if (isRecursionAllowedFor(obj)) { + queue.push({target: dereferenced, key: key, obj: obj}); + } else { + dereferenced[key] = itemObj.getRaw(key); + } + } else { + dereferenced[key] = obj; + } + } + if (objId) { + processed[objId] = dereferenced; + } + item.target[item.key] = dereferenced; + } + return all; + }, + + getKeys: function Dict_getKeys() { + return Object.keys(this.map); + }, + + set: function Dict_set(key, value) { + this.map[key] = value; + }, + + has: function Dict_has(key) { + return key in this.map; + }, + + forEach: function Dict_forEach(callback) { + for (var key in this.map) { + callback(key, this.get(key)); + } + } + }; + + Dict.empty = new Dict(null); + + return Dict; +})(); + +var Ref = (function RefClosure() { + function Ref(num, gen) { + this.num = num; + this.gen = gen; + } + + Ref.prototype = { + toString: function Ref_toString() { + // This function is hot, so we make the string as compact as possible. + // |this.gen| is almost always zero, so we treat that case specially. + var str = this.num + 'R'; + if (this.gen !== 0) { + str += this.gen; + } + return str; + } + }; + + return Ref; +})(); + +// The reference is identified by number and generation. +// This structure stores only one instance of the reference. +var RefSet = (function RefSetClosure() { + function RefSet() { + this.dict = {}; + } + + RefSet.prototype = { + has: function RefSet_has(ref) { + return ref.toString() in this.dict; + }, + + put: function RefSet_put(ref) { + this.dict[ref.toString()] = true; + }, + + remove: function RefSet_remove(ref) { + delete this.dict[ref.toString()]; + } + }; + + return RefSet; +})(); + +var RefSetCache = (function RefSetCacheClosure() { + function RefSetCache() { + this.dict = Object.create(null); + } + + RefSetCache.prototype = { + get: function RefSetCache_get(ref) { + return this.dict[ref.toString()]; + }, + + has: function RefSetCache_has(ref) { + return ref.toString() in this.dict; + }, + + put: function RefSetCache_put(ref, obj) { + this.dict[ref.toString()] = obj; + }, + + putAlias: function RefSetCache_putAlias(ref, aliasRef) { + this.dict[ref.toString()] = this.get(aliasRef); + }, + + forEach: function RefSetCache_forEach(fn, thisArg) { + for (var i in this.dict) { + fn.call(thisArg, this.dict[i]); + } + }, + + clear: function RefSetCache_clear() { + this.dict = Object.create(null); + } + }; + + return RefSetCache; +})(); + +var Catalog = (function CatalogClosure() { + function Catalog(pdfManager, xref) { + this.pdfManager = pdfManager; + this.xref = xref; + this.catDict = xref.getCatalogObj(); + this.fontCache = new RefSetCache(); + assert(isDict(this.catDict), + 'catalog object is not a dictionary'); + + this.pagePromises = []; + } + + Catalog.prototype = { + get metadata() { + var streamRef = this.catDict.getRaw('Metadata'); + if (!isRef(streamRef)) { + return shadow(this, 'metadata', null); + } + + var encryptMetadata = (!this.xref.encrypt ? false : + this.xref.encrypt.encryptMetadata); + + var stream = this.xref.fetch(streamRef, !encryptMetadata); + var metadata; + if (stream && isDict(stream.dict)) { + var type = stream.dict.get('Type'); + var subtype = stream.dict.get('Subtype'); + + if (isName(type) && isName(subtype) && + type.name === 'Metadata' && subtype.name === 'XML') { + // XXX: This should examine the charset the XML document defines, + // however since there are currently no real means to decode + // arbitrary charsets, let's just hope that the author of the PDF + // was reasonable enough to stick with the XML default charset, + // which is UTF-8. + try { + metadata = stringToUTF8String(bytesToString(stream.getBytes())); + } catch (e) { + info('Skipping invalid metadata.'); + } + } + } + + return shadow(this, 'metadata', metadata); + }, + get toplevelPagesDict() { + var pagesObj = this.catDict.get('Pages'); + assert(isDict(pagesObj), 'invalid top-level pages dictionary'); + // shadow the prototype getter + return shadow(this, 'toplevelPagesDict', pagesObj); + }, + get documentOutline() { + var obj = null; + try { + obj = this.readDocumentOutline(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Unable to read document outline'); + } + return shadow(this, 'documentOutline', obj); + }, + readDocumentOutline: function Catalog_readDocumentOutline() { + var xref = this.xref; + var obj = this.catDict.get('Outlines'); + var root = { items: [] }; + if (isDict(obj)) { + obj = obj.getRaw('First'); + var processed = new RefSet(); + if (isRef(obj)) { + var queue = [{obj: obj, parent: root}]; + // to avoid recursion keeping track of the items + // in the processed dictionary + processed.put(obj); + while (queue.length > 0) { + var i = queue.shift(); + var outlineDict = xref.fetchIfRef(i.obj); + if (outlineDict === null) { + continue; + } + if (!outlineDict.has('Title')) { + error('Invalid outline item'); + } + var dest = outlineDict.get('A'); + if (dest) { + dest = dest.get('D'); + } else if (outlineDict.has('Dest')) { + dest = outlineDict.getRaw('Dest'); + if (isName(dest)) { + dest = dest.name; + } + } + var title = outlineDict.get('Title'); + var outlineItem = { + dest: dest, + title: stringToPDFString(title), + color: outlineDict.get('C') || [0, 0, 0], + count: outlineDict.get('Count'), + bold: !!(outlineDict.get('F') & 2), + italic: !!(outlineDict.get('F') & 1), + items: [] + }; + i.parent.items.push(outlineItem); + obj = outlineDict.getRaw('First'); + if (isRef(obj) && !processed.has(obj)) { + queue.push({obj: obj, parent: outlineItem}); + processed.put(obj); + } + obj = outlineDict.getRaw('Next'); + if (isRef(obj) && !processed.has(obj)) { + queue.push({obj: obj, parent: i.parent}); + processed.put(obj); + } + } + } + } + return (root.items.length > 0 ? root.items : null); + }, + get numPages() { + var obj = this.toplevelPagesDict.get('Count'); + assert( + isInt(obj), + 'page count in top level pages object is not an integer' + ); + // shadow the prototype getter + return shadow(this, 'num', obj); + }, + get destinations() { + function fetchDestination(dest) { + return isDict(dest) ? dest.get('D') : dest; + } + + var xref = this.xref; + var dests = {}, nameTreeRef, nameDictionaryRef; + var obj = this.catDict.get('Names'); + if (obj && obj.has('Dests')) { + nameTreeRef = obj.getRaw('Dests'); + } else if (this.catDict.has('Dests')) { + nameDictionaryRef = this.catDict.get('Dests'); + } + + if (nameDictionaryRef) { + // reading simple destination dictionary + obj = nameDictionaryRef; + obj.forEach(function catalogForEach(key, value) { + if (!value) { + return; + } + dests[key] = fetchDestination(value); + }); + } + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + var names = nameTree.getAll(); + for (var name in names) { + if (!names.hasOwnProperty(name)) { + continue; + } + dests[name] = fetchDestination(names[name]); + } + } + return shadow(this, 'destinations', dests); + }, + getDestination: function Catalog_getDestination(destinationId) { + function fetchDestination(dest) { + return isDict(dest) ? dest.get('D') : dest; + } + + var xref = this.xref; + var dest, nameTreeRef, nameDictionaryRef; + var obj = this.catDict.get('Names'); + if (obj && obj.has('Dests')) { + nameTreeRef = obj.getRaw('Dests'); + } else if (this.catDict.has('Dests')) { + nameDictionaryRef = this.catDict.get('Dests'); + } + + if (nameDictionaryRef) { + // reading simple destination dictionary + obj = nameDictionaryRef; + obj.forEach(function catalogForEach(key, value) { + if (!value) { + return; + } + if (key === destinationId) { + dest = fetchDestination(value); + } + }); + } + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + dest = fetchDestination(nameTree.get(destinationId)); + } + return dest; + }, + get attachments() { + var xref = this.xref; + var attachments = null, nameTreeRef; + var obj = this.catDict.get('Names'); + if (obj) { + nameTreeRef = obj.getRaw('EmbeddedFiles'); + } + + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + var names = nameTree.getAll(); + for (var name in names) { + if (!names.hasOwnProperty(name)) { + continue; + } + var fs = new FileSpec(names[name], xref); + if (!attachments) { + attachments = {}; + } + attachments[stringToPDFString(name)] = fs.serializable; + } + } + return shadow(this, 'attachments', attachments); + }, + get javaScript() { + var xref = this.xref; + var obj = this.catDict.get('Names'); + + var javaScript = []; + if (obj && obj.has('JavaScript')) { + var nameTree = new NameTree(obj.getRaw('JavaScript'), xref); + var names = nameTree.getAll(); + for (var name in names) { + if (!names.hasOwnProperty(name)) { + continue; + } + // We don't really use the JavaScript right now. This code is + // defensive so we don't cause errors on document load. + var jsDict = names[name]; + if (!isDict(jsDict)) { + continue; + } + var type = jsDict.get('S'); + if (!isName(type) || type.name !== 'JavaScript') { + continue; + } + var js = jsDict.get('JS'); + if (!isString(js) && !isStream(js)) { + continue; + } + if (isStream(js)) { + js = bytesToString(js.getBytes()); + } + javaScript.push(stringToPDFString(js)); + } + } + + // Append OpenAction actions to javaScript array + var openactionDict = this.catDict.get('OpenAction'); + if (isDict(openactionDict)) { + var objType = openactionDict.get('Type'); + var actionType = openactionDict.get('S'); + var action = openactionDict.get('N'); + var isPrintAction = (isName(objType) && objType.name === 'Action' && + isName(actionType) && actionType.name === 'Named' && + isName(action) && action.name === 'Print'); + + if (isPrintAction) { + javaScript.push('print(true);'); + } + } + + return shadow(this, 'javaScript', javaScript); + }, + + cleanup: function Catalog_cleanup() { + var promises = []; + this.fontCache.forEach(function (promise) { + promises.push(promise); + }); + return Promise.all(promises).then(function (translatedFonts) { + for (var i = 0, ii = translatedFonts.length; i < ii; i++) { + var font = translatedFonts[i].dict; + delete font.translated; + } + this.fontCache.clear(); + }.bind(this)); + }, + + getPage: function Catalog_getPage(pageIndex) { + if (!(pageIndex in this.pagePromises)) { + this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then( + function (a) { + var dict = a[0]; + var ref = a[1]; + return new Page(this.pdfManager, this.xref, pageIndex, dict, ref, + this.fontCache); + }.bind(this) + ); + } + return this.pagePromises[pageIndex]; + }, + + getPageDict: function Catalog_getPageDict(pageIndex) { + var capability = createPromiseCapability(); + var nodesToVisit = [this.catDict.getRaw('Pages')]; + var currentPageIndex = 0; + var xref = this.xref; + var checkAllKids = false; + + function next() { + while (nodesToVisit.length) { + var currentNode = nodesToVisit.pop(); + + if (isRef(currentNode)) { + xref.fetchAsync(currentNode).then(function (obj) { + if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) { + if (pageIndex === currentPageIndex) { + capability.resolve([obj, currentNode]); + } else { + currentPageIndex++; + next(); + } + return; + } + nodesToVisit.push(obj); + next(); + }, capability.reject); + return; + } + + // Must be a child page dictionary. + assert( + isDict(currentNode), + 'page dictionary kid reference points to wrong type of object' + ); + var count = currentNode.get('Count'); + // If the current node doesn't have any children, avoid getting stuck + // in an empty node further down in the tree (see issue5644.pdf). + if (count === 0) { + checkAllKids = true; + } + // Skip nodes where the page can't be. + if (currentPageIndex + count <= pageIndex) { + currentPageIndex += count; + continue; + } + + var kids = currentNode.get('Kids'); + assert(isArray(kids), 'page dictionary kids object is not an array'); + if (!checkAllKids && count === kids.length) { + // Nodes that don't have the page have been skipped and this is the + // bottom of the tree which means the page requested must be a + // descendant of this pages node. Ideally we would just resolve the + // promise with the page ref here, but there is the case where more + // pages nodes could link to single a page (see issue 3666 pdf). To + // handle this push it back on the queue so if it is a pages node it + // will be descended into. + nodesToVisit = [kids[pageIndex - currentPageIndex]]; + currentPageIndex = pageIndex; + + } else { + for (var last = kids.length - 1; last >= 0; last--) { + nodesToVisit.push(kids[last]); + } + } + } + capability.reject('Page index ' + pageIndex + ' not found.'); + } + next(); + return capability.promise; + }, + + getPageIndex: function Catalog_getPageIndex(ref) { + // The page tree nodes have the count of all the leaves below them. To get + // how many pages are before we just have to walk up the tree and keep + // adding the count of siblings to the left of the node. + var xref = this.xref; + function pagesBeforeRef(kidRef) { + var total = 0; + var parentRef; + return xref.fetchAsync(kidRef).then(function (node) { + if (!node) { + return null; + } + parentRef = node.getRaw('Parent'); + return node.getAsync('Parent'); + }).then(function (parent) { + if (!parent) { + return null; + } + return parent.getAsync('Kids'); + }).then(function (kids) { + if (!kids) { + return null; + } + var kidPromises = []; + var found = false; + for (var i = 0; i < kids.length; i++) { + var kid = kids[i]; + assert(isRef(kid), 'kids must be a ref'); + if (kid.num === kidRef.num) { + found = true; + break; + } + kidPromises.push(xref.fetchAsync(kid).then(function (kid) { + if (kid.has('Count')) { + var count = kid.get('Count'); + total += count; + } else { // page leaf node + total++; + } + })); + } + if (!found) { + error('kid ref not found in parents kids'); + } + return Promise.all(kidPromises).then(function () { + return [total, parentRef]; + }); + }); + } + + var total = 0; + function next(ref) { + return pagesBeforeRef(ref).then(function (args) { + if (!args) { + return total; + } + var count = args[0]; + var parentRef = args[1]; + total += count; + return next(parentRef); + }); + } + + return next(ref); + } + }; + + return Catalog; +})(); + +var XRef = (function XRefClosure() { + function XRef(stream, password) { + this.stream = stream; + this.entries = []; + this.xrefstms = {}; + // prepare the XRef cache + this.cache = []; + this.password = password; + this.stats = { + streamTypes: [], + fontTypes: [] + }; + } + + XRef.prototype = { + setStartXRef: function XRef_setStartXRef(startXRef) { + // Store the starting positions of xref tables as we process them + // so we can recover from missing data errors + this.startXRefQueue = [startXRef]; + }, + + parse: function XRef_parse(recoveryMode) { + var trailerDict; + if (!recoveryMode) { + trailerDict = this.readXRef(); + } else { + warn('Indexing all PDF objects'); + trailerDict = this.indexObjects(); + } + trailerDict.assignXref(this); + this.trailer = trailerDict; + var encrypt = trailerDict.get('Encrypt'); + if (encrypt) { + var ids = trailerDict.get('ID'); + var fileId = (ids && ids.length) ? ids[0] : ''; + this.encrypt = new CipherTransformFactory(encrypt, fileId, + this.password); + } + + // get the root dictionary (catalog) object + if (!(this.root = trailerDict.get('Root'))) { + error('Invalid root reference'); + } + }, + + processXRefTable: function XRef_processXRefTable(parser) { + if (!('tableState' in this)) { + // Stores state of the table as we process it so we can resume + // from middle of table in case of missing data error + this.tableState = { + entryNum: 0, + streamPos: parser.lexer.stream.pos, + parserBuf1: parser.buf1, + parserBuf2: parser.buf2 + }; + } + + var obj = this.readXRefTable(parser); + + // Sanity check + if (!isCmd(obj, 'trailer')) { + error('Invalid XRef table: could not find trailer dictionary'); + } + // Read trailer dictionary, e.g. + // trailer + // << /Size 22 + // /Root 20R + // /Info 10R + // /ID [ <81b14aafa313db63dbd6f981e49f94f4> ] + // >> + // The parser goes through the entire stream << ... >> and provides + // a getter interface for the key-value table + var dict = parser.getObj(); + + // The pdflib PDF generator can generate a nested trailer dictionary + if (!isDict(dict) && dict.dict) { + dict = dict.dict; + } + if (!isDict(dict)) { + error('Invalid XRef table: could not parse trailer dictionary'); + } + delete this.tableState; + + return dict; + }, + + readXRefTable: function XRef_readXRefTable(parser) { + // Example of cross-reference table: + // xref + // 0 1 <-- subsection header (first obj #, obj count) + // 0000000000 65535 f <-- actual object (offset, generation #, f/n) + // 23 2 <-- subsection header ... and so on ... + // 0000025518 00002 n + // 0000025635 00000 n + // trailer + // ... + + var stream = parser.lexer.stream; + var tableState = this.tableState; + stream.pos = tableState.streamPos; + parser.buf1 = tableState.parserBuf1; + parser.buf2 = tableState.parserBuf2; + + // Outer loop is over subsection headers + var obj; + + while (true) { + if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) { + if (isCmd(obj = parser.getObj(), 'trailer')) { + break; + } + tableState.firstEntryNum = obj; + tableState.entryCount = parser.getObj(); + } + + var first = tableState.firstEntryNum; + var count = tableState.entryCount; + if (!isInt(first) || !isInt(count)) { + error('Invalid XRef table: wrong types in subsection header'); + } + // Inner loop is over objects themselves + for (var i = tableState.entryNum; i < count; i++) { + tableState.streamPos = stream.pos; + tableState.entryNum = i; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + + var entry = {}; + entry.offset = parser.getObj(); + entry.gen = parser.getObj(); + var type = parser.getObj(); + + if (isCmd(type, 'f')) { + entry.free = true; + } else if (isCmd(type, 'n')) { + entry.uncompressed = true; + } + + // Validate entry obj + if (!isInt(entry.offset) || !isInt(entry.gen) || + !(entry.free || entry.uncompressed)) { + error('Invalid entry in XRef subsection: ' + first + ', ' + count); + } + + if (!this.entries[i + first]) { + this.entries[i + first] = entry; + } + } + + tableState.entryNum = 0; + tableState.streamPos = stream.pos; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + delete tableState.firstEntryNum; + delete tableState.entryCount; + } + + // Per issue 3248: hp scanners generate bad XRef + if (first === 1 && this.entries[1] && this.entries[1].free) { + // shifting the entries + this.entries.shift(); + } + + // Sanity check: as per spec, first object must be free + if (this.entries[0] && !this.entries[0].free) { + error('Invalid XRef table: unexpected first object'); + } + return obj; + }, + + processXRefStream: function XRef_processXRefStream(stream) { + if (!('streamState' in this)) { + // Stores state of the stream as we process it so we can resume + // from middle of stream in case of missing data error + var streamParameters = stream.dict; + var byteWidths = streamParameters.get('W'); + var range = streamParameters.get('Index'); + if (!range) { + range = [0, streamParameters.get('Size')]; + } + + this.streamState = { + entryRanges: range, + byteWidths: byteWidths, + entryNum: 0, + streamPos: stream.pos + }; + } + this.readXRefStream(stream); + delete this.streamState; + + return stream.dict; + }, + + readXRefStream: function XRef_readXRefStream(stream) { + var i, j; + var streamState = this.streamState; + stream.pos = streamState.streamPos; + + var byteWidths = streamState.byteWidths; + var typeFieldWidth = byteWidths[0]; + var offsetFieldWidth = byteWidths[1]; + var generationFieldWidth = byteWidths[2]; + + var entryRanges = streamState.entryRanges; + while (entryRanges.length > 0) { + var first = entryRanges[0]; + var n = entryRanges[1]; + + if (!isInt(first) || !isInt(n)) { + error('Invalid XRef range fields: ' + first + ', ' + n); + } + if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) || + !isInt(generationFieldWidth)) { + error('Invalid XRef entry fields length: ' + first + ', ' + n); + } + for (i = streamState.entryNum; i < n; ++i) { + streamState.entryNum = i; + streamState.streamPos = stream.pos; + + var type = 0, offset = 0, generation = 0; + for (j = 0; j < typeFieldWidth; ++j) { + type = (type << 8) | stream.getByte(); + } + // if type field is absent, its default value is 1 + if (typeFieldWidth === 0) { + type = 1; + } + for (j = 0; j < offsetFieldWidth; ++j) { + offset = (offset << 8) | stream.getByte(); + } + for (j = 0; j < generationFieldWidth; ++j) { + generation = (generation << 8) | stream.getByte(); + } + var entry = {}; + entry.offset = offset; + entry.gen = generation; + switch (type) { + case 0: + entry.free = true; + break; + case 1: + entry.uncompressed = true; + break; + case 2: + break; + default: + error('Invalid XRef entry type: ' + type); + } + if (!this.entries[first + i]) { + this.entries[first + i] = entry; + } + } + + streamState.entryNum = 0; + streamState.streamPos = stream.pos; + entryRanges.splice(0, 2); + } + }, + + indexObjects: function XRef_indexObjects() { + // Simple scan through the PDF content to find objects, + // trailers and XRef streams. + function readToken(data, offset) { + var token = '', ch = data[offset]; + while (ch !== 13 && ch !== 10) { + if (++offset >= data.length) { + break; + } + token += String.fromCharCode(ch); + ch = data[offset]; + } + return token; + } + function skipUntil(data, offset, what) { + var length = what.length, dataLength = data.length; + var skipped = 0; + // finding byte sequence + while (offset < dataLength) { + var i = 0; + while (i < length && data[offset + i] === what[i]) { + ++i; + } + if (i >= length) { + break; // sequence found + } + offset++; + skipped++; + } + return skipped; + } + var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]); + var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, + 101, 102]); + var endobjBytes = new Uint8Array([101, 110, 100, 111, 98, 106]); + var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]); + + var stream = this.stream; + stream.pos = 0; + var buffer = stream.getBytes(); + var position = stream.start, length = buffer.length; + var trailers = [], xrefStms = []; + while (position < length) { + var ch = buffer[position]; + if (ch === 32 || ch === 9 || ch === 13 || ch === 10) { + ++position; + continue; + } + if (ch === 37) { // %-comment + do { + ++position; + if (position >= length) { + break; + } + ch = buffer[position]; + } while (ch !== 13 && ch !== 10); + continue; + } + var token = readToken(buffer, position); + var m; + if (token === 'xref') { + position += skipUntil(buffer, position, trailerBytes); + trailers.push(position); + position += skipUntil(buffer, position, startxrefBytes); + } else if ((m = /^(\d+)\s+(\d+)\s+obj\b/.exec(token))) { + if (typeof this.entries[m[1]] === 'undefined') { + this.entries[m[1]] = { + offset: position, + gen: m[2] | 0, + uncompressed: true + }; + } + var contentLength = skipUntil(buffer, position, endobjBytes) + 7; + var content = buffer.subarray(position, position + contentLength); + + // checking XRef stream suspect + // (it shall have '/XRef' and next char is not a letter) + var xrefTagOffset = skipUntil(content, 0, xrefBytes); + if (xrefTagOffset < contentLength && + content[xrefTagOffset + 5] < 64) { + xrefStms.push(position); + this.xrefstms[position] = 1; // don't read it recursively + } + + position += contentLength; + } else { + position += token.length + 1; + } + } + // reading XRef streams + var i, ii; + for (i = 0, ii = xrefStms.length; i < ii; ++i) { + this.startXRefQueue.push(xrefStms[i]); + this.readXRef(/* recoveryMode */ true); + } + // finding main trailer + var dict; + for (i = 0, ii = trailers.length; i < ii; ++i) { + stream.pos = trailers[i]; + var parser = new Parser(new Lexer(stream), true, this); + var obj = parser.getObj(); + if (!isCmd(obj, 'trailer')) { + continue; + } + // read the trailer dictionary + if (!isDict(dict = parser.getObj())) { + continue; + } + // taking the first one with 'ID' + if (dict.has('ID')) { + return dict; + } + } + // no tailer with 'ID', taking last one (if exists) + if (dict) { + return dict; + } + // nothing helps + // calling error() would reject worker with an UnknownErrorException. + throw new InvalidPDFException('Invalid PDF structure'); + }, + + readXRef: function XRef_readXRef(recoveryMode) { + var stream = this.stream; + + try { + while (this.startXRefQueue.length) { + var startXRef = this.startXRefQueue[0]; + + stream.pos = startXRef + stream.start; + + var parser = new Parser(new Lexer(stream), true, this); + var obj = parser.getObj(); + var dict; + + // Get dictionary + if (isCmd(obj, 'xref')) { + // Parse end-of-file XRef + dict = this.processXRefTable(parser); + if (!this.topDict) { + this.topDict = dict; + } + + // Recursively get other XRefs 'XRefStm', if any + obj = dict.get('XRefStm'); + if (isInt(obj)) { + var pos = obj; + // ignore previously loaded xref streams + // (possible infinite recursion) + if (!(pos in this.xrefstms)) { + this.xrefstms[pos] = 1; + this.startXRefQueue.push(pos); + } + } + } else if (isInt(obj)) { + // Parse in-stream XRef + if (!isInt(parser.getObj()) || + !isCmd(parser.getObj(), 'obj') || + !isStream(obj = parser.getObj())) { + error('Invalid XRef stream'); + } + dict = this.processXRefStream(obj); + if (!this.topDict) { + this.topDict = dict; + } + if (!dict) { + error('Failed to read XRef stream'); + } + } else { + error('Invalid XRef stream header'); + } + + // Recursively get previous dictionary, if any + obj = dict.get('Prev'); + if (isInt(obj)) { + this.startXRefQueue.push(obj); + } else if (isRef(obj)) { + // The spec says Prev must not be a reference, i.e. "/Prev NNN" + // This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R" + this.startXRefQueue.push(obj.num); + } + + this.startXRefQueue.shift(); + } + + return this.topDict; + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + info('(while reading XRef): ' + e); + } + + if (recoveryMode) { + return; + } + throw new XRefParseException(); + }, + + getEntry: function XRef_getEntry(i) { + var xrefEntry = this.entries[i]; + if (xrefEntry && !xrefEntry.free && xrefEntry.offset) { + return xrefEntry; + } + return null; + }, + + fetchIfRef: function XRef_fetchIfRef(obj) { + if (!isRef(obj)) { + return obj; + } + return this.fetch(obj); + }, + + fetch: function XRef_fetch(ref, suppressEncryption) { + assert(isRef(ref), 'ref object is not a reference'); + var num = ref.num; + if (num in this.cache) { + var cacheEntry = this.cache[num]; + return cacheEntry; + } + + var xrefEntry = this.getEntry(num); + + // the referenced entry can be free + if (xrefEntry === null) { + return (this.cache[num] = null); + } + + if (xrefEntry.uncompressed) { + xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption); + } else { + xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption); + } + if (isDict(xrefEntry)){ + xrefEntry.objId = ref.toString(); + } else if (isStream(xrefEntry)) { + xrefEntry.dict.objId = ref.toString(); + } + return xrefEntry; + }, + + fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry, + suppressEncryption) { + var gen = ref.gen; + var num = ref.num; + if (xrefEntry.gen !== gen) { + error('inconsistent generation in XRef'); + } + var stream = this.stream.makeSubStream(xrefEntry.offset + + this.stream.start); + var parser = new Parser(new Lexer(stream), true, this); + var obj1 = parser.getObj(); + var obj2 = parser.getObj(); + var obj3 = parser.getObj(); + if (!isInt(obj1) || parseInt(obj1, 10) !== num || + !isInt(obj2) || parseInt(obj2, 10) !== gen || + !isCmd(obj3)) { + error('bad XRef entry'); + } + if (!isCmd(obj3, 'obj')) { + // some bad PDFs use "obj1234" and really mean 1234 + if (obj3.cmd.indexOf('obj') === 0) { + num = parseInt(obj3.cmd.substring(3), 10); + if (!isNaN(num)) { + return num; + } + } + error('bad XRef entry'); + } + if (this.encrypt && !suppressEncryption) { + xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen)); + } else { + xrefEntry = parser.getObj(); + } + if (!isStream(xrefEntry)) { + this.cache[num] = xrefEntry; + } + return xrefEntry; + }, + + fetchCompressed: function XRef_fetchCompressed(xrefEntry, + suppressEncryption) { + var tableOffset = xrefEntry.offset; + var stream = this.fetch(new Ref(tableOffset, 0)); + if (!isStream(stream)) { + error('bad ObjStm stream'); + } + var first = stream.dict.get('First'); + var n = stream.dict.get('N'); + if (!isInt(first) || !isInt(n)) { + error('invalid first and n parameters for ObjStm stream'); + } + var parser = new Parser(new Lexer(stream), false, this); + parser.allowStreams = true; + var i, entries = [], num, nums = []; + // read the object numbers to populate cache + for (i = 0; i < n; ++i) { + num = parser.getObj(); + if (!isInt(num)) { + error('invalid object number in the ObjStm stream: ' + num); + } + nums.push(num); + var offset = parser.getObj(); + if (!isInt(offset)) { + error('invalid object offset in the ObjStm stream: ' + offset); + } + } + // read stream objects for cache + for (i = 0; i < n; ++i) { + entries.push(parser.getObj()); + num = nums[i]; + var entry = this.entries[num]; + if (entry && entry.offset === tableOffset && entry.gen === i) { + this.cache[num] = entries[i]; + } + } + xrefEntry = entries[xrefEntry.gen]; + if (xrefEntry === undefined) { + error('bad XRef entry for compressed object'); + } + return xrefEntry; + }, + + fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) { + if (!isRef(obj)) { + return Promise.resolve(obj); + } + return this.fetchAsync(obj); + }, + + fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) { + var streamManager = this.stream.manager; + var xref = this; + return new Promise(function tryFetch(resolve, reject) { + try { + resolve(xref.fetch(ref, suppressEncryption)); + } catch (e) { + if (e instanceof MissingDataException) { + streamManager.requestRange(e.begin, e.end, function () { + tryFetch(resolve, reject); + }); + return; + } + reject(e); + } + }); + }, + + getCatalogObj: function XRef_getCatalogObj() { + return this.root; + } + }; + + return XRef; +})(); + +/** + * A NameTree is like a Dict but has some advantageous properties, see the + * spec (7.9.6) for more details. + * TODO: implement all the Dict functions and make this more efficent. + */ +var NameTree = (function NameTreeClosure() { + function NameTree(root, xref) { + this.root = root; + this.xref = xref; + } + + NameTree.prototype = { + getAll: function NameTree_getAll() { + var dict = {}; + if (!this.root) { + return dict; + } + var xref = this.xref; + // reading name tree + var processed = new RefSet(); + processed.put(this.root); + var queue = [this.root]; + while (queue.length > 0) { + var i, n; + var obj = xref.fetchIfRef(queue.shift()); + if (!isDict(obj)) { + continue; + } + if (obj.has('Kids')) { + var kids = obj.get('Kids'); + for (i = 0, n = kids.length; i < n; i++) { + var kid = kids[i]; + if (processed.has(kid)) { + error('invalid destinations'); + } + queue.push(kid); + processed.put(kid); + } + continue; + } + var names = obj.get('Names'); + if (names) { + for (i = 0, n = names.length; i < n; i += 2) { + dict[names[i]] = xref.fetchIfRef(names[i + 1]); + } + } + } + return dict; + }, + + get: function NameTree_get(destinationId) { + if (!this.root) { + return null; + } + + var xref = this.xref; + var kidsOrNames = xref.fetchIfRef(this.root); + var loopCount = 0; + var MAX_NAMES_LEVELS = 10; + var l, r, m; + + // Perform a binary search to quickly find the entry that + // contains the named destination we are looking for. + while (kidsOrNames.has('Kids')) { + loopCount++; + if (loopCount > MAX_NAMES_LEVELS) { + warn('Search depth limit for named destionations has been reached.'); + return null; + } + + var kids = kidsOrNames.get('Kids'); + if (!isArray(kids)) { + return null; + } + + l = 0; + r = kids.length - 1; + while (l <= r) { + m = (l + r) >> 1; + var kid = xref.fetchIfRef(kids[m]); + var limits = kid.get('Limits'); + + if (destinationId < limits[0]) { + r = m - 1; + } else if (destinationId > limits[1]) { + l = m + 1; + } else { + kidsOrNames = xref.fetchIfRef(kids[m]); + break; + } + } + if (l > r) { + return null; + } + } + + // If we get here, then we have found the right entry. Now + // go through the named destinations in the Named dictionary + // until we find the exact destination we're looking for. + var names = kidsOrNames.get('Names'); + if (isArray(names)) { + // Perform a binary search to reduce the lookup time. + l = 0; + r = names.length - 2; + while (l <= r) { + // Check only even indices (0, 2, 4, ...) because the + // odd indices contain the actual D array. + m = (l + r) & ~1; + if (destinationId < names[m]) { + r = m - 2; + } else if (destinationId > names[m]) { + l = m + 2; + } else { + return xref.fetchIfRef(names[m + 1]); + } + } + } + return null; + } + }; + return NameTree; +})(); + +/** + * "A PDF file can refer to the contents of another file by using a File + * Specification (PDF 1.1)", see the spec (7.11) for more details. + * NOTE: Only embedded files are supported (as part of the attachments support) + * TODO: support the 'URL' file system (with caching if !/V), portable + * collections attributes and related files (/RF) + */ +var FileSpec = (function FileSpecClosure() { + function FileSpec(root, xref) { + if (!root || !isDict(root)) { + return; + } + this.xref = xref; + this.root = root; + if (root.has('FS')) { + this.fs = root.get('FS'); + } + this.description = root.has('Desc') ? + stringToPDFString(root.get('Desc')) : + ''; + if (root.has('RF')) { + warn('Related file specifications are not supported'); + } + this.contentAvailable = true; + if (!root.has('EF')) { + this.contentAvailable = false; + warn('Non-embedded file specifications are not supported'); + } + } + + function pickPlatformItem(dict) { + // Look for the filename in this order: + // UF, F, Unix, Mac, DOS + if (dict.has('UF')) { + return dict.get('UF'); + } else if (dict.has('F')) { + return dict.get('F'); + } else if (dict.has('Unix')) { + return dict.get('Unix'); + } else if (dict.has('Mac')) { + return dict.get('Mac'); + } else if (dict.has('DOS')) { + return dict.get('DOS'); + } else { + return null; + } + } + + FileSpec.prototype = { + get filename() { + if (!this._filename && this.root) { + var filename = pickPlatformItem(this.root) || 'unnamed'; + this._filename = stringToPDFString(filename). + replace(/\\\\/g, '\\'). + replace(/\\\//g, '/'). + replace(/\\/g, '/'); + } + return this._filename; + }, + get content() { + if (!this.contentAvailable) { + return null; + } + if (!this.contentRef && this.root) { + this.contentRef = pickPlatformItem(this.root.get('EF')); + } + var content = null; + if (this.contentRef) { + var xref = this.xref; + var fileObj = xref.fetchIfRef(this.contentRef); + if (fileObj && isStream(fileObj)) { + content = fileObj.getBytes(); + } else { + warn('Embedded file specification points to non-existing/invalid ' + + 'content'); + } + } else { + warn('Embedded file specification does not have a content'); + } + return content; + }, + get serializable() { + return { + filename: this.filename, + content: this.content + }; + } + }; + return FileSpec; +})(); + +/** + * A helper for loading missing data in object graphs. It traverses the graph + * depth first and queues up any objects that have missing data. Once it has + * has traversed as many objects that are available it attempts to bundle the + * missing data requests and then resume from the nodes that weren't ready. + * + * NOTE: It provides protection from circular references by keeping track of + * of loaded references. However, you must be careful not to load any graphs + * that have references to the catalog or other pages since that will cause the + * entire PDF document object graph to be traversed. + */ +var ObjectLoader = (function() { + function mayHaveChildren(value) { + return isRef(value) || isDict(value) || isArray(value) || isStream(value); + } + + function addChildren(node, nodesToVisit) { + var value; + if (isDict(node) || isStream(node)) { + var map; + if (isDict(node)) { + map = node.map; + } else { + map = node.dict.map; + } + for (var key in map) { + value = map[key]; + if (mayHaveChildren(value)) { + nodesToVisit.push(value); + } + } + } else if (isArray(node)) { + for (var i = 0, ii = node.length; i < ii; i++) { + value = node[i]; + if (mayHaveChildren(value)) { + nodesToVisit.push(value); + } + } + } + } + + function ObjectLoader(obj, keys, xref) { + this.obj = obj; + this.keys = keys; + this.xref = xref; + this.refSet = null; + } + + ObjectLoader.prototype = { + load: function ObjectLoader_load() { + var keys = this.keys; + this.capability = createPromiseCapability(); + // Don't walk the graph if all the data is already loaded. + if (!(this.xref.stream instanceof ChunkedStream) || + this.xref.stream.getMissingChunks().length === 0) { + this.capability.resolve(); + return this.capability.promise; + } + + this.refSet = new RefSet(); + // Setup the initial nodes to visit. + var nodesToVisit = []; + for (var i = 0; i < keys.length; i++) { + nodesToVisit.push(this.obj[keys[i]]); + } + + this.walk(nodesToVisit); + return this.capability.promise; + }, + + walk: function ObjectLoader_walk(nodesToVisit) { + var nodesToRevisit = []; + var pendingRequests = []; + // DFS walk of the object graph. + while (nodesToVisit.length) { + var currentNode = nodesToVisit.pop(); + + // Only references or chunked streams can cause missing data exceptions. + if (isRef(currentNode)) { + // Skip nodes that have already been visited. + if (this.refSet.has(currentNode)) { + continue; + } + try { + var ref = currentNode; + this.refSet.put(ref); + currentNode = this.xref.fetch(currentNode); + } catch (e) { + if (!(e instanceof MissingDataException)) { + throw e; + } + nodesToRevisit.push(currentNode); + pendingRequests.push({ begin: e.begin, end: e.end }); + } + } + if (currentNode && currentNode.getBaseStreams) { + var baseStreams = currentNode.getBaseStreams(); + var foundMissingData = false; + for (var i = 0; i < baseStreams.length; i++) { + var stream = baseStreams[i]; + if (stream.getMissingChunks && stream.getMissingChunks().length) { + foundMissingData = true; + pendingRequests.push({ + begin: stream.start, + end: stream.end + }); + } + } + if (foundMissingData) { + nodesToRevisit.push(currentNode); + } + } + + addChildren(currentNode, nodesToVisit); + } + + if (pendingRequests.length) { + this.xref.stream.manager.requestRanges(pendingRequests, + function pendingRequestCallback() { + nodesToVisit = nodesToRevisit; + for (var i = 0; i < nodesToRevisit.length; i++) { + var node = nodesToRevisit[i]; + // Remove any reference nodes from the currrent refset so they + // aren't skipped when we revist them. + if (isRef(node)) { + this.refSet.remove(node); + } + } + this.walk(nodesToVisit); + }.bind(this)); + return; + } + // Everything is loaded. + this.refSet = null; + this.capability.resolve(); + } + }; + + return ObjectLoader; +})(); + + +var ISOAdobeCharset = [ + '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', + 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', + 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', + 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', + 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', + 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', + 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', + 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', + 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', + 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', + 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', + 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', + 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', + 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', + 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', + 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', + 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', + 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', + 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', + 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', + 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', + 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', + 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', + 'ugrave', 'yacute', 'ydieresis', 'zcaron' +]; + +var ExpertCharset = [ + '.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', + 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', + 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', + 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', + 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', + 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', + 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', + 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', + 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', + 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', + 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', + 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', + 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', + 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', + 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', + 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', + 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', + 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', + 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', + 'Cedillasmall', 'onequarter', 'onehalf', 'threequarters', + 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', + 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', + 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', + 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', + 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', + 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', + 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', + 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', + 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', + 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', + 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', + 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', + 'Ydieresissmall' +]; + +var ExpertSubsetCharset = [ + '.notdef', 'space', 'dollaroldstyle', 'dollarsuperior', + 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', + 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', + 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', + 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', + 'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior', + 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', + 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', + 'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted', + 'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter', + 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', + 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', + 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', + 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', + 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', + 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', + 'periodinferior', 'commainferior' +]; + + +var DEFAULT_ICON_SIZE = 22; // px +var SUPPORTED_TYPES = ['Link', 'Text', 'Widget']; + +var Annotation = (function AnnotationClosure() { + // 12.5.5: Algorithm: Appearance streams + function getTransformMatrix(rect, bbox, matrix) { + var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix); + var minX = bounds[0]; + var minY = bounds[1]; + var maxX = bounds[2]; + var maxY = bounds[3]; + + if (minX === maxX || minY === maxY) { + // From real-life file, bbox was [0, 0, 0, 0]. In this case, + // just apply the transform for rect + return [1, 0, 0, 1, rect[0], rect[1]]; + } + + var xRatio = (rect[2] - rect[0]) / (maxX - minX); + var yRatio = (rect[3] - rect[1]) / (maxY - minY); + return [ + xRatio, + 0, + 0, + yRatio, + rect[0] - minX * xRatio, + rect[1] - minY * yRatio + ]; + } + + function getDefaultAppearance(dict) { + var appearanceState = dict.get('AP'); + if (!isDict(appearanceState)) { + return; + } + + var appearance; + var appearances = appearanceState.get('N'); + if (isDict(appearances)) { + var as = dict.get('AS'); + if (as && appearances.has(as.name)) { + appearance = appearances.get(as.name); + } + } else { + appearance = appearances; + } + return appearance; + } + + function Annotation(params) { + var dict = params.dict; + var data = this.data = {}; + + data.subtype = dict.get('Subtype').name; + var rect = dict.get('Rect') || [0, 0, 0, 0]; + data.rect = Util.normalizeRect(rect); + data.annotationFlags = dict.get('F'); + + var color = dict.get('C'); + if (!color) { + // The PDF spec does not mention how a missing color array is interpreted. + // Adobe Reader seems to default to black in this case. + data.color = [0, 0, 0]; + } else if (isArray(color)) { + switch (color.length) { + case 0: + // Empty array denotes transparent border. + data.color = null; + break; + case 1: + // TODO: implement DeviceGray + break; + case 3: + data.color = color; + break; + case 4: + // TODO: implement DeviceCMYK + break; + } + } + + // Some types of annotations have border style dict which has more + // info than the border array + if (dict.has('BS')) { + var borderStyle = dict.get('BS'); + data.borderWidth = borderStyle.has('W') ? borderStyle.get('W') : 1; + } else { + var borderArray = dict.get('Border') || [0, 0, 1]; + data.borderWidth = borderArray[2] || 0; + + // TODO: implement proper support for annotations with line dash patterns. + var dashArray = borderArray[3]; + if (data.borderWidth > 0 && dashArray) { + if (!isArray(dashArray)) { + // Ignore the border if dashArray is not actually an array, + // this is consistent with the behaviour in Adobe Reader. + data.borderWidth = 0; + } else { + var dashArrayLength = dashArray.length; + if (dashArrayLength > 0) { + // According to the PDF specification: the elements in a dashArray + // shall be numbers that are nonnegative and not all equal to zero. + var isInvalid = false; + var numPositive = 0; + for (var i = 0; i < dashArrayLength; i++) { + var validNumber = (+dashArray[i] >= 0); + if (!validNumber) { + isInvalid = true; + break; + } else if (dashArray[i] > 0) { + numPositive++; + } + } + if (isInvalid || numPositive === 0) { + data.borderWidth = 0; + } + } + } + } + } + + this.appearance = getDefaultAppearance(dict); + data.hasAppearance = !!this.appearance; + data.id = params.ref.num; + } + + Annotation.prototype = { + + getData: function Annotation_getData() { + return this.data; + }, + + isInvisible: function Annotation_isInvisible() { + var data = this.data; + if (data && SUPPORTED_TYPES.indexOf(data.subtype) !== -1) { + return false; + } else { + return !!(data && + data.annotationFlags && // Default: not invisible + data.annotationFlags & 0x1); // Invisible + } + }, + + isViewable: function Annotation_isViewable() { + var data = this.data; + return !!(!this.isInvisible() && + data && + (!data.annotationFlags || + !(data.annotationFlags & 0x22)) && // Hidden or NoView + data.rect); // rectangle is necessary + }, + + isPrintable: function Annotation_isPrintable() { + var data = this.data; + return !!(!this.isInvisible() && + data && + data.annotationFlags && // Default: not printable + data.annotationFlags & 0x4 && // Print + !(data.annotationFlags & 0x2) && // Hidden + data.rect); // rectangle is necessary + }, + + loadResources: function Annotation_loadResources(keys) { + return new Promise(function (resolve, reject) { + this.appearance.dict.getAsync('Resources').then(function (resources) { + if (!resources) { + resolve(); + return; + } + var objectLoader = new ObjectLoader(resources.map, + keys, + resources.xref); + objectLoader.load().then(function() { + resolve(resources); + }, reject); + }, reject); + }.bind(this)); + }, + + getOperatorList: function Annotation_getOperatorList(evaluator) { + + if (!this.appearance) { + return Promise.resolve(new OperatorList()); + } + + var data = this.data; + + var appearanceDict = this.appearance.dict; + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'ColorSpace', + 'Pattern', + 'Shading', + 'XObject', + 'Font' + // ProcSet + // Properties + ]); + var bbox = appearanceDict.get('BBox') || [0, 0, 1, 1]; + var matrix = appearanceDict.get('Matrix') || [1, 0, 0, 1, 0 ,0]; + var transform = getTransformMatrix(data.rect, bbox, matrix); + var self = this; + + return resourcesPromise.then(function(resources) { + var opList = new OperatorList(); + opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]); + return evaluator.getOperatorList(self.appearance, resources, opList). + then(function () { + opList.addOp(OPS.endAnnotation, []); + self.appearance.reset(); + return opList; + }); + }); + } + }; + + Annotation.getConstructor = + function Annotation_getConstructor(subtype, fieldType) { + + if (!subtype) { + return; + } + + // TODO(mack): Implement FreeText annotations + if (subtype === 'Link') { + return LinkAnnotation; + } else if (subtype === 'Text') { + return TextAnnotation; + } else if (subtype === 'Widget') { + if (!fieldType) { + return; + } + + if (fieldType === 'Tx') { + return TextWidgetAnnotation; + } else { + return WidgetAnnotation; + } + } else { + return Annotation; + } + }; + + Annotation.fromRef = function Annotation_fromRef(xref, ref) { + + var dict = xref.fetchIfRef(ref); + if (!isDict(dict)) { + return; + } + + var subtype = dict.get('Subtype'); + subtype = isName(subtype) ? subtype.name : ''; + if (!subtype) { + return; + } + + var fieldType = Util.getInheritableProperty(dict, 'FT'); + fieldType = isName(fieldType) ? fieldType.name : ''; + + var Constructor = Annotation.getConstructor(subtype, fieldType); + if (!Constructor) { + return; + } + + var params = { + dict: dict, + ref: ref, + }; + + var annotation = new Constructor(params); + + if (annotation.isViewable() || annotation.isPrintable()) { + return annotation; + } else { + if (SUPPORTED_TYPES.indexOf(subtype) === -1) { + warn('unimplemented annotation type: ' + subtype); + } + } + }; + + Annotation.appendToOperatorList = function Annotation_appendToOperatorList( + annotations, opList, pdfManager, partialEvaluator, intent) { + + function reject(e) { + annotationsReadyCapability.reject(e); + } + + var annotationsReadyCapability = createPromiseCapability(); + + var annotationPromises = []; + for (var i = 0, n = annotations.length; i < n; ++i) { + if (intent === 'display' && annotations[i].isViewable() || + intent === 'print' && annotations[i].isPrintable()) { + annotationPromises.push( + annotations[i].getOperatorList(partialEvaluator)); + } + } + Promise.all(annotationPromises).then(function(datas) { + opList.addOp(OPS.beginAnnotations, []); + for (var i = 0, n = datas.length; i < n; ++i) { + var annotOpList = datas[i]; + opList.addOpList(annotOpList); + } + opList.addOp(OPS.endAnnotations, []); + annotationsReadyCapability.resolve(); + }, reject); + + return annotationsReadyCapability.promise; + }; + + return Annotation; +})(); + +var WidgetAnnotation = (function WidgetAnnotationClosure() { + + function WidgetAnnotation(params) { + Annotation.call(this, params); + + var dict = params.dict; + var data = this.data; + + data.fieldValue = stringToPDFString( + Util.getInheritableProperty(dict, 'V') || ''); + data.alternativeText = stringToPDFString(dict.get('TU') || ''); + data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || ''; + var fieldType = Util.getInheritableProperty(dict, 'FT'); + data.fieldType = isName(fieldType) ? fieldType.name : ''; + data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0; + this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty; + + // Building the full field name by collecting the field and + // its ancestors 'T' data and joining them using '.'. + var fieldName = []; + var namedItem = dict; + var ref = params.ref; + while (namedItem) { + var parent = namedItem.get('Parent'); + var parentRef = namedItem.getRaw('Parent'); + var name = namedItem.get('T'); + if (name) { + fieldName.unshift(stringToPDFString(name)); + } else if (parent && ref) { + // The field name is absent, that means more than one field + // with the same name may exist. Replacing the empty name + // with the '`' plus index in the parent's 'Kids' array. + // This is not in the PDF spec but necessary to id the + // the input controls. + var kids = parent.get('Kids'); + var j, jj; + for (j = 0, jj = kids.length; j < jj; j++) { + var kidRef = kids[j]; + if (kidRef.num === ref.num && kidRef.gen === ref.gen) { + break; + } + } + fieldName.unshift('`' + j); + } + namedItem = parent; + ref = parentRef; + } + data.fullName = fieldName.join('.'); + } + + var parent = Annotation.prototype; + Util.inherit(WidgetAnnotation, Annotation, { + isViewable: function WidgetAnnotation_isViewable() { + if (this.data.fieldType === 'Sig') { + warn('unimplemented annotation type: Widget signature'); + return false; + } + + return parent.isViewable.call(this); + } + }); + + return WidgetAnnotation; +})(); + +var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { + function TextWidgetAnnotation(params) { + WidgetAnnotation.call(this, params); + + this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q'); + this.data.annotationType = AnnotationType.WIDGET; + this.data.hasHtml = !this.data.hasAppearance && !!this.data.fieldValue; + } + + Util.inherit(TextWidgetAnnotation, WidgetAnnotation, { + getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) { + if (this.appearance) { + return Annotation.prototype.getOperatorList.call(this, evaluator); + } + + var opList = new OperatorList(); + var data = this.data; + + // Even if there is an appearance stream, ignore it. This is the + // behaviour used by Adobe Reader. + if (!data.defaultAppearance) { + return Promise.resolve(opList); + } + + var stream = new Stream(stringToBytes(data.defaultAppearance)); + return evaluator.getOperatorList(stream, this.fieldResources, opList). + then(function () { + return opList; + }); + } + }); + + return TextWidgetAnnotation; +})(); + +var InteractiveAnnotation = (function InteractiveAnnotationClosure() { + function InteractiveAnnotation(params) { + Annotation.call(this, params); + + this.data.hasHtml = true; + } + + Util.inherit(InteractiveAnnotation, Annotation, { }); + + return InteractiveAnnotation; +})(); + +var TextAnnotation = (function TextAnnotationClosure() { + function TextAnnotation(params) { + InteractiveAnnotation.call(this, params); + + var dict = params.dict; + var data = this.data; + + var content = dict.get('Contents'); + var title = dict.get('T'); + data.annotationType = AnnotationType.TEXT; + data.content = stringToPDFString(content || ''); + data.title = stringToPDFString(title || ''); + + if (data.hasAppearance) { + data.name = 'NoIcon'; + } else { + data.rect[1] = data.rect[3] - DEFAULT_ICON_SIZE; + data.rect[2] = data.rect[0] + DEFAULT_ICON_SIZE; + data.name = dict.has('Name') ? dict.get('Name').name : 'Note'; + } + + if (dict.has('C')) { + data.hasBgColor = true; + } + } + + Util.inherit(TextAnnotation, InteractiveAnnotation, { }); + + return TextAnnotation; +})(); + +var LinkAnnotation = (function LinkAnnotationClosure() { + function LinkAnnotation(params) { + InteractiveAnnotation.call(this, params); + + var dict = params.dict; + var data = this.data; + data.annotationType = AnnotationType.LINK; + + var action = dict.get('A'); + if (action && isDict(action)) { + var linkType = action.get('S').name; + if (linkType === 'URI') { + var url = action.get('URI'); + if (isName(url)) { + // Some bad PDFs do not put parentheses around relative URLs. + url = '/' + url.name; + } else if (url) { + url = addDefaultProtocolToUrl(url); + } + // TODO: pdf spec mentions urls can be relative to a Base + // entry in the dictionary. + if (!isValidUrl(url, false)) { + url = ''; + } + // According to ISO 32000-1:2008, section 12.6.4.7, + // URI should to be encoded in 7-bit ASCII. + // Some bad PDFs may have URIs in UTF-8 encoding, see Bugzilla 1122280. + try { + data.url = stringToUTF8String(url); + } catch (e) { + // Fall back to a simple copy. + data.url = url; + } + } else if (linkType === 'GoTo') { + data.dest = action.get('D'); + } else if (linkType === 'GoToR') { + var urlDict = action.get('F'); + if (isDict(urlDict)) { + // We assume that the 'url' is a Filspec dictionary + // and fetch the url without checking any further + url = urlDict.get('F') || ''; + } + + // TODO: pdf reference says that GoToR + // can also have 'NewWindow' attribute + if (!isValidUrl(url, false)) { + url = ''; + } + data.url = url; + data.dest = action.get('D'); + } else if (linkType === 'Named') { + data.action = action.get('N').name; + } else { + warn('unrecognized link type: ' + linkType); + } + } else if (dict.has('Dest')) { + // simple destination link + var dest = dict.get('Dest'); + data.dest = isName(dest) ? dest.name : dest; + } + } + + // Lets URLs beginning with 'www.' default to using the 'http://' protocol. + function addDefaultProtocolToUrl(url) { + if (url && url.indexOf('www.') === 0) { + return ('http://' + url); + } + return url; + } + + Util.inherit(LinkAnnotation, InteractiveAnnotation, { }); + + return LinkAnnotation; +})(); + + +var PDFFunction = (function PDFFunctionClosure() { + var CONSTRUCT_SAMPLED = 0; + var CONSTRUCT_INTERPOLATED = 2; + var CONSTRUCT_STICHED = 3; + var CONSTRUCT_POSTSCRIPT = 4; + + return { + getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps, + str) { + var i, ii; + var length = 1; + for (i = 0, ii = size.length; i < ii; i++) { + length *= size[i]; + } + length *= outputSize; + + var array = new Array(length); + var codeSize = 0; + var codeBuf = 0; + // 32 is a valid bps so shifting won't work + var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1); + + var strBytes = str.getBytes((length * bps + 7) / 8); + var strIdx = 0; + for (i = 0; i < length; i++) { + while (codeSize < bps) { + codeBuf <<= 8; + codeBuf |= strBytes[strIdx++]; + codeSize += 8; + } + codeSize -= bps; + array[i] = (codeBuf >> codeSize) * sampleMul; + codeBuf &= (1 << codeSize) - 1; + } + return array; + }, + + getIR: function PDFFunction_getIR(xref, fn) { + var dict = fn.dict; + if (!dict) { + dict = fn; + } + + var types = [this.constructSampled, + null, + this.constructInterpolated, + this.constructStiched, + this.constructPostScript]; + + var typeNum = dict.get('FunctionType'); + var typeFn = types[typeNum]; + if (!typeFn) { + error('Unknown type of function'); + } + + return typeFn.call(this, fn, dict, xref); + }, + + fromIR: function PDFFunction_fromIR(IR) { + var type = IR[0]; + switch (type) { + case CONSTRUCT_SAMPLED: + return this.constructSampledFromIR(IR); + case CONSTRUCT_INTERPOLATED: + return this.constructInterpolatedFromIR(IR); + case CONSTRUCT_STICHED: + return this.constructStichedFromIR(IR); + //case CONSTRUCT_POSTSCRIPT: + default: + return this.constructPostScriptFromIR(IR); + } + }, + + parse: function PDFFunction_parse(xref, fn) { + var IR = this.getIR(xref, fn); + return this.fromIR(IR); + }, + + parseArray: function PDFFunction_parseArray(xref, fnObj) { + if (!isArray(fnObj)) { + // not an array -- parsing as regular function + return this.parse(xref, fnObj); + } + + var fnArray = []; + for (var j = 0, jj = fnObj.length; j < jj; j++) { + var obj = xref.fetchIfRef(fnObj[j]); + fnArray.push(PDFFunction.parse(xref, obj)); + } + return function (src, srcOffset, dest, destOffset) { + for (var i = 0, ii = fnArray.length; i < ii; i++) { + fnArray[i](src, srcOffset, dest, destOffset + i); + } + }; + }, + + constructSampled: function PDFFunction_constructSampled(str, dict) { + function toMultiArray(arr) { + var inputLength = arr.length; + var out = []; + var index = 0; + for (var i = 0; i < inputLength; i += 2) { + out[index] = [arr[i], arr[i + 1]]; + ++index; + } + return out; + } + var domain = dict.get('Domain'); + var range = dict.get('Range'); + + if (!domain || !range) { + error('No domain or range'); + } + + var inputSize = domain.length / 2; + var outputSize = range.length / 2; + + domain = toMultiArray(domain); + range = toMultiArray(range); + + var size = dict.get('Size'); + var bps = dict.get('BitsPerSample'); + var order = dict.get('Order') || 1; + if (order !== 1) { + // No description how cubic spline interpolation works in PDF32000:2008 + // As in poppler, ignoring order, linear interpolation may work as good + info('No support for cubic spline interpolation: ' + order); + } + + var encode = dict.get('Encode'); + if (!encode) { + encode = []; + for (var i = 0; i < inputSize; ++i) { + encode.push(0); + encode.push(size[i] - 1); + } + } + encode = toMultiArray(encode); + + var decode = dict.get('Decode'); + if (!decode) { + decode = range; + } else { + decode = toMultiArray(decode); + } + + var samples = this.getSampleArray(size, outputSize, bps, str); + + return [ + CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, + outputSize, Math.pow(2, bps) - 1, range + ]; + }, + + constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) { + // See chapter 3, page 109 of the PDF reference + function interpolate(x, xmin, xmax, ymin, ymax) { + return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin))); + } + + return function constructSampledFromIRResult(src, srcOffset, + dest, destOffset) { + // See chapter 3, page 110 of the PDF reference. + var m = IR[1]; + var domain = IR[2]; + var encode = IR[3]; + var decode = IR[4]; + var samples = IR[5]; + var size = IR[6]; + var n = IR[7]; + //var mask = IR[8]; + var range = IR[9]; + + // Building the cube vertices: its part and sample index + // http://rjwagner49.com/Mathematics/Interpolation.pdf + var cubeVertices = 1 << m; + var cubeN = new Float64Array(cubeVertices); + var cubeVertex = new Uint32Array(cubeVertices); + var i, j; + for (j = 0; j < cubeVertices; j++) { + cubeN[j] = 1; + } + + var k = n, pos = 1; + // Map x_i to y_j for 0 <= i < m using the sampled function. + for (i = 0; i < m; ++i) { + // x_i' = min(max(x_i, Domain_2i), Domain_2i+1) + var domain_2i = domain[i][0]; + var domain_2i_1 = domain[i][1]; + var xi = Math.min(Math.max(src[srcOffset +i], domain_2i), + domain_2i_1); + + // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1, + // Encode_2i, Encode_2i+1) + var e = interpolate(xi, domain_2i, domain_2i_1, + encode[i][0], encode[i][1]); + + // e_i' = min(max(e_i, 0), Size_i - 1) + var size_i = size[i]; + e = Math.min(Math.max(e, 0), size_i - 1); + + // Adjusting the cube: N and vertex sample index + var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1; + var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0); + var n1 = e - e0; // (e - e0) / (e1 - e0); + var offset0 = e0 * k; + var offset1 = offset0 + k; // e1 * k + for (j = 0; j < cubeVertices; j++) { + if (j & pos) { + cubeN[j] *= n1; + cubeVertex[j] += offset1; + } else { + cubeN[j] *= n0; + cubeVertex[j] += offset0; + } + } + + k *= size_i; + pos <<= 1; + } + + for (j = 0; j < n; ++j) { + // Sum all cube vertices' samples portions + var rj = 0; + for (i = 0; i < cubeVertices; i++) { + rj += samples[cubeVertex[i] + j] * cubeN[i]; + } + + // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1, + // Decode_2j, Decode_2j+1) + rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]); + + // y_j = min(max(r_j, range_2j), range_2j+1) + dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), + range[j][1]); + } + }; + }, + + constructInterpolated: function PDFFunction_constructInterpolated(str, + dict) { + var c0 = dict.get('C0') || [0]; + var c1 = dict.get('C1') || [1]; + var n = dict.get('N'); + + if (!isArray(c0) || !isArray(c1)) { + error('Illegal dictionary for interpolated function'); + } + + var length = c0.length; + var diff = []; + for (var i = 0; i < length; ++i) { + diff.push(c1[i] - c0[i]); + } + + return [CONSTRUCT_INTERPOLATED, c0, diff, n]; + }, + + constructInterpolatedFromIR: + function PDFFunction_constructInterpolatedFromIR(IR) { + var c0 = IR[1]; + var diff = IR[2]; + var n = IR[3]; + + var length = diff.length; + + return function constructInterpolatedFromIRResult(src, srcOffset, + dest, destOffset) { + var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n); + + for (var j = 0; j < length; ++j) { + dest[destOffset + j] = c0[j] + (x * diff[j]); + } + }; + }, + + constructStiched: function PDFFunction_constructStiched(fn, dict, xref) { + var domain = dict.get('Domain'); + + if (!domain) { + error('No domain'); + } + + var inputSize = domain.length / 2; + if (inputSize !== 1) { + error('Bad domain for stiched function'); + } + + var fnRefs = dict.get('Functions'); + var fns = []; + for (var i = 0, ii = fnRefs.length; i < ii; ++i) { + fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i]))); + } + + var bounds = dict.get('Bounds'); + var encode = dict.get('Encode'); + + return [CONSTRUCT_STICHED, domain, bounds, encode, fns]; + }, + + constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) { + var domain = IR[1]; + var bounds = IR[2]; + var encode = IR[3]; + var fnsIR = IR[4]; + var fns = []; + var tmpBuf = new Float32Array(1); + + for (var i = 0, ii = fnsIR.length; i < ii; i++) { + fns.push(PDFFunction.fromIR(fnsIR[i])); + } + + return function constructStichedFromIRResult(src, srcOffset, + dest, destOffset) { + var clip = function constructStichedFromIRClip(v, min, max) { + if (v > max) { + v = max; + } else if (v < min) { + v = min; + } + return v; + }; + + // clip to domain + var v = clip(src[srcOffset], domain[0], domain[1]); + // calulate which bound the value is in + for (var i = 0, ii = bounds.length; i < ii; ++i) { + if (v < bounds[i]) { + break; + } + } + + // encode value into domain of function + var dmin = domain[0]; + if (i > 0) { + dmin = bounds[i - 1]; + } + var dmax = domain[1]; + if (i < bounds.length) { + dmax = bounds[i]; + } + + var rmin = encode[2 * i]; + var rmax = encode[2 * i + 1]; + + tmpBuf[0] = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); + + // call the appropriate function + fns[i](tmpBuf, 0, dest, destOffset); + }; + }, + + constructPostScript: function PDFFunction_constructPostScript(fn, dict, + xref) { + var domain = dict.get('Domain'); + var range = dict.get('Range'); + + if (!domain) { + error('No domain.'); + } + + if (!range) { + error('No range.'); + } + + var lexer = new PostScriptLexer(fn); + var parser = new PostScriptParser(lexer); + var code = parser.parse(); + + return [CONSTRUCT_POSTSCRIPT, domain, range, code]; + }, + + constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR( + IR) { + var domain = IR[1]; + var range = IR[2]; + var code = IR[3]; + + var compiled = (new PostScriptCompiler()).compile(code, domain, range); + if (compiled) { + // Compiled function consists of simple expressions such as addition, + // subtraction, Math.max, and also contains 'var' and 'return' + // statements. See the generation in the PostScriptCompiler below. + /*jshint -W054 */ + return new Function('src', 'srcOffset', 'dest', 'destOffset', compiled); + } + + info('Unable to compile PS function'); + + var numOutputs = range.length >> 1; + var numInputs = domain.length >> 1; + var evaluator = new PostScriptEvaluator(code); + // Cache the values for a big speed up, the cache size is limited though + // since the number of possible values can be huge from a PS function. + var cache = {}; + // The MAX_CACHE_SIZE is set to ~4x the maximum number of distinct values + // seen in our tests. + var MAX_CACHE_SIZE = 2048 * 4; + var cache_available = MAX_CACHE_SIZE; + var tmpBuf = new Float32Array(numInputs); + + return function constructPostScriptFromIRResult(src, srcOffset, + dest, destOffset) { + var i, value; + var key = ''; + var input = tmpBuf; + for (i = 0; i < numInputs; i++) { + value = src[srcOffset + i]; + input[i] = value; + key += value + '_'; + } + + var cachedValue = cache[key]; + if (cachedValue !== undefined) { + dest.set(cachedValue, destOffset); + return; + } + + var output = new Float32Array(numOutputs); + var stack = evaluator.execute(input); + var stackIndex = stack.length - numOutputs; + for (i = 0; i < numOutputs; i++) { + value = stack[stackIndex + i]; + var bound = range[i * 2]; + if (value < bound) { + value = bound; + } else { + bound = range[i * 2 +1]; + if (value > bound) { + value = bound; + } + } + output[i] = value; + } + if (cache_available > 0) { + cache_available--; + cache[key] = output; + } + dest.set(output, destOffset); + }; + } + }; +})(); + +function isPDFFunction(v) { + var fnDict; + if (typeof v !== 'object') { + return false; + } else if (isDict(v)) { + fnDict = v; + } else if (isStream(v)) { + fnDict = v.dict; + } else { + return false; + } + return fnDict.has('FunctionType'); +} + +var PostScriptStack = (function PostScriptStackClosure() { + var MAX_STACK_SIZE = 100; + function PostScriptStack(initialStack) { + this.stack = !initialStack ? [] : + Array.prototype.slice.call(initialStack, 0); + } + + PostScriptStack.prototype = { + push: function PostScriptStack_push(value) { + if (this.stack.length >= MAX_STACK_SIZE) { + error('PostScript function stack overflow.'); + } + this.stack.push(value); + }, + pop: function PostScriptStack_pop() { + if (this.stack.length <= 0) { + error('PostScript function stack underflow.'); + } + return this.stack.pop(); + }, + copy: function PostScriptStack_copy(n) { + if (this.stack.length + n >= MAX_STACK_SIZE) { + error('PostScript function stack overflow.'); + } + var stack = this.stack; + for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) { + stack.push(stack[i]); + } + }, + index: function PostScriptStack_index(n) { + this.push(this.stack[this.stack.length - n - 1]); + }, + // rotate the last n stack elements p times + roll: function PostScriptStack_roll(n, p) { + var stack = this.stack; + var l = stack.length - n; + var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t; + for (i = l, j = r; i < j; i++, j--) { + t = stack[i]; stack[i] = stack[j]; stack[j] = t; + } + for (i = l, j = c - 1; i < j; i++, j--) { + t = stack[i]; stack[i] = stack[j]; stack[j] = t; + } + for (i = c, j = r; i < j; i++, j--) { + t = stack[i]; stack[i] = stack[j]; stack[j] = t; + } + } + }; + return PostScriptStack; +})(); +var PostScriptEvaluator = (function PostScriptEvaluatorClosure() { + function PostScriptEvaluator(operators) { + this.operators = operators; + } + PostScriptEvaluator.prototype = { + execute: function PostScriptEvaluator_execute(initialStack) { + var stack = new PostScriptStack(initialStack); + var counter = 0; + var operators = this.operators; + var length = operators.length; + var operator, a, b; + while (counter < length) { + operator = operators[counter++]; + if (typeof operator === 'number') { + // Operator is really an operand and should be pushed to the stack. + stack.push(operator); + continue; + } + switch (operator) { + // non standard ps operators + case 'jz': // jump if false + b = stack.pop(); + a = stack.pop(); + if (!a) { + counter = b; + } + break; + case 'j': // jump + a = stack.pop(); + counter = a; + break; + + // all ps operators in alphabetical order (excluding if/ifelse) + case 'abs': + a = stack.pop(); + stack.push(Math.abs(a)); + break; + case 'add': + b = stack.pop(); + a = stack.pop(); + stack.push(a + b); + break; + case 'and': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a && b); + } else { + stack.push(a & b); + } + break; + case 'atan': + a = stack.pop(); + stack.push(Math.atan(a)); + break; + case 'bitshift': + b = stack.pop(); + a = stack.pop(); + if (a > 0) { + stack.push(a << b); + } else { + stack.push(a >> b); + } + break; + case 'ceiling': + a = stack.pop(); + stack.push(Math.ceil(a)); + break; + case 'copy': + a = stack.pop(); + stack.copy(a); + break; + case 'cos': + a = stack.pop(); + stack.push(Math.cos(a)); + break; + case 'cvi': + a = stack.pop() | 0; + stack.push(a); + break; + case 'cvr': + // noop + break; + case 'div': + b = stack.pop(); + a = stack.pop(); + stack.push(a / b); + break; + case 'dup': + stack.copy(1); + break; + case 'eq': + b = stack.pop(); + a = stack.pop(); + stack.push(a === b); + break; + case 'exch': + stack.roll(2, 1); + break; + case 'exp': + b = stack.pop(); + a = stack.pop(); + stack.push(Math.pow(a, b)); + break; + case 'false': + stack.push(false); + break; + case 'floor': + a = stack.pop(); + stack.push(Math.floor(a)); + break; + case 'ge': + b = stack.pop(); + a = stack.pop(); + stack.push(a >= b); + break; + case 'gt': + b = stack.pop(); + a = stack.pop(); + stack.push(a > b); + break; + case 'idiv': + b = stack.pop(); + a = stack.pop(); + stack.push((a / b) | 0); + break; + case 'index': + a = stack.pop(); + stack.index(a); + break; + case 'le': + b = stack.pop(); + a = stack.pop(); + stack.push(a <= b); + break; + case 'ln': + a = stack.pop(); + stack.push(Math.log(a)); + break; + case 'log': + a = stack.pop(); + stack.push(Math.log(a) / Math.LN10); + break; + case 'lt': + b = stack.pop(); + a = stack.pop(); + stack.push(a < b); + break; + case 'mod': + b = stack.pop(); + a = stack.pop(); + stack.push(a % b); + break; + case 'mul': + b = stack.pop(); + a = stack.pop(); + stack.push(a * b); + break; + case 'ne': + b = stack.pop(); + a = stack.pop(); + stack.push(a !== b); + break; + case 'neg': + a = stack.pop(); + stack.push(-a); + break; + case 'not': + a = stack.pop(); + if (isBool(a)) { + stack.push(!a); + } else { + stack.push(~a); + } + break; + case 'or': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a || b); + } else { + stack.push(a | b); + } + break; + case 'pop': + stack.pop(); + break; + case 'roll': + b = stack.pop(); + a = stack.pop(); + stack.roll(a, b); + break; + case 'round': + a = stack.pop(); + stack.push(Math.round(a)); + break; + case 'sin': + a = stack.pop(); + stack.push(Math.sin(a)); + break; + case 'sqrt': + a = stack.pop(); + stack.push(Math.sqrt(a)); + break; + case 'sub': + b = stack.pop(); + a = stack.pop(); + stack.push(a - b); + break; + case 'true': + stack.push(true); + break; + case 'truncate': + a = stack.pop(); + a = a < 0 ? Math.ceil(a) : Math.floor(a); + stack.push(a); + break; + case 'xor': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a !== b); + } else { + stack.push(a ^ b); + } + break; + default: + error('Unknown operator ' + operator); + break; + } + } + return stack.stack; + } + }; + return PostScriptEvaluator; +})(); + +// Most of the PDFs functions consist of simple operations such as: +// roll, exch, sub, cvr, pop, index, dup, mul, if, gt, add. +// +// We can compile most of such programs, and at the same moment, we can +// optimize some expressions using basic math properties. Keeping track of +// min/max values will allow us to avoid extra Math.min/Math.max calls. +var PostScriptCompiler = (function PostScriptCompilerClosure() { + function AstNode(type) { + this.type = type; + } + AstNode.prototype.visit = function (visitor) { + throw new Error('abstract method'); + }; + + function AstArgument(index, min, max) { + AstNode.call(this, 'args'); + this.index = index; + this.min = min; + this.max = max; + } + AstArgument.prototype = Object.create(AstNode.prototype); + AstArgument.prototype.visit = function (visitor) { + visitor.visitArgument(this); + }; + + function AstLiteral(number) { + AstNode.call(this, 'literal'); + this.number = number; + this.min = number; + this.max = number; + } + AstLiteral.prototype = Object.create(AstNode.prototype); + AstLiteral.prototype.visit = function (visitor) { + visitor.visitLiteral(this); + }; + + function AstBinaryOperation(op, arg1, arg2, min, max) { + AstNode.call(this, 'binary'); + this.op = op; + this.arg1 = arg1; + this.arg2 = arg2; + this.min = min; + this.max = max; + } + AstBinaryOperation.prototype = Object.create(AstNode.prototype); + AstBinaryOperation.prototype.visit = function (visitor) { + visitor.visitBinaryOperation(this); + }; + + function AstMin(arg, max) { + AstNode.call(this, 'max'); + this.arg = arg; + this.min = arg.min; + this.max = max; + } + AstMin.prototype = Object.create(AstNode.prototype); + AstMin.prototype.visit = function (visitor) { + visitor.visitMin(this); + }; + + function AstVariable(index, min, max) { + AstNode.call(this, 'var'); + this.index = index; + this.min = min; + this.max = max; + } + AstVariable.prototype = Object.create(AstNode.prototype); + AstVariable.prototype.visit = function (visitor) { + visitor.visitVariable(this); + }; + + function AstVariableDefinition(variable, arg) { + AstNode.call(this, 'definition'); + this.variable = variable; + this.arg = arg; + } + AstVariableDefinition.prototype = Object.create(AstNode.prototype); + AstVariableDefinition.prototype.visit = function (visitor) { + visitor.visitVariableDefinition(this); + }; + + function ExpressionBuilderVisitor() { + this.parts = []; + } + ExpressionBuilderVisitor.prototype = { + visitArgument: function (arg) { + this.parts.push('Math.max(', arg.min, ', Math.min(', + arg.max, ', src[srcOffset + ', arg.index, ']))'); + }, + visitVariable: function (variable) { + this.parts.push('v', variable.index); + }, + visitLiteral: function (literal) { + this.parts.push(literal.number); + }, + visitBinaryOperation: function (operation) { + this.parts.push('('); + operation.arg1.visit(this); + this.parts.push(' ', operation.op, ' '); + operation.arg2.visit(this); + this.parts.push(')'); + }, + visitVariableDefinition: function (definition) { + this.parts.push('var '); + definition.variable.visit(this); + this.parts.push(' = '); + definition.arg.visit(this); + this.parts.push(';'); + }, + visitMin: function (max) { + this.parts.push('Math.min('); + max.arg.visit(this); + this.parts.push(', ', max.max, ')'); + }, + toString: function () { + return this.parts.join(''); + } + }; + + function buildAddOperation(num1, num2) { + if (num2.type === 'literal' && num2.number === 0) { + // optimization: second operand is 0 + return num1; + } + if (num1.type === 'literal' && num1.number === 0) { + // optimization: first operand is 0 + return num2; + } + if (num2.type === 'literal' && num1.type === 'literal') { + // optimization: operands operand are literals + return new AstLiteral(num1.number + num2.number); + } + return new AstBinaryOperation('+', num1, num2, + num1.min + num2.min, num1.max + num2.max); + } + + function buildMulOperation(num1, num2) { + if (num2.type === 'literal') { + // optimization: second operands is a literal... + if (num2.number === 0) { + return new AstLiteral(0); // and it's 0 + } else if (num2.number === 1) { + return num1; // and it's 1 + } else if (num1.type === 'literal') { + // ... and first operands is a literal too + return new AstLiteral(num1.number * num2.number); + } + } + if (num1.type === 'literal') { + // optimization: first operands is a literal... + if (num1.number === 0) { + return new AstLiteral(0); // and it's 0 + } else if (num1.number === 1) { + return num2; // and it's 1 + } + } + var min = Math.min(num1.min * num2.min, num1.min * num2.max, + num1.max * num2.min, num1.max * num2.max); + var max = Math.max(num1.min * num2.min, num1.min * num2.max, + num1.max * num2.min, num1.max * num2.max); + return new AstBinaryOperation('*', num1, num2, min, max); + } + + function buildSubOperation(num1, num2) { + if (num2.type === 'literal') { + // optimization: second operands is a literal... + if (num2.number === 0) { + return num1; // ... and it's 0 + } else if (num1.type === 'literal') { + // ... and first operands is a literal too + return new AstLiteral(num1.number - num2.number); + } + } + if (num2.type === 'binary' && num2.op === '-' && + num1.type === 'literal' && num1.number === 1 && + num2.arg1.type === 'literal' && num2.arg1.number === 1) { + // optimization for case: 1 - (1 - x) + return num2.arg2; + } + return new AstBinaryOperation('-', num1, num2, + num1.min - num2.max, num1.max - num2.min); + } + + function buildMinOperation(num1, max) { + if (num1.min >= max) { + // optimization: num1 min value is not less than required max + return new AstLiteral(max); // just returning max + } else if (num1.max <= max) { + // optimization: num1 max value is not greater than required max + return num1; // just returning an argument + } + return new AstMin(num1, max); + } + + function PostScriptCompiler() {} + PostScriptCompiler.prototype = { + compile: function PostScriptCompiler_compile(code, domain, range) { + var stack = []; + var i, ii; + var instructions = []; + var inputSize = domain.length >> 1, outputSize = range.length >> 1; + var lastRegister = 0; + var n, j, min, max; + var num1, num2, ast1, ast2, tmpVar, item; + for (i = 0; i < inputSize; i++) { + stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1])); + } + + for (i = 0, ii = code.length; i < ii; i++) { + item = code[i]; + if (typeof item === 'number') { + stack.push(new AstLiteral(item)); + continue; + } + + switch (item) { + case 'add': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildAddOperation(num1, num2)); + break; + case 'cvr': + if (stack.length < 1) { + return null; + } + break; + case 'mul': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildMulOperation(num1, num2)); + break; + case 'sub': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildSubOperation(num1, num2)); + break; + case 'exch': + if (stack.length < 2) { + return null; + } + ast1 = stack.pop(); ast2 = stack.pop(); + stack.push(ast1, ast2); + break; + case 'pop': + if (stack.length < 1) { + return null; + } + stack.pop(); + break; + case 'index': + if (stack.length < 1) { + return null; + } + num1 = stack.pop(); + if (num1.type !== 'literal') { + return null; + } + n = num1.number; + if (n < 0 || (n|0) !== n || stack.length < n) { + return null; + } + ast1 = stack[stack.length - n - 1]; + if (ast1.type === 'literal' || ast1.type === 'var') { + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - n - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case 'dup': + if (stack.length < 1) { + return null; + } + if (typeof code[i + 1] === 'number' && code[i + 2] === 'gt' && + code[i + 3] === i + 7 && code[i + 4] === 'jz' && + code[i + 5] === 'pop' && code[i + 6] === code[i + 1]) { + // special case of the commands sequence for the min operation + num1 = stack.pop(); + stack.push(buildMinOperation(num1, code[i + 1])); + i += 6; + break; + } + ast1 = stack[stack.length - 1]; + if (ast1.type === 'literal' || ast1.type === 'var') { + // we don't have to save into intermediate variable a literal or + // variable. + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case 'roll': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + if (num2.type !== 'literal' || num1.type !== 'literal') { + // both roll operands must be numbers + return null; + } + j = num2.number; + n = num1.number; + if (n <= 0 || (n|0) !== n || (j|0) !== j || stack.length < n) { + // ... and integers + return null; + } + j = ((j % n) + n) % n; + if (j === 0) { + break; // just skipping -- there are nothing to rotate + } + Array.prototype.push.apply(stack, + stack.splice(stack.length - n, n - j)); + break; + default: + return null; // unsupported operator + } + } + + if (stack.length !== outputSize) { + return null; + } + + var result = []; + instructions.forEach(function (instruction) { + var statementBuilder = new ExpressionBuilderVisitor(); + instruction.visit(statementBuilder); + result.push(statementBuilder.toString()); + }); + stack.forEach(function (expr, i) { + var statementBuilder = new ExpressionBuilderVisitor(); + expr.visit(statementBuilder); + var min = range[i * 2], max = range[i * 2 + 1]; + var out = [statementBuilder.toString()]; + if (min > expr.min) { + out.unshift('Math.max(', min, ', '); + out.push(')'); + } + if (max < expr.max) { + out.unshift('Math.min(', max, ', '); + out.push(')'); + } + out.unshift('dest[destOffset + ', i, '] = '); + out.push(';'); + result.push(out.join('')); + }); + return result.join('\n'); + } + }; + + return PostScriptCompiler; +})(); + + +var ColorSpace = (function ColorSpaceClosure() { + // Constructor should define this.numComps, this.defaultColor, this.name + function ColorSpace() { + error('should not call ColorSpace constructor'); + } + + ColorSpace.prototype = { + /** + * Converts the color value to the RGB color. The color components are + * located in the src array starting from the srcOffset. Returns the array + * of the rgb components, each value ranging from [0,255]. + */ + getRgb: function ColorSpace_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; + }, + /** + * Converts the color value to the RGB color, similar to the getRgb method. + * The result placed into the dest array starting from the destOffset. + */ + getRgbItem: function ColorSpace_getRgbItem(src, srcOffset, + dest, destOffset) { + error('Should not call ColorSpace.getRgbItem'); + }, + /** + * Converts the specified number of the color values to the RGB colors. + * The colors are located in the src array starting from the srcOffset. + * The result is placed into the dest array starting from the destOffset. + * The src array items shall be in [0,2^bits) range, the dest array items + * will be in [0,255] range. alpha01 indicates how many alpha components + * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA + * array). + */ + getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + error('Should not call ColorSpace.getRgbBuffer'); + }, + /** + * Determines the number of bytes required to store the result of the + * conversion done by the getRgbBuffer method. As in getRgbBuffer, + * |alpha01| is either 0 (RGB output) or 1 (RGBA output). + */ + getOutputLength: function ColorSpace_getOutputLength(inputLength, + alpha01) { + error('Should not call ColorSpace.getOutputLength'); + }, + /** + * Returns true if source data will be equal the result/output data. + */ + isPassthrough: function ColorSpace_isPassthrough(bits) { + return false; + }, + /** + * Fills in the RGB colors in the destination buffer. alpha01 indicates + * how many alpha components there are in the dest array; it will be either + * 0 (RGB array) or 1 (RGBA array). + */ + fillRgb: function ColorSpace_fillRgb(dest, originalWidth, + originalHeight, width, height, + actualHeight, bpc, comps, alpha01) { + var count = originalWidth * originalHeight; + var rgbBuf = null; + var numComponentColors = 1 << bpc; + var needsResizing = originalHeight !== height || originalWidth !== width; + var i, ii; + + if (this.isPassthrough(bpc)) { + rgbBuf = comps; + } else if (this.numComps === 1 && count > numComponentColors && + this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { + // Optimization: create a color map when there is just one component and + // we are converting more colors than the size of the color map. We + // don't build the map if the colorspace is gray or rgb since those + // methods are faster than building a map. This mainly offers big speed + // ups for indexed and alternate colorspaces. + // + // TODO it may be worth while to cache the color map. While running + // testing I never hit a cache so I will leave that out for now (perhaps + // we are reparsing colorspaces too much?). + var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : + new Uint16Array(numComponentColors); + var key; + for (i = 0; i < numComponentColors; i++) { + allColors[i] = i; + } + var colorMap = new Uint8Array(numComponentColors * 3); + this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, + /* alpha01 = */ 0); + + var destPos, rgbPos; + if (!needsResizing) { + // Fill in the RGB values directly into |dest|. + destPos = 0; + for (i = 0; i < count; ++i) { + key = comps[i] * 3; + dest[destPos++] = colorMap[key]; + dest[destPos++] = colorMap[key + 1]; + dest[destPos++] = colorMap[key + 2]; + destPos += alpha01; + } + } else { + rgbBuf = new Uint8Array(count * 3); + rgbPos = 0; + for (i = 0; i < count; ++i) { + key = comps[i] * 3; + rgbBuf[rgbPos++] = colorMap[key]; + rgbBuf[rgbPos++] = colorMap[key + 1]; + rgbBuf[rgbPos++] = colorMap[key + 2]; + } + } + } else { + if (!needsResizing) { + // Fill in the RGB values directly into |dest|. + this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, + alpha01); + } else { + rgbBuf = new Uint8Array(count * 3); + this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, + /* alpha01 = */ 0); + } + } + + if (rgbBuf) { + if (needsResizing) { + PDFImage.resize(rgbBuf, bpc, 3, originalWidth, originalHeight, width, + height, dest, alpha01); + } else { + rgbPos = 0; + destPos = 0; + for (i = 0, ii = width * actualHeight; i < ii; i++) { + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + destPos += alpha01; + } + } + } + }, + /** + * True if the colorspace has components in the default range of [0, 1]. + * This should be true for all colorspaces except for lab color spaces + * which are [0,100], [-128, 127], [-128, 127]. + */ + usesZeroToOneRange: true + }; + + ColorSpace.parse = function ColorSpace_parse(cs, xref, res) { + var IR = ColorSpace.parseToIR(cs, xref, res); + if (IR instanceof AlternateCS) { + return IR; + } + return ColorSpace.fromIR(IR); + }; + + ColorSpace.fromIR = function ColorSpace_fromIR(IR) { + var name = isArray(IR) ? IR[0] : IR; + var whitePoint, blackPoint, gamma; + + switch (name) { + case 'DeviceGrayCS': + return this.singletons.gray; + case 'DeviceRgbCS': + return this.singletons.rgb; + case 'DeviceCmykCS': + return this.singletons.cmyk; + case 'CalGrayCS': + whitePoint = IR[1].WhitePoint; + blackPoint = IR[1].BlackPoint; + gamma = IR[1].Gamma; + return new CalGrayCS(whitePoint, blackPoint, gamma); + case 'CalRGBCS': + whitePoint = IR[1].WhitePoint; + blackPoint = IR[1].BlackPoint; + gamma = IR[1].Gamma; + var matrix = IR[1].Matrix; + return new CalRGBCS(whitePoint, blackPoint, gamma, matrix); + case 'PatternCS': + var basePatternCS = IR[1]; + if (basePatternCS) { + basePatternCS = ColorSpace.fromIR(basePatternCS); + } + return new PatternCS(basePatternCS); + case 'IndexedCS': + var baseIndexedCS = IR[1]; + var hiVal = IR[2]; + var lookup = IR[3]; + return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup); + case 'AlternateCS': + var numComps = IR[1]; + var alt = IR[2]; + var tintFnIR = IR[3]; + + return new AlternateCS(numComps, ColorSpace.fromIR(alt), + PDFFunction.fromIR(tintFnIR)); + case 'LabCS': + whitePoint = IR[1].WhitePoint; + blackPoint = IR[1].BlackPoint; + var range = IR[1].Range; + return new LabCS(whitePoint, blackPoint, range); + default: + error('Unknown name ' + name); + } + return null; + }; + + ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) { + if (isName(cs)) { + var colorSpaces = res.get('ColorSpace'); + if (isDict(colorSpaces)) { + var refcs = colorSpaces.get(cs.name); + if (refcs) { + cs = refcs; + } + } + } + + cs = xref.fetchIfRef(cs); + var mode; + + if (isName(cs)) { + mode = cs.name; + this.mode = mode; + + switch (mode) { + case 'DeviceGray': + case 'G': + return 'DeviceGrayCS'; + case 'DeviceRGB': + case 'RGB': + return 'DeviceRgbCS'; + case 'DeviceCMYK': + case 'CMYK': + return 'DeviceCmykCS'; + case 'Pattern': + return ['PatternCS', null]; + default: + error('unrecognized colorspace ' + mode); + } + } else if (isArray(cs)) { + mode = cs[0].name; + this.mode = mode; + var numComps, params; + + switch (mode) { + case 'DeviceGray': + case 'G': + return 'DeviceGrayCS'; + case 'DeviceRGB': + case 'RGB': + return 'DeviceRgbCS'; + case 'DeviceCMYK': + case 'CMYK': + return 'DeviceCmykCS'; + case 'CalGray': + params = xref.fetchIfRef(cs[1]).getAll(); + return ['CalGrayCS', params]; + case 'CalRGB': + params = xref.fetchIfRef(cs[1]).getAll(); + return ['CalRGBCS', params]; + case 'ICCBased': + var stream = xref.fetchIfRef(cs[1]); + var dict = stream.dict; + numComps = dict.get('N'); + if (numComps === 1) { + return 'DeviceGrayCS'; + } else if (numComps === 3) { + return 'DeviceRgbCS'; + } else if (numComps === 4) { + return 'DeviceCmykCS'; + } + break; + case 'Pattern': + var basePatternCS = cs[1]; + if (basePatternCS) { + basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res); + } + return ['PatternCS', basePatternCS]; + case 'Indexed': + case 'I': + var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res); + var hiVal = cs[2] + 1; + var lookup = xref.fetchIfRef(cs[3]); + if (isStream(lookup)) { + lookup = lookup.getBytes(); + } + return ['IndexedCS', baseIndexedCS, hiVal, lookup]; + case 'Separation': + case 'DeviceN': + var name = cs[1]; + numComps = 1; + if (isName(name)) { + numComps = 1; + } else if (isArray(name)) { + numComps = name.length; + } + var alt = ColorSpace.parseToIR(cs[2], xref, res); + var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3])); + return ['AlternateCS', numComps, alt, tintFnIR]; + case 'Lab': + params = cs[1].getAll(); + return ['LabCS', params]; + default: + error('unimplemented color space object "' + mode + '"'); + } + } else { + error('unrecognized color space object: "' + cs + '"'); + } + return null; + }; + /** + * Checks if a decode map matches the default decode map for a color space. + * This handles the general decode maps where there are two values per + * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color. + * This does not handle Lab, Indexed, or Pattern decode maps since they are + * slightly different. + * @param {Array} decode Decode map (usually from an image). + * @param {Number} n Number of components the color space has. + */ + ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) { + if (!decode) { + return true; + } + + if (n * 2 !== decode.length) { + warn('The decode map is not the correct length'); + return true; + } + for (var i = 0, ii = decode.length; i < ii; i += 2) { + if (decode[i] !== 0 || decode[i + 1] !== 1) { + return false; + } + } + return true; + }; + + ColorSpace.singletons = { + get gray() { + return shadow(this, 'gray', new DeviceGrayCS()); + }, + get rgb() { + return shadow(this, 'rgb', new DeviceRgbCS()); + }, + get cmyk() { + return shadow(this, 'cmyk', new DeviceCmykCS()); + } + }; + + return ColorSpace; +})(); + +/** + * Alternate color space handles both Separation and DeviceN color spaces. A + * Separation color space is actually just a DeviceN with one color component. + * Both color spaces use a tinting function to convert colors to a base color + * space. + */ +var AlternateCS = (function AlternateCSClosure() { + function AlternateCS(numComps, base, tintFn) { + this.name = 'Alternate'; + this.numComps = numComps; + this.defaultColor = new Float32Array(numComps); + for (var i = 0; i < numComps; ++i) { + this.defaultColor[i] = 1; + } + this.base = base; + this.tintFn = tintFn; + this.tmpBuf = new Float32Array(base.numComps); + } + + AlternateCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function AlternateCS_getRgbItem(src, srcOffset, + dest, destOffset) { + var tmpBuf = this.tmpBuf; + this.tintFn(src, srcOffset, tmpBuf, 0); + this.base.getRgbItem(tmpBuf, 0, dest, destOffset); + }, + getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var tintFn = this.tintFn; + var base = this.base; + var scale = 1 / ((1 << bits) - 1); + var baseNumComps = base.numComps; + var usesZeroToOneRange = base.usesZeroToOneRange; + var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && + alpha01 === 0; + var pos = isPassthrough ? destOffset : 0; + var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count); + var numComps = this.numComps; + + var scaled = new Float32Array(numComps); + var tinted = new Float32Array(baseNumComps); + var i, j; + if (usesZeroToOneRange) { + for (i = 0; i < count; i++) { + for (j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; + } + tintFn(scaled, 0, tinted, 0); + for (j = 0; j < baseNumComps; j++) { + baseBuf[pos++] = tinted[j] * 255; + } + } + } else { + for (i = 0; i < count; i++) { + for (j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; + } + tintFn(scaled, 0, tinted, 0); + base.getRgbItem(tinted, 0, baseBuf, pos); + pos += baseNumComps; + } + } + if (!isPassthrough) { + base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); + } + }, + getOutputLength: function AlternateCS_getOutputLength(inputLength, + alpha01) { + return this.base.getOutputLength(inputLength * + this.base.numComps / this.numComps, + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + + return AlternateCS; +})(); + +var PatternCS = (function PatternCSClosure() { + function PatternCS(baseCS) { + this.name = 'Pattern'; + this.base = baseCS; + } + PatternCS.prototype = {}; + + return PatternCS; +})(); + +var IndexedCS = (function IndexedCSClosure() { + function IndexedCS(base, highVal, lookup) { + this.name = 'Indexed'; + this.numComps = 1; + this.defaultColor = new Uint8Array([0]); + this.base = base; + this.highVal = highVal; + + var baseNumComps = base.numComps; + var length = baseNumComps * highVal; + var lookupArray; + + if (isStream(lookup)) { + lookupArray = new Uint8Array(length); + var bytes = lookup.getBytes(length); + lookupArray.set(bytes); + } else if (isString(lookup)) { + lookupArray = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + lookupArray[i] = lookup.charCodeAt(i); + } + } else if (lookup instanceof Uint8Array || lookup instanceof Array) { + lookupArray = lookup; + } else { + error('Unrecognized lookup table: ' + lookup); + } + this.lookup = lookupArray; + } + + IndexedCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function IndexedCS_getRgbItem(src, srcOffset, + dest, destOffset) { + var numComps = this.base.numComps; + var start = src[srcOffset] * numComps; + this.base.getRgbItem(this.lookup, start, dest, destOffset); + }, + getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var base = this.base; + var numComps = base.numComps; + var outputDelta = base.getOutputLength(numComps, alpha01); + var lookup = this.lookup; + + for (var i = 0; i < count; ++i) { + var lookupPos = src[srcOffset++] * numComps; + base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); + destOffset += outputDelta; + } + }, + getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps, + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) { + // indexed color maps shouldn't be changed + return true; + }, + usesZeroToOneRange: true + }; + return IndexedCS; +})(); + +var DeviceGrayCS = (function DeviceGrayCSClosure() { + function DeviceGrayCS() { + this.name = 'DeviceGray'; + this.numComps = 1; + this.defaultColor = new Float32Array([0]); + } + + DeviceGrayCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset, + dest, destOffset) { + var c = (src[srcOffset] * 255) | 0; + c = c < 0 ? 0 : c > 255 ? 255 : c; + dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; + }, + getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < count; ++i) { + var c = (scale * src[j++]) | 0; + dest[q++] = c; + dest[q++] = c; + dest[q++] = c; + q += alpha01; + } + }, + getOutputLength: function DeviceGrayCS_getOutputLength(inputLength, + alpha01) { + return inputLength * (3 + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return DeviceGrayCS; +})(); + +var DeviceRgbCS = (function DeviceRgbCSClosure() { + function DeviceRgbCS() { + this.name = 'DeviceRGB'; + this.numComps = 3; + this.defaultColor = new Float32Array([0, 0, 0]); + } + DeviceRgbCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset, + dest, destOffset) { + var r = (src[srcOffset] * 255) | 0; + var g = (src[srcOffset + 1] * 255) | 0; + var b = (src[srcOffset + 2] * 255) | 0; + dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r; + dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g; + dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b; + }, + getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + if (bits === 8 && alpha01 === 0) { + dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); + return; + } + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < count; ++i) { + dest[q++] = (scale * src[j++]) | 0; + dest[q++] = (scale * src[j++]) | 0; + dest[q++] = (scale * src[j++]) | 0; + q += alpha01; + } + }, + getOutputLength: function DeviceRgbCS_getOutputLength(inputLength, + alpha01) { + return (inputLength * (3 + alpha01) / 3) | 0; + }, + isPassthrough: function DeviceRgbCS_isPassthrough(bits) { + return bits === 8; + }, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return DeviceRgbCS; +})(); + +var DeviceCmykCS = (function DeviceCmykCSClosure() { + // The coefficients below was found using numerical analysis: the method of + // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors, + // where color_value is the tabular value from the table of sampled RGB colors + // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding + // CMYK color conversion using the estimation below: + // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255 + function convertToRgb(src, srcOffset, srcScale, dest, destOffset) { + var c = src[srcOffset + 0] * srcScale; + var m = src[srcOffset + 1] * srcScale; + var y = src[srcOffset + 2] * srcScale; + var k = src[srcOffset + 3] * srcScale; + + var r = + (c * (-4.387332384609988 * c + 54.48615194189176 * m + + 18.82290502165302 * y + 212.25662451639585 * k + + -285.2331026137004) + + m * (1.7149763477362134 * m - 5.6096736904047315 * y + + -17.873870861415444 * k - 5.497006427196366) + + y * (-2.5217340131683033 * y - 21.248923337353073 * k + + 17.5119270841813) + + k * (-21.86122147463605 * k - 189.48180835922747) + 255) | 0; + var g = + (c * (8.841041422036149 * c + 60.118027045597366 * m + + 6.871425592049007 * y + 31.159100130055922 * k + + -79.2970844816548) + + m * (-15.310361306967817 * m + 17.575251261109482 * y + + 131.35250912493976 * k - 190.9453302588951) + + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + + k * (-20.737325471181034 * k - 187.80453709719578) + 255) | 0; + var b = + (c * (0.8842522430003296 * c + 8.078677503112928 * m + + 30.89978309703729 * y - 0.23883238689178934 * k + + -14.183576799673286) + + m * (10.49593273432072 * m + 63.02378494754052 * y + + 50.606957656360734 * k - 112.23884253719248) + + y * (0.03296041114873217 * y + 115.60384449646641 * k + + -193.58209356861505) + + k * (-22.33816807309886 * k - 180.12613974708367) + 255) | 0; + + dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r; + dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g; + dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b; + } + + function DeviceCmykCS() { + this.name = 'DeviceCMYK'; + this.numComps = 4; + this.defaultColor = new Float32Array([0, 0, 0, 1]); + } + DeviceCmykCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset, + dest, destOffset) { + convertToRgb(src, srcOffset, 1, dest, destOffset); + }, + getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var scale = 1 / ((1 << bits) - 1); + for (var i = 0; i < count; i++) { + convertToRgb(src, srcOffset, scale, dest, destOffset); + srcOffset += 4; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function DeviceCmykCS_getOutputLength(inputLength, + alpha01) { + return (inputLength / 4 * (3 + alpha01)) | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + + return DeviceCmykCS; +})(); + +// +// CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245 +// +var CalGrayCS = (function CalGrayCSClosure() { + function CalGrayCS(whitePoint, blackPoint, gamma) { + this.name = 'CalGray'; + this.numComps = 1; + this.defaultColor = new Float32Array([0]); + + if (!whitePoint) { + error('WhitePoint missing - required for color space CalGray'); + } + blackPoint = blackPoint || [0, 0, 0]; + gamma = gamma || 1; + + // Translate arguments to spec variables. + this.XW = whitePoint[0]; + this.YW = whitePoint[1]; + this.ZW = whitePoint[2]; + + this.XB = blackPoint[0]; + this.YB = blackPoint[1]; + this.ZB = blackPoint[2]; + + this.G = gamma; + + // Validate variables as per spec. + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + error('Invalid WhitePoint components for ' + this.name + + ', no fallback available'); + } + + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info('Invalid BlackPoint for ' + this.name + ', falling back to default'); + this.XB = this.YB = this.ZB = 0; + } + + if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { + warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB + + ', ZB: ' + this.ZB + ', only default values are supported.'); + } + + if (this.G < 1) { + info('Invalid Gamma: ' + this.G + ' for ' + this.name + + ', falling back to default'); + this.G = 1; + } + } + + function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { + // A represents a gray component of a calibrated gray space. + // A <---> AG in the spec + var A = src[srcOffset] * scale; + var AG = Math.pow(A, cs.G); + + // Computes L as per spec. ( = cs.YW * AG ) + // Except if other than default BlackPoint values are used. + var L = cs.YW * AG; + // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4. + // Convert values to rgb range [0, 255]. + var val = Math.max(295.8 * Math.pow(L, 0.333333333333333333) - 40.8, 0) | 0; + dest[destOffset] = val; + dest[destOffset + 1] = val; + dest[destOffset + 2] = val; + } + + CalGrayCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function CalGrayCS_getRgbItem(src, srcOffset, + dest, destOffset) { + convertToRgb(this, src, srcOffset, dest, destOffset, 1); + }, + getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var scale = 1 / ((1 << bits) - 1); + + for (var i = 0; i < count; ++i) { + convertToRgb(this, src, srcOffset, dest, destOffset, scale); + srcOffset += 1; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return CalGrayCS; +})(); + +// +// CalRGBCS: Based on "PDF Reference, Sixth Ed", p.247 +// +var CalRGBCS = (function CalRGBCSClosure() { + + // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these + // matrices. + var BRADFORD_SCALE_MATRIX = new Float32Array([ + 0.8951, 0.2664, -0.1614, + -0.7502, 1.7135, 0.0367, + 0.0389, -0.0685, 1.0296]); + + var BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([ + 0.9869929, -0.1470543, 0.1599627, + 0.4323053, 0.5183603, 0.0492912, + -0.0085287, 0.0400428, 0.9684867]); + + // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html. + var SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([ + 3.2404542, -1.5371385, -0.4985314, + -0.9692660, 1.8760108, 0.0415560, + 0.0556434, -0.2040259, 1.0572252]); + + var FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]); + + var tempNormalizeMatrix = new Float32Array(3); + var tempConvertMatrix1 = new Float32Array(3); + var tempConvertMatrix2 = new Float32Array(3); + + var DECODE_L_CONSTANT = Math.pow(((8 + 16) / 116), 3) / 8.0; + + function CalRGBCS(whitePoint, blackPoint, gamma, matrix) { + this.name = 'CalRGB'; + this.numComps = 3; + this.defaultColor = new Float32Array(3); + + if (!whitePoint) { + error('WhitePoint missing - required for color space CalRGB'); + } + blackPoint = blackPoint || new Float32Array(3); + gamma = gamma || new Float32Array([1, 1, 1]); + matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]); + + // Translate arguments to spec variables. + var XW = whitePoint[0]; + var YW = whitePoint[1]; + var ZW = whitePoint[2]; + this.whitePoint = whitePoint; + + var XB = blackPoint[0]; + var YB = blackPoint[1]; + var ZB = blackPoint[2]; + this.blackPoint = blackPoint; + + this.GR = gamma[0]; + this.GG = gamma[1]; + this.GB = gamma[2]; + + this.MXA = matrix[0]; + this.MYA = matrix[1]; + this.MZA = matrix[2]; + this.MXB = matrix[3]; + this.MYB = matrix[4]; + this.MZB = matrix[5]; + this.MXC = matrix[6]; + this.MYC = matrix[7]; + this.MZC = matrix[8]; + + // Validate variables as per spec. + if (XW < 0 || ZW < 0 || YW !== 1) { + error('Invalid WhitePoint components for ' + this.name + + ', no fallback available'); + } + + if (XB < 0 || YB < 0 || ZB < 0) { + info('Invalid BlackPoint for ' + this.name + ' [' + XB + ', ' + YB + + ', ' + ZB + '], falling back to default'); + this.blackPoint = new Float32Array(3); + } + + if (this.GR < 0 || this.GG < 0 || this.GB < 0) { + info('Invalid Gamma [' + this.GR + ', ' + this.GG + ', ' + this.GB + + '] for ' + this.name + ', falling back to default'); + this.GR = this.GG = this.GB = 1; + } + + if (this.MXA < 0 || this.MYA < 0 || this.MZA < 0 || + this.MXB < 0 || this.MYB < 0 || this.MZB < 0 || + this.MXC < 0 || this.MYC < 0 || this.MZC < 0) { + info('Invalid Matrix for ' + this.name + ' [' + + this.MXA + ', ' + this.MYA + ', ' + this.MZA + + this.MXB + ', ' + this.MYB + ', ' + this.MZB + + this.MXC + ', ' + this.MYC + ', ' + this.MZC + + '], falling back to default'); + this.MXA = this.MYB = this.MZC = 1; + this.MXB = this.MYA = this.MZA = this.MXC = this.MYC = this.MZB = 0; + } + } + + function matrixProduct(a, b, result) { + result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2]; + result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2]; + } + + function convertToFlat(sourceWhitePoint, LMS, result) { + result[0] = LMS[0] * 1 / sourceWhitePoint[0]; + result[1] = LMS[1] * 1 / sourceWhitePoint[1]; + result[2] = LMS[2] * 1 / sourceWhitePoint[2]; + } + + function convertToD65(sourceWhitePoint, LMS, result) { + var D65X = 0.95047; + var D65Y = 1; + var D65Z = 1.08883; + + result[0] = LMS[0] * D65X / sourceWhitePoint[0]; + result[1] = LMS[1] * D65Y / sourceWhitePoint[1]; + result[2] = LMS[2] * D65Z / sourceWhitePoint[2]; + } + + function sRGBTransferFunction(color) { + // See http://en.wikipedia.org/wiki/SRGB. + if (color <= 0.0031308){ + return adjustToRange(0, 1, 12.92 * color); + } + + return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055); + } + + function adjustToRange(min, max, value) { + return Math.max(min, Math.min(max, value)); + } + + function decodeL(L) { + if (L < 0) { + return -decodeL(-L); + } + + if (L > 8.0) { + return Math.pow(((L + 16) / 116), 3); + } + + return L * DECODE_L_CONSTANT; + } + + function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) { + + // In case the blackPoint is already the default blackPoint then there is + // no need to do compensation. + if (sourceBlackPoint[0] === 0 && + sourceBlackPoint[1] === 0 && + sourceBlackPoint[2] === 0) { + result[0] = XYZ_Flat[0]; + result[1] = XYZ_Flat[1]; + result[2] = XYZ_Flat[2]; + return; + } + + // For the blackPoint calculation details, please see + // http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/ + // AdobeBPC.pdf. + // The destination blackPoint is the default blackPoint [0, 0, 0]. + var zeroDecodeL = decodeL(0); + + var X_DST = zeroDecodeL; + var X_SRC = decodeL(sourceBlackPoint[0]); + + var Y_DST = zeroDecodeL; + var Y_SRC = decodeL(sourceBlackPoint[1]); + + var Z_DST = zeroDecodeL; + var Z_SRC = decodeL(sourceBlackPoint[2]); + + var X_Scale = (1 - X_DST) / (1 - X_SRC); + var X_Offset = 1 - X_Scale; + + var Y_Scale = (1 - Y_DST) / (1 - Y_SRC); + var Y_Offset = 1 - Y_Scale; + + var Z_Scale = (1 - Z_DST) / (1 - Z_SRC); + var Z_Offset = 1 - Z_Scale; + + result[0] = XYZ_Flat[0] * X_Scale + X_Offset; + result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset; + result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset; + } + + function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) { + + // In case the whitePoint is already flat then there is no need to do + // normalization. + if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) { + result[0] = XYZ_In[0]; + result[1] = XYZ_In[1]; + result[2] = XYZ_In[2]; + return; + } + + var LMS = result; + matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + + var LMS_Flat = tempNormalizeMatrix; + convertToFlat(sourceWhitePoint, LMS, LMS_Flat); + + matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result); + } + + function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) { + + var LMS = result; + matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + + var LMS_D65 = tempNormalizeMatrix; + convertToD65(sourceWhitePoint, LMS, LMS_D65); + + matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result); + } + + function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { + // A, B and C represent a red, green and blue components of a calibrated + // rgb space. + var A = adjustToRange(0, 1, src[srcOffset] * scale); + var B = adjustToRange(0, 1, src[srcOffset + 1] * scale); + var C = adjustToRange(0, 1, src[srcOffset + 2] * scale); + + // A <---> AGR in the spec + // B <---> BGG in the spec + // C <---> CGB in the spec + var AGR = Math.pow(A, cs.GR); + var BGG = Math.pow(B, cs.GG); + var CGB = Math.pow(C, cs.GB); + + // Computes intermediate variables L, M, N as per spec. + // To decode X, Y, Z values map L, M, N directly to them. + var X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB; + var Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB; + var Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB; + + // The following calculations are based on this document: + // http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/ + // AdobeBPC.pdf. + var XYZ = tempConvertMatrix1; + XYZ[0] = X; + XYZ[1] = Y; + XYZ[2] = Z; + var XYZ_Flat = tempConvertMatrix2; + + normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat); + + var XYZ_Black = tempConvertMatrix1; + compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black); + + var XYZ_D65 = tempConvertMatrix2; + normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65); + + var SRGB = tempConvertMatrix1; + matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB); + + var sR = sRGBTransferFunction(SRGB[0]); + var sG = sRGBTransferFunction(SRGB[1]); + var sB = sRGBTransferFunction(SRGB[2]); + + // Convert the values to rgb range [0, 255]. + dest[destOffset] = Math.round(sR * 255); + dest[destOffset + 1] = Math.round(sG * 255); + dest[destOffset + 2] = Math.round(sB * 255); + } + + CalRGBCS.prototype = { + getRgb: function CalRGBCS_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; + }, + getRgbItem: function CalRGBCS_getRgbItem(src, srcOffset, + dest, destOffset) { + convertToRgb(this, src, srcOffset, dest, destOffset, 1); + }, + getRgbBuffer: function CalRGBCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var scale = 1 / ((1 << bits) - 1); + + for (var i = 0; i < count; ++i) { + convertToRgb(this, src, srcOffset, dest, destOffset, scale); + srcOffset += 3; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function CalRGBCS_getOutputLength(inputLength, alpha01) { + return (inputLength * (3 + alpha01) / 3) | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function CalRGBCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return CalRGBCS; +})(); + +// +// LabCS: Based on "PDF Reference, Sixth Ed", p.250 +// +var LabCS = (function LabCSClosure() { + function LabCS(whitePoint, blackPoint, range) { + this.name = 'Lab'; + this.numComps = 3; + this.defaultColor = new Float32Array([0, 0, 0]); + + if (!whitePoint) { + error('WhitePoint missing - required for color space Lab'); + } + blackPoint = blackPoint || [0, 0, 0]; + range = range || [-100, 100, -100, 100]; + + // Translate args to spec variables + this.XW = whitePoint[0]; + this.YW = whitePoint[1]; + this.ZW = whitePoint[2]; + this.amin = range[0]; + this.amax = range[1]; + this.bmin = range[2]; + this.bmax = range[3]; + + // These are here just for completeness - the spec doesn't offer any + // formulas that use BlackPoint in Lab + this.XB = blackPoint[0]; + this.YB = blackPoint[1]; + this.ZB = blackPoint[2]; + + // Validate vars as per spec + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + error('Invalid WhitePoint components, no fallback available'); + } + + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info('Invalid BlackPoint, falling back to default'); + this.XB = this.YB = this.ZB = 0; + } + + if (this.amin > this.amax || this.bmin > this.bmax) { + info('Invalid Range, falling back to defaults'); + this.amin = -100; + this.amax = 100; + this.bmin = -100; + this.bmax = 100; + } + } + + // Function g(x) from spec + function fn_g(x) { + if (x >= 6 / 29) { + return x * x * x; + } else { + return (108 / 841) * (x - 4 / 29); + } + } + + function decode(value, high1, low2, high2) { + return low2 + (value) * (high2 - low2) / (high1); + } + + // If decoding is needed maxVal should be 2^bits per component - 1. + function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) { + // XXX: Lab input is in the range of [0, 100], [amin, amax], [bmin, bmax] + // not the usual [0, 1]. If a command like setFillColor is used the src + // values will already be within the correct range. However, if we are + // converting an image we have to map the values to the correct range given + // above. + // Ls,as,bs <---> L*,a*,b* in the spec + var Ls = src[srcOffset]; + var as = src[srcOffset + 1]; + var bs = src[srcOffset + 2]; + if (maxVal !== false) { + Ls = decode(Ls, maxVal, 0, 100); + as = decode(as, maxVal, cs.amin, cs.amax); + bs = decode(bs, maxVal, cs.bmin, cs.bmax); + } + + // Adjust limits of 'as' and 'bs' + as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as; + bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs; + + // Computes intermediate variables X,Y,Z as per spec + var M = (Ls + 16) / 116; + var L = M + (as / 500); + var N = M - (bs / 200); + + var X = cs.XW * fn_g(L); + var Y = cs.YW * fn_g(M); + var Z = cs.ZW * fn_g(N); + + var r, g, b; + // Using different conversions for D50 and D65 white points, + // per http://www.color.org/srgb.pdf + if (cs.ZW < 1) { + // Assuming D50 (X=0.9642, Y=1.00, Z=0.8249) + r = X * 3.1339 + Y * -1.6170 + Z * -0.4906; + g = X * -0.9785 + Y * 1.9160 + Z * 0.0333; + b = X * 0.0720 + Y * -0.2290 + Z * 1.4057; + } else { + // Assuming D65 (X=0.9505, Y=1.00, Z=1.0888) + r = X * 3.2406 + Y * -1.5372 + Z * -0.4986; + g = X * -0.9689 + Y * 1.8758 + Z * 0.0415; + b = X * 0.0557 + Y * -0.2040 + Z * 1.0570; + } + // clamp color values to [0,1] range then convert to [0,255] range. + dest[destOffset] = r <= 0 ? 0 : r >= 1 ? 255 : Math.sqrt(r) * 255 | 0; + dest[destOffset + 1] = g <= 0 ? 0 : g >= 1 ? 255 : Math.sqrt(g) * 255 | 0; + dest[destOffset + 2] = b <= 0 ? 0 : b >= 1 ? 255 : Math.sqrt(b) * 255 | 0; + } + + LabCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) { + convertToRgb(this, src, srcOffset, false, dest, destOffset); + }, + getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var maxVal = (1 << bits) - 1; + for (var i = 0; i < count; i++) { + convertToRgb(this, src, srcOffset, maxVal, dest, destOffset); + srcOffset += 3; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) { + return (inputLength * (3 + alpha01) / 3) | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) { + // XXX: Decoding is handled with the lab conversion because of the strange + // ranges that are used. + return true; + }, + usesZeroToOneRange: false + }; + return LabCS; +})(); + + +var ARCFourCipher = (function ARCFourCipherClosure() { + function ARCFourCipher(key) { + this.a = 0; + this.b = 0; + var s = new Uint8Array(256); + var i, j = 0, tmp, keyLength = key.length; + for (i = 0; i < 256; ++i) { + s[i] = i; + } + for (i = 0; i < 256; ++i) { + tmp = s[i]; + j = (j + tmp + key[i % keyLength]) & 0xFF; + s[i] = s[j]; + s[j] = tmp; + } + this.s = s; + } + + ARCFourCipher.prototype = { + encryptBlock: function ARCFourCipher_encryptBlock(data) { + var i, n = data.length, tmp, tmp2; + var a = this.a, b = this.b, s = this.s; + var output = new Uint8Array(n); + for (i = 0; i < n; ++i) { + a = (a + 1) & 0xFF; + tmp = s[a]; + b = (b + tmp) & 0xFF; + tmp2 = s[b]; + s[a] = tmp2; + s[b] = tmp; + output[i] = data[i] ^ s[(tmp + tmp2) & 0xFF]; + } + this.a = a; + this.b = b; + return output; + } + }; + ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock; + + return ARCFourCipher; +})(); + +var calculateMD5 = (function calculateMD5Closure() { + var r = new Uint8Array([ + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]); + + var k = new Int32Array([ + -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, + -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, + 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, + 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, + 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, + 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, + -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, + -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, + -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, + -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, + -145523070, -1120210379, 718787259, -343485551]); + + function hash(data, offset, length) { + var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878; + // pre-processing + var paddedLength = (length + 72) & ~63; // data + 9 extra bytes + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 8; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = (length << 3) & 0xFF; + padded[i++] = (length >> 5) & 0xFF; + padded[i++] = (length >> 13) & 0xFF; + padded[i++] = (length >> 21) & 0xFF; + padded[i++] = (length >>> 29) & 0xFF; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + var w = new Int32Array(16); + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j, i += 4) { + w[j] = (padded[i] | (padded[i + 1] << 8) | + (padded[i + 2] << 16) | (padded[i + 3] << 24)); + } + var a = h0, b = h1, c = h2, d = h3, f, g; + for (j = 0; j < 64; ++j) { + if (j < 16) { + f = (b & c) | ((~b) & d); + g = j; + } else if (j < 32) { + f = (d & b) | ((~d) & c); + g = (5 * j + 1) & 15; + } else if (j < 48) { + f = b ^ c ^ d; + g = (3 * j + 5) & 15; + } else { + f = c ^ (b | (~d)); + g = (7 * j) & 15; + } + var tmp = d, rotateArg = (a + f + k[j] + w[g]) | 0, rotate = r[j]; + d = c; + c = b; + b = (b + ((rotateArg << rotate) | (rotateArg >>> (32 - rotate)))) | 0; + a = tmp; + } + h0 = (h0 + a) | 0; + h1 = (h1 + b) | 0; + h2 = (h2 + c) | 0; + h3 = (h3 + d) | 0; + } + return new Uint8Array([ + h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >>> 24) & 0xFF, + h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >>> 24) & 0xFF, + h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >>> 24) & 0xFF, + h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >>> 24) & 0xFF + ]); + } + + return hash; +})(); +var Word64 = (function Word64Closure() { + function Word64(highInteger, lowInteger) { + this.high = highInteger | 0; + this.low = lowInteger | 0; + } + Word64.prototype = { + and: function Word64_and(word) { + this.high &= word.high; + this.low &= word.low; + }, + xor: function Word64_xor(word) { + this.high ^= word.high; + this.low ^= word.low; + }, + + or: function Word64_or(word) { + this.high |= word.high; + this.low |= word.low; + }, + + shiftRight: function Word64_shiftRight(places) { + if (places >= 32) { + this.low = (this.high >>> (places - 32)) | 0; + this.high = 0; + } else { + this.low = (this.low >>> places) | (this.high << (32 - places)); + this.high = (this.high >>> places) | 0; + } + }, + + shiftLeft: function Word64_shiftLeft(places) { + if (places >= 32) { + this.high = this.low << (places - 32); + this.low = 0; + } else { + this.high = (this.high << places) | (this.low >>> (32 - places)); + this.low = this.low << places; + } + }, + + rotateRight: function Word64_rotateRight(places) { + var low, high; + if (places & 32) { + high = this.low; + low = this.high; + } else { + low = this.low; + high = this.high; + } + places &= 31; + this.low = (low >>> places) | (high << (32 - places)); + this.high = (high >>> places) | (low << (32 - places)); + }, + + not: function Word64_not() { + this.high = ~this.high; + this.low = ~this.low; + }, + + add: function Word64_add(word) { + var lowAdd = (this.low >>> 0) + (word.low >>> 0); + var highAdd = (this.high >>> 0) + (word.high >>> 0); + if (lowAdd > 0xFFFFFFFF) { + highAdd += 1; + } + this.low = lowAdd | 0; + this.high = highAdd | 0; + }, + + copyTo: function Word64_copyTo(bytes, offset) { + bytes[offset] = (this.high >>> 24) & 0xFF; + bytes[offset + 1] = (this.high >> 16) & 0xFF; + bytes[offset + 2] = (this.high >> 8) & 0xFF; + bytes[offset + 3] = this.high & 0xFF; + bytes[offset + 4] = (this.low >>> 24) & 0xFF; + bytes[offset + 5] = (this.low >> 16) & 0xFF; + bytes[offset + 6] = (this.low >> 8) & 0xFF; + bytes[offset + 7] = this.low & 0xFF; + }, + + assign: function Word64_assign(word) { + this.high = word.high; + this.low = word.low; + } + }; + return Word64; +})(); + +var calculateSHA256 = (function calculateSHA256Closure() { + function rotr(x, n) { + return (x >>> n) | (x << 32 - n); + } + + function ch(x, y, z) { + return (x & y) ^ (~x & z); + } + + function maj(x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); + } + + function sigma(x) { + return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); + } + + function sigmaPrime(x) { + return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); + } + + function littleSigma(x) { + return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3; + } + + function littleSigmaPrime(x) { + return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10; + } + + var k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; + + function hash(data, offset, length) { + // initial hash values + var h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, + h3 = 0xa54ff53a, h4 = 0x510e527f, h5 = 0x9b05688c, + h6 = 0x1f83d9ab, h7 = 0x5be0cd19; + // pre-processing + var paddedLength = Math.ceil((length + 9) / 64) * 64; + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 8; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = (length >>> 29) & 0xFF; + padded[i++] = (length >> 21) & 0xFF; + padded[i++] = (length >> 13) & 0xFF; + padded[i++] = (length >> 5) & 0xFF; + padded[i++] = (length << 3) & 0xFF; + var w = new Uint32Array(64); + // for each 512 bit block + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j) { + w[j] = (padded[i] << 24 | (padded[i + 1] << 16) | + (padded[i + 2] << 8) | (padded[i + 3])); + i += 4; + } + + for (j = 16; j < 64; ++j) { + w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + + littleSigma(w[j - 15]) + w[j - 16] | 0; + } + var a = h0, b = h1, c = h2, d = h3, e = h4, + f = h5, g = h6, h = h7, t1, t2; + for (j = 0; j < 64; ++j) { + t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j]; + t2 = sigma(a) + maj(a, b, c); + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + h0 = (h0 + a) | 0; + h1 = (h1 + b) | 0; + h2 = (h2 + c) | 0; + h3 = (h3 + d) | 0; + h4 = (h4 + e) | 0; + h5 = (h5 + f) | 0; + h6 = (h6 + g) | 0; + h7 = (h7 + h) | 0; + } + return new Uint8Array([ + (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, (h0) & 0xFF, + (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, (h1) & 0xFF, + (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, (h2) & 0xFF, + (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, (h3) & 0xFF, + (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, (h4) & 0xFF, + (h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, (h5) & 0xFF, + (h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, (h6) & 0xFF, + (h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, (h7) & 0xFF + ]); + } + + return hash; +})(); + +var calculateSHA512 = (function calculateSHA512Closure() { + function ch(result, x, y, z, tmp) { + result.assign(x); + result.and(y); + tmp.assign(x); + tmp.not(); + tmp.and(z); + result.xor(tmp); + } + + function maj(result, x, y, z, tmp) { + result.assign(x); + result.and(y); + tmp.assign(x); + tmp.and(z); + result.xor(tmp); + tmp.assign(y); + tmp.and(z); + result.xor(tmp); + } + + function sigma(result, x, tmp) { + result.assign(x); + result.rotateRight(28); + tmp.assign(x); + tmp.rotateRight(34); + result.xor(tmp); + tmp.assign(x); + tmp.rotateRight(39); + result.xor(tmp); + } + + function sigmaPrime(result, x, tmp) { + result.assign(x); + result.rotateRight(14); + tmp.assign(x); + tmp.rotateRight(18); + result.xor(tmp); + tmp.assign(x); + tmp.rotateRight(41); + result.xor(tmp); + } + + function littleSigma(result, x, tmp) { + result.assign(x); + result.rotateRight(1); + tmp.assign(x); + tmp.rotateRight(8); + result.xor(tmp); + tmp.assign(x); + tmp.shiftRight(7); + result.xor(tmp); + } + + function littleSigmaPrime(result, x, tmp) { + result.assign(x); + result.rotateRight(19); + tmp.assign(x); + tmp.rotateRight(61); + result.xor(tmp); + tmp.assign(x); + tmp.shiftRight(6); + result.xor(tmp); + } + + var k = [ + new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), + new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), + new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), + new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), + new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), + new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), + new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), + new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), + new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), + new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), + new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), + new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), + new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), + new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), + new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), + new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), + new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), + new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), + new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), + new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), + new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), + new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), + new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), + new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), + new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), + new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), + new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), + new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), + new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), + new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), + new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), + new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), + new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), + new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), + new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), + new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), + new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), + new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), + new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), + new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)]; + + function hash(data, offset, length, mode384) { + mode384 = !!mode384; + // initial hash values + var h0, h1, h2, h3, h4, h5, h6, h7; + if (!mode384) { + h0 = new Word64(0x6a09e667, 0xf3bcc908); + h1 = new Word64(0xbb67ae85, 0x84caa73b); + h2 = new Word64(0x3c6ef372, 0xfe94f82b); + h3 = new Word64(0xa54ff53a, 0x5f1d36f1); + h4 = new Word64(0x510e527f, 0xade682d1); + h5 = new Word64(0x9b05688c, 0x2b3e6c1f); + h6 = new Word64(0x1f83d9ab, 0xfb41bd6b); + h7 = new Word64(0x5be0cd19, 0x137e2179); + } + else { + // SHA384 is exactly the same + // except with different starting values and a trimmed result + h0 = new Word64(0xcbbb9d5d, 0xc1059ed8); + h1 = new Word64(0x629a292a, 0x367cd507); + h2 = new Word64(0x9159015a, 0x3070dd17); + h3 = new Word64(0x152fecd8, 0xf70e5939); + h4 = new Word64(0x67332667, 0xffc00b31); + h5 = new Word64(0x8eb44a87, 0x68581511); + h6 = new Word64(0xdb0c2e0d, 0x64f98fa7); + h7 = new Word64(0x47b5481d, 0xbefa4fa4); + } + + // pre-processing + var paddedLength = Math.ceil((length + 17) / 128) * 128; + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 16; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = (length >>> 29) & 0xFF; + padded[i++] = (length >> 21) & 0xFF; + padded[i++] = (length >> 13) & 0xFF; + padded[i++] = (length >> 5) & 0xFF; + padded[i++] = (length << 3) & 0xFF; + + var w = new Array(80); + for (i = 0; i < 80; i++) { + w[i] = new Word64(0, 0); + } + var a = new Word64(0, 0), b = new Word64(0, 0), c = new Word64(0, 0); + var d = new Word64(0, 0), e = new Word64(0, 0), f = new Word64(0, 0); + var g = new Word64(0, 0), h = new Word64(0, 0); + var t1 = new Word64(0, 0), t2 = new Word64(0, 0); + var tmp1 = new Word64(0, 0), tmp2 = new Word64(0, 0), tmp3; + + // for each 1024 bit block + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j) { + w[j].high = (padded[i] << 24) | (padded[i + 1] << 16) | + (padded[i + 2] << 8) | (padded[i + 3]); + w[j].low = (padded[i + 4]) << 24 | (padded[i + 5]) << 16 | + (padded[i + 6]) << 8 | (padded[i + 7]); + i += 8; + } + for (j = 16; j < 80; ++j) { + tmp3 = w[j]; + littleSigmaPrime(tmp3, w[j - 2], tmp2); + tmp3.add(w[j - 7]); + littleSigma(tmp1, w[j - 15], tmp2); + tmp3.add(tmp1); + tmp3.add(w[j - 16]); + } + + a.assign(h0); b.assign(h1); c.assign(h2); d.assign(h3); + e.assign(h4); f.assign(h5); g.assign(h6); h.assign(h7); + for (j = 0; j < 80; ++j) { + t1.assign(h); + sigmaPrime(tmp1, e, tmp2); + t1.add(tmp1); + ch(tmp1, e, f, g, tmp2); + t1.add(tmp1); + t1.add(k[j]); + t1.add(w[j]); + + sigma(t2, a, tmp2); + maj(tmp1, a, b, c, tmp2); + t2.add(tmp1); + + tmp3 = h; + h = g; + g = f; + f = e; + d.add(t1); + e = d; + d = c; + c = b; + b = a; + tmp3.assign(t1); + tmp3.add(t2); + a = tmp3; + } + h0.add(a); + h1.add(b); + h2.add(c); + h3.add(d); + h4.add(e); + h5.add(f); + h6.add(g); + h7.add(h); + } + + var result; + if (!mode384) { + result = new Uint8Array(64); + h0.copyTo(result,0); + h1.copyTo(result,8); + h2.copyTo(result,16); + h3.copyTo(result,24); + h4.copyTo(result,32); + h5.copyTo(result,40); + h6.copyTo(result,48); + h7.copyTo(result,56); + } + else { + result = new Uint8Array(48); + h0.copyTo(result,0); + h1.copyTo(result,8); + h2.copyTo(result,16); + h3.copyTo(result,24); + h4.copyTo(result,32); + h5.copyTo(result,40); + } + return result; + } + + return hash; +})(); +var calculateSHA384 = (function calculateSHA384Closure() { + function hash(data, offset, length) { + return calculateSHA512(data, offset, length, true); + } + + return hash; +})(); +var NullCipher = (function NullCipherClosure() { + function NullCipher() { + } + + NullCipher.prototype = { + decryptBlock: function NullCipher_decryptBlock(data) { + return data; + } + }; + + return NullCipher; +})(); + +var AES128Cipher = (function AES128CipherClosure() { + var rcon = new Uint8Array([ + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, + 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, + 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d]); + + var s = new Uint8Array([ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16]); + + var inv_s = new Uint8Array([ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d]); + var mixCol = new Uint8Array(256); + for (var i = 0; i < 256; i++) { + if (i < 128) { + mixCol[i] = i << 1; + } else { + mixCol[i] = (i << 1) ^ 0x1b; + } + } + var mix = new Uint32Array([ + 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, + 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, + 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, + 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, + 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, + 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, + 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, + 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, + 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, + 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, + 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, + 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, + 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, + 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, + 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, + 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, + 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, + 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, + 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, + 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, + 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, + 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, + 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, + 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, + 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, + 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, + 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, + 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, + 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, + 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, + 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, + 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, + 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, + 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, + 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, + 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, + 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, + 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, + 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, + 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, + 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, + 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, + 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); + + function expandKey128(cipherKey) { + var b = 176, result = new Uint8Array(b); + result.set(cipherKey); + for (var j = 16, i = 1; j < b; ++i) { + // RotWord + var t1 = result[j - 3], t2 = result[j - 2], + t3 = result[j - 1], t4 = result[j - 4]; + // SubWord + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + // Rcon + t1 = t1 ^ rcon[i]; + for (var n = 0; n < 4; ++n) { + result[j] = (t1 ^= result[j - 16]); + j++; + result[j] = (t2 ^= result[j - 16]); + j++; + result[j] = (t3 ^= result[j - 16]); + j++; + result[j] = (t4 ^= result[j - 16]); + j++; + } + } + return result; + } + + function decrypt128(input, key) { + var state = new Uint8Array(16); + state.set(input); + var i, j, k; + var t, u, v; + // AddRoundKey + for (j = 0, k = 160; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (i = 9; i >= 1; --i) { + // InvShiftRows + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + // InvSubBytes + for (j = 0; j < 16; ++j) { + state[j] = inv_s[state[j]]; + } + // AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + // InvMixColumns + for (j = 0; j < 16; j += 4) { + var s0 = mix[state[j]], s1 = mix[state[j + 1]], + s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; + t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ + (s3 >>> 24) ^ (s3 << 8)); + state[j] = (t >>> 24) & 0xFF; + state[j + 1] = (t >> 16) & 0xFF; + state[j + 2] = (t >> 8) & 0xFF; + state[j + 3] = t & 0xFF; + } + } + // InvShiftRows + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (j = 0; j < 16; ++j) { + // InvSubBytes + state[j] = inv_s[state[j]]; + // AddRoundKey + state[j] ^= key[j]; + } + return state; + } + + function encrypt128(input, key) { + var t, u, v, k; + var state = new Uint8Array(16); + state.set(input); + for (j = 0; j < 16; ++j) { + // AddRoundKey + state[j] ^= key[j]; + } + + for (i = 1; i < 10; i++) { + //SubBytes + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + //ShiftRows + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + //MixColumns + for (var j = 0; j < 16; j += 4) { + var s0 = state[j + 0], s1 = state[j + 1]; + var s2 = state[j + 2], s3 = state[j + 3]; + t = s0 ^ s1 ^ s2 ^ s3; + state[j + 0] ^= t ^ mixCol[s0 ^ s1]; + state[j + 1] ^= t ^ mixCol[s1 ^ s2]; + state[j + 2] ^= t ^ mixCol[s2 ^ s3]; + state[j + 3] ^= t ^ mixCol[s3 ^ s0]; + } + //AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + } + + //SubBytes + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + //ShiftRows + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + //AddRoundKey + for (j = 0, k = 160; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + return state; + } + + function AES128Cipher(key) { + this.key = expandKey128(key); + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + + function decryptBlock2(data, finalize) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = [], iv = this.iv; + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + // buffer is full, decrypting + var plain = decrypt128(buffer, this.key); + // xor-ing the IV vector to get plain text + for (j = 0; j < 16; ++j) { + plain[j] ^= iv[j]; + } + iv = buffer; + result.push(plain); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + if (finalize) { + // undo a padding that is described in RFC 2898 + var lastBlock = result[result.length - 1]; + var psLen = lastBlock[15]; + if (psLen <= 16) { + for (i = 15, ii = 16 - psLen; i >= ii; --i) { + if (lastBlock[i] !== psLen) { + // Invalid padding, assume that the block has no padding. + psLen = 0; + break; + } + } + outputLength -= psLen; + result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); + } + } + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + + AES128Cipher.prototype = { + decryptBlock: function AES128Cipher_decryptBlock(data, finalize) { + var i, sourceLength = data.length; + var buffer = this.buffer, bufferLength = this.bufferPosition; + // waiting for IV values -- they are at the start of the stream + for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { + buffer[bufferLength] = data[i]; + } + if (bufferLength < 16) { + // need more data + this.bufferLength = bufferLength; + return new Uint8Array([]); + } + this.iv = buffer; + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + // starting decryption + this.decryptBlock = decryptBlock2; + return this.decryptBlock(data.subarray(16), finalize); + }, + encrypt: function AES128Cipher_encrypt(data, iv) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = []; + if (!iv) { + iv = new Uint8Array(16); + } + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + for (j = 0; j < 16; ++j) { + buffer[j] ^= iv[j]; + } + + // buffer is full, encrypting + var cipher = encrypt128(buffer, this.key); + iv = cipher; + result.push(cipher); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + }; + + return AES128Cipher; +})(); + +var AES256Cipher = (function AES256CipherClosure() { + var rcon = new Uint8Array([ + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, + 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, + 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d]); + + var s = new Uint8Array([ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16]); + + var inv_s = new Uint8Array([ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d]); + + var mixCol = new Uint8Array(256); + for (var i = 0; i < 256; i++) { + if (i < 128) { + mixCol[i] = i << 1; + } else { + mixCol[i] = (i << 1) ^ 0x1b; + } + } + var mix = new Uint32Array([ + 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, + 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, + 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, + 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, + 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, + 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, + 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, + 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, + 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, + 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, + 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, + 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, + 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, + 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, + 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, + 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, + 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, + 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, + 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, + 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, + 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, + 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, + 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, + 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, + 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, + 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, + 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, + 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, + 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, + 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, + 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, + 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, + 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, + 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, + 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, + 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, + 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, + 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, + 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, + 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, + 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, + 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, + 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); + + function expandKey256(cipherKey) { + var b = 240, result = new Uint8Array(b); + var r = 1; + + result.set(cipherKey); + for (var j = 32, i = 1; j < b; ++i) { + if (j % 32 === 16) { + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + } else if (j % 32 === 0) { + // RotWord + var t1 = result[j - 3], t2 = result[j - 2], + t3 = result[j - 1], t4 = result[j - 4]; + // SubWord + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + // Rcon + t1 = t1 ^ r; + if ((r <<= 1) >= 256) { + r = (r ^ 0x1b) & 0xFF; + } + } + + for (var n = 0; n < 4; ++n) { + result[j] = (t1 ^= result[j - 32]); + j++; + result[j] = (t2 ^= result[j - 32]); + j++; + result[j] = (t3 ^= result[j - 32]); + j++; + result[j] = (t4 ^= result[j - 32]); + j++; + } + } + return result; + } + + function decrypt256(input, key) { + var state = new Uint8Array(16); + state.set(input); + var i, j, k; + var t, u, v; + // AddRoundKey + for (j = 0, k = 224; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (i = 13; i >= 1; --i) { + // InvShiftRows + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + // InvSubBytes + for (j = 0; j < 16; ++j) { + state[j] = inv_s[state[j]]; + } + // AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + // InvMixColumns + for (j = 0; j < 16; j += 4) { + var s0 = mix[state[j]], s1 = mix[state[j + 1]], + s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; + t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ + (s3 >>> 24) ^ (s3 << 8)); + state[j] = (t >>> 24) & 0xFF; + state[j + 1] = (t >> 16) & 0xFF; + state[j + 2] = (t >> 8) & 0xFF; + state[j + 3] = t & 0xFF; + } + } + // InvShiftRows + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (j = 0; j < 16; ++j) { + // InvSubBytes + state[j] = inv_s[state[j]]; + // AddRoundKey + state[j] ^= key[j]; + } + return state; + } + + function encrypt256(input, key) { + var t, u, v, k; + var state = new Uint8Array(16); + state.set(input); + for (j = 0; j < 16; ++j) { + // AddRoundKey + state[j] ^= key[j]; + } + + for (i = 1; i < 14; i++) { + //SubBytes + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + //ShiftRows + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + //MixColumns + for (var j = 0; j < 16; j += 4) { + var s0 = state[j + 0], s1 = state[j + 1]; + var s2 = state[j + 2], s3 = state[j + 3]; + t = s0 ^ s1 ^ s2 ^ s3; + state[j + 0] ^= t ^ mixCol[s0 ^ s1]; + state[j + 1] ^= t ^ mixCol[s1 ^ s2]; + state[j + 2] ^= t ^ mixCol[s2 ^ s3]; + state[j + 3] ^= t ^ mixCol[s3 ^ s0]; + } + //AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + } + + //SubBytes + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + //ShiftRows + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + //AddRoundKey + for (j = 0, k = 224; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + + return state; + + } + + function AES256Cipher(key) { + this.key = expandKey256(key); + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + + function decryptBlock2(data, finalize) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = [], iv = this.iv; + + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + // buffer is full, decrypting + var plain = decrypt256(buffer, this.key); + // xor-ing the IV vector to get plain text + for (j = 0; j < 16; ++j) { + plain[j] ^= iv[j]; + } + iv = buffer; + result.push(plain); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + if (finalize) { + // undo a padding that is described in RFC 2898 + var lastBlock = result[result.length - 1]; + var psLen = lastBlock[15]; + if (psLen <= 16) { + for (i = 15, ii = 16 - psLen; i >= ii; --i) { + if (lastBlock[i] !== psLen) { + // Invalid padding, assume that the block has no padding. + psLen = 0; + break; + } + } + outputLength -= psLen; + result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); + } + } + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + + } + + AES256Cipher.prototype = { + decryptBlock: function AES256Cipher_decryptBlock(data, finalize, iv) { + var i, sourceLength = data.length; + var buffer = this.buffer, bufferLength = this.bufferPosition; + // if not supplied an IV wait for IV values + // they are at the start of the stream + if (iv) { + this.iv = iv; + } else { + for (i = 0; bufferLength < 16 && + i < sourceLength; ++i, ++bufferLength) { + buffer[bufferLength] = data[i]; + } + if (bufferLength < 16) { + //need more data + this.bufferLength = bufferLength; + return new Uint8Array([]); + } + this.iv = buffer; + data = data.subarray(16); + } + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + // starting decryption + this.decryptBlock = decryptBlock2; + return this.decryptBlock(data, finalize); + }, + encrypt: function AES256Cipher_encrypt(data, iv) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = []; + if (!iv) { + iv = new Uint8Array(16); + } + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + for (j = 0; j < 16; ++j) { + buffer[j] ^= iv[j]; + } + + // buffer is full, encrypting + var cipher = encrypt256(buffer, this.key); + this.iv = cipher; + result.push(cipher); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + }; + + return AES256Cipher; +})(); + +var PDF17 = (function PDF17Closure() { + + function compareByteArrays(array1, array2) { + if (array1.length !== array2.length) { + return false; + } + for (var i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + } + + function PDF17() { + } + + PDF17.prototype = { + checkOwnerPassword: function PDF17_checkOwnerPassword(password, + ownerValidationSalt, + userBytes, + ownerPassword) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerValidationSalt, password.length); + hashData.set(userBytes, password.length + ownerValidationSalt.length); + var result = calculateSHA256(hashData, 0, hashData.length); + return compareByteArrays(result, ownerPassword); + }, + checkUserPassword: function PDF17_checkUserPassword(password, + userValidationSalt, + userPassword) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userValidationSalt, password.length); + var result = calculateSHA256(hashData, 0, hashData.length); + return compareByteArrays(result, userPassword); + }, + getOwnerKey: function PDF17_getOwnerKey(password, ownerKeySalt, userBytes, + ownerEncryption) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerKeySalt, password.length); + hashData.set(userBytes, password.length + ownerKeySalt.length); + var key = calculateSHA256(hashData, 0, hashData.length); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(ownerEncryption, + false, + new Uint8Array(16)); + + }, + getUserKey: function PDF17_getUserKey(password, userKeySalt, + userEncryption) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userKeySalt, password.length); + //key is the decryption key for the UE string + var key = calculateSHA256(hashData, 0, hashData.length); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(userEncryption, + false, + new Uint8Array(16)); + } + }; + return PDF17; +})(); + +var PDF20 = (function PDF20Closure() { + + function concatArrays(array1, array2) { + var t = new Uint8Array(array1.length + array2.length); + t.set(array1, 0); + t.set(array2, array1.length); + return t; + } + + function calculatePDF20Hash(password, input, userBytes) { + //This refers to Algorithm 2.B as defined in ISO 32000-2 + var k = calculateSHA256(input, 0, input.length).subarray(0, 32); + var e = [0]; + var i = 0; + while (i < 64 || e[e.length - 1] > i - 32) { + var arrayLength = password.length + k.length + userBytes.length; + + var k1 = new Uint8Array(arrayLength * 64); + var array = concatArrays(password, k); + array = concatArrays(array, userBytes); + for (var j = 0, pos = 0; j < 64; j++, pos += arrayLength) { + k1.set(array, pos); + } + //AES128 CBC NO PADDING with + //first 16 bytes of k as the key and the second 16 as the iv. + var cipher = new AES128Cipher(k.subarray(0, 16)); + e = cipher.encrypt(k1, k.subarray(16, 32)); + //Now we have to take the first 16 bytes of an unsigned + //big endian integer... and compute the remainder + //modulo 3.... That is a fairly large number and + //JavaScript isn't going to handle that well... + //So we're using a trick that allows us to perform + //modulo math byte by byte + var remainder = 0; + for (var z = 0; z < 16; z++) { + remainder *= (256 % 3); + remainder %= 3; + remainder += ((e[z] >>> 0) % 3); + remainder %= 3; + } + if (remainder === 0) { + k = calculateSHA256(e, 0, e.length); + } + else if (remainder === 1) { + k = calculateSHA384(e, 0, e.length); + } + else if (remainder === 2) { + k = calculateSHA512(e, 0, e.length); + } + i++; + } + return k.subarray(0, 32); + } + + function PDF20() { + } + + function compareByteArrays(array1, array2) { + if (array1.length !== array2.length) { + return false; + } + for (var i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + } + + PDF20.prototype = { + hash: function PDF20_hash(password, concatBytes, userBytes) { + return calculatePDF20Hash(password, concatBytes, userBytes); + }, + checkOwnerPassword: function PDF20_checkOwnerPassword(password, + ownerValidationSalt, + userBytes, + ownerPassword) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerValidationSalt, password.length); + hashData.set(userBytes, password.length + ownerValidationSalt.length); + var result = calculatePDF20Hash(password, hashData, userBytes); + return compareByteArrays(result, ownerPassword); + }, + checkUserPassword: function PDF20_checkUserPassword(password, + userValidationSalt, + userPassword) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userValidationSalt, password.length); + var result = calculatePDF20Hash(password, hashData, []); + return compareByteArrays(result, userPassword); + }, + getOwnerKey: function PDF20_getOwnerKey(password, ownerKeySalt, userBytes, + ownerEncryption) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerKeySalt, password.length); + hashData.set(userBytes, password.length + ownerKeySalt.length); + var key = calculatePDF20Hash(password, hashData, userBytes); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(ownerEncryption, + false, + new Uint8Array(16)); + + }, + getUserKey: function PDF20_getUserKey(password, userKeySalt, + userEncryption) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userKeySalt, password.length); + //key is the decryption key for the UE string + var key = calculatePDF20Hash(password, hashData, []); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(userEncryption, + false, + new Uint8Array(16)); + } + }; + return PDF20; +})(); + +var CipherTransform = (function CipherTransformClosure() { + function CipherTransform(stringCipherConstructor, streamCipherConstructor) { + this.stringCipherConstructor = stringCipherConstructor; + this.streamCipherConstructor = streamCipherConstructor; + } + + CipherTransform.prototype = { + createStream: function CipherTransform_createStream(stream, length) { + var cipher = new this.streamCipherConstructor(); + return new DecryptStream(stream, length, + function cipherTransformDecryptStream(data, finalize) { + return cipher.decryptBlock(data, finalize); + } + ); + }, + decryptString: function CipherTransform_decryptString(s) { + var cipher = new this.stringCipherConstructor(); + var data = stringToBytes(s); + data = cipher.decryptBlock(data, true); + return bytesToString(data); + } + }; + return CipherTransform; +})(); + +var CipherTransformFactory = (function CipherTransformFactoryClosure() { + var defaultPasswordBytes = new Uint8Array([ + 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, + 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, + 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, + 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]); + + function createEncryptionKey20(revision, password, ownerPassword, + ownerValidationSalt, ownerKeySalt, uBytes, + userPassword, userValidationSalt, userKeySalt, + ownerEncryption, userEncryption, perms) { + if (password) { + var passwordLength = Math.min(127, password.length); + password = password.subarray(0, passwordLength); + } else { + password = []; + } + var pdfAlgorithm; + if (revision === 6) { + pdfAlgorithm = new PDF20(); + } else { + pdfAlgorithm = new PDF17(); + } + + if (pdfAlgorithm) { + if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, + userPassword)) { + return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption); + } else if (pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, + uBytes, + ownerPassword)) { + return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, + ownerEncryption); + } + } + + return null; + } + + function prepareKeyData(fileId, password, ownerPassword, userPassword, + flags, revision, keyLength, encryptMetadata) { + var hashDataSize = 40 + ownerPassword.length + fileId.length; + var hashData = new Uint8Array(hashDataSize), i = 0, j, n; + if (password) { + n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + } + j = 0; + while (i < 32) { + hashData[i++] = defaultPasswordBytes[j++]; + } + // as now the padded password in the hashData[0..i] + for (j = 0, n = ownerPassword.length; j < n; ++j) { + hashData[i++] = ownerPassword[j]; + } + hashData[i++] = flags & 0xFF; + hashData[i++] = (flags >> 8) & 0xFF; + hashData[i++] = (flags >> 16) & 0xFF; + hashData[i++] = (flags >>> 24) & 0xFF; + for (j = 0, n = fileId.length; j < n; ++j) { + hashData[i++] = fileId[j]; + } + if (revision >= 4 && !encryptMetadata) { + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + } + var hash = calculateMD5(hashData, 0, i); + var keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, keyLengthInBytes); + } + } + var encryptionKey = hash.subarray(0, keyLengthInBytes); + var cipher, checkData; + + if (revision >= 3) { + for (i = 0; i < 32; ++i) { + hashData[i] = defaultPasswordBytes[i]; + } + for (j = 0, n = fileId.length; j < n; ++j) { + hashData[i++] = fileId[j]; + } + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); + n = encryptionKey.length; + var derivedKey = new Uint8Array(n), k; + for (j = 1; j <= 19; ++j) { + for (k = 0; k < n; ++k) { + derivedKey[k] = encryptionKey[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + checkData = cipher.encryptBlock(checkData); + } + for (j = 0, n = checkData.length; j < n; ++j) { + if (userPassword[j] !== checkData[j]) { + return null; + } + } + } else { + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(defaultPasswordBytes); + for (j = 0, n = checkData.length; j < n; ++j) { + if (userPassword[j] !== checkData[j]) { + return null; + } + } + } + return encryptionKey; + } + + function decodeUserPassword(password, ownerPassword, revision, keyLength) { + var hashData = new Uint8Array(32), i = 0, j, n; + n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + j = 0; + while (i < 32) { + hashData[i++] = defaultPasswordBytes[j++]; + } + var hash = calculateMD5(hashData, 0, i); + var keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, hash.length); + } + } + + var cipher, userPassword; + if (revision >= 3) { + userPassword = ownerPassword; + var derivedKey = new Uint8Array(keyLengthInBytes), k; + for (j = 19; j >= 0; j--) { + for (k = 0; k < keyLengthInBytes; ++k) { + derivedKey[k] = hash[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + userPassword = cipher.encryptBlock(userPassword); + } + } else { + cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes)); + userPassword = cipher.encryptBlock(ownerPassword); + } + return userPassword; + } + + var identityName = Name.get('Identity'); + + function CipherTransformFactory(dict, fileId, password) { + var filter = dict.get('Filter'); + if (!isName(filter) || filter.name !== 'Standard') { + error('unknown encryption method'); + } + this.dict = dict; + var algorithm = dict.get('V'); + if (!isInt(algorithm) || + (algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && + algorithm !== 5)) { + error('unsupported encryption algorithm'); + } + this.algorithm = algorithm; + var keyLength = dict.get('Length') || 40; + if (!isInt(keyLength) || + keyLength < 40 || (keyLength % 8) !== 0) { + error('invalid key length'); + } + + // prepare keys + var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32); + var userPassword = stringToBytes(dict.get('U')).subarray(0, 32); + var flags = dict.get('P'); + var revision = dict.get('R'); + // meaningful when V is 4 or 5 + var encryptMetadata = ((algorithm === 4 || algorithm === 5) && + dict.get('EncryptMetadata') !== false); + this.encryptMetadata = encryptMetadata; + + var fileIdBytes = stringToBytes(fileId); + var passwordBytes; + if (password) { + if (revision === 6) { + try { + password = utf8StringToString(password); + } catch (ex) { + warn('CipherTransformFactory: ' + + 'Unable to convert UTF8 encoded password.'); + } + } + passwordBytes = stringToBytes(password); + } + + var encryptionKey; + if (algorithm !== 5) { + encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, + ownerPassword, userPassword, flags, + revision, keyLength, encryptMetadata); + } + else { + var ownerValidationSalt = stringToBytes(dict.get('O')).subarray(32, 40); + var ownerKeySalt = stringToBytes(dict.get('O')).subarray(40, 48); + var uBytes = stringToBytes(dict.get('U')).subarray(0, 48); + var userValidationSalt = stringToBytes(dict.get('U')).subarray(32, 40); + var userKeySalt = stringToBytes(dict.get('U')).subarray(40, 48); + var ownerEncryption = stringToBytes(dict.get('OE')); + var userEncryption = stringToBytes(dict.get('UE')); + var perms = stringToBytes(dict.get('Perms')); + encryptionKey = + createEncryptionKey20(revision, passwordBytes, + ownerPassword, ownerValidationSalt, + ownerKeySalt, uBytes, + userPassword, userValidationSalt, + userKeySalt, ownerEncryption, + userEncryption, perms); + } + if (!encryptionKey && !password) { + throw new PasswordException('No password given', + PasswordResponses.NEED_PASSWORD); + } else if (!encryptionKey && password) { + // Attempting use the password as an owner password + var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, + revision, keyLength); + encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, + ownerPassword, userPassword, flags, + revision, keyLength, encryptMetadata); + } + + if (!encryptionKey) { + throw new PasswordException('Incorrect Password', + PasswordResponses.INCORRECT_PASSWORD); + } + + this.encryptionKey = encryptionKey; + + if (algorithm >= 4) { + this.cf = dict.get('CF'); + this.stmf = dict.get('StmF') || identityName; + this.strf = dict.get('StrF') || identityName; + this.eff = dict.get('EFF') || this.stmf; + } + } + + function buildObjectKey(num, gen, encryptionKey, isAes) { + var key = new Uint8Array(encryptionKey.length + 9), i, n; + for (i = 0, n = encryptionKey.length; i < n; ++i) { + key[i] = encryptionKey[i]; + } + key[i++] = num & 0xFF; + key[i++] = (num >> 8) & 0xFF; + key[i++] = (num >> 16) & 0xFF; + key[i++] = gen & 0xFF; + key[i++] = (gen >> 8) & 0xFF; + if (isAes) { + key[i++] = 0x73; + key[i++] = 0x41; + key[i++] = 0x6C; + key[i++] = 0x54; + } + var hash = calculateMD5(key, 0, i); + return hash.subarray(0, Math.min(encryptionKey.length + 5, 16)); + } + + function buildCipherConstructor(cf, name, num, gen, key) { + var cryptFilter = cf.get(name.name); + var cfm; + if (cryptFilter !== null && cryptFilter !== undefined) { + cfm = cryptFilter.get('CFM'); + } + if (!cfm || cfm.name === 'None') { + return function cipherTransformFactoryBuildCipherConstructorNone() { + return new NullCipher(); + }; + } + if ('V2' === cfm.name) { + return function cipherTransformFactoryBuildCipherConstructorV2() { + return new ARCFourCipher(buildObjectKey(num, gen, key, false)); + }; + } + if ('AESV2' === cfm.name) { + return function cipherTransformFactoryBuildCipherConstructorAESV2() { + return new AES128Cipher(buildObjectKey(num, gen, key, true)); + }; + } + if ('AESV3' === cfm.name) { + return function cipherTransformFactoryBuildCipherConstructorAESV3() { + return new AES256Cipher(key); + }; + } + error('Unknown crypto method'); + } + + CipherTransformFactory.prototype = { + createCipherTransform: + function CipherTransformFactory_createCipherTransform(num, gen) { + if (this.algorithm === 4 || this.algorithm === 5) { + return new CipherTransform( + buildCipherConstructor(this.cf, this.stmf, + num, gen, this.encryptionKey), + buildCipherConstructor(this.cf, this.strf, + num, gen, this.encryptionKey)); + } + // algorithms 1 and 2 + var key = buildObjectKey(num, gen, this.encryptionKey, false); + var cipherConstructor = function buildCipherCipherConstructor() { + return new ARCFourCipher(key); + }; + return new CipherTransform(cipherConstructor, cipherConstructor); + } + }; + + return CipherTransformFactory; +})(); + + +var PatternType = { + FUNCTION_BASED: 1, + AXIAL: 2, + RADIAL: 3, + FREE_FORM_MESH: 4, + LATTICE_FORM_MESH: 5, + COONS_PATCH_MESH: 6, + TENSOR_PATCH_MESH: 7 +}; + +var Pattern = (function PatternClosure() { + // Constructor should define this.getPattern + function Pattern() { + error('should not call Pattern constructor'); + } + + Pattern.prototype = { + // Input: current Canvas context + // Output: the appropriate fillStyle or strokeStyle + getPattern: function Pattern_getPattern(ctx) { + error('Should not call Pattern.getStyle: ' + ctx); + } + }; + + Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, + res) { + + var dict = isStream(shading) ? shading.dict : shading; + var type = dict.get('ShadingType'); + + try { + switch (type) { + case PatternType.AXIAL: + case PatternType.RADIAL: + // Both radial and axial shadings are handled by RadialAxial shading. + return new Shadings.RadialAxial(dict, matrix, xref, res); + case PatternType.FREE_FORM_MESH: + case PatternType.LATTICE_FORM_MESH: + case PatternType.COONS_PATCH_MESH: + case PatternType.TENSOR_PATCH_MESH: + return new Shadings.Mesh(shading, matrix, xref, res); + default: + throw new Error('Unknown PatternType: ' + type); + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern); + warn(ex); + return new Shadings.Dummy(); + } + }; + return Pattern; +})(); + +var Shadings = {}; + +// A small number to offset the first/last color stops so we can insert ones to +// support extend. Number.MIN_VALUE appears to be too small and breaks the +// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number +// internally so we have to go bigger. +Shadings.SMALL_NUMBER = 1e-2; + +// Radial and axial shading have very similar implementations +// If needed, the implementations can be broken into two classes +Shadings.RadialAxial = (function RadialAxialClosure() { + function RadialAxial(dict, matrix, xref, res) { + this.matrix = matrix; + this.coordsArr = dict.get('Coords'); + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + this.cs = cs; + + var t0 = 0.0, t1 = 1.0; + if (dict.has('Domain')) { + var domainArr = dict.get('Domain'); + t0 = domainArr[0]; + t1 = domainArr[1]; + } + + var extendStart = false, extendEnd = false; + if (dict.has('Extend')) { + var extendArr = dict.get('Extend'); + extendStart = extendArr[0]; + extendEnd = extendArr[1]; + } + + if (this.shadingType === PatternType.RADIAL && + (!extendStart || !extendEnd)) { + // Radial gradient only currently works if either circle is fully within + // the other circle. + var x1 = this.coordsArr[0]; + var y1 = this.coordsArr[1]; + var r1 = this.coordsArr[2]; + var x2 = this.coordsArr[3]; + var y2 = this.coordsArr[4]; + var r2 = this.coordsArr[5]; + var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + if (r1 <= r2 + distance && + r2 <= r1 + distance) { + warn('Unsupported radial gradient.'); + } + } + + this.extendStart = extendStart; + this.extendEnd = extendEnd; + + var fnObj = dict.get('Function'); + var fn = PDFFunction.parseArray(xref, fnObj); + + // 10 samples seems good enough for now, but probably won't work + // if there are sharp color changes. Ideally, we would implement + // the spec faithfully and add lossless optimizations. + var diff = t1 - t0; + var step = diff / 10; + + var colorStops = this.colorStops = []; + + // Protect against bad domains so we don't end up in an infinte loop below. + if (t0 >= t1 || step <= 0) { + // Acrobat doesn't seem to handle these cases so we'll ignore for + // now. + info('Bad shading domain.'); + return; + } + + var color = new Float32Array(cs.numComps), ratio = new Float32Array(1); + var rgbColor; + for (var i = t0; i <= t1; i += step) { + ratio[0] = i; + fn(ratio, 0, color, 0); + rgbColor = cs.getRgb(color, 0); + var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); + colorStops.push([(i - t0) / diff, cssColor]); + } + + var background = 'transparent'; + if (dict.has('Background')) { + rgbColor = cs.getRgb(dict.get('Background'), 0); + background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); + } + + if (!extendStart) { + // Insert a color stop at the front and offset the first real color stop + // so it doesn't conflict with the one we insert. + colorStops.unshift([0, background]); + colorStops[1][0] += Shadings.SMALL_NUMBER; + } + if (!extendEnd) { + // Same idea as above in extendStart but for the end. + colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER; + colorStops.push([1, background]); + } + + this.colorStops = colorStops; + } + + RadialAxial.prototype = { + getIR: function RadialAxial_getIR() { + var coordsArr = this.coordsArr; + var shadingType = this.shadingType; + var type, p0, p1, r0, r1; + if (shadingType === PatternType.AXIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[2], coordsArr[3]]; + r0 = null; + r1 = null; + type = 'axial'; + } else if (shadingType === PatternType.RADIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[3], coordsArr[4]]; + r0 = coordsArr[2]; + r1 = coordsArr[5]; + type = 'radial'; + } else { + error('getPattern type unknown: ' + shadingType); + } + + var matrix = this.matrix; + if (matrix) { + p0 = Util.applyTransform(p0, matrix); + p1 = Util.applyTransform(p1, matrix); + } + + return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1]; + } + }; + + return RadialAxial; +})(); + +// All mesh shading. For now, they will be presented as set of the triangles +// to be drawn on the canvas and rgb color for each vertex. +Shadings.Mesh = (function MeshClosure() { + function MeshStreamReader(stream, context) { + this.stream = stream; + this.context = context; + this.buffer = 0; + this.bufferLength = 0; + + var numComps = context.numComps; + this.tmpCompsBuf = new Float32Array(numComps); + var csNumComps = context.colorSpace; + this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : + this.tmpCompsBuf; + } + MeshStreamReader.prototype = { + get hasData() { + if (this.stream.end) { + return this.stream.pos < this.stream.end; + } + if (this.bufferLength > 0) { + return true; + } + var nextByte = this.stream.getByte(); + if (nextByte < 0) { + return false; + } + this.buffer = nextByte; + this.bufferLength = 8; + return true; + }, + readBits: function MeshStreamReader_readBits(n) { + var buffer = this.buffer; + var bufferLength = this.bufferLength; + if (n === 32) { + if (bufferLength === 0) { + return ((this.stream.getByte() << 24) | + (this.stream.getByte() << 16) | (this.stream.getByte() << 8) | + this.stream.getByte()) >>> 0; + } + buffer = (buffer << 24) | (this.stream.getByte() << 16) | + (this.stream.getByte() << 8) | this.stream.getByte(); + var nextByte = this.stream.getByte(); + this.buffer = nextByte & ((1 << bufferLength) - 1); + return ((buffer << (8 - bufferLength)) | + ((nextByte & 0xFF) >> bufferLength)) >>> 0; + } + if (n === 8 && bufferLength === 0) { + return this.stream.getByte(); + } + while (bufferLength < n) { + buffer = (buffer << 8) | this.stream.getByte(); + bufferLength += 8; + } + bufferLength -= n; + this.bufferLength = bufferLength; + this.buffer = buffer & ((1 << bufferLength) - 1); + return buffer >> bufferLength; + }, + align: function MeshStreamReader_align() { + this.buffer = 0; + this.bufferLength = 0; + }, + readFlag: function MeshStreamReader_readFlag() { + return this.readBits(this.context.bitsPerFlag); + }, + readCoordinate: function MeshStreamReader_readCoordinate() { + var bitsPerCoordinate = this.context.bitsPerCoordinate; + var xi = this.readBits(bitsPerCoordinate); + var yi = this.readBits(bitsPerCoordinate); + var decode = this.context.decode; + var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : + 2.3283064365386963e-10; // 2 ^ -32 + return [ + xi * scale * (decode[1] - decode[0]) + decode[0], + yi * scale * (decode[3] - decode[2]) + decode[2] + ]; + }, + readComponents: function MeshStreamReader_readComponents() { + var numComps = this.context.numComps; + var bitsPerComponent = this.context.bitsPerComponent; + var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : + 2.3283064365386963e-10; // 2 ^ -32 + var decode = this.context.decode; + var components = this.tmpCompsBuf; + for (var i = 0, j = 4; i < numComps; i++, j += 2) { + var ci = this.readBits(bitsPerComponent); + components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j]; + } + var color = this.tmpCsCompsBuf; + if (this.context.colorFn) { + this.context.colorFn(components, 0, color, 0); + } + return this.context.colorSpace.getRgb(color, 0); + } + }; + + function decodeType4Shading(mesh, reader) { + var coords = mesh.coords; + var colors = mesh.colors; + var operators = []; + var ps = []; // not maintaining cs since that will match ps + var verticesLeft = 0; // assuming we have all data to start a new triangle + while (reader.hasData) { + var f = reader.readFlag(); + var coord = reader.readCoordinate(); + var color = reader.readComponents(); + if (verticesLeft === 0) { // ignoring flags if we started a triangle + assert(0 <= f && f <= 2, 'Unknown type4 flag'); + switch (f) { + case 0: + verticesLeft = 3; + break; + case 1: + ps.push(ps[ps.length - 2], ps[ps.length - 1]); + verticesLeft = 1; + break; + case 2: + ps.push(ps[ps.length - 3], ps[ps.length - 1]); + verticesLeft = 1; + break; + } + operators.push(f); + } + ps.push(coords.length); + coords.push(coord); + colors.push(color); + verticesLeft--; + + reader.align(); + } + + var psPacked = new Int32Array(ps); + + mesh.figures.push({ + type: 'triangles', + coords: psPacked, + colors: psPacked + }); + } + + function decodeType5Shading(mesh, reader, verticesPerRow) { + var coords = mesh.coords; + var colors = mesh.colors; + var ps = []; // not maintaining cs since that will match ps + while (reader.hasData) { + var coord = reader.readCoordinate(); + var color = reader.readComponents(); + ps.push(coords.length); + coords.push(coord); + colors.push(color); + } + + var psPacked = new Int32Array(ps); + + mesh.figures.push({ + type: 'lattice', + coords: psPacked, + colors: psPacked, + verticesPerRow: verticesPerRow + }); + } + + var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3; + var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20; + + var TRIANGLE_DENSITY = 20; // count of triangles per entire mesh bounds + + var getB = (function getBClosure() { + function buildB(count) { + var lut = []; + for (var i = 0; i <= count; i++) { + var t = i / count, t_ = 1 - t; + lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, + 3 * t * t * t_, t * t * t])); + } + return lut; + } + var cache = []; + return function getB(count) { + if (!cache[count]) { + cache[count] = buildB(count); + } + return cache[count]; + }; + })(); + + function buildFigureFromPatch(mesh, index) { + var figure = mesh.figures[index]; + assert(figure.type === 'patch', 'Unexpected patch mesh figure'); + + var coords = mesh.coords, colors = mesh.colors; + var pi = figure.coords; + var ci = figure.colors; + + var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], + coords[pi[12]][0], coords[pi[15]][0]); + var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], + coords[pi[12]][1], coords[pi[15]][1]); + var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], + coords[pi[12]][0], coords[pi[15]][0]); + var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], + coords[pi[12]][1], coords[pi[15]][1]); + var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / + (mesh.bounds[2] - mesh.bounds[0])); + splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, + Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy)); + var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / + (mesh.bounds[3] - mesh.bounds[1])); + splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, + Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy)); + + var verticesPerRow = splitXBy + 1; + var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow); + var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow); + var k = 0; + var cl = new Uint8Array(3), cr = new Uint8Array(3); + var c0 = colors[ci[0]], c1 = colors[ci[1]], + c2 = colors[ci[2]], c3 = colors[ci[3]]; + var bRow = getB(splitYBy), bCol = getB(splitXBy); + for (var row = 0; row <= splitYBy; row++) { + cl[0] = ((c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy) | 0; + cl[1] = ((c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy) | 0; + cl[2] = ((c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy) | 0; + + cr[0] = ((c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy) | 0; + cr[1] = ((c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy) | 0; + cr[2] = ((c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy) | 0; + + for (var col = 0; col <= splitXBy; col++, k++) { + if ((row === 0 || row === splitYBy) && + (col === 0 || col === splitXBy)) { + continue; + } + var x = 0, y = 0; + var q = 0; + for (var i = 0; i <= 3; i++) { + for (var j = 0; j <= 3; j++, q++) { + var m = bRow[row][i] * bCol[col][j]; + x += coords[pi[q]][0] * m; + y += coords[pi[q]][1] * m; + } + } + figureCoords[k] = coords.length; + coords.push([x, y]); + figureColors[k] = colors.length; + var newColor = new Uint8Array(3); + newColor[0] = ((cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy) | 0; + newColor[1] = ((cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy) | 0; + newColor[2] = ((cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy) | 0; + colors.push(newColor); + } + } + figureCoords[0] = pi[0]; + figureColors[0] = ci[0]; + figureCoords[splitXBy] = pi[3]; + figureColors[splitXBy] = ci[1]; + figureCoords[verticesPerRow * splitYBy] = pi[12]; + figureColors[verticesPerRow * splitYBy] = ci[2]; + figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15]; + figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3]; + + mesh.figures[index] = { + type: 'lattice', + coords: figureCoords, + colors: figureColors, + verticesPerRow: verticesPerRow + }; + } + + function decodeType6Shading(mesh, reader) { + // A special case of Type 7. The p11, p12, p21, p22 automatically filled + var coords = mesh.coords; + var colors = mesh.colors; + var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33 + var cs = new Int32Array(4); // c00, c30, c03, c33 + while (reader.hasData) { + var f = reader.readFlag(); + assert(0 <= f && f <= 3, 'Unknown type6 flag'); + var i, ii; + var pi = coords.length; + for (i = 0, ii = (f !== 0 ? 8 : 12); i < ii; i++) { + coords.push(reader.readCoordinate()); + } + var ci = colors.length; + for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) { + colors.push(reader.readComponents()); + } + var tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6; + ps[ 8] = pi + 2; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7; + ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 8; + ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9; + cs[2] = ci + 1; cs[3] = ci + 2; + cs[0] = ci; cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15]; + ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2; + ps[ 8] = pi + 6; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 1; + ps[ 4] = pi + 7; /* calculated below */ ps[ 7] = pi; + ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4; + tmp1 = cs[2]; tmp2 = cs[3]; + cs[2] = ci + 1; cs[3] = ci; + cs[0] = tmp1; cs[1] = tmp2; + break; + case 2: + ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5; + ps[ 8] = ps[11]; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 4; + ps[ 4] = ps[7]; /* calculated below */ ps[ 7] = pi + 3; + ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2; + cs[2] = cs[3]; cs[3] = ci + 1; + cs[0] = cs[1]; cs[1] = ci; + break; + case 3: + ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3]; + ps[ 8] = pi; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7; + ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 6; + ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5; + cs[2] = cs[0]; cs[3] = cs[1]; + cs[0] = ci; cs[1] = ci + 1; + break; + } + // set p11, p12, p21, p22 + ps[5] = coords.length; + coords.push([ + (-4 * coords[ps[0]][0] - coords[ps[15]][0] + + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - + 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, + (-4 * coords[ps[0]][1] - coords[ps[15]][1] + + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - + 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9 + ]); + ps[6] = coords.length; + coords.push([ + (-4 * coords[ps[3]][0] - coords[ps[12]][0] + + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - + 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, + (-4 * coords[ps[3]][1] - coords[ps[12]][1] + + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - + 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9 + ]); + ps[9] = coords.length; + coords.push([ + (-4 * coords[ps[12]][0] - coords[ps[3]][0] + + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - + 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, + (-4 * coords[ps[12]][1] - coords[ps[3]][1] + + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - + 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9 + ]); + ps[10] = coords.length; + coords.push([ + (-4 * coords[ps[15]][0] - coords[ps[0]][0] + + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - + 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, + (-4 * coords[ps[15]][1] - coords[ps[0]][1] + + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - + 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9 + ]); + mesh.figures.push({ + type: 'patch', + coords: new Int32Array(ps), // making copies of ps and cs + colors: new Int32Array(cs) + }); + } + } + + function decodeType7Shading(mesh, reader) { + var coords = mesh.coords; + var colors = mesh.colors; + var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33 + var cs = new Int32Array(4); // c00, c30, c03, c33 + while (reader.hasData) { + var f = reader.readFlag(); + assert(0 <= f && f <= 3, 'Unknown type7 flag'); + var i, ii; + var pi = coords.length; + for (i = 0, ii = (f !== 0 ? 12 : 16); i < ii; i++) { + coords.push(reader.readCoordinate()); + } + var ci = colors.length; + for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) { + colors.push(reader.readComponents()); + } + var tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6; + ps[ 8] = pi + 2; ps[ 9] = pi + 13; ps[10] = pi + 14; ps[11] = pi + 7; + ps[ 4] = pi + 1; ps[ 5] = pi + 12; ps[ 6] = pi + 15; ps[ 7] = pi + 8; + ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9; + cs[2] = ci + 1; cs[3] = ci + 2; + cs[0] = ci; cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15]; + ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2; + ps[ 8] = pi + 6; ps[ 9] = pi + 11; ps[10] = pi + 10; ps[11] = pi + 1; + ps[ 4] = pi + 7; ps[ 5] = pi + 8; ps[ 6] = pi + 9; ps[ 7] = pi; + ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4; + tmp1 = cs[2]; tmp2 = cs[3]; + cs[2] = ci + 1; cs[3] = ci; + cs[0] = tmp1; cs[1] = tmp2; + break; + case 2: + ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5; + ps[ 8] = ps[11]; ps[ 9] = pi + 8; ps[10] = pi + 11; ps[11] = pi + 4; + ps[ 4] = ps[7]; ps[ 5] = pi + 9; ps[ 6] = pi + 10; ps[ 7] = pi + 3; + ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2; + cs[2] = cs[3]; cs[3] = ci + 1; + cs[0] = cs[1]; cs[1] = ci; + break; + case 3: + ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3]; + ps[ 8] = pi; ps[ 9] = pi + 9; ps[10] = pi + 8; ps[11] = pi + 7; + ps[ 4] = pi + 1; ps[ 5] = pi + 10; ps[ 6] = pi + 11; ps[ 7] = pi + 6; + ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5; + cs[2] = cs[0]; cs[3] = cs[1]; + cs[0] = ci; cs[1] = ci + 1; + break; + } + mesh.figures.push({ + type: 'patch', + coords: new Int32Array(ps), // making copies of ps and cs + colors: new Int32Array(cs) + }); + } + } + + function updateBounds(mesh) { + var minX = mesh.coords[0][0], minY = mesh.coords[0][1], + maxX = minX, maxY = minY; + for (var i = 1, ii = mesh.coords.length; i < ii; i++) { + var x = mesh.coords[i][0], y = mesh.coords[i][1]; + minX = minX > x ? x : minX; + minY = minY > y ? y : minY; + maxX = maxX < x ? x : maxX; + maxY = maxY < y ? y : maxY; + } + mesh.bounds = [minX, minY, maxX, maxY]; + } + + function packData(mesh) { + var i, ii, j, jj; + + var coords = mesh.coords; + var coordsPacked = new Float32Array(coords.length * 2); + for (i = 0, j = 0, ii = coords.length; i < ii; i++) { + var xy = coords[i]; + coordsPacked[j++] = xy[0]; + coordsPacked[j++] = xy[1]; + } + mesh.coords = coordsPacked; + + var colors = mesh.colors; + var colorsPacked = new Uint8Array(colors.length * 3); + for (i = 0, j = 0, ii = colors.length; i < ii; i++) { + var c = colors[i]; + colorsPacked[j++] = c[0]; + colorsPacked[j++] = c[1]; + colorsPacked[j++] = c[2]; + } + mesh.colors = colorsPacked; + + var figures = mesh.figures; + for (i = 0, ii = figures.length; i < ii; i++) { + var figure = figures[i], ps = figure.coords, cs = figure.colors; + for (j = 0, jj = ps.length; j < jj; j++) { + ps[j] *= 2; + cs[j] *= 3; + } + } + } + + function Mesh(stream, matrix, xref, res) { + assert(isStream(stream), 'Mesh data is not a stream'); + var dict = stream.dict; + this.matrix = matrix; + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + this.bbox = dict.get('BBox'); + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + this.cs = cs; + this.background = dict.has('Background') ? + cs.getRgb(dict.get('Background'), 0) : null; + + var fnObj = dict.get('Function'); + var fn = fnObj ? PDFFunction.parseArray(xref, fnObj) : null; + + this.coords = []; + this.colors = []; + this.figures = []; + + var decodeContext = { + bitsPerCoordinate: dict.get('BitsPerCoordinate'), + bitsPerComponent: dict.get('BitsPerComponent'), + bitsPerFlag: dict.get('BitsPerFlag'), + decode: dict.get('Decode'), + colorFn: fn, + colorSpace: cs, + numComps: fn ? 1 : cs.numComps + }; + var reader = new MeshStreamReader(stream, decodeContext); + + var patchMesh = false; + switch (this.shadingType) { + case PatternType.FREE_FORM_MESH: + decodeType4Shading(this, reader); + break; + case PatternType.LATTICE_FORM_MESH: + var verticesPerRow = dict.get('VerticesPerRow') | 0; + assert(verticesPerRow >= 2, 'Invalid VerticesPerRow'); + decodeType5Shading(this, reader, verticesPerRow); + break; + case PatternType.COONS_PATCH_MESH: + decodeType6Shading(this, reader); + patchMesh = true; + break; + case PatternType.TENSOR_PATCH_MESH: + decodeType7Shading(this, reader); + patchMesh = true; + break; + default: + error('Unsupported mesh type.'); + break; + } + + if (patchMesh) { + // dirty bounds calculation for determining, how dense shall be triangles + updateBounds(this); + for (var i = 0, ii = this.figures.length; i < ii; i++) { + buildFigureFromPatch(this, i); + } + } + // calculate bounds + updateBounds(this); + + packData(this); + } + + Mesh.prototype = { + getIR: function Mesh_getIR() { + return ['Mesh', this.shadingType, this.coords, this.colors, this.figures, + this.bounds, this.matrix, this.bbox, this.background]; + } + }; + + return Mesh; +})(); + +Shadings.Dummy = (function DummyClosure() { + function Dummy() { + this.type = 'Pattern'; + } + + Dummy.prototype = { + getIR: function Dummy_getIR() { + return ['Dummy']; + } + }; + return Dummy; +})(); + +function getTilingPatternIR(operatorList, dict, args) { + var matrix = dict.get('Matrix'); + var bbox = dict.get('BBox'); + var xstep = dict.get('XStep'); + var ystep = dict.get('YStep'); + var paintType = dict.get('PaintType'); + var tilingType = dict.get('TilingType'); + + return [ + 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, + paintType, tilingType + ]; +} + + +var PartialEvaluator = (function PartialEvaluatorClosure() { + function PartialEvaluator(pdfManager, xref, handler, pageIndex, + uniquePrefix, idCounters, fontCache) { + this.pdfManager = pdfManager; + this.xref = xref; + this.handler = handler; + this.pageIndex = pageIndex; + this.uniquePrefix = uniquePrefix; + this.idCounters = idCounters; + this.fontCache = fontCache; + } + + // Trying to minimize Date.now() usage and check every 100 time + var TIME_SLOT_DURATION_MS = 20; + var CHECK_TIME_EVERY = 100; + function TimeSlotManager() { + this.reset(); + } + TimeSlotManager.prototype = { + check: function TimeSlotManager_check() { + if (++this.checked < CHECK_TIME_EVERY) { + return false; + } + this.checked = 0; + return this.endTime <= Date.now(); + }, + reset: function TimeSlotManager_reset() { + this.endTime = Date.now() + TIME_SLOT_DURATION_MS; + this.checked = 0; + } + }; + + var deferred = Promise.resolve(); + + var TILING_PATTERN = 1, SHADING_PATTERN = 2; + + PartialEvaluator.prototype = { + hasBlendModes: function PartialEvaluator_hasBlendModes(resources) { + if (!isDict(resources)) { + return false; + } + + var processed = Object.create(null); + if (resources.objId) { + processed[resources.objId] = true; + } + + var nodes = [resources]; + while (nodes.length) { + var key; + var node = nodes.shift(); + // First check the current resources for blend modes. + var graphicStates = node.get('ExtGState'); + if (isDict(graphicStates)) { + graphicStates = graphicStates.getAll(); + for (key in graphicStates) { + var graphicState = graphicStates[key]; + var bm = graphicState['BM']; + if (isName(bm) && bm.name !== 'Normal') { + return true; + } + } + } + // Descend into the XObjects to look for more resources and blend modes. + var xObjects = node.get('XObject'); + if (!isDict(xObjects)) { + continue; + } + xObjects = xObjects.getAll(); + for (key in xObjects) { + var xObject = xObjects[key]; + if (!isStream(xObject)) { + continue; + } + if (xObject.dict.objId) { + if (processed[xObject.dict.objId]) { + // stream has objId and is processed already + continue; + } + processed[xObject.dict.objId] = true; + } + var xResources = xObject.dict.get('Resources'); + // Checking objId to detect an infinite loop. + if (isDict(xResources) && + (!xResources.objId || !processed[xResources.objId])) { + nodes.push(xResources); + if (xResources.objId) { + processed[xResources.objId] = true; + } + } + } + } + return false; + }, + + buildFormXObject: function PartialEvaluator_buildFormXObject(resources, + xobj, smask, + operatorList, + initialState) { + var matrix = xobj.dict.get('Matrix'); + var bbox = xobj.dict.get('BBox'); + var group = xobj.dict.get('Group'); + if (group) { + var groupOptions = { + matrix: matrix, + bbox: bbox, + smask: smask, + isolated: false, + knockout: false + }; + + var groupSubtype = group.get('S'); + var colorSpace; + if (isName(groupSubtype) && groupSubtype.name === 'Transparency') { + groupOptions.isolated = (group.get('I') || false); + groupOptions.knockout = (group.get('K') || false); + colorSpace = (group.has('CS') ? + ColorSpace.parse(group.get('CS'), this.xref, resources) : null); + } + + if (smask && smask.backdrop) { + colorSpace = colorSpace || ColorSpace.singletons.rgb; + smask.backdrop = colorSpace.getRgb(smask.backdrop, 0); + } + + operatorList.addOp(OPS.beginGroup, [groupOptions]); + } + + operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]); + + return this.getOperatorList(xobj, + (xobj.dict.get('Resources') || resources), operatorList, initialState). + then(function () { + operatorList.addOp(OPS.paintFormXObjectEnd, []); + + if (group) { + operatorList.addOp(OPS.endGroup, [groupOptions]); + } + }); + }, + + buildPaintImageXObject: + function PartialEvaluator_buildPaintImageXObject(resources, image, + inline, operatorList, + cacheKey, imageCache) { + var self = this; + var dict = image.dict; + var w = dict.get('Width', 'W'); + var h = dict.get('Height', 'H'); + + if (!(w && isNum(w)) || !(h && isNum(h))) { + warn('Image dimensions are missing, or not numbers.'); + return; + } + if (PDFJS.maxImageSize !== -1 && w * h > PDFJS.maxImageSize) { + warn('Image exceeded maximum allowed size and was removed.'); + return; + } + + var imageMask = (dict.get('ImageMask', 'IM') || false); + var imgData, args; + if (imageMask) { + // This depends on a tmpCanvas being filled with the + // current fillStyle, such that processing the pixel + // data can't be done here. Instead of creating a + // complete PDFImage, only read the information needed + // for later. + + var width = dict.get('Width', 'W'); + var height = dict.get('Height', 'H'); + var bitStrideLength = (width + 7) >> 3; + var imgArray = image.getBytes(bitStrideLength * height); + var decode = dict.get('Decode', 'D'); + var inverseDecode = (!!decode && decode[0] > 0); + + imgData = PDFImage.createMask(imgArray, width, height, + image instanceof DecodeStream, + inverseDecode); + imgData.cached = true; + args = [imgData]; + operatorList.addOp(OPS.paintImageMaskXObject, args); + if (cacheKey) { + imageCache[cacheKey] = { + fn: OPS.paintImageMaskXObject, + args: args + }; + } + return; + } + + var softMask = (dict.get('SMask', 'SM') || false); + var mask = (dict.get('Mask') || false); + + var SMALL_IMAGE_DIMENSIONS = 200; + // Inlining small images into the queue as RGB data + if (inline && !softMask && !mask && !(image instanceof JpegStream) && + (w + h) < SMALL_IMAGE_DIMENSIONS) { + var imageObj = new PDFImage(this.xref, resources, image, + inline, null, null); + // We force the use of RGBA_32BPP images here, because we can't handle + // any other kind. + imgData = imageObj.createImageData(/* forceRGBA = */ true); + operatorList.addOp(OPS.paintInlineImageXObject, [imgData]); + return; + } + + // If there is no imageMask, create the PDFImage and a lot + // of image processing can be done here. + var uniquePrefix = (this.uniquePrefix || ''); + var objId = 'img_' + uniquePrefix + (++this.idCounters.obj); + operatorList.addDependency(objId); + args = [objId, w, h]; + + if (!softMask && !mask && image instanceof JpegStream && + image.isNativelySupported(this.xref, resources)) { + // These JPEGs don't need any more processing so we can just send it. + operatorList.addOp(OPS.paintJpegXObject, args); + this.handler.send('obj', + [objId, this.pageIndex, 'JpegStream', image.getIR()]); + return; + } + + PDFImage.buildImage(self.handler, self.xref, resources, image, inline). + then(function(imageObj) { + var imgData = imageObj.createImageData(/* forceRGBA = */ false); + self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData], + [imgData.data.buffer]); + }).then(undefined, function (reason) { + warn('Unable to decode image: ' + reason); + self.handler.send('obj', [objId, self.pageIndex, 'Image', null]); + }); + + operatorList.addOp(OPS.paintImageXObject, args); + if (cacheKey) { + imageCache[cacheKey] = { + fn: OPS.paintImageXObject, + args: args + }; + } + }, + + handleSMask: function PartialEvaluator_handleSmask(smask, resources, + operatorList, + stateManager) { + var smaskContent = smask.get('G'); + var smaskOptions = { + subtype: smask.get('S').name, + backdrop: smask.get('BC') + }; + return this.buildFormXObject(resources, smaskContent, smaskOptions, + operatorList, stateManager.state.clone()); + }, + + handleTilingType: + function PartialEvaluator_handleTilingType(fn, args, resources, + pattern, patternDict, + operatorList) { + // Create an IR of the pattern code. + var tilingOpList = new OperatorList(); + return this.getOperatorList(pattern, + (patternDict.get('Resources') || resources), tilingOpList). + then(function () { + // Add the dependencies to the parent operator list so they are + // resolved before sub operator list is executed synchronously. + operatorList.addDependencies(tilingOpList.dependencies); + operatorList.addOp(fn, getTilingPatternIR({ + fnArray: tilingOpList.fnArray, + argsArray: tilingOpList.argsArray + }, patternDict, args)); + }); + }, + + handleSetFont: + function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, + operatorList, state) { + // TODO(mack): Not needed? + var fontName; + if (fontArgs) { + fontArgs = fontArgs.slice(); + fontName = fontArgs[0].name; + } + + var self = this; + return this.loadFont(fontName, fontRef, this.xref, resources).then( + function (translated) { + if (!translated.font.isType3Font) { + return translated; + } + return translated.loadType3Data(self, resources, operatorList).then( + function () { + return translated; + }); + }).then(function (translated) { + state.font = translated.font; + translated.send(self.handler); + return translated.loadedName; + }); + }, + + handleText: function PartialEvaluator_handleText(chars, state) { + var font = state.font; + var glyphs = font.charsToGlyphs(chars); + var isAddToPathSet = !!(state.textRenderingMode & + TextRenderingMode.ADD_TO_PATH_FLAG); + if (font.data && (isAddToPathSet || PDFJS.disableFontFace)) { + var buildPath = function (fontChar) { + if (!font.renderer.hasBuiltPath(fontChar)) { + var path = font.renderer.getPathJs(fontChar); + this.handler.send('commonobj', [ + font.loadedName + '_path_' + fontChar, + 'FontPath', + path + ]); + } + }.bind(this); + + for (var i = 0, ii = glyphs.length; i < ii; i++) { + var glyph = glyphs[i]; + if (glyph === null) { + continue; + } + buildPath(glyph.fontChar); + + // If the glyph has an accent we need to build a path for its + // fontChar too, otherwise CanvasGraphics_paintChar will fail. + var accent = glyph.accent; + if (accent && accent.fontChar) { + buildPath(accent.fontChar); + } + } + } + + return glyphs; + }, + + setGState: function PartialEvaluator_setGState(resources, gState, + operatorList, xref, + stateManager) { + // This array holds the converted/processed state data. + var gStateObj = []; + var gStateMap = gState.map; + var self = this; + var promise = Promise.resolve(); + for (var key in gStateMap) { + var value = gStateMap[key]; + switch (key) { + case 'Type': + break; + case 'LW': + case 'LC': + case 'LJ': + case 'ML': + case 'D': + case 'RI': + case 'FL': + case 'CA': + case 'ca': + gStateObj.push([key, value]); + break; + case 'Font': + promise = promise.then(function () { + return self.handleSetFont(resources, null, value[0], + operatorList, stateManager.state). + then(function (loadedName) { + operatorList.addDependency(loadedName); + gStateObj.push([key, [loadedName, value[1]]]); + }); + }); + break; + case 'BM': + gStateObj.push([key, value]); + break; + case 'SMask': + if (isName(value) && value.name === 'None') { + gStateObj.push([key, false]); + break; + } + var dict = xref.fetchIfRef(value); + if (isDict(dict)) { + promise = promise.then(function () { + return self.handleSMask(dict, resources, operatorList, + stateManager); + }); + gStateObj.push([key, true]); + } else { + warn('Unsupported SMask type'); + } + + break; + // Only generate info log messages for the following since + // they are unlikely to have a big impact on the rendering. + case 'OP': + case 'op': + case 'OPM': + case 'BG': + case 'BG2': + case 'UCR': + case 'UCR2': + case 'TR': + case 'TR2': + case 'HT': + case 'SM': + case 'SA': + case 'AIS': + case 'TK': + // TODO implement these operators. + info('graphic state operator ' + key); + break; + default: + info('Unknown graphic state operator ' + key); + break; + } + } + return promise.then(function () { + if (gStateObj.length >= 0) { + operatorList.addOp(OPS.setGState, [gStateObj]); + } + }); + }, + + loadFont: function PartialEvaluator_loadFont(fontName, font, xref, + resources) { + + function errorFont() { + return Promise.resolve(new TranslatedFont('g_font_error', + new ErrorFont('Font ' + fontName + ' is not available'), font)); + } + var fontRef; + if (font) { // Loading by ref. + assert(isRef(font)); + fontRef = font; + } else { // Loading by name. + var fontRes = resources.get('Font'); + if (fontRes) { + fontRef = fontRes.getRaw(fontName); + } else { + warn('fontRes not available'); + return errorFont(); + } + } + if (!fontRef) { + warn('fontRef not available'); + return errorFont(); + } + + if (this.fontCache.has(fontRef)) { + return this.fontCache.get(fontRef); + } + + font = xref.fetchIfRef(fontRef); + if (!isDict(font)) { + return errorFont(); + } + + // We are holding font.translated references just for fontRef that are not + // dictionaries (Dict). See explanation below. + if (font.translated) { + return font.translated; + } + + var fontCapability = createPromiseCapability(); + + var preEvaluatedFont = this.preEvaluateFont(font, xref); + var descriptor = preEvaluatedFont.descriptor; + var fontID = fontRef.num + '_' + fontRef.gen; + if (isDict(descriptor)) { + if (!descriptor.fontAliases) { + descriptor.fontAliases = Object.create(null); + } + + var fontAliases = descriptor.fontAliases; + var hash = preEvaluatedFont.hash; + if (fontAliases[hash]) { + var aliasFontRef = fontAliases[hash].aliasRef; + if (aliasFontRef && this.fontCache.has(aliasFontRef)) { + this.fontCache.putAlias(fontRef, aliasFontRef); + return this.fontCache.get(fontRef); + } + } + + if (!fontAliases[hash]) { + fontAliases[hash] = { + fontID: Font.getFontID() + }; + } + + fontAliases[hash].aliasRef = fontRef; + fontID = fontAliases[hash].fontID; + } + + // Workaround for bad PDF generators that don't reference fonts + // properly, i.e. by not using an object identifier. + // Check if the fontRef is a Dict (as opposed to a standard object), + // in which case we don't cache the font and instead reference it by + // fontName in font.loadedName below. + var fontRefIsDict = isDict(fontRef); + if (!fontRefIsDict) { + this.fontCache.put(fontRef, fontCapability.promise); + } + + // Keep track of each font we translated so the caller can + // load them asynchronously before calling display on a page. + font.loadedName = 'g_font_' + (fontRefIsDict ? + fontName.replace(/\W/g, '') : fontID); + + font.translated = fontCapability.promise; + + // TODO move promises into translate font + var translatedPromise; + try { + translatedPromise = Promise.resolve( + this.translateFont(preEvaluatedFont, xref)); + } catch (e) { + translatedPromise = Promise.reject(e); + } + + translatedPromise.then(function (translatedFont) { + if (translatedFont.fontType !== undefined) { + var xrefFontStats = xref.stats.fontTypes; + xrefFontStats[translatedFont.fontType] = true; + } + + fontCapability.resolve(new TranslatedFont(font.loadedName, + translatedFont, font)); + }, function (reason) { + // TODO fontCapability.reject? + UnsupportedManager.notify(UNSUPPORTED_FEATURES.font); + + try { + // error, but it's still nice to have font type reported + var descriptor = preEvaluatedFont.descriptor; + var fontFile3 = descriptor && descriptor.get('FontFile3'); + var subtype = fontFile3 && fontFile3.get('Subtype'); + var fontType = getFontType(preEvaluatedFont.type, + subtype && subtype.name); + var xrefFontStats = xref.stats.fontTypes; + xrefFontStats[fontType] = true; + } catch (ex) { } + + fontCapability.resolve(new TranslatedFont(font.loadedName, + new ErrorFont(reason instanceof Error ? reason.message : reason), + font)); + }); + return fontCapability.promise; + }, + + buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) { + var lastIndex = operatorList.length - 1; + if (!args) { + args = []; + } + if (lastIndex < 0 || + operatorList.fnArray[lastIndex] !== OPS.constructPath) { + operatorList.addOp(OPS.constructPath, [[fn], args]); + } else { + var opArgs = operatorList.argsArray[lastIndex]; + opArgs[0].push(fn); + Array.prototype.push.apply(opArgs[1], args); + } + }, + + handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args, + cs, patterns, resources, xref) { + // compile tiling patterns + var patternName = args[args.length - 1]; + // SCN/scn applies patterns along with normal colors + var pattern; + if (isName(patternName) && + (pattern = patterns.get(patternName.name))) { + var dict = (isStream(pattern) ? pattern.dict : pattern); + var typeNum = dict.get('PatternType'); + + if (typeNum === TILING_PATTERN) { + var color = cs.base ? cs.base.getRgb(args, 0) : null; + return this.handleTilingType(fn, color, resources, pattern, + dict, operatorList); + } else if (typeNum === SHADING_PATTERN) { + var shading = dict.get('Shading'); + var matrix = dict.get('Matrix'); + pattern = Pattern.parseShading(shading, matrix, xref, resources); + operatorList.addOp(fn, pattern.getIR()); + return Promise.resolve(); + } else { + return Promise.reject('Unknown PatternType: ' + typeNum); + } + } + // TODO shall we fail here? + operatorList.addOp(fn, args); + return Promise.resolve(); + }, + + getOperatorList: function PartialEvaluator_getOperatorList(stream, + resources, + operatorList, + initialState) { + + var self = this; + var xref = this.xref; + var imageCache = {}; + + assert(operatorList); + + resources = (resources || Dict.empty); + var xobjs = (resources.get('XObject') || Dict.empty); + var patterns = (resources.get('Pattern') || Dict.empty); + var stateManager = new StateManager(initialState || new EvalState()); + var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + var timeSlotManager = new TimeSlotManager(); + + return new Promise(function next(resolve, reject) { + timeSlotManager.reset(); + var stop, operation = {}, i, ii, cs; + while (!(stop = timeSlotManager.check())) { + // The arguments parsed by read() are used beyond this loop, so we + // cannot reuse the same array on each iteration. Therefore we pass + // in |null| as the initial value (see the comment on + // EvaluatorPreprocessor_read() for why). + operation.args = null; + if (!(preprocessor.read(operation))) { + break; + } + var args = operation.args; + var fn = operation.fn; + + switch (fn | 0) { + case OPS.paintXObject: + if (args[0].code) { + break; + } + // eagerly compile XForm objects + var name = args[0].name; + if (imageCache[name] !== undefined) { + operatorList.addOp(imageCache[name].fn, imageCache[name].args); + args = null; + continue; + } + + var xobj = xobjs.get(name); + if (xobj) { + assert(isStream(xobj), 'XObject should be a stream'); + + var type = xobj.dict.get('Subtype'); + assert(isName(type), + 'XObject should have a Name subtype'); + + if (type.name === 'Form') { + stateManager.save(); + return self.buildFormXObject(resources, xobj, null, + operatorList, + stateManager.state.clone()). + then(function () { + stateManager.restore(); + next(resolve, reject); + }, reject); + } else if (type.name === 'Image') { + self.buildPaintImageXObject(resources, xobj, false, + operatorList, name, imageCache); + args = null; + continue; + } else if (type.name === 'PS') { + // PostScript XObjects are unused when viewing documents. + // See section 4.7.1 of Adobe's PDF reference. + info('Ignored XObject subtype PS'); + continue; + } else { + error('Unhandled XObject subtype ' + type.name); + } + } + break; + case OPS.setFont: + var fontSize = args[1]; + // eagerly collect all fonts + return self.handleSetFont(resources, args, null, + operatorList, stateManager.state). + then(function (loadedName) { + operatorList.addDependency(loadedName); + operatorList.addOp(OPS.setFont, [loadedName, fontSize]); + next(resolve, reject); + }, reject); + case OPS.endInlineImage: + var cacheKey = args[0].cacheKey; + if (cacheKey) { + var cacheEntry = imageCache[cacheKey]; + if (cacheEntry !== undefined) { + operatorList.addOp(cacheEntry.fn, cacheEntry.args); + args = null; + continue; + } + } + self.buildPaintImageXObject(resources, args[0], true, + operatorList, cacheKey, imageCache); + args = null; + continue; + case OPS.showText: + args[0] = self.handleText(args[0], stateManager.state); + break; + case OPS.showSpacedText: + var arr = args[0]; + var combinedGlyphs = []; + var arrLength = arr.length; + for (i = 0; i < arrLength; ++i) { + var arrItem = arr[i]; + if (isString(arrItem)) { + Array.prototype.push.apply(combinedGlyphs, + self.handleText(arrItem, stateManager.state)); + } else if (isNum(arrItem)) { + combinedGlyphs.push(arrItem); + } + } + args[0] = combinedGlyphs; + fn = OPS.showText; + break; + case OPS.nextLineShowText: + operatorList.addOp(OPS.nextLine); + args[0] = self.handleText(args[0], stateManager.state); + fn = OPS.showText; + break; + case OPS.nextLineSetSpacingShowText: + operatorList.addOp(OPS.nextLine); + operatorList.addOp(OPS.setWordSpacing, [args.shift()]); + operatorList.addOp(OPS.setCharSpacing, [args.shift()]); + args[0] = self.handleText(args[0], stateManager.state); + fn = OPS.showText; + break; + case OPS.setTextRenderingMode: + stateManager.state.textRenderingMode = args[0]; + break; + + case OPS.setFillColorSpace: + stateManager.state.fillColorSpace = + ColorSpace.parse(args[0], xref, resources); + continue; + case OPS.setStrokeColorSpace: + stateManager.state.strokeColorSpace = + ColorSpace.parse(args[0], xref, resources); + continue; + case OPS.setFillColor: + cs = stateManager.state.fillColorSpace; + args = cs.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeColor: + cs = stateManager.state.strokeColorSpace; + args = cs.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillGray: + stateManager.state.fillColorSpace = ColorSpace.singletons.gray; + args = ColorSpace.singletons.gray.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeGray: + stateManager.state.strokeColorSpace = ColorSpace.singletons.gray; + args = ColorSpace.singletons.gray.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillCMYKColor: + stateManager.state.fillColorSpace = ColorSpace.singletons.cmyk; + args = ColorSpace.singletons.cmyk.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeCMYKColor: + stateManager.state.strokeColorSpace = ColorSpace.singletons.cmyk; + args = ColorSpace.singletons.cmyk.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillRGBColor: + stateManager.state.fillColorSpace = ColorSpace.singletons.rgb; + args = ColorSpace.singletons.rgb.getRgb(args, 0); + break; + case OPS.setStrokeRGBColor: + stateManager.state.strokeColorSpace = ColorSpace.singletons.rgb; + args = ColorSpace.singletons.rgb.getRgb(args, 0); + break; + case OPS.setFillColorN: + cs = stateManager.state.fillColorSpace; + if (cs.name === 'Pattern') { + return self.handleColorN(operatorList, OPS.setFillColorN, + args, cs, patterns, resources, xref).then(function() { + next(resolve, reject); + }, reject); + } + args = cs.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeColorN: + cs = stateManager.state.strokeColorSpace; + if (cs.name === 'Pattern') { + return self.handleColorN(operatorList, OPS.setStrokeColorN, + args, cs, patterns, resources, xref).then(function() { + next(resolve, reject); + }, reject); + } + args = cs.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + + case OPS.shadingFill: + var shadingRes = resources.get('Shading'); + if (!shadingRes) { + error('No shading resource found'); + } + + var shading = shadingRes.get(args[0].name); + if (!shading) { + error('No shading object found'); + } + + var shadingFill = Pattern.parseShading(shading, null, xref, + resources); + var patternIR = shadingFill.getIR(); + args = [patternIR]; + fn = OPS.shadingFill; + break; + case OPS.setGState: + var dictName = args[0]; + var extGState = resources.get('ExtGState'); + + if (!isDict(extGState) || !extGState.has(dictName.name)) { + break; + } + + var gState = extGState.get(dictName.name); + return self.setGState(resources, gState, operatorList, xref, + stateManager).then(function() { + next(resolve, reject); + }, reject); + case OPS.moveTo: + case OPS.lineTo: + case OPS.curveTo: + case OPS.curveTo2: + case OPS.curveTo3: + case OPS.closePath: + self.buildPath(operatorList, fn, args); + continue; + case OPS.rectangle: + self.buildPath(operatorList, fn, args); + continue; + } + operatorList.addOp(fn, args); + } + if (stop) { + deferred.then(function () { + next(resolve, reject); + }); + return; + } + // Some PDFs don't close all restores inside object/form. + // Closing those for them. + for (i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) { + operatorList.addOp(OPS.restore, []); + } + resolve(); + }); + }, + + getTextContent: function PartialEvaluator_getTextContent(stream, resources, + stateManager) { + + stateManager = (stateManager || new StateManager(new TextState())); + + var textContent = { + items: [], + styles: Object.create(null) + }; + var bidiTexts = textContent.items; + var SPACE_FACTOR = 0.3; + var MULTI_SPACE_FACTOR = 1.5; + + var self = this; + var xref = this.xref; + + resources = (xref.fetchIfRef(resources) || Dict.empty); + + // The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd. + var xobjs = null; + var xobjsCache = {}; + + var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + + var textState; + + function newTextChunk() { + var font = textState.font; + if (!(font.loadedName in textContent.styles)) { + textContent.styles[font.loadedName] = { + fontFamily: font.fallbackName, + ascent: font.ascent, + descent: font.descent, + vertical: font.vertical + }; + } + return { + // |str| is initially an array which we push individual chars to, and + // then runBidi() overwrites it with the final string. + str: [], + dir: null, + width: 0, + height: 0, + transform: null, + fontName: font.loadedName + }; + } + + function runBidi(textChunk) { + var str = textChunk.str.join(''); + var bidiResult = PDFJS.bidi(str, -1, textState.font.vertical); + textChunk.str = bidiResult.str; + textChunk.dir = bidiResult.dir; + return textChunk; + } + + function handleSetFont(fontName, fontRef) { + return self.loadFont(fontName, fontRef, xref, resources). + then(function (translated) { + textState.font = translated.font; + textState.fontMatrix = translated.font.fontMatrix || + FONT_IDENTITY_MATRIX; + }); + } + + function buildTextGeometry(chars, textChunk) { + var font = textState.font; + textChunk = textChunk || newTextChunk(); + if (!textChunk.transform) { + // 9.4.4 Text Space Details + var tsm = [textState.fontSize * textState.textHScale, 0, + 0, textState.fontSize, + 0, textState.textRise]; + + if (font.isType3Font && + textState.fontMatrix !== FONT_IDENTITY_MATRIX && + textState.fontSize === 1) { + var glyphHeight = font.bbox[3] - font.bbox[1]; + if (glyphHeight > 0) { + glyphHeight = glyphHeight * textState.fontMatrix[3]; + tsm[3] *= glyphHeight; + } + } + + var trm = textChunk.transform = Util.transform(textState.ctm, + Util.transform(textState.textMatrix, tsm)); + if (!font.vertical) { + textChunk.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]); + } else { + textChunk.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]); + } + } + var width = 0; + var height = 0; + var glyphs = font.charsToGlyphs(chars); + var defaultVMetrics = font.defaultVMetrics; + for (var i = 0; i < glyphs.length; i++) { + var glyph = glyphs[i]; + if (!glyph) { // Previous glyph was a space. + width += textState.wordSpacing * textState.textHScale; + continue; + } + var vMetricX = null; + var vMetricY = null; + var glyphWidth = null; + if (font.vertical) { + if (glyph.vmetric) { + glyphWidth = glyph.vmetric[0]; + vMetricX = glyph.vmetric[1]; + vMetricY = glyph.vmetric[2]; + } else { + glyphWidth = glyph.width; + vMetricX = glyph.width * 0.5; + vMetricY = defaultVMetrics[2]; + } + } else { + glyphWidth = glyph.width; + } + + var glyphUnicode = glyph.unicode; + if (NormalizedUnicodes[glyphUnicode] !== undefined) { + glyphUnicode = NormalizedUnicodes[glyphUnicode]; + } + glyphUnicode = reverseIfRtl(glyphUnicode); + + // The following will calculate the x and y of the individual glyphs. + // if (font.vertical) { + // tsm[4] -= vMetricX * Math.abs(textState.fontSize) * + // textState.fontMatrix[0]; + // tsm[5] -= vMetricY * textState.fontSize * + // textState.fontMatrix[0]; + // } + // var trm = Util.transform(textState.textMatrix, tsm); + // var pt = Util.applyTransform([trm[4], trm[5]], textState.ctm); + // var x = pt[0]; + // var y = pt[1]; + + var charSpacing = 0; + if (textChunk.str.length > 0) { + // Apply char spacing only when there are chars. + // As a result there is only spacing between glyphs. + charSpacing = textState.charSpacing; + } + + var tx = 0; + var ty = 0; + if (!font.vertical) { + var w0 = glyphWidth * textState.fontMatrix[0]; + tx = (w0 * textState.fontSize + charSpacing) * + textState.textHScale; + width += tx; + } else { + var w1 = glyphWidth * textState.fontMatrix[0]; + ty = w1 * textState.fontSize + charSpacing; + height += ty; + } + textState.translateTextMatrix(tx, ty); + + textChunk.str.push(glyphUnicode); + } + + var a = textState.textLineMatrix[0]; + var b = textState.textLineMatrix[1]; + var scaleLineX = Math.sqrt(a * a + b * b); + a = textState.ctm[0]; + b = textState.ctm[1]; + var scaleCtmX = Math.sqrt(a * a + b * b); + if (!font.vertical) { + textChunk.width += width * scaleCtmX * scaleLineX; + } else { + textChunk.height += Math.abs(height * scaleCtmX * scaleLineX); + } + return textChunk; + } + + var timeSlotManager = new TimeSlotManager(); + + return new Promise(function next(resolve, reject) { + timeSlotManager.reset(); + var stop, operation = {}, args = []; + while (!(stop = timeSlotManager.check())) { + // The arguments parsed by read() are not used beyond this loop, so + // we can reuse the same array on every iteration, thus avoiding + // unnecessary allocations. + args.length = 0; + operation.args = args; + if (!(preprocessor.read(operation))) { + break; + } + textState = stateManager.state; + var fn = operation.fn; + args = operation.args; + + switch (fn | 0) { + case OPS.setFont: + textState.fontSize = args[1]; + return handleSetFont(args[0].name).then(function() { + next(resolve, reject); + }, reject); + case OPS.setTextRise: + textState.textRise = args[0]; + break; + case OPS.setHScale: + textState.textHScale = args[0] / 100; + break; + case OPS.setLeading: + textState.leading = args[0]; + break; + case OPS.moveText: + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS.setLeadingMoveText: + textState.leading = -args[1]; + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS.nextLine: + textState.carriageReturn(); + break; + case OPS.setTextMatrix: + textState.setTextMatrix(args[0], args[1], args[2], args[3], + args[4], args[5]); + textState.setTextLineMatrix(args[0], args[1], args[2], args[3], + args[4], args[5]); + break; + case OPS.setCharSpacing: + textState.charSpacing = args[0]; + break; + case OPS.setWordSpacing: + textState.wordSpacing = args[0]; + break; + case OPS.beginText: + textState.textMatrix = IDENTITY_MATRIX.slice(); + textState.textLineMatrix = IDENTITY_MATRIX.slice(); + break; + case OPS.showSpacedText: + var items = args[0]; + var textChunk = newTextChunk(); + var offset; + for (var j = 0, jj = items.length; j < jj; j++) { + if (typeof items[j] === 'string') { + buildTextGeometry(items[j], textChunk); + } else { + var val = items[j] / 1000; + if (!textState.font.vertical) { + offset = -val * textState.fontSize * textState.textHScale * + textState.textMatrix[0]; + textState.translateTextMatrix(offset, 0); + textChunk.width += offset; + } else { + offset = -val * textState.fontSize * + textState.textMatrix[3]; + textState.translateTextMatrix(0, offset); + textChunk.height += offset; + } + if (items[j] < 0 && textState.font.spaceWidth > 0) { + var fakeSpaces = -items[j] / textState.font.spaceWidth; + if (fakeSpaces > MULTI_SPACE_FACTOR) { + fakeSpaces = Math.round(fakeSpaces); + while (fakeSpaces--) { + textChunk.str.push(' '); + } + } else if (fakeSpaces > SPACE_FACTOR) { + textChunk.str.push(' '); + } + } + } + } + bidiTexts.push(runBidi(textChunk)); + break; + case OPS.showText: + bidiTexts.push(runBidi(buildTextGeometry(args[0]))); + break; + case OPS.nextLineShowText: + textState.carriageReturn(); + bidiTexts.push(runBidi(buildTextGeometry(args[0]))); + break; + case OPS.nextLineSetSpacingShowText: + textState.wordSpacing = args[0]; + textState.charSpacing = args[1]; + textState.carriageReturn(); + bidiTexts.push(runBidi(buildTextGeometry(args[2]))); + break; + case OPS.paintXObject: + if (args[0].code) { + break; + } + + if (!xobjs) { + xobjs = (resources.get('XObject') || Dict.empty); + } + + var name = args[0].name; + if (xobjsCache.key === name) { + if (xobjsCache.texts) { + Util.appendToArray(bidiTexts, xobjsCache.texts.items); + Util.extendObj(textContent.styles, xobjsCache.texts.styles); + } + break; + } + + var xobj = xobjs.get(name); + if (!xobj) { + break; + } + assert(isStream(xobj), 'XObject should be a stream'); + + var type = xobj.dict.get('Subtype'); + assert(isName(type), + 'XObject should have a Name subtype'); + + if ('Form' !== type.name) { + xobjsCache.key = name; + xobjsCache.texts = null; + break; + } + + stateManager.save(); + var matrix = xobj.dict.get('Matrix'); + if (isArray(matrix) && matrix.length === 6) { + stateManager.transform(matrix); + } + + return self.getTextContent(xobj, + xobj.dict.get('Resources') || resources, stateManager). + then(function (formTextContent) { + Util.appendToArray(bidiTexts, formTextContent.items); + Util.extendObj(textContent.styles, formTextContent.styles); + stateManager.restore(); + + xobjsCache.key = name; + xobjsCache.texts = formTextContent; + + next(resolve, reject); + }, reject); + case OPS.setGState: + var dictName = args[0]; + var extGState = resources.get('ExtGState'); + + if (!isDict(extGState) || !extGState.has(dictName.name)) { + break; + } + + var gsStateMap = extGState.get(dictName.name); + var gsStateFont = null; + for (var key in gsStateMap) { + if (key === 'Font') { + assert(!gsStateFont); + gsStateFont = gsStateMap[key]; + } + } + if (gsStateFont) { + textState.fontSize = gsStateFont[1]; + return handleSetFont(gsStateFont[0]).then(function() { + next(resolve, reject); + }, reject); + } + break; + } // switch + } // while + if (stop) { + deferred.then(function () { + next(resolve, reject); + }); + return; + } + resolve(textContent); + }); + }, + + extractDataStructures: function + partialEvaluatorExtractDataStructures(dict, baseDict, + xref, properties) { + // 9.10.2 + var toUnicode = (dict.get('ToUnicode') || baseDict.get('ToUnicode')); + if (toUnicode) { + properties.toUnicode = this.readToUnicode(toUnicode); + } + if (properties.composite) { + // CIDSystemInfo helps to match CID to glyphs + var cidSystemInfo = dict.get('CIDSystemInfo'); + if (isDict(cidSystemInfo)) { + properties.cidSystemInfo = { + registry: cidSystemInfo.get('Registry'), + ordering: cidSystemInfo.get('Ordering'), + supplement: cidSystemInfo.get('Supplement') + }; + } + + var cidToGidMap = dict.get('CIDToGIDMap'); + if (isStream(cidToGidMap)) { + properties.cidToGidMap = this.readCidToGidMap(cidToGidMap); + } + } + + // Based on 9.6.6 of the spec the encoding can come from multiple places + // and depends on the font type. The base encoding and differences are + // read here, but the encoding that is actually used is chosen during + // glyph mapping in the font. + // TODO: Loading the built in encoding in the font would allow the + // differences to be merged in here not require us to hold on to it. + var differences = []; + var baseEncodingName = null; + var encoding; + if (dict.has('Encoding')) { + encoding = dict.get('Encoding'); + if (isDict(encoding)) { + baseEncodingName = encoding.get('BaseEncoding'); + baseEncodingName = (isName(baseEncodingName) ? + baseEncodingName.name : null); + // Load the differences between the base and original + if (encoding.has('Differences')) { + var diffEncoding = encoding.get('Differences'); + var index = 0; + for (var j = 0, jj = diffEncoding.length; j < jj; j++) { + var data = diffEncoding[j]; + if (isNum(data)) { + index = data; + } else if (isName(data)) { + differences[index++] = data.name; + } else if (isRef(data)) { + diffEncoding[j--] = xref.fetch(data); + + } else { + error('Invalid entry in \'Differences\' array: ' + data); + } + } + } + } else if (isName(encoding)) { + baseEncodingName = encoding.name; + } else { + error('Encoding is not a Name nor a Dict'); + } + // According to table 114 if the encoding is a named encoding it must be + // one of these predefined encodings. + if ((baseEncodingName !== 'MacRomanEncoding' && + baseEncodingName !== 'MacExpertEncoding' && + baseEncodingName !== 'WinAnsiEncoding')) { + baseEncodingName = null; + } + } + + if (baseEncodingName) { + properties.defaultEncoding = Encodings[baseEncodingName].slice(); + } else { + encoding = (properties.type === 'TrueType' ? + Encodings.WinAnsiEncoding : Encodings.StandardEncoding); + // The Symbolic attribute can be misused for regular fonts + // Heuristic: we have to check if the font is a standard one also + if (!!(properties.flags & FontFlags.Symbolic)) { + encoding = Encodings.MacRomanEncoding; + if (!properties.file) { + if (/Symbol/i.test(properties.name)) { + encoding = Encodings.SymbolSetEncoding; + } else if (/Dingbats/i.test(properties.name)) { + encoding = Encodings.ZapfDingbatsEncoding; + } + } + } + properties.defaultEncoding = encoding; + } + + properties.differences = differences; + properties.baseEncodingName = baseEncodingName; + properties.dict = dict; + }, + + readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) { + var cmap, cmapObj = toUnicode; + if (isName(cmapObj)) { + cmap = CMapFactory.create(cmapObj, + { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xFFFF); + } + return new ToUnicodeMap(cmap.getMap()); + } else if (isStream(cmapObj)) { + cmap = CMapFactory.create(cmapObj, + { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xFFFF); + } + cmap = cmap.getMap(); + // Convert UTF-16BE + // NOTE: cmap can be a sparse array, so use forEach instead of for(;;) + // to iterate over all keys. + cmap.forEach(function(token, i) { + var str = []; + for (var k = 0; k < token.length; k += 2) { + var w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); + if ((w1 & 0xF800) !== 0xD800) { // w1 < 0xD800 || w1 > 0xDFFF + str.push(w1); + continue; + } + k += 2; + var w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); + str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000); + } + cmap[i] = String.fromCharCode.apply(String, str); + }); + return new ToUnicodeMap(cmap); + } + return null; + }, + + readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) { + // Extract the encoding from the CIDToGIDMap + var glyphsData = cidToGidStream.getBytes(); + + // Set encoding 0 to later verify the font has an encoding + var result = []; + for (var j = 0, jj = glyphsData.length; j < jj; j++) { + var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; + if (glyphID === 0) { + continue; + } + var code = j >> 1; + result[code] = glyphID; + } + return result; + }, + + extractWidths: function PartialEvaluator_extractWidths(dict, xref, + descriptor, + properties) { + var glyphsWidths = []; + var defaultWidth = 0; + var glyphsVMetrics = []; + var defaultVMetrics; + var i, ii, j, jj, start, code, widths; + if (properties.composite) { + defaultWidth = dict.get('DW') || 1000; + + widths = dict.get('W'); + if (widths) { + for (i = 0, ii = widths.length; i < ii; i++) { + start = widths[i++]; + code = xref.fetchIfRef(widths[i]); + if (isArray(code)) { + for (j = 0, jj = code.length; j < jj; j++) { + glyphsWidths[start++] = code[j]; + } + } else { + var width = widths[++i]; + for (j = start; j <= code; j++) { + glyphsWidths[j] = width; + } + } + } + } + + if (properties.vertical) { + var vmetrics = (dict.get('DW2') || [880, -1000]); + defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]]; + vmetrics = dict.get('W2'); + if (vmetrics) { + for (i = 0, ii = vmetrics.length; i < ii; i++) { + start = vmetrics[i++]; + code = xref.fetchIfRef(vmetrics[i]); + if (isArray(code)) { + for (j = 0, jj = code.length; j < jj; j++) { + glyphsVMetrics[start++] = [code[j++], code[j++], code[j]]; + } + } else { + var vmetric = [vmetrics[++i], vmetrics[++i], vmetrics[++i]]; + for (j = start; j <= code; j++) { + glyphsVMetrics[j] = vmetric; + } + } + } + } + } + } else { + var firstChar = properties.firstChar; + widths = dict.get('Widths'); + if (widths) { + j = firstChar; + for (i = 0, ii = widths.length; i < ii; i++) { + glyphsWidths[j++] = widths[i]; + } + defaultWidth = (parseFloat(descriptor.get('MissingWidth')) || 0); + } else { + // Trying get the BaseFont metrics (see comment above). + var baseFontName = dict.get('BaseFont'); + if (isName(baseFontName)) { + var metrics = this.getBaseFontMetrics(baseFontName.name); + + glyphsWidths = this.buildCharCodeToWidth(metrics.widths, + properties); + defaultWidth = metrics.defaultWidth; + } + } + } + + // Heuristic: detection of monospace font by checking all non-zero widths + var isMonospace = true; + var firstWidth = defaultWidth; + for (var glyph in glyphsWidths) { + var glyphWidth = glyphsWidths[glyph]; + if (!glyphWidth) { + continue; + } + if (!firstWidth) { + firstWidth = glyphWidth; + continue; + } + if (firstWidth !== glyphWidth) { + isMonospace = false; + break; + } + } + if (isMonospace) { + properties.flags |= FontFlags.FixedPitch; + } + + properties.defaultWidth = defaultWidth; + properties.widths = glyphsWidths; + properties.defaultVMetrics = defaultVMetrics; + properties.vmetrics = glyphsVMetrics; + }, + + isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) { + // Simulating descriptor flags attribute + var fontNameWoStyle = baseFontName.split('-')[0]; + return (fontNameWoStyle in serifFonts) || + (fontNameWoStyle.search(/serif/gi) !== -1); + }, + + getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) { + var defaultWidth = 0; + var widths = []; + var monospace = false; + var lookupName = (stdFontMap[name] || name); + + if (!(lookupName in Metrics)) { + // Use default fonts for looking up font metrics if the passed + // font is not a base font + if (this.isSerifFont(name)) { + lookupName = 'Times-Roman'; + } else { + lookupName = 'Helvetica'; + } + } + var glyphWidths = Metrics[lookupName]; + + if (isNum(glyphWidths)) { + defaultWidth = glyphWidths; + monospace = true; + } else { + widths = glyphWidths; + } + + return { + defaultWidth: defaultWidth, + monospace: monospace, + widths: widths + }; + }, + + buildCharCodeToWidth: + function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName, + properties) { + var widths = Object.create(null); + var differences = properties.differences; + var encoding = properties.defaultEncoding; + for (var charCode = 0; charCode < 256; charCode++) { + if (charCode in differences && + widthsByGlyphName[differences[charCode]]) { + widths[charCode] = widthsByGlyphName[differences[charCode]]; + continue; + } + if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) { + widths[charCode] = widthsByGlyphName[encoding[charCode]]; + + } + } + return widths; + }, + + preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict, xref) { + var baseDict = dict; + var type = dict.get('Subtype'); + assert(isName(type), 'invalid font Subtype'); + + var composite = false; + var uint8array; + if (type.name === 'Type0') { + // If font is a composite + // - get the descendant font + // - set the type according to the descendant font + // - get the FontDescriptor from the descendant font + var df = dict.get('DescendantFonts'); + if (!df) { + error('Descendant fonts are not specified'); + } + dict = (isArray(df) ? xref.fetchIfRef(df[0]) : df); + + type = dict.get('Subtype'); + assert(isName(type), 'invalid font Subtype'); + composite = true; + } + + var descriptor = dict.get('FontDescriptor'); + if (descriptor) { + var hash = new MurmurHash3_64(); + var encoding = baseDict.getRaw('Encoding'); + if (isName(encoding)) { + hash.update(encoding.name); + } else if (isRef(encoding)) { + hash.update(encoding.num + '_' + encoding.gen); + } else if (isDict(encoding)) { + var keys = encoding.getKeys(); + for (var i = 0, ii = keys.length; i < ii; i++) { + var entry = encoding.getRaw(keys[i]); + if (isName(entry)) { + hash.update(entry.name); + } else if (isRef(entry)) { + hash.update(entry.num + '_' + entry.gen); + } else if (isArray(entry)) { // 'Differences' entry. + // Ideally we should check the contents of the array, but to avoid + // parsing it here and then again in |extractDataStructures|, + // we only use the array length for now (fixes bug1157493.pdf). + hash.update(entry.length.toString()); + } + } + } + + var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode'); + if (isStream(toUnicode)) { + var stream = toUnicode.str || toUnicode; + uint8array = stream.buffer ? + new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : + new Uint8Array(stream.bytes.buffer, + stream.start, stream.end - stream.start); + hash.update(uint8array); + + } else if (isName(toUnicode)) { + hash.update(toUnicode.name); + } + + var widths = dict.get('Widths') || baseDict.get('Widths'); + if (widths) { + uint8array = new Uint8Array(new Uint32Array(widths).buffer); + hash.update(uint8array); + } + } + + return { + descriptor: descriptor, + dict: dict, + baseDict: baseDict, + composite: composite, + type: type.name, + hash: hash ? hash.hexdigest() : '' + }; + }, + + translateFont: function PartialEvaluator_translateFont(preEvaluatedFont, + xref) { + var baseDict = preEvaluatedFont.baseDict; + var dict = preEvaluatedFont.dict; + var composite = preEvaluatedFont.composite; + var descriptor = preEvaluatedFont.descriptor; + var type = preEvaluatedFont.type; + var maxCharIndex = (composite ? 0xFFFF : 0xFF); + var properties; + + if (!descriptor) { + if (type === 'Type3') { + // FontDescriptor is only required for Type3 fonts when the document + // is a tagged pdf. Create a barbebones one to get by. + descriptor = new Dict(null); + descriptor.set('FontName', Name.get(type)); + descriptor.set('FontBBox', dict.get('FontBBox')); + } else { + // Before PDF 1.5 if the font was one of the base 14 fonts, having a + // FontDescriptor was not required. + // This case is here for compatibility. + var baseFontName = dict.get('BaseFont'); + if (!isName(baseFontName)) { + error('Base font is not specified'); + } + + // Using base font name as a font name. + baseFontName = baseFontName.name.replace(/[,_]/g, '-'); + var metrics = this.getBaseFontMetrics(baseFontName); + + // Simulating descriptor flags attribute + var fontNameWoStyle = baseFontName.split('-')[0]; + var flags = + (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | + (metrics.monospace ? FontFlags.FixedPitch : 0) | + (symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic : + FontFlags.Nonsymbolic); + + properties = { + type: type, + name: baseFontName, + widths: metrics.widths, + defaultWidth: metrics.defaultWidth, + flags: flags, + firstChar: 0, + lastChar: maxCharIndex + }; + this.extractDataStructures(dict, dict, xref, properties); + properties.widths = this.buildCharCodeToWidth(metrics.widths, + properties); + return new Font(baseFontName, null, properties); + } + } + + // According to the spec if 'FontDescriptor' is declared, 'FirstChar', + // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem + // to ignore this rule when a variant of a standart font is used. + // TODO Fill the width array depending on which of the base font this is + // a variant. + var firstChar = (dict.get('FirstChar') || 0); + var lastChar = (dict.get('LastChar') || maxCharIndex); + + var fontName = descriptor.get('FontName'); + var baseFont = dict.get('BaseFont'); + // Some bad PDFs have a string as the font name. + if (isString(fontName)) { + fontName = Name.get(fontName); + } + if (isString(baseFont)) { + baseFont = Name.get(baseFont); + } + + if (type !== 'Type3') { + var fontNameStr = fontName && fontName.name; + var baseFontStr = baseFont && baseFont.name; + if (fontNameStr !== baseFontStr) { + info('The FontDescriptor\'s FontName is "' + fontNameStr + + '" but should be the same as the Font\'s BaseFont "' + + baseFontStr + '"'); + // Workaround for cases where e.g. fontNameStr = 'Arial' and + // baseFontStr = 'Arial,Bold' (needed when no font file is embedded). + if (fontNameStr && baseFontStr && + baseFontStr.indexOf(fontNameStr) === 0) { + fontName = baseFont; + } + } + } + fontName = (fontName || baseFont); + + assert(isName(fontName), 'invalid font name'); + + var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3'); + if (fontFile) { + if (fontFile.dict) { + var subtype = fontFile.dict.get('Subtype'); + if (subtype) { + subtype = subtype.name; + } + var length1 = fontFile.dict.get('Length1'); + var length2 = fontFile.dict.get('Length2'); + } + } + + properties = { + type: type, + name: fontName.name, + subtype: subtype, + file: fontFile, + length1: length1, + length2: length2, + loadedName: baseDict.loadedName, + composite: composite, + wideChars: composite, + fixedPitch: false, + fontMatrix: (dict.get('FontMatrix') || FONT_IDENTITY_MATRIX), + firstChar: firstChar || 0, + lastChar: (lastChar || maxCharIndex), + bbox: descriptor.get('FontBBox'), + ascent: descriptor.get('Ascent'), + descent: descriptor.get('Descent'), + xHeight: descriptor.get('XHeight'), + capHeight: descriptor.get('CapHeight'), + flags: descriptor.get('Flags'), + italicAngle: descriptor.get('ItalicAngle'), + coded: false + }; + + if (composite) { + var cidEncoding = baseDict.get('Encoding'); + if (isName(cidEncoding)) { + properties.cidEncoding = cidEncoding.name; + } + properties.cMap = CMapFactory.create(cidEncoding, + { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); + properties.vertical = properties.cMap.vertical; + } + this.extractDataStructures(dict, baseDict, xref, properties); + this.extractWidths(dict, xref, descriptor, properties); + + if (type === 'Type3') { + properties.isType3Font = true; + } + + return new Font(fontName.name, fontFile, properties); + } + }; + + return PartialEvaluator; +})(); + +var TranslatedFont = (function TranslatedFontClosure() { + function TranslatedFont(loadedName, font, dict) { + this.loadedName = loadedName; + this.font = font; + this.dict = dict; + this.type3Loaded = null; + this.sent = false; + } + TranslatedFont.prototype = { + send: function (handler) { + if (this.sent) { + return; + } + var fontData = this.font.exportData(); + handler.send('commonobj', [ + this.loadedName, + 'Font', + fontData + ]); + this.sent = true; + }, + loadType3Data: function (evaluator, resources, parentOperatorList) { + assert(this.font.isType3Font); + + if (this.type3Loaded) { + return this.type3Loaded; + } + + var translatedFont = this.font; + var loadCharProcsPromise = Promise.resolve(); + var charProcs = this.dict.get('CharProcs').getAll(); + var fontResources = this.dict.get('Resources') || resources; + var charProcKeys = Object.keys(charProcs); + var charProcOperatorList = {}; + for (var i = 0, n = charProcKeys.length; i < n; ++i) { + loadCharProcsPromise = loadCharProcsPromise.then(function (key) { + var glyphStream = charProcs[key]; + var operatorList = new OperatorList(); + return evaluator.getOperatorList(glyphStream, fontResources, + operatorList).then(function () { + charProcOperatorList[key] = operatorList.getIR(); + + // Add the dependencies to the parent operator list so they are + // resolved before sub operator list is executed synchronously. + parentOperatorList.addDependencies(operatorList.dependencies); + }, function (reason) { + warn('Type3 font resource \"' + key + '\" is not available'); + var operatorList = new OperatorList(); + charProcOperatorList[key] = operatorList.getIR(); + }); + }.bind(this, charProcKeys[i])); + } + this.type3Loaded = loadCharProcsPromise.then(function () { + translatedFont.charProcOperatorList = charProcOperatorList; + }); + return this.type3Loaded; + } + }; + return TranslatedFont; +})(); + +var OperatorList = (function OperatorListClosure() { + var CHUNK_SIZE = 1000; + var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size + + function getTransfers(queue) { + var transfers = []; + var fnArray = queue.fnArray, argsArray = queue.argsArray; + for (var i = 0, ii = queue.length; i < ii; i++) { + switch (fnArray[i]) { + case OPS.paintInlineImageXObject: + case OPS.paintInlineImageXObjectGroup: + case OPS.paintImageMaskXObject: + var arg = argsArray[i][0]; // first param in imgData + if (!arg.cached) { + transfers.push(arg.data.buffer); + } + break; + } + } + return transfers; + } + + function OperatorList(intent, messageHandler, pageIndex) { + this.messageHandler = messageHandler; + this.fnArray = []; + this.argsArray = []; + this.dependencies = {}; + this.pageIndex = pageIndex; + this.intent = intent; + } + + OperatorList.prototype = { + get length() { + return this.argsArray.length; + }, + + addOp: function(fn, args) { + this.fnArray.push(fn); + this.argsArray.push(args); + if (this.messageHandler) { + if (this.fnArray.length >= CHUNK_SIZE) { + this.flush(); + } else if (this.fnArray.length >= CHUNK_SIZE_ABOUT && + (fn === OPS.restore || fn === OPS.endText)) { + // heuristic to flush on boundary of restore or endText + this.flush(); + } + } + }, + + addDependency: function(dependency) { + if (dependency in this.dependencies) { + return; + } + this.dependencies[dependency] = true; + this.addOp(OPS.dependency, [dependency]); + }, + + addDependencies: function(dependencies) { + for (var key in dependencies) { + this.addDependency(key); + } + }, + + addOpList: function(opList) { + Util.extendObj(this.dependencies, opList.dependencies); + for (var i = 0, ii = opList.length; i < ii; i++) { + this.addOp(opList.fnArray[i], opList.argsArray[i]); + } + }, + + getIR: function() { + return { + fnArray: this.fnArray, + argsArray: this.argsArray, + length: this.length + }; + }, + + flush: function(lastChunk) { + if (this.intent !== 'oplist') { + new QueueOptimizer().optimize(this); + } + var transfers = getTransfers(this); + this.messageHandler.send('RenderPageChunk', { + operatorList: { + fnArray: this.fnArray, + argsArray: this.argsArray, + lastChunk: lastChunk, + length: this.length + }, + pageIndex: this.pageIndex, + intent: this.intent + }, transfers); + this.dependencies = {}; + this.fnArray.length = 0; + this.argsArray.length = 0; + } + }; + + return OperatorList; +})(); + +var StateManager = (function StateManagerClosure() { + function StateManager(initialState) { + this.state = initialState; + this.stateStack = []; + } + StateManager.prototype = { + save: function () { + var old = this.state; + this.stateStack.push(this.state); + this.state = old.clone(); + }, + restore: function () { + var prev = this.stateStack.pop(); + if (prev) { + this.state = prev; + } + }, + transform: function (args) { + this.state.ctm = Util.transform(this.state.ctm, args); + } + }; + return StateManager; +})(); + +var TextState = (function TextStateClosure() { + function TextState() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.fontSize = 0; + this.font = null; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.textMatrix = IDENTITY_MATRIX.slice(); + this.textLineMatrix = IDENTITY_MATRIX.slice(); + this.charSpacing = 0; + this.wordSpacing = 0; + this.leading = 0; + this.textHScale = 1; + this.textRise = 0; + } + + TextState.prototype = { + setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { + var m = this.textMatrix; + m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; + }, + setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { + var m = this.textLineMatrix; + m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; + }, + translateTextMatrix: function TextState_translateTextMatrix(x, y) { + var m = this.textMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + }, + translateTextLineMatrix: function TextState_translateTextMatrix(x, y) { + var m = this.textLineMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + }, + calcRenderMatrix: function TextState_calcRendeMatrix(ctm) { + // 9.4.4 Text Space Details + var tsm = [this.fontSize * this.textHScale, 0, + 0, this.fontSize, + 0, this.textRise]; + return Util.transform(ctm, Util.transform(this.textMatrix, tsm)); + }, + carriageReturn: function TextState_carriageReturn() { + this.translateTextLineMatrix(0, -this.leading); + this.textMatrix = this.textLineMatrix.slice(); + }, + clone: function TextState_clone() { + var clone = Object.create(this); + clone.textMatrix = this.textMatrix.slice(); + clone.textLineMatrix = this.textLineMatrix.slice(); + clone.fontMatrix = this.fontMatrix.slice(); + return clone; + } + }; + return TextState; +})(); + +var EvalState = (function EvalStateClosure() { + function EvalState() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.font = null; + this.textRenderingMode = TextRenderingMode.FILL; + this.fillColorSpace = ColorSpace.singletons.gray; + this.strokeColorSpace = ColorSpace.singletons.gray; + } + EvalState.prototype = { + clone: function CanvasExtraState_clone() { + return Object.create(this); + }, + }; + return EvalState; +})(); + +var EvaluatorPreprocessor = (function EvaluatorPreprocessorClosure() { + // Specifies properties for each command + // + // If variableArgs === true: [0, `numArgs`] expected + // If variableArgs === false: exactly `numArgs` expected + var OP_MAP = { + // Graphic state + w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false }, + J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false }, + j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false }, + M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false }, + d: { id: OPS.setDash, numArgs: 2, variableArgs: false }, + ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false }, + i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false }, + gs: { id: OPS.setGState, numArgs: 1, variableArgs: false }, + q: { id: OPS.save, numArgs: 0, variableArgs: false }, + Q: { id: OPS.restore, numArgs: 0, variableArgs: false }, + cm: { id: OPS.transform, numArgs: 6, variableArgs: false }, + + // Path + m: { id: OPS.moveTo, numArgs: 2, variableArgs: false }, + l: { id: OPS.lineTo, numArgs: 2, variableArgs: false }, + c: { id: OPS.curveTo, numArgs: 6, variableArgs: false }, + v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false }, + y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false }, + h: { id: OPS.closePath, numArgs: 0, variableArgs: false }, + re: { id: OPS.rectangle, numArgs: 4, variableArgs: false }, + S: { id: OPS.stroke, numArgs: 0, variableArgs: false }, + s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false }, + f: { id: OPS.fill, numArgs: 0, variableArgs: false }, + F: { id: OPS.fill, numArgs: 0, variableArgs: false }, + 'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false }, + B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false }, + 'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false }, + b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false }, + 'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false }, + n: { id: OPS.endPath, numArgs: 0, variableArgs: false }, + + // Clipping + W: { id: OPS.clip, numArgs: 0, variableArgs: false }, + 'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false }, + + // Text + BT: { id: OPS.beginText, numArgs: 0, variableArgs: false }, + ET: { id: OPS.endText, numArgs: 0, variableArgs: false }, + Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false }, + Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false }, + Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false }, + TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false }, + Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false }, + Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false }, + Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false }, + Td: { id: OPS.moveText, numArgs: 2, variableArgs: false }, + TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false }, + Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false }, + 'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false }, + Tj: { id: OPS.showText, numArgs: 1, variableArgs: false }, + TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false }, + '\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false }, + '"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3, + variableArgs: false }, + + // Type3 fonts + d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false }, + d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false }, + + // Color + CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false }, + cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false }, + SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true }, + SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true }, + sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true }, + scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true }, + G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false }, + g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false }, + RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false }, + rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false }, + K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false }, + k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false }, + + // Shading + sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false }, + + // Images + BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false }, + ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false }, + EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false }, + + // XObjects + Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false }, + MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false }, + DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false }, + BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false }, + BDC: { id: OPS.beginMarkedContentProps, numArgs: 2, + variableArgs: false }, + EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false }, + + // Compatibility + BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false }, + EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false }, + + // (reserved partial commands for the lexer) + BM: null, + BD: null, + 'true': null, + fa: null, + fal: null, + fals: null, + 'false': null, + nu: null, + nul: null, + 'null': null + }; + + function EvaluatorPreprocessor(stream, xref, stateManager) { + // TODO(mduan): pass array of knownCommands rather than OP_MAP + // dictionary + this.parser = new Parser(new Lexer(stream, OP_MAP), false, xref); + this.stateManager = stateManager; + this.nonProcessedArgs = []; + } + + EvaluatorPreprocessor.prototype = { + get savedStatesDepth() { + return this.stateManager.stateStack.length; + }, + + // |operation| is an object with two fields: + // + // - |fn| is an out param. + // + // - |args| is an inout param. On entry, it should have one of two values. + // + // - An empty array. This indicates that the caller is providing the + // array in which the args will be stored in. The caller should use + // this value if it can reuse a single array for each call to read(). + // + // - |null|. This indicates that the caller needs this function to create + // the array in which any args are stored in. If there are zero args, + // this function will leave |operation.args| as |null| (thus avoiding + // allocations that would occur if we used an empty array to represent + // zero arguments). Otherwise, it will replace |null| with a new array + // containing the arguments. The caller should use this value if it + // cannot reuse an array for each call to read(). + // + // These two modes are present because this function is very hot and so + // avoiding allocations where possible is worthwhile. + // + read: function EvaluatorPreprocessor_read(operation) { + var args = operation.args; + while (true) { + var obj = this.parser.getObj(); + if (isCmd(obj)) { + var cmd = obj.cmd; + // Check that the command is valid + var opSpec = OP_MAP[cmd]; + if (!opSpec) { + warn('Unknown command "' + cmd + '"'); + continue; + } + + var fn = opSpec.id; + var numArgs = opSpec.numArgs; + var argsLength = args !== null ? args.length : 0; + + if (!opSpec.variableArgs) { + // Postscript commands can be nested, e.g. /F2 /GS2 gs 5.711 Tf + if (argsLength !== numArgs) { + var nonProcessedArgs = this.nonProcessedArgs; + while (argsLength > numArgs) { + nonProcessedArgs.push(args.shift()); + argsLength--; + } + while (argsLength < numArgs && nonProcessedArgs.length !== 0) { + if (!args) { + args = []; + } + args.unshift(nonProcessedArgs.pop()); + argsLength++; + } + } + + if (argsLength < numArgs) { + // If we receive too few args, it's not possible to possible + // to execute the command, so skip the command + info('Command ' + fn + ': because expected ' + + numArgs + ' args, but received ' + argsLength + + ' args; skipping'); + args = null; + continue; + } + } else if (argsLength > numArgs) { + info('Command ' + fn + ': expected [0,' + numArgs + + '] args, but received ' + argsLength + ' args'); + } + + // TODO figure out how to type-check vararg functions + this.preprocessCommand(fn, args); + + operation.fn = fn; + operation.args = args; + return true; + } else { + if (isEOF(obj)) { + return false; // no more commands + } + // argument + if (obj !== null) { + if (!args) { + args = []; + } + args.push((obj instanceof Dict ? obj.getAll() : obj)); + assert(args.length <= 33, 'Too many arguments'); + } + } + } + }, + + preprocessCommand: + function EvaluatorPreprocessor_preprocessCommand(fn, args) { + switch (fn | 0) { + case OPS.save: + this.stateManager.save(); + break; + case OPS.restore: + this.stateManager.restore(); + break; + case OPS.transform: + this.stateManager.transform(args); + break; + } + } + }; + return EvaluatorPreprocessor; +})(); + +var QueueOptimizer = (function QueueOptimizerClosure() { + function addState(parentState, pattern, fn) { + var state = parentState; + for (var i = 0, ii = pattern.length - 1; i < ii; i++) { + var item = pattern[i]; + state = (state[item] || (state[item] = [])); + } + state[pattern[pattern.length - 1]] = fn; + } + + function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, + argsArray) { + // Handles special case of mainly LaTeX documents which use image masks to + // draw lines with the current fill style. + // 'count' groups of (save, transform, paintImageMaskXObject, restore)+ + // have been found at iFirstSave. + var iFirstPIMXO = iFirstSave + 2; + for (var i = 0; i < count; i++) { + var arg = argsArray[iFirstPIMXO + 4 * i]; + var imageMask = arg.length === 1 && arg[0]; + if (imageMask && imageMask.width === 1 && imageMask.height === 1 && + (!imageMask.data.length || + (imageMask.data.length === 1 && imageMask.data[0] === 0))) { + fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask; + continue; + } + break; + } + return count - i; + } + + var InitialState = []; + + // This replaces (save, transform, paintInlineImageXObject, restore)+ + // sequences with one |paintInlineImageXObjectGroup| operation. + addState(InitialState, + [OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore], + function foundInlineImageGroup(context) { + var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10; + var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200; + var MAX_WIDTH = 1000; + var IMAGE_PADDING = 1; + + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIIXO = curr - 1; + + // Look for the quartets. + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || + fnArray[i + 1] !== OPS.transform || + fnArray[i + 2] !== OPS.paintInlineImageXObject || + fnArray[i + 3] !== OPS.restore) { + break; // ops don't match + } + i += 4; + } + + // At this point, i is the index of the first op past the last valid + // quartet. + var count = Math.min((i - iFirstSave) / 4, + MAX_IMAGES_IN_INLINE_IMAGES_BLOCK); + if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) { + return i; + } + + // assuming that heights of those image is too small (~1 pixel) + // packing as much as possible by lines + var maxX = 0; + var map = [], maxLineHeight = 0; + var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING; + var q; + for (q = 0; q < count; q++) { + var transform = argsArray[iFirstTransform + (q << 2)]; + var img = argsArray[iFirstPIIXO + (q << 2)][0]; + if (currentX + img.width > MAX_WIDTH) { + // starting new line + maxX = Math.max(maxX, currentX); + currentY += maxLineHeight + 2 * IMAGE_PADDING; + currentX = 0; + maxLineHeight = 0; + } + map.push({ + transform: transform, + x: currentX, y: currentY, + w: img.width, h: img.height + }); + currentX += img.width + 2 * IMAGE_PADDING; + maxLineHeight = Math.max(maxLineHeight, img.height); + } + var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING; + var imgHeight = currentY + maxLineHeight + IMAGE_PADDING; + var imgData = new Uint8Array(imgWidth * imgHeight * 4); + var imgRowSize = imgWidth << 2; + for (q = 0; q < count; q++) { + var data = argsArray[iFirstPIIXO + (q << 2)][0].data; + // Copy image by lines and extends pixels into padding. + var rowSize = map[q].w << 2; + var dataOffset = 0; + var offset = (map[q].x + map[q].y * imgWidth) << 2; + imgData.set(data.subarray(0, rowSize), offset - imgRowSize); + for (var k = 0, kk = map[q].h; k < kk; k++) { + imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset); + dataOffset += rowSize; + offset += imgRowSize; + } + imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset); + while (offset >= 0) { + data[offset - 4] = data[offset]; + data[offset - 3] = data[offset + 1]; + data[offset - 2] = data[offset + 2]; + data[offset - 1] = data[offset + 3]; + data[offset + rowSize] = data[offset + rowSize - 4]; + data[offset + rowSize + 1] = data[offset + rowSize - 3]; + data[offset + rowSize + 2] = data[offset + rowSize - 2]; + data[offset + rowSize + 3] = data[offset + rowSize - 1]; + offset -= imgRowSize; + } + } + + // Replace queue items. + fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup); + argsArray.splice(iFirstSave, count * 4, + [{ width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP, + data: imgData }, map]); + + return iFirstSave + 1; + }); + + // This replaces (save, transform, paintImageMaskXObject, restore)+ + // sequences with one |paintImageMaskXObjectGroup| or one + // |paintImageMaskXObjectRepeat| operation. + addState(InitialState, + [OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore], + function foundImageMaskGroup(context) { + var MIN_IMAGES_IN_MASKS_BLOCK = 10; + var MAX_IMAGES_IN_MASKS_BLOCK = 100; + var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000; + + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIMXO = curr - 1; + + // Look for the quartets. + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || + fnArray[i + 1] !== OPS.transform || + fnArray[i + 2] !== OPS.paintImageMaskXObject || + fnArray[i + 3] !== OPS.restore) { + break; // ops don't match + } + i += 4; + } + + // At this point, i is the index of the first op past the last valid + // quartet. + var count = (i - iFirstSave) / 4; + count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, + argsArray); + if (count < MIN_IMAGES_IN_MASKS_BLOCK) { + return i; + } + + var q; + var isSameImage = false; + var iTransform, transformArgs; + var firstPIMXOArg0 = argsArray[iFirstPIMXO][0]; + if (argsArray[iFirstTransform][1] === 0 && + argsArray[iFirstTransform][2] === 0) { + isSameImage = true; + var firstTransformArg0 = argsArray[iFirstTransform][0]; + var firstTransformArg3 = argsArray[iFirstTransform][3]; + iTransform = iFirstTransform + 4; + var iPIMXO = iFirstPIMXO + 4; + for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) { + transformArgs = argsArray[iTransform]; + if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || + transformArgs[0] !== firstTransformArg0 || + transformArgs[1] !== 0 || + transformArgs[2] !== 0 || + transformArgs[3] !== firstTransformArg3) { + if (q < MIN_IMAGES_IN_MASKS_BLOCK) { + isSameImage = false; + } else { + count = q; + } + break; // different image or transform + } + } + } + + if (isSameImage) { + count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK); + var positions = new Float32Array(count * 2); + iTransform = iFirstTransform; + for (q = 0; q < count; q++, iTransform += 4) { + transformArgs = argsArray[iTransform]; + positions[(q << 1)] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + + // Replace queue items. + fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, + [firstPIMXOArg0, firstTransformArg0, firstTransformArg3, positions]); + } else { + count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK); + var images = []; + for (q = 0; q < count; q++) { + transformArgs = argsArray[iFirstTransform + (q << 2)]; + var maskParams = argsArray[iFirstPIMXO + (q << 2)][0]; + images.push({ data: maskParams.data, width: maskParams.width, + height: maskParams.height, + transform: transformArgs }); + } + + // Replace queue items. + fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup); + argsArray.splice(iFirstSave, count * 4, [images]); + } + + return iFirstSave + 1; + }); + + // This replaces (save, transform, paintImageXObject, restore)+ sequences + // with one paintImageXObjectRepeat operation, if the |transform| and + // |paintImageXObjectRepeat| ops are appropriate. + addState(InitialState, + [OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore], + function (context) { + var MIN_IMAGES_IN_BLOCK = 3; + var MAX_IMAGES_IN_BLOCK = 1000; + + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIXO = curr - 1; + var iFirstRestore = curr; + + if (argsArray[iFirstTransform][1] !== 0 || + argsArray[iFirstTransform][2] !== 0) { + return iFirstRestore + 1; // transform has the wrong form + } + + // Look for the quartets. + var firstPIXOArg0 = argsArray[iFirstPIXO][0]; + var firstTransformArg0 = argsArray[iFirstTransform][0]; + var firstTransformArg3 = argsArray[iFirstTransform][3]; + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || + fnArray[i + 1] !== OPS.transform || + fnArray[i + 2] !== OPS.paintImageXObject || + fnArray[i + 3] !== OPS.restore) { + break; // ops don't match + } + if (argsArray[i + 1][0] !== firstTransformArg0 || + argsArray[i + 1][1] !== 0 || + argsArray[i + 1][2] !== 0 || + argsArray[i + 1][3] !== firstTransformArg3) { + break; // transforms don't match + } + if (argsArray[i + 2][0] !== firstPIXOArg0) { + break; // images don't match + } + i += 4; + } + + // At this point, i is the index of the first op past the last valid + // quartet. + var count = Math.min((i - iFirstSave) / 4, MAX_IMAGES_IN_BLOCK); + if (count < MIN_IMAGES_IN_BLOCK) { + return i; + } + + // Extract the (x,y) positions from all of the matching transforms. + var positions = new Float32Array(count * 2); + var iTransform = iFirstTransform; + for (var q = 0; q < count; q++, iTransform += 4) { + var transformArgs = argsArray[iTransform]; + positions[(q << 1)] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + + // Replace queue items. + var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, + positions]; + fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, args); + + return iFirstSave + 1; + }); + + // This replaces (beginText, setFont, setTextMatrix, showText, endText)+ + // sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+ + // sequences, if the font for each one is the same. + addState(InitialState, + [OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText], + function (context) { + var MIN_CHARS_IN_BLOCK = 3; + var MAX_CHARS_IN_BLOCK = 1000; + + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstBeginText = curr - 4; + var iFirstSetFont = curr - 3; + var iFirstSetTextMatrix = curr - 2; + var iFirstShowText = curr - 1; + var iFirstEndText = curr; + + // Look for the quintets. + var firstSetFontArg0 = argsArray[iFirstSetFont][0]; + var firstSetFontArg1 = argsArray[iFirstSetFont][1]; + var i = iFirstBeginText + 5; + var ii = fnArray.length; + while (i + 4 < ii) { + if (fnArray[i] !== OPS.beginText || + fnArray[i + 1] !== OPS.setFont || + fnArray[i + 2] !== OPS.setTextMatrix || + fnArray[i + 3] !== OPS.showText || + fnArray[i + 4] !== OPS.endText) { + break; // ops don't match + } + if (argsArray[i + 1][0] !== firstSetFontArg0 || + argsArray[i + 1][1] !== firstSetFontArg1) { + break; // fonts don't match + } + i += 5; + } + + // At this point, i is the index of the first op past the last valid + // quintet. + var count = Math.min(((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK); + if (count < MIN_CHARS_IN_BLOCK) { + return i; + } + + // If the preceding quintet is (, setFont, setTextMatrix, + // showText, endText), include that as well. (E.g. might be + // |dependency|.) + var iFirst = iFirstBeginText; + if (iFirstBeginText >= 4 && + fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && + fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && + fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && + fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && + argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && + argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) { + count++; + iFirst -= 5; + } + + // Remove (endText, beginText, setFont) trios. + var iEndText = iFirst + 4; + for (var q = 1; q < count; q++) { + fnArray.splice(iEndText, 3); + argsArray.splice(iEndText, 3); + iEndText += 2; + } + + return iEndText + 1; + }); + + function QueueOptimizer() {} + + QueueOptimizer.prototype = { + optimize: function QueueOptimizer_optimize(queue) { + var fnArray = queue.fnArray, argsArray = queue.argsArray; + var context = { + iCurr: 0, + fnArray: fnArray, + argsArray: argsArray + }; + var state; + var i = 0, ii = fnArray.length; + while (i < ii) { + state = (state || InitialState)[fnArray[i]]; + if (typeof state === 'function') { // we found some handler + context.iCurr = i; + // state() returns the index of the first non-matching op (if we + // didn't match) or the first op past the modified ops (if we did + // match and replace). + i = state(context); + state = undefined; // reset the state machine + ii = context.fnArray.length; + } else { + i++; + } + } + } + }; + return QueueOptimizer; +})(); + + +var BUILT_IN_CMAPS = [ +// << Start unicode maps. +'Adobe-GB1-UCS2', +'Adobe-CNS1-UCS2', +'Adobe-Japan1-UCS2', +'Adobe-Korea1-UCS2', +// >> End unicode maps. +'78-EUC-H', +'78-EUC-V', +'78-H', +'78-RKSJ-H', +'78-RKSJ-V', +'78-V', +'78ms-RKSJ-H', +'78ms-RKSJ-V', +'83pv-RKSJ-H', +'90ms-RKSJ-H', +'90ms-RKSJ-V', +'90msp-RKSJ-H', +'90msp-RKSJ-V', +'90pv-RKSJ-H', +'90pv-RKSJ-V', +'Add-H', +'Add-RKSJ-H', +'Add-RKSJ-V', +'Add-V', +'Adobe-CNS1-0', +'Adobe-CNS1-1', +'Adobe-CNS1-2', +'Adobe-CNS1-3', +'Adobe-CNS1-4', +'Adobe-CNS1-5', +'Adobe-CNS1-6', +'Adobe-GB1-0', +'Adobe-GB1-1', +'Adobe-GB1-2', +'Adobe-GB1-3', +'Adobe-GB1-4', +'Adobe-GB1-5', +'Adobe-Japan1-0', +'Adobe-Japan1-1', +'Adobe-Japan1-2', +'Adobe-Japan1-3', +'Adobe-Japan1-4', +'Adobe-Japan1-5', +'Adobe-Japan1-6', +'Adobe-Korea1-0', +'Adobe-Korea1-1', +'Adobe-Korea1-2', +'B5-H', +'B5-V', +'B5pc-H', +'B5pc-V', +'CNS-EUC-H', +'CNS-EUC-V', +'CNS1-H', +'CNS1-V', +'CNS2-H', +'CNS2-V', +'ETHK-B5-H', +'ETHK-B5-V', +'ETen-B5-H', +'ETen-B5-V', +'ETenms-B5-H', +'ETenms-B5-V', +'EUC-H', +'EUC-V', +'Ext-H', +'Ext-RKSJ-H', +'Ext-RKSJ-V', +'Ext-V', +'GB-EUC-H', +'GB-EUC-V', +'GB-H', +'GB-V', +'GBK-EUC-H', +'GBK-EUC-V', +'GBK2K-H', +'GBK2K-V', +'GBKp-EUC-H', +'GBKp-EUC-V', +'GBT-EUC-H', +'GBT-EUC-V', +'GBT-H', +'GBT-V', +'GBTpc-EUC-H', +'GBTpc-EUC-V', +'GBpc-EUC-H', +'GBpc-EUC-V', +'H', +'HKdla-B5-H', +'HKdla-B5-V', +'HKdlb-B5-H', +'HKdlb-B5-V', +'HKgccs-B5-H', +'HKgccs-B5-V', +'HKm314-B5-H', +'HKm314-B5-V', +'HKm471-B5-H', +'HKm471-B5-V', +'HKscs-B5-H', +'HKscs-B5-V', +'Hankaku', +'Hiragana', +'KSC-EUC-H', +'KSC-EUC-V', +'KSC-H', +'KSC-Johab-H', +'KSC-Johab-V', +'KSC-V', +'KSCms-UHC-H', +'KSCms-UHC-HW-H', +'KSCms-UHC-HW-V', +'KSCms-UHC-V', +'KSCpc-EUC-H', +'KSCpc-EUC-V', +'Katakana', +'NWP-H', +'NWP-V', +'RKSJ-H', +'RKSJ-V', +'Roman', +'UniCNS-UCS2-H', +'UniCNS-UCS2-V', +'UniCNS-UTF16-H', +'UniCNS-UTF16-V', +'UniCNS-UTF32-H', +'UniCNS-UTF32-V', +'UniCNS-UTF8-H', +'UniCNS-UTF8-V', +'UniGB-UCS2-H', +'UniGB-UCS2-V', +'UniGB-UTF16-H', +'UniGB-UTF16-V', +'UniGB-UTF32-H', +'UniGB-UTF32-V', +'UniGB-UTF8-H', +'UniGB-UTF8-V', +'UniJIS-UCS2-H', +'UniJIS-UCS2-HW-H', +'UniJIS-UCS2-HW-V', +'UniJIS-UCS2-V', +'UniJIS-UTF16-H', +'UniJIS-UTF16-V', +'UniJIS-UTF32-H', +'UniJIS-UTF32-V', +'UniJIS-UTF8-H', +'UniJIS-UTF8-V', +'UniJIS2004-UTF16-H', +'UniJIS2004-UTF16-V', +'UniJIS2004-UTF32-H', +'UniJIS2004-UTF32-V', +'UniJIS2004-UTF8-H', +'UniJIS2004-UTF8-V', +'UniJISPro-UCS2-HW-V', +'UniJISPro-UCS2-V', +'UniJISPro-UTF8-V', +'UniJISX0213-UTF32-H', +'UniJISX0213-UTF32-V', +'UniJISX02132004-UTF32-H', +'UniJISX02132004-UTF32-V', +'UniKS-UCS2-H', +'UniKS-UCS2-V', +'UniKS-UTF16-H', +'UniKS-UTF16-V', +'UniKS-UTF32-H', +'UniKS-UTF32-V', +'UniKS-UTF8-H', +'UniKS-UTF8-V', +'V', +'WP-Symbol']; + +// CMap, not to be confused with TrueType's cmap. +var CMap = (function CMapClosure() { + function CMap(builtInCMap) { + // Codespace ranges are stored as follows: + // [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]] + // where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...] + this.codespaceRanges = [[], [], [], []]; + this.numCodespaceRanges = 0; + // Map entries have one of two forms. + // - cid chars are 16-bit unsigned integers, stored as integers. + // - bf chars are variable-length byte sequences, stored as strings, with + // one byte per character. + this._map = []; + this.name = ''; + this.vertical = false; + this.useCMap = null; + this.builtInCMap = builtInCMap; + } + CMap.prototype = { + addCodespaceRange: function(n, low, high) { + this.codespaceRanges[n - 1].push(low, high); + this.numCodespaceRanges++; + }, + + mapCidRange: function(low, high, dstLow) { + while (low <= high) { + this._map[low++] = dstLow++; + } + }, + + mapBfRange: function(low, high, dstLow) { + var lastByte = dstLow.length - 1; + while (low <= high) { + this._map[low++] = dstLow; + // Only the last byte has to be incremented. + dstLow = dstLow.substr(0, lastByte) + + String.fromCharCode(dstLow.charCodeAt(lastByte) + 1); + } + }, + + mapBfRangeToArray: function(low, high, array) { + var i = 0, ii = array.length; + while (low <= high && i < ii) { + this._map[low] = array[i++]; + ++low; + } + }, + + // This is used for both bf and cid chars. + mapOne: function(src, dst) { + this._map[src] = dst; + }, + + lookup: function(code) { + return this._map[code]; + }, + + contains: function(code) { + return this._map[code] !== undefined; + }, + + forEach: function(callback) { + // Most maps have fewer than 65536 entries, and for those we use normal + // array iteration. But really sparse tables are possible -- e.g. with + // indices in the *billions*. For such tables we use for..in, which isn't + // ideal because it stringifies the indices for all present elements, but + // it does avoid iterating over every undefined entry. + var map = this._map; + var length = map.length; + var i; + if (length <= 0x10000) { + for (i = 0; i < length; i++) { + if (map[i] !== undefined) { + callback(i, map[i]); + } + } + } else { + for (i in this._map) { + callback(i, map[i]); + } + } + }, + + charCodeOf: function(value) { + return this._map.indexOf(value); + }, + + getMap: function() { + return this._map; + }, + + readCharCode: function(str, offset, out) { + var c = 0; + var codespaceRanges = this.codespaceRanges; + var codespaceRangesLen = this.codespaceRanges.length; + // 9.7.6.2 CMap Mapping + // The code length is at most 4. + for (var n = 0; n < codespaceRangesLen; n++) { + c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0; + // Check each codespace range to see if it falls within. + var codespaceRange = codespaceRanges[n]; + for (var k = 0, kk = codespaceRange.length; k < kk;) { + var low = codespaceRange[k++]; + var high = codespaceRange[k++]; + if (c >= low && c <= high) { + out.charcode = c; + out.length = n + 1; + return; + } + } + } + out.charcode = 0; + out.length = 1; + }, + + get isIdentityCMap() { + if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) { + return false; + } + if (this._map.length !== 0x10000) { + return false; + } + for (var i = 0; i < 0x10000; i++) { + if (this._map[i] !== i) { + return false; + } + } + return true; + } + }; + return CMap; +})(); + +// A special case of CMap, where the _map array implicitly has a length of +// 65536 and each element is equal to its index. +var IdentityCMap = (function IdentityCMapClosure() { + function IdentityCMap(vertical, n) { + CMap.call(this); + this.vertical = vertical; + this.addCodespaceRange(n, 0, 0xffff); + } + Util.inherit(IdentityCMap, CMap, {}); + + IdentityCMap.prototype = { + addCodespaceRange: CMap.prototype.addCodespaceRange, + + mapCidRange: function(low, high, dstLow) { + error('should not call mapCidRange'); + }, + + mapBfRange: function(low, high, dstLow) { + error('should not call mapBfRange'); + }, + + mapBfRangeToArray: function(low, high, array) { + error('should not call mapBfRangeToArray'); + }, + + mapOne: function(src, dst) { + error('should not call mapCidOne'); + }, + + lookup: function(code) { + return (isInt(code) && code <= 0xffff) ? code : undefined; + }, + + contains: function(code) { + return isInt(code) && code <= 0xffff; + }, + + forEach: function(callback) { + for (var i = 0; i <= 0xffff; i++) { + callback(i, i); + } + }, + + charCodeOf: function(value) { + return (isInt(value) && value <= 0xffff) ? value : -1; + }, + + getMap: function() { + // Sometimes identity maps must be instantiated, but it's rare. + var map = new Array(0x10000); + for (var i = 0; i <= 0xffff; i++) { + map[i] = i; + } + return map; + }, + + readCharCode: CMap.prototype.readCharCode, + + get isIdentityCMap() { + error('should not access .isIdentityCMap'); + } + }; + + return IdentityCMap; +})(); + +var BinaryCMapReader = (function BinaryCMapReaderClosure() { + function fetchBinaryData(url) { + var nonBinaryRequest = PDFJS.disableWorker; + var request = new XMLHttpRequest(); + request.open('GET', url, false); + if (!nonBinaryRequest) { + try { + request.responseType = 'arraybuffer'; + nonBinaryRequest = request.responseType !== 'arraybuffer'; + } catch (e) { + nonBinaryRequest = true; + } + } + if (nonBinaryRequest && request.overrideMimeType) { + request.overrideMimeType('text/plain; charset=x-user-defined'); + } + request.send(null); + if (nonBinaryRequest ? !request.responseText : !request.response) { + error('Unable to get binary cMap at: ' + url); + } + if (nonBinaryRequest) { + var data = Array.prototype.map.call(request.responseText, function (ch) { + return ch.charCodeAt(0) & 255; + }); + return new Uint8Array(data); + } + return new Uint8Array(request.response); + } + + function hexToInt(a, size) { + var n = 0; + for (var i = 0; i <= size; i++) { + n = (n << 8) | a[i]; + } + return n >>> 0; + } + + function hexToStr(a, size) { + // This code is hot. Special-case some common values to avoid creating an + // object with subarray(). + if (size === 1) { + return String.fromCharCode(a[0], a[1]); + } + if (size === 3) { + return String.fromCharCode(a[0], a[1], a[2], a[3]); + } + return String.fromCharCode.apply(null, a.subarray(0, size + 1)); + } + + function addHex(a, b, size) { + var c = 0; + for (var i = size; i >= 0; i--) { + c += a[i] + b[i]; + a[i] = c & 255; + c >>= 8; + } + } + + function incHex(a, size) { + var c = 1; + for (var i = size; i >= 0 && c > 0; i--) { + c += a[i]; + a[i] = c & 255; + c >>= 8; + } + } + + var MAX_NUM_SIZE = 16; + var MAX_ENCODED_NUM_SIZE = 19; // ceil(MAX_NUM_SIZE * 7 / 8) + + function BinaryCMapStream(data) { + this.buffer = data; + this.pos = 0; + this.end = data.length; + this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE); + } + + BinaryCMapStream.prototype = { + readByte: function () { + if (this.pos >= this.end) { + return -1; + } + return this.buffer[this.pos++]; + }, + readNumber: function () { + var n = 0; + var last; + do { + var b = this.readByte(); + if (b < 0) { + error('unexpected EOF in bcmap'); + } + last = !(b & 0x80); + n = (n << 7) | (b & 0x7F); + } while (!last); + return n; + }, + readSigned: function () { + var n = this.readNumber(); + return (n & 1) ? ~(n >>> 1) : n >>> 1; + }, + readHex: function (num, size) { + num.set(this.buffer.subarray(this.pos, + this.pos + size + 1)); + this.pos += size + 1; + }, + readHexNumber: function (num, size) { + var last; + var stack = this.tmpBuf, sp = 0; + do { + var b = this.readByte(); + if (b < 0) { + error('unexpected EOF in bcmap'); + } + last = !(b & 0x80); + stack[sp++] = b & 0x7F; + } while (!last); + var i = size, buffer = 0, bufferSize = 0; + while (i >= 0) { + while (bufferSize < 8 && stack.length > 0) { + buffer = (stack[--sp] << bufferSize) | buffer; + bufferSize += 7; + } + num[i] = buffer & 255; + i--; + buffer >>= 8; + bufferSize -= 8; + } + }, + readHexSigned: function (num, size) { + this.readHexNumber(num, size); + var sign = num[size] & 1 ? 255 : 0; + var c = 0; + for (var i = 0; i <= size; i++) { + c = ((c & 1) << 8) | num[i]; + num[i] = (c >> 1) ^ sign; + } + }, + readString: function () { + var len = this.readNumber(); + var s = ''; + for (var i = 0; i < len; i++) { + s += String.fromCharCode(this.readNumber()); + } + return s; + } + }; + + function processBinaryCMap(url, cMap, extend) { + var data = fetchBinaryData(url); + var stream = new BinaryCMapStream(data); + + var header = stream.readByte(); + cMap.vertical = !!(header & 1); + + var useCMap = null; + var start = new Uint8Array(MAX_NUM_SIZE); + var end = new Uint8Array(MAX_NUM_SIZE); + var char = new Uint8Array(MAX_NUM_SIZE); + var charCode = new Uint8Array(MAX_NUM_SIZE); + var tmp = new Uint8Array(MAX_NUM_SIZE); + var code; + + var b; + while ((b = stream.readByte()) >= 0) { + var type = b >> 5; + if (type === 7) { // metadata, e.g. comment or usecmap + switch (b & 0x1F) { + case 0: + stream.readString(); // skipping comment + break; + case 1: + useCMap = stream.readString(); + break; + } + continue; + } + var sequence = !!(b & 0x10); + var dataSize = b & 15; + + assert(dataSize + 1 <= MAX_NUM_SIZE); + + var ucs2DataSize = 1; + var subitemsCount = stream.readNumber(); + var i; + switch (type) { + case 0: // codespacerange + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), + hexToInt(end, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), + hexToInt(end, dataSize)); + } + break; + case 1: // notdefrange + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + // undefined range, skipping + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + // nop + } + break; + case 2: // cidchar + stream.readHex(char, dataSize); + code = stream.readNumber(); + cMap.mapOne(hexToInt(char, dataSize), code); + for (i = 1; i < subitemsCount; i++) { + incHex(char, dataSize); + if (!sequence) { + stream.readHexNumber(tmp, dataSize); + addHex(char, tmp, dataSize); + } + code = stream.readSigned() + (code + 1); + cMap.mapOne(hexToInt(char, dataSize), code); + } + break; + case 3: // cidrange + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), + code); + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + if (!sequence) { + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), + code); + } + break; + case 4: // bfchar + stream.readHex(char, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapOne(hexToInt(char, ucs2DataSize), + hexToStr(charCode, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(char, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(tmp, ucs2DataSize); + addHex(char, tmp, ucs2DataSize); + } + incHex(charCode, dataSize); + stream.readHexSigned(tmp, dataSize); + addHex(charCode, tmp, dataSize); + cMap.mapOne(hexToInt(char, ucs2DataSize), + hexToStr(charCode, dataSize)); + } + break; + case 5: // bfrange + stream.readHex(start, ucs2DataSize); + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), + hexToInt(end, ucs2DataSize), + hexToStr(charCode, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(end, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(start, ucs2DataSize); + addHex(start, end, ucs2DataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), + hexToInt(end, ucs2DataSize), + hexToStr(charCode, dataSize)); + } + break; + default: + error('Unknown type: ' + type); + break; + } + } + + if (useCMap) { + extend(useCMap); + } + return cMap; + } + + function BinaryCMapReader() {} + + BinaryCMapReader.prototype = { + read: processBinaryCMap + }; + + return BinaryCMapReader; +})(); + +var CMapFactory = (function CMapFactoryClosure() { + function strToInt(str) { + var a = 0; + for (var i = 0; i < str.length; i++) { + a = (a << 8) | str.charCodeAt(i); + } + return a >>> 0; + } + + function expectString(obj) { + if (!isString(obj)) { + error('Malformed CMap: expected string.'); + } + } + + function expectInt(obj) { + if (!isInt(obj)) { + error('Malformed CMap: expected int.'); + } + } + + function parseBfChar(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endbfchar')) { + return; + } + expectString(obj); + var src = strToInt(obj); + obj = lexer.getObj(); + // TODO are /dstName used? + expectString(obj); + var dst = obj; + cMap.mapOne(src, dst); + } + } + + function parseBfRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endbfrange')) { + return; + } + expectString(obj); + var low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + var high = strToInt(obj); + obj = lexer.getObj(); + if (isInt(obj) || isString(obj)) { + var dstLow = isInt(obj) ? String.fromCharCode(obj) : obj; + cMap.mapBfRange(low, high, dstLow); + } else if (isCmd(obj, '[')) { + obj = lexer.getObj(); + var array = []; + while (!isCmd(obj, ']') && !isEOF(obj)) { + array.push(obj); + obj = lexer.getObj(); + } + cMap.mapBfRangeToArray(low, high, array); + } else { + break; + } + } + error('Invalid bf range.'); + } + + function parseCidChar(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcidchar')) { + return; + } + expectString(obj); + var src = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + var dst = obj; + cMap.mapOne(src, dst); + } + } + + function parseCidRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcidrange')) { + return; + } + expectString(obj); + var low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + var high = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + var dstLow = obj; + cMap.mapCidRange(low, high, dstLow); + } + } + + function parseCodespaceRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcodespacerange')) { + return; + } + if (!isString(obj)) { + break; + } + var low = strToInt(obj); + obj = lexer.getObj(); + if (!isString(obj)) { + break; + } + var high = strToInt(obj); + cMap.addCodespaceRange(obj.length, low, high); + } + error('Invalid codespace range.'); + } + + function parseWMode(cMap, lexer) { + var obj = lexer.getObj(); + if (isInt(obj)) { + cMap.vertical = !!obj; + } + } + + function parseCMapName(cMap, lexer) { + var obj = lexer.getObj(); + if (isName(obj) && isString(obj.name)) { + cMap.name = obj.name; + } + } + + function parseCMap(cMap, lexer, builtInCMapParams, useCMap) { + var previous; + var embededUseCMap; + objLoop: while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } else if (isName(obj)) { + if (obj.name === 'WMode') { + parseWMode(cMap, lexer); + } else if (obj.name === 'CMapName') { + parseCMapName(cMap, lexer); + } + previous = obj; + } else if (isCmd(obj)) { + switch (obj.cmd) { + case 'endcmap': + break objLoop; + case 'usecmap': + if (isName(previous)) { + embededUseCMap = previous.name; + } + break; + case 'begincodespacerange': + parseCodespaceRange(cMap, lexer); + break; + case 'beginbfchar': + parseBfChar(cMap, lexer); + break; + case 'begincidchar': + parseCidChar(cMap, lexer); + break; + case 'beginbfrange': + parseBfRange(cMap, lexer); + break; + case 'begincidrange': + parseCidRange(cMap, lexer); + break; + } + } + } + + if (!useCMap && embededUseCMap) { + // Load the usecmap definition from the file only if there wasn't one + // specified. + useCMap = embededUseCMap; + } + if (useCMap) { + extendCMap(cMap, builtInCMapParams, useCMap); + } + } + + function extendCMap(cMap, builtInCMapParams, useCMap) { + cMap.useCMap = createBuiltInCMap(useCMap, builtInCMapParams); + // If there aren't any code space ranges defined clone all the parent ones + // into this cMap. + if (cMap.numCodespaceRanges === 0) { + var useCodespaceRanges = cMap.useCMap.codespaceRanges; + for (var i = 0; i < useCodespaceRanges.length; i++) { + cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); + } + cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; + } + // Merge the map into the current one, making sure not to override + // any previously defined entries. + cMap.useCMap.forEach(function(key, value) { + if (!cMap.contains(key)) { + cMap.mapOne(key, cMap.useCMap.lookup(key)); + } + }); + } + + function parseBinaryCMap(name, builtInCMapParams) { + var url = builtInCMapParams.url + name + '.bcmap'; + var cMap = new CMap(true); + new BinaryCMapReader().read(url, cMap, function (useCMap) { + extendCMap(cMap, builtInCMapParams, useCMap); + }); + return cMap; + } + + function createBuiltInCMap(name, builtInCMapParams) { + if (name === 'Identity-H') { + return new IdentityCMap(false, 2); + } else if (name === 'Identity-V') { + return new IdentityCMap(true, 2); + } + if (BUILT_IN_CMAPS.indexOf(name) === -1) { + error('Unknown cMap name: ' + name); + } + assert(builtInCMapParams, 'built-in cMap parameters are not provided'); + + if (builtInCMapParams.packed) { + return parseBinaryCMap(name, builtInCMapParams); + } + + var request = new XMLHttpRequest(); + var url = builtInCMapParams.url + name; + request.open('GET', url, false); + request.send(null); + if (!request.responseText) { + error('Unable to get cMap at: ' + url); + } + var cMap = new CMap(true); + var lexer = new Lexer(new StringStream(request.responseText)); + parseCMap(cMap, lexer, builtInCMapParams, null); + return cMap; + } + + return { + create: function (encoding, builtInCMapParams, useCMap) { + if (isName(encoding)) { + return createBuiltInCMap(encoding.name, builtInCMapParams); + } else if (isStream(encoding)) { + var cMap = new CMap(); + var lexer = new Lexer(encoding); + try { + parseCMap(cMap, lexer, builtInCMapParams, useCMap); + } catch (e) { + warn('Invalid CMap data. ' + e); + } + if (cMap.isIdentityCMap) { + return createBuiltInCMap(cMap.name, builtInCMapParams); + } + return cMap; + } + error('Encoding required.'); + } + }; +})(); + + +// Unicode Private Use Area +var PRIVATE_USE_OFFSET_START = 0xE000; +var PRIVATE_USE_OFFSET_END = 0xF8FF; +var SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = false; + +// PDF Glyph Space Units are one Thousandth of a TextSpace Unit +// except for Type 3 fonts +var PDF_GLYPH_SPACE_UNITS = 1000; + +// Hinting is currently disabled due to unknown problems on windows +// in tracemonkey and various other pdfs with type1 fonts. +var HINTING_ENABLED = false; + +// Accented charactars are not displayed properly on windows, using this flag +// to control analysis of seac charstrings. +var SEAC_ANALYSIS_ENABLED = false; + +var FontFlags = { + FixedPitch: 1, + Serif: 2, + Symbolic: 4, + Script: 8, + Nonsymbolic: 32, + Italic: 64, + AllCap: 65536, + SmallCap: 131072, + ForceBold: 262144 +}; + +var Encodings = { + ExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', + 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', + 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', + 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', + 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', + 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', + 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', + 'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', + 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior', + 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', + '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', + 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', + 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', + 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', + 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', + 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', + 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', + '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', + 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', + 'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall', + 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters', + 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior', + 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', + 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', + 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', + 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', + 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', + 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', + 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', + 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', + 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', + 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', + 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', + 'Ydieresissmall'], + MacExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle', + 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', + 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', + 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', + 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', + 'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '', + 'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter', + 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff', + 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', + 'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', + 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', + 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', + 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', + 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', + 'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '', + 'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall', + 'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall', + 'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall', + 'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '', + 'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior', + 'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior', + 'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior', + 'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '', + 'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior', + 'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall', + 'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '', + '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '', + 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior', + 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', + 'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior', + 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior', + '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall', + 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior', + 'periodsuperior', 'Dotaccentsmall', 'Ringsmall'], + MacRomanEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', + 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', + 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', + 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', + 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', + 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', + 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', + 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', + 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', + 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', + 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', + 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', + 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', + 'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE', + 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', + 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', + 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', + 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand', + 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', + 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', + 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', + 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', + 'ogonek', 'caron'], + StandardEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', + 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown', + 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', + 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', + 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', + 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', + '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', + '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', + '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'], + WinAnsiEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', + 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase', + 'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron', + 'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft', + 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', + 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet', + 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright', + 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered', + 'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', + 'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior', + 'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters', + 'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis', + 'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', + 'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', + 'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', + 'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', + 'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve', + 'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash', + 'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn', + 'ydieresis'], + SymbolSetEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent', + 'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus', + 'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', + 'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi', + 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa', + 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau', + 'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft', + 'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex', + 'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', + 'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', + 'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', + 'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal', + 'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade', + 'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree', + 'plusminus', 'second', 'greaterequal', 'multiply', 'proportional', + 'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence', + 'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn', + 'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply', + 'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset', + 'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element', + 'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif', + 'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot', + 'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup', + 'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans', + 'copyrightsans', 'trademarksans', 'summation', 'parenlefttp', + 'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex', + 'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', + '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt', + 'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp', + 'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid', + 'bracerightbt'], + ZapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117', + 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19', + 'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7', + 'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36', + 'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46', + 'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56', + 'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66', + 'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75', + 'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97', + 'a98', 'a99', 'a100', '', 'a89', 'a90', 'a93', 'a94', 'a91', 'a92', 'a205', + 'a85', 'a206', 'a86', 'a87', 'a88', 'a95', 'a96', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103', + 'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120', + 'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129', + 'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138', + 'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147', + 'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156', + 'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165', + 'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173', + 'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180', + 'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197', 'a185', + 'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190', 'a191'] +}; + +/** + * Hold a map of decoded fonts and of the standard fourteen Type1 + * fonts and their acronyms. + */ +var stdFontMap = { + 'ArialNarrow': 'Helvetica', + 'ArialNarrow-Bold': 'Helvetica-Bold', + 'ArialNarrow-BoldItalic': 'Helvetica-BoldOblique', + 'ArialNarrow-Italic': 'Helvetica-Oblique', + 'ArialBlack': 'Helvetica', + 'ArialBlack-Bold': 'Helvetica-Bold', + 'ArialBlack-BoldItalic': 'Helvetica-BoldOblique', + 'ArialBlack-Italic': 'Helvetica-Oblique', + 'Arial': 'Helvetica', + 'Arial-Bold': 'Helvetica-Bold', + 'Arial-BoldItalic': 'Helvetica-BoldOblique', + 'Arial-Italic': 'Helvetica-Oblique', + 'Arial-BoldItalicMT': 'Helvetica-BoldOblique', + 'Arial-BoldMT': 'Helvetica-Bold', + 'Arial-ItalicMT': 'Helvetica-Oblique', + 'ArialMT': 'Helvetica', + 'Courier-Bold': 'Courier-Bold', + 'Courier-BoldItalic': 'Courier-BoldOblique', + 'Courier-Italic': 'Courier-Oblique', + 'CourierNew': 'Courier', + 'CourierNew-Bold': 'Courier-Bold', + 'CourierNew-BoldItalic': 'Courier-BoldOblique', + 'CourierNew-Italic': 'Courier-Oblique', + 'CourierNewPS-BoldItalicMT': 'Courier-BoldOblique', + 'CourierNewPS-BoldMT': 'Courier-Bold', + 'CourierNewPS-ItalicMT': 'Courier-Oblique', + 'CourierNewPSMT': 'Courier', + 'Helvetica': 'Helvetica', + 'Helvetica-Bold': 'Helvetica-Bold', + 'Helvetica-BoldItalic': 'Helvetica-BoldOblique', + 'Helvetica-BoldOblique': 'Helvetica-BoldOblique', + 'Helvetica-Italic': 'Helvetica-Oblique', + 'Helvetica-Oblique':'Helvetica-Oblique', + 'Symbol-Bold': 'Symbol', + 'Symbol-BoldItalic': 'Symbol', + 'Symbol-Italic': 'Symbol', + 'TimesNewRoman': 'Times-Roman', + 'TimesNewRoman-Bold': 'Times-Bold', + 'TimesNewRoman-BoldItalic': 'Times-BoldItalic', + 'TimesNewRoman-Italic': 'Times-Italic', + 'TimesNewRomanPS': 'Times-Roman', + 'TimesNewRomanPS-Bold': 'Times-Bold', + 'TimesNewRomanPS-BoldItalic': 'Times-BoldItalic', + 'TimesNewRomanPS-BoldItalicMT': 'Times-BoldItalic', + 'TimesNewRomanPS-BoldMT': 'Times-Bold', + 'TimesNewRomanPS-Italic': 'Times-Italic', + 'TimesNewRomanPS-ItalicMT': 'Times-Italic', + 'TimesNewRomanPSMT': 'Times-Roman', + 'TimesNewRomanPSMT-Bold': 'Times-Bold', + 'TimesNewRomanPSMT-BoldItalic': 'Times-BoldItalic', + 'TimesNewRomanPSMT-Italic': 'Times-Italic' +}; + +/** + * Holds the map of the non-standard fonts that might be included as a standard + * fonts without glyph data. + */ +var nonStdFontMap = { + 'CenturyGothic': 'Helvetica', + 'CenturyGothic-Bold': 'Helvetica-Bold', + 'CenturyGothic-BoldItalic': 'Helvetica-BoldOblique', + 'CenturyGothic-Italic': 'Helvetica-Oblique', + 'ComicSansMS': 'Comic Sans MS', + 'ComicSansMS-Bold': 'Comic Sans MS-Bold', + 'ComicSansMS-BoldItalic': 'Comic Sans MS-BoldItalic', + 'ComicSansMS-Italic': 'Comic Sans MS-Italic', + 'LucidaConsole': 'Courier', + 'LucidaConsole-Bold': 'Courier-Bold', + 'LucidaConsole-BoldItalic': 'Courier-BoldOblique', + 'LucidaConsole-Italic': 'Courier-Oblique', + 'MS-Gothic': 'MS Gothic', + 'MS-Gothic-Bold': 'MS Gothic-Bold', + 'MS-Gothic-BoldItalic': 'MS Gothic-BoldItalic', + 'MS-Gothic-Italic': 'MS Gothic-Italic', + 'MS-Mincho': 'MS Mincho', + 'MS-Mincho-Bold': 'MS Mincho-Bold', + 'MS-Mincho-BoldItalic': 'MS Mincho-BoldItalic', + 'MS-Mincho-Italic': 'MS Mincho-Italic', + 'MS-PGothic': 'MS PGothic', + 'MS-PGothic-Bold': 'MS PGothic-Bold', + 'MS-PGothic-BoldItalic': 'MS PGothic-BoldItalic', + 'MS-PGothic-Italic': 'MS PGothic-Italic', + 'MS-PMincho': 'MS PMincho', + 'MS-PMincho-Bold': 'MS PMincho-Bold', + 'MS-PMincho-BoldItalic': 'MS PMincho-BoldItalic', + 'MS-PMincho-Italic': 'MS PMincho-Italic', + 'Wingdings': 'ZapfDingbats' +}; + +var serifFonts = { + 'Adobe Jenson': true, 'Adobe Text': true, 'Albertus': true, + 'Aldus': true, 'Alexandria': true, 'Algerian': true, + 'American Typewriter': true, 'Antiqua': true, 'Apex': true, + 'Arno': true, 'Aster': true, 'Aurora': true, + 'Baskerville': true, 'Bell': true, 'Bembo': true, + 'Bembo Schoolbook': true, 'Benguiat': true, 'Berkeley Old Style': true, + 'Bernhard Modern': true, 'Berthold City': true, 'Bodoni': true, + 'Bauer Bodoni': true, 'Book Antiqua': true, 'Bookman': true, + 'Bordeaux Roman': true, 'Californian FB': true, 'Calisto': true, + 'Calvert': true, 'Capitals': true, 'Cambria': true, + 'Cartier': true, 'Caslon': true, 'Catull': true, + 'Centaur': true, 'Century Old Style': true, 'Century Schoolbook': true, + 'Chaparral': true, 'Charis SIL': true, 'Cheltenham': true, + 'Cholla Slab': true, 'Clarendon': true, 'Clearface': true, + 'Cochin': true, 'Colonna': true, 'Computer Modern': true, + 'Concrete Roman': true, 'Constantia': true, 'Cooper Black': true, + 'Corona': true, 'Ecotype': true, 'Egyptienne': true, + 'Elephant': true, 'Excelsior': true, 'Fairfield': true, + 'FF Scala': true, 'Folkard': true, 'Footlight': true, + 'FreeSerif': true, 'Friz Quadrata': true, 'Garamond': true, + 'Gentium': true, 'Georgia': true, 'Gloucester': true, + 'Goudy Old Style': true, 'Goudy Schoolbook': true, 'Goudy Pro Font': true, + 'Granjon': true, 'Guardian Egyptian': true, 'Heather': true, + 'Hercules': true, 'High Tower Text': true, 'Hiroshige': true, + 'Hoefler Text': true, 'Humana Serif': true, 'Imprint': true, + 'Ionic No. 5': true, 'Janson': true, 'Joanna': true, + 'Korinna': true, 'Lexicon': true, 'Liberation Serif': true, + 'Linux Libertine': true, 'Literaturnaya': true, 'Lucida': true, + 'Lucida Bright': true, 'Melior': true, 'Memphis': true, + 'Miller': true, 'Minion': true, 'Modern': true, + 'Mona Lisa': true, 'Mrs Eaves': true, 'MS Serif': true, + 'Museo Slab': true, 'New York': true, 'Nimbus Roman': true, + 'NPS Rawlinson Roadway': true, 'Palatino': true, 'Perpetua': true, + 'Plantin': true, 'Plantin Schoolbook': true, 'Playbill': true, + 'Poor Richard': true, 'Rawlinson Roadway': true, 'Renault': true, + 'Requiem': true, 'Rockwell': true, 'Roman': true, + 'Rotis Serif': true, 'Sabon': true, 'Scala': true, + 'Seagull': true, 'Sistina': true, 'Souvenir': true, + 'STIX': true, 'Stone Informal': true, 'Stone Serif': true, + 'Sylfaen': true, 'Times': true, 'Trajan': true, + 'Trinité': true, 'Trump Mediaeval': true, 'Utopia': true, + 'Vale Type': true, 'Bitstream Vera': true, 'Vera Serif': true, + 'Versailles': true, 'Wanted': true, 'Weiss': true, + 'Wide Latin': true, 'Windsor': true, 'XITS': true +}; + +var symbolsFonts = { + 'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true +}; + +// Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID fonts +// but does not embed the CID to GID mapping. The mapping is incomplete for all +// glyphs, but common for some set of the standard fonts. +var GlyphMapForStandardFonts = { + '2': 10, '3': 32, '4': 33, '5': 34, '6': 35, '7': 36, '8': 37, '9': 38, + '10': 39, '11': 40, '12': 41, '13': 42, '14': 43, '15': 44, '16': 45, + '17': 46, '18': 47, '19': 48, '20': 49, '21': 50, '22': 51, '23': 52, + '24': 53, '25': 54, '26': 55, '27': 56, '28': 57, '29': 58, '30': 894, + '31': 60, '32': 61, '33': 62, '34': 63, '35': 64, '36': 65, '37': 66, + '38': 67, '39': 68, '40': 69, '41': 70, '42': 71, '43': 72, '44': 73, + '45': 74, '46': 75, '47': 76, '48': 77, '49': 78, '50': 79, '51': 80, + '52': 81, '53': 82, '54': 83, '55': 84, '56': 85, '57': 86, '58': 87, + '59': 88, '60': 89, '61': 90, '62': 91, '63': 92, '64': 93, '65': 94, + '66': 95, '67': 96, '68': 97, '69': 98, '70': 99, '71': 100, '72': 101, + '73': 102, '74': 103, '75': 104, '76': 105, '77': 106, '78': 107, '79': 108, + '80': 109, '81': 110, '82': 111, '83': 112, '84': 113, '85': 114, '86': 115, + '87': 116, '88': 117, '89': 118, '90': 119, '91': 120, '92': 121, '93': 122, + '94': 123, '95': 124, '96': 125, '97': 126, '98': 196, '99': 197, '100': 199, + '101': 201, '102': 209, '103': 214, '104': 220, '105': 225, '106': 224, + '107': 226, '108': 228, '109': 227, '110': 229, '111': 231, '112': 233, + '113': 232, '114': 234, '115': 235, '116': 237, '117': 236, '118': 238, + '119': 239, '120': 241, '121': 243, '122': 242, '123': 244, '124': 246, + '125': 245, '126': 250, '127': 249, '128': 251, '129': 252, '130': 8224, + '131': 176, '132': 162, '133': 163, '134': 167, '135': 8226, '136': 182, + '137': 223, '138': 174, '139': 169, '140': 8482, '141': 180, '142': 168, + '143': 8800, '144': 198, '145': 216, '146': 8734, '147': 177, '148': 8804, + '149': 8805, '150': 165, '151': 181, '152': 8706, '153': 8721, '154': 8719, + '156': 8747, '157': 170, '158': 186, '159': 8486, '160': 230, '161': 248, + '162': 191, '163': 161, '164': 172, '165': 8730, '166': 402, '167': 8776, + '168': 8710, '169': 171, '170': 187, '171': 8230, '210': 218, '223': 711, + '224': 321, '225': 322, '227': 353, '229': 382, '234': 253, '252': 263, + '253': 268, '254': 269, '258': 258, '260': 260, '261': 261, '265': 280, + '266': 281, '268': 283, '269': 313, '275': 323, '276': 324, '278': 328, + '284': 345, '285': 346, '286': 347, '292': 367, '295': 377, '296': 378, + '298': 380, '305': 963, + '306': 964, '307': 966, '308': 8215, '309': 8252, '310': 8319, '311': 8359, + '312': 8592, '313': 8593, '337': 9552, '493': 1039, '494': 1040, '705': 1524, + '706': 8362, '710': 64288, '711': 64298, '759': 1617, '761': 1776, + '763': 1778, '775': 1652, '777': 1764, '778': 1780, '779': 1781, '780': 1782, + '782': 771, '783': 64726, '786': 8363, '788': 8532, '790': 768, '791': 769, + '792': 768, '795': 803, '797': 64336, '798': 64337, '799': 64342, + '800': 64343, '801': 64344, '802': 64345, '803': 64362, '804': 64363, + '805': 64364, '2424': 7821, '2425': 7822, '2426': 7823, '2427': 7824, + '2428': 7825, '2429': 7826, '2430': 7827, '2433': 7682, '2678': 8045, + '2679': 8046, '2830': 1552, '2838': 686, '2840': 751, '2842': 753, + '2843': 754, '2844': 755, '2846': 757, '2856': 767, '2857': 848, '2858': 849, + '2862': 853, '2863': 854, '2864': 855, '2865': 861, '2866': 862, '2906': 7460, + '2908': 7462, '2909': 7463, '2910': 7464, '2912': 7466, '2913': 7467, + '2914': 7468, '2916': 7470, '2917': 7471, '2918': 7472, '2920': 7474, + '2921': 7475, '2922': 7476, '2924': 7478, '2925': 7479, '2926': 7480, + '2928': 7482, '2929': 7483, '2930': 7484, '2932': 7486, '2933': 7487, + '2934': 7488, '2936': 7490, '2937': 7491, '2938': 7492, '2940': 7494, + '2941': 7495, '2942': 7496, '2944': 7498, '2946': 7500, '2948': 7502, + '2950': 7504, '2951': 7505, '2952': 7506, '2954': 7508, '2955': 7509, + '2956': 7510, '2958': 7512, '2959': 7513, '2960': 7514, '2962': 7516, + '2963': 7517, '2964': 7518, '2966': 7520, '2967': 7521, '2968': 7522, + '2970': 7524, '2971': 7525, '2972': 7526, '2974': 7528, '2975': 7529, + '2976': 7530, '2978': 1537, '2979': 1538, '2980': 1539, '2982': 1549, + '2983': 1551, '2984': 1552, '2986': 1554, '2987': 1555, '2988': 1556, + '2990': 1623, '2991': 1624, '2995': 1775, '2999': 1791, '3002': 64290, + '3003': 64291, '3004': 64292, '3006': 64294, '3007': 64295, '3008': 64296, + '3011': 1900, '3014': 8223, '3015': 8244, '3017': 7532, '3018': 7533, + '3019': 7534, '3075': 7590, '3076': 7591, '3079': 7594, '3080': 7595, + '3083': 7598, '3084': 7599, '3087': 7602, '3088': 7603, '3091': 7606, + '3092': 7607, '3095': 7610, '3096': 7611, '3099': 7614, '3100': 7615, + '3103': 7618, '3104': 7619, '3107': 8337, '3108': 8338, '3116': 1884, + '3119': 1885, '3120': 1885, '3123': 1886, '3124': 1886, '3127': 1887, + '3128': 1887, '3131': 1888, '3132': 1888, '3135': 1889, '3136': 1889, + '3139': 1890, '3140': 1890, '3143': 1891, '3144': 1891, '3147': 1892, + '3148': 1892, '3153': 580, '3154': 581, '3157': 584, '3158': 585, '3161': 588, + '3162': 589, '3165': 891, '3166': 892, '3169': 1274, '3170': 1275, + '3173': 1278, '3174': 1279, '3181': 7622, '3182': 7623, '3282': 11799, + '3316': 578, '3379': 42785, '3393': 1159, '3416': 8377 +}; + +// Some characters, e.g. copyrightserif, are mapped to the private use area and +// might not be displayed using standard fonts. Mapping/hacking well-known chars +// to the similar equivalents in the normal characters range. +var SpecialPUASymbols = { + '63721': 0x00A9, // copyrightsans (0xF8E9) => copyright + '63193': 0x00A9, // copyrightserif (0xF6D9) => copyright + '63720': 0x00AE, // registersans (0xF8E8) => registered + '63194': 0x00AE, // registerserif (0xF6DA) => registered + '63722': 0x2122, // trademarksans (0xF8EA) => trademark + '63195': 0x2122, // trademarkserif (0xF6DB) => trademark + '63729': 0x23A7, // bracelefttp (0xF8F1) + '63730': 0x23A8, // braceleftmid (0xF8F2) + '63731': 0x23A9, // braceleftbt (0xF8F3) + '63740': 0x23AB, // bracerighttp (0xF8FC) + '63741': 0x23AC, // bracerightmid (0xF8FD) + '63742': 0x23AD, // bracerightbt (0xF8FE) + '63726': 0x23A1, // bracketlefttp (0xF8EE) + '63727': 0x23A2, // bracketleftex (0xF8EF) + '63728': 0x23A3, // bracketleftbt (0xF8F0) + '63737': 0x23A4, // bracketrighttp (0xF8F9) + '63738': 0x23A5, // bracketrightex (0xF8FA) + '63739': 0x23A6, // bracketrightbt (0xF8FB) + '63723': 0x239B, // parenlefttp (0xF8EB) + '63724': 0x239C, // parenleftex (0xF8EC) + '63725': 0x239D, // parenleftbt (0xF8ED) + '63734': 0x239E, // parenrighttp (0xF8F6) + '63735': 0x239F, // parenrightex (0xF8F7) + '63736': 0x23A0, // parenrightbt (0xF8F8) +}; +function mapSpecialUnicodeValues(code) { + if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials unicode block. + return 0; + } else if (code >= 0xF600 && code <= 0xF8FF) { + return (SpecialPUASymbols[code] || code); + } + return code; +} + +var UnicodeRanges = [ + { 'begin': 0x0000, 'end': 0x007F }, // Basic Latin + { 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement + { 'begin': 0x0100, 'end': 0x017F }, // Latin Extended-A + { 'begin': 0x0180, 'end': 0x024F }, // Latin Extended-B + { 'begin': 0x0250, 'end': 0x02AF }, // IPA Extensions + { 'begin': 0x02B0, 'end': 0x02FF }, // Spacing Modifier Letters + { 'begin': 0x0300, 'end': 0x036F }, // Combining Diacritical Marks + { 'begin': 0x0370, 'end': 0x03FF }, // Greek and Coptic + { 'begin': 0x2C80, 'end': 0x2CFF }, // Coptic + { 'begin': 0x0400, 'end': 0x04FF }, // Cyrillic + { 'begin': 0x0530, 'end': 0x058F }, // Armenian + { 'begin': 0x0590, 'end': 0x05FF }, // Hebrew + { 'begin': 0xA500, 'end': 0xA63F }, // Vai + { 'begin': 0x0600, 'end': 0x06FF }, // Arabic + { 'begin': 0x07C0, 'end': 0x07FF }, // NKo + { 'begin': 0x0900, 'end': 0x097F }, // Devanagari + { 'begin': 0x0980, 'end': 0x09FF }, // Bengali + { 'begin': 0x0A00, 'end': 0x0A7F }, // Gurmukhi + { 'begin': 0x0A80, 'end': 0x0AFF }, // Gujarati + { 'begin': 0x0B00, 'end': 0x0B7F }, // Oriya + { 'begin': 0x0B80, 'end': 0x0BFF }, // Tamil + { 'begin': 0x0C00, 'end': 0x0C7F }, // Telugu + { 'begin': 0x0C80, 'end': 0x0CFF }, // Kannada + { 'begin': 0x0D00, 'end': 0x0D7F }, // Malayalam + { 'begin': 0x0E00, 'end': 0x0E7F }, // Thai + { 'begin': 0x0E80, 'end': 0x0EFF }, // Lao + { 'begin': 0x10A0, 'end': 0x10FF }, // Georgian + { 'begin': 0x1B00, 'end': 0x1B7F }, // Balinese + { 'begin': 0x1100, 'end': 0x11FF }, // Hangul Jamo + { 'begin': 0x1E00, 'end': 0x1EFF }, // Latin Extended Additional + { 'begin': 0x1F00, 'end': 0x1FFF }, // Greek Extended + { 'begin': 0x2000, 'end': 0x206F }, // General Punctuation + { 'begin': 0x2070, 'end': 0x209F }, // Superscripts And Subscripts + { 'begin': 0x20A0, 'end': 0x20CF }, // Currency Symbol + { 'begin': 0x20D0, 'end': 0x20FF }, // Combining Diacritical Marks For Symbols + { 'begin': 0x2100, 'end': 0x214F }, // Letterlike Symbols + { 'begin': 0x2150, 'end': 0x218F }, // Number Forms + { 'begin': 0x2190, 'end': 0x21FF }, // Arrows + { 'begin': 0x2200, 'end': 0x22FF }, // Mathematical Operators + { 'begin': 0x2300, 'end': 0x23FF }, // Miscellaneous Technical + { 'begin': 0x2400, 'end': 0x243F }, // Control Pictures + { 'begin': 0x2440, 'end': 0x245F }, // Optical Character Recognition + { 'begin': 0x2460, 'end': 0x24FF }, // Enclosed Alphanumerics + { 'begin': 0x2500, 'end': 0x257F }, // Box Drawing + { 'begin': 0x2580, 'end': 0x259F }, // Block Elements + { 'begin': 0x25A0, 'end': 0x25FF }, // Geometric Shapes + { 'begin': 0x2600, 'end': 0x26FF }, // Miscellaneous Symbols + { 'begin': 0x2700, 'end': 0x27BF }, // Dingbats + { 'begin': 0x3000, 'end': 0x303F }, // CJK Symbols And Punctuation + { 'begin': 0x3040, 'end': 0x309F }, // Hiragana + { 'begin': 0x30A0, 'end': 0x30FF }, // Katakana + { 'begin': 0x3100, 'end': 0x312F }, // Bopomofo + { 'begin': 0x3130, 'end': 0x318F }, // Hangul Compatibility Jamo + { 'begin': 0xA840, 'end': 0xA87F }, // Phags-pa + { 'begin': 0x3200, 'end': 0x32FF }, // Enclosed CJK Letters And Months + { 'begin': 0x3300, 'end': 0x33FF }, // CJK Compatibility + { 'begin': 0xAC00, 'end': 0xD7AF }, // Hangul Syllables + { 'begin': 0xD800, 'end': 0xDFFF }, // Non-Plane 0 * + { 'begin': 0x10900, 'end': 0x1091F }, // Phoenicia + { 'begin': 0x4E00, 'end': 0x9FFF }, // CJK Unified Ideographs + { 'begin': 0xE000, 'end': 0xF8FF }, // Private Use Area (plane 0) + { 'begin': 0x31C0, 'end': 0x31EF }, // CJK Strokes + { 'begin': 0xFB00, 'end': 0xFB4F }, // Alphabetic Presentation Forms + { 'begin': 0xFB50, 'end': 0xFDFF }, // Arabic Presentation Forms-A + { 'begin': 0xFE20, 'end': 0xFE2F }, // Combining Half Marks + { 'begin': 0xFE10, 'end': 0xFE1F }, // Vertical Forms + { 'begin': 0xFE50, 'end': 0xFE6F }, // Small Form Variants + { 'begin': 0xFE70, 'end': 0xFEFF }, // Arabic Presentation Forms-B + { 'begin': 0xFF00, 'end': 0xFFEF }, // Halfwidth And Fullwidth Forms + { 'begin': 0xFFF0, 'end': 0xFFFF }, // Specials + { 'begin': 0x0F00, 'end': 0x0FFF }, // Tibetan + { 'begin': 0x0700, 'end': 0x074F }, // Syriac + { 'begin': 0x0780, 'end': 0x07BF }, // Thaana + { 'begin': 0x0D80, 'end': 0x0DFF }, // Sinhala + { 'begin': 0x1000, 'end': 0x109F }, // Myanmar + { 'begin': 0x1200, 'end': 0x137F }, // Ethiopic + { 'begin': 0x13A0, 'end': 0x13FF }, // Cherokee + { 'begin': 0x1400, 'end': 0x167F }, // Unified Canadian Aboriginal Syllabics + { 'begin': 0x1680, 'end': 0x169F }, // Ogham + { 'begin': 0x16A0, 'end': 0x16FF }, // Runic + { 'begin': 0x1780, 'end': 0x17FF }, // Khmer + { 'begin': 0x1800, 'end': 0x18AF }, // Mongolian + { 'begin': 0x2800, 'end': 0x28FF }, // Braille Patterns + { 'begin': 0xA000, 'end': 0xA48F }, // Yi Syllables + { 'begin': 0x1700, 'end': 0x171F }, // Tagalog + { 'begin': 0x10300, 'end': 0x1032F }, // Old Italic + { 'begin': 0x10330, 'end': 0x1034F }, // Gothic + { 'begin': 0x10400, 'end': 0x1044F }, // Deseret + { 'begin': 0x1D000, 'end': 0x1D0FF }, // Byzantine Musical Symbols + { 'begin': 0x1D400, 'end': 0x1D7FF }, // Mathematical Alphanumeric Symbols + { 'begin': 0xFF000, 'end': 0xFFFFD }, // Private Use (plane 15) + { 'begin': 0xFE00, 'end': 0xFE0F }, // Variation Selectors + { 'begin': 0xE0000, 'end': 0xE007F }, // Tags + { 'begin': 0x1900, 'end': 0x194F }, // Limbu + { 'begin': 0x1950, 'end': 0x197F }, // Tai Le + { 'begin': 0x1980, 'end': 0x19DF }, // New Tai Lue + { 'begin': 0x1A00, 'end': 0x1A1F }, // Buginese + { 'begin': 0x2C00, 'end': 0x2C5F }, // Glagolitic + { 'begin': 0x2D30, 'end': 0x2D7F }, // Tifinagh + { 'begin': 0x4DC0, 'end': 0x4DFF }, // Yijing Hexagram Symbols + { 'begin': 0xA800, 'end': 0xA82F }, // Syloti Nagri + { 'begin': 0x10000, 'end': 0x1007F }, // Linear B Syllabary + { 'begin': 0x10140, 'end': 0x1018F }, // Ancient Greek Numbers + { 'begin': 0x10380, 'end': 0x1039F }, // Ugaritic + { 'begin': 0x103A0, 'end': 0x103DF }, // Old Persian + { 'begin': 0x10450, 'end': 0x1047F }, // Shavian + { 'begin': 0x10480, 'end': 0x104AF }, // Osmanya + { 'begin': 0x10800, 'end': 0x1083F }, // Cypriot Syllabary + { 'begin': 0x10A00, 'end': 0x10A5F }, // Kharoshthi + { 'begin': 0x1D300, 'end': 0x1D35F }, // Tai Xuan Jing Symbols + { 'begin': 0x12000, 'end': 0x123FF }, // Cuneiform + { 'begin': 0x1D360, 'end': 0x1D37F }, // Counting Rod Numerals + { 'begin': 0x1B80, 'end': 0x1BBF }, // Sundanese + { 'begin': 0x1C00, 'end': 0x1C4F }, // Lepcha + { 'begin': 0x1C50, 'end': 0x1C7F }, // Ol Chiki + { 'begin': 0xA880, 'end': 0xA8DF }, // Saurashtra + { 'begin': 0xA900, 'end': 0xA92F }, // Kayah Li + { 'begin': 0xA930, 'end': 0xA95F }, // Rejang + { 'begin': 0xAA00, 'end': 0xAA5F }, // Cham + { 'begin': 0x10190, 'end': 0x101CF }, // Ancient Symbols + { 'begin': 0x101D0, 'end': 0x101FF }, // Phaistos Disc + { 'begin': 0x102A0, 'end': 0x102DF }, // Carian + { 'begin': 0x1F030, 'end': 0x1F09F } // Domino Tiles +]; + +var MacStandardGlyphOrdering = [ + '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', + 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', + 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', + 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', + 'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', + 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', + 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', + 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', + 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', + 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', + 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', + 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', + 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', + 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', + 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', + 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', + 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', + 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', + 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', + 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', + 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', + 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', + 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', + 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', + 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', + 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', + 'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', + 'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter', + 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', + 'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat']; + +function getUnicodeRangeFor(value) { + for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) { + var range = UnicodeRanges[i]; + if (value >= range.begin && value < range.end) { + return i; + } + } + return -1; +} + +function isRTLRangeFor(value) { + var range = UnicodeRanges[13]; + if (value >= range.begin && value < range.end) { + return true; + } + range = UnicodeRanges[11]; + if (value >= range.begin && value < range.end) { + return true; + } + return false; +} + +// The normalization table is obtained by filtering the Unicode characters +// database with entries. +var NormalizedUnicodes = { + '\u00A8': '\u0020\u0308', + '\u00AF': '\u0020\u0304', + '\u00B4': '\u0020\u0301', + '\u00B5': '\u03BC', + '\u00B8': '\u0020\u0327', + '\u0132': '\u0049\u004A', + '\u0133': '\u0069\u006A', + '\u013F': '\u004C\u00B7', + '\u0140': '\u006C\u00B7', + '\u0149': '\u02BC\u006E', + '\u017F': '\u0073', + '\u01C4': '\u0044\u017D', + '\u01C5': '\u0044\u017E', + '\u01C6': '\u0064\u017E', + '\u01C7': '\u004C\u004A', + '\u01C8': '\u004C\u006A', + '\u01C9': '\u006C\u006A', + '\u01CA': '\u004E\u004A', + '\u01CB': '\u004E\u006A', + '\u01CC': '\u006E\u006A', + '\u01F1': '\u0044\u005A', + '\u01F2': '\u0044\u007A', + '\u01F3': '\u0064\u007A', + '\u02D8': '\u0020\u0306', + '\u02D9': '\u0020\u0307', + '\u02DA': '\u0020\u030A', + '\u02DB': '\u0020\u0328', + '\u02DC': '\u0020\u0303', + '\u02DD': '\u0020\u030B', + '\u037A': '\u0020\u0345', + '\u0384': '\u0020\u0301', + '\u03D0': '\u03B2', + '\u03D1': '\u03B8', + '\u03D2': '\u03A5', + '\u03D5': '\u03C6', + '\u03D6': '\u03C0', + '\u03F0': '\u03BA', + '\u03F1': '\u03C1', + '\u03F2': '\u03C2', + '\u03F4': '\u0398', + '\u03F5': '\u03B5', + '\u03F9': '\u03A3', + '\u0587': '\u0565\u0582', + '\u0675': '\u0627\u0674', + '\u0676': '\u0648\u0674', + '\u0677': '\u06C7\u0674', + '\u0678': '\u064A\u0674', + '\u0E33': '\u0E4D\u0E32', + '\u0EB3': '\u0ECD\u0EB2', + '\u0EDC': '\u0EAB\u0E99', + '\u0EDD': '\u0EAB\u0EA1', + '\u0F77': '\u0FB2\u0F81', + '\u0F79': '\u0FB3\u0F81', + '\u1E9A': '\u0061\u02BE', + '\u1FBD': '\u0020\u0313', + '\u1FBF': '\u0020\u0313', + '\u1FC0': '\u0020\u0342', + '\u1FFE': '\u0020\u0314', + '\u2002': '\u0020', + '\u2003': '\u0020', + '\u2004': '\u0020', + '\u2005': '\u0020', + '\u2006': '\u0020', + '\u2008': '\u0020', + '\u2009': '\u0020', + '\u200A': '\u0020', + '\u2017': '\u0020\u0333', + '\u2024': '\u002E', + '\u2025': '\u002E\u002E', + '\u2026': '\u002E\u002E\u002E', + '\u2033': '\u2032\u2032', + '\u2034': '\u2032\u2032\u2032', + '\u2036': '\u2035\u2035', + '\u2037': '\u2035\u2035\u2035', + '\u203C': '\u0021\u0021', + '\u203E': '\u0020\u0305', + '\u2047': '\u003F\u003F', + '\u2048': '\u003F\u0021', + '\u2049': '\u0021\u003F', + '\u2057': '\u2032\u2032\u2032\u2032', + '\u205F': '\u0020', + '\u20A8': '\u0052\u0073', + '\u2100': '\u0061\u002F\u0063', + '\u2101': '\u0061\u002F\u0073', + '\u2103': '\u00B0\u0043', + '\u2105': '\u0063\u002F\u006F', + '\u2106': '\u0063\u002F\u0075', + '\u2107': '\u0190', + '\u2109': '\u00B0\u0046', + '\u2116': '\u004E\u006F', + '\u2121': '\u0054\u0045\u004C', + '\u2135': '\u05D0', + '\u2136': '\u05D1', + '\u2137': '\u05D2', + '\u2138': '\u05D3', + '\u213B': '\u0046\u0041\u0058', + '\u2160': '\u0049', + '\u2161': '\u0049\u0049', + '\u2162': '\u0049\u0049\u0049', + '\u2163': '\u0049\u0056', + '\u2164': '\u0056', + '\u2165': '\u0056\u0049', + '\u2166': '\u0056\u0049\u0049', + '\u2167': '\u0056\u0049\u0049\u0049', + '\u2168': '\u0049\u0058', + '\u2169': '\u0058', + '\u216A': '\u0058\u0049', + '\u216B': '\u0058\u0049\u0049', + '\u216C': '\u004C', + '\u216D': '\u0043', + '\u216E': '\u0044', + '\u216F': '\u004D', + '\u2170': '\u0069', + '\u2171': '\u0069\u0069', + '\u2172': '\u0069\u0069\u0069', + '\u2173': '\u0069\u0076', + '\u2174': '\u0076', + '\u2175': '\u0076\u0069', + '\u2176': '\u0076\u0069\u0069', + '\u2177': '\u0076\u0069\u0069\u0069', + '\u2178': '\u0069\u0078', + '\u2179': '\u0078', + '\u217A': '\u0078\u0069', + '\u217B': '\u0078\u0069\u0069', + '\u217C': '\u006C', + '\u217D': '\u0063', + '\u217E': '\u0064', + '\u217F': '\u006D', + '\u222C': '\u222B\u222B', + '\u222D': '\u222B\u222B\u222B', + '\u222F': '\u222E\u222E', + '\u2230': '\u222E\u222E\u222E', + '\u2474': '\u0028\u0031\u0029', + '\u2475': '\u0028\u0032\u0029', + '\u2476': '\u0028\u0033\u0029', + '\u2477': '\u0028\u0034\u0029', + '\u2478': '\u0028\u0035\u0029', + '\u2479': '\u0028\u0036\u0029', + '\u247A': '\u0028\u0037\u0029', + '\u247B': '\u0028\u0038\u0029', + '\u247C': '\u0028\u0039\u0029', + '\u247D': '\u0028\u0031\u0030\u0029', + '\u247E': '\u0028\u0031\u0031\u0029', + '\u247F': '\u0028\u0031\u0032\u0029', + '\u2480': '\u0028\u0031\u0033\u0029', + '\u2481': '\u0028\u0031\u0034\u0029', + '\u2482': '\u0028\u0031\u0035\u0029', + '\u2483': '\u0028\u0031\u0036\u0029', + '\u2484': '\u0028\u0031\u0037\u0029', + '\u2485': '\u0028\u0031\u0038\u0029', + '\u2486': '\u0028\u0031\u0039\u0029', + '\u2487': '\u0028\u0032\u0030\u0029', + '\u2488': '\u0031\u002E', + '\u2489': '\u0032\u002E', + '\u248A': '\u0033\u002E', + '\u248B': '\u0034\u002E', + '\u248C': '\u0035\u002E', + '\u248D': '\u0036\u002E', + '\u248E': '\u0037\u002E', + '\u248F': '\u0038\u002E', + '\u2490': '\u0039\u002E', + '\u2491': '\u0031\u0030\u002E', + '\u2492': '\u0031\u0031\u002E', + '\u2493': '\u0031\u0032\u002E', + '\u2494': '\u0031\u0033\u002E', + '\u2495': '\u0031\u0034\u002E', + '\u2496': '\u0031\u0035\u002E', + '\u2497': '\u0031\u0036\u002E', + '\u2498': '\u0031\u0037\u002E', + '\u2499': '\u0031\u0038\u002E', + '\u249A': '\u0031\u0039\u002E', + '\u249B': '\u0032\u0030\u002E', + '\u249C': '\u0028\u0061\u0029', + '\u249D': '\u0028\u0062\u0029', + '\u249E': '\u0028\u0063\u0029', + '\u249F': '\u0028\u0064\u0029', + '\u24A0': '\u0028\u0065\u0029', + '\u24A1': '\u0028\u0066\u0029', + '\u24A2': '\u0028\u0067\u0029', + '\u24A3': '\u0028\u0068\u0029', + '\u24A4': '\u0028\u0069\u0029', + '\u24A5': '\u0028\u006A\u0029', + '\u24A6': '\u0028\u006B\u0029', + '\u24A7': '\u0028\u006C\u0029', + '\u24A8': '\u0028\u006D\u0029', + '\u24A9': '\u0028\u006E\u0029', + '\u24AA': '\u0028\u006F\u0029', + '\u24AB': '\u0028\u0070\u0029', + '\u24AC': '\u0028\u0071\u0029', + '\u24AD': '\u0028\u0072\u0029', + '\u24AE': '\u0028\u0073\u0029', + '\u24AF': '\u0028\u0074\u0029', + '\u24B0': '\u0028\u0075\u0029', + '\u24B1': '\u0028\u0076\u0029', + '\u24B2': '\u0028\u0077\u0029', + '\u24B3': '\u0028\u0078\u0029', + '\u24B4': '\u0028\u0079\u0029', + '\u24B5': '\u0028\u007A\u0029', + '\u2A0C': '\u222B\u222B\u222B\u222B', + '\u2A74': '\u003A\u003A\u003D', + '\u2A75': '\u003D\u003D', + '\u2A76': '\u003D\u003D\u003D', + '\u2E9F': '\u6BCD', + '\u2EF3': '\u9F9F', + '\u2F00': '\u4E00', + '\u2F01': '\u4E28', + '\u2F02': '\u4E36', + '\u2F03': '\u4E3F', + '\u2F04': '\u4E59', + '\u2F05': '\u4E85', + '\u2F06': '\u4E8C', + '\u2F07': '\u4EA0', + '\u2F08': '\u4EBA', + '\u2F09': '\u513F', + '\u2F0A': '\u5165', + '\u2F0B': '\u516B', + '\u2F0C': '\u5182', + '\u2F0D': '\u5196', + '\u2F0E': '\u51AB', + '\u2F0F': '\u51E0', + '\u2F10': '\u51F5', + '\u2F11': '\u5200', + '\u2F12': '\u529B', + '\u2F13': '\u52F9', + '\u2F14': '\u5315', + '\u2F15': '\u531A', + '\u2F16': '\u5338', + '\u2F17': '\u5341', + '\u2F18': '\u535C', + '\u2F19': '\u5369', + '\u2F1A': '\u5382', + '\u2F1B': '\u53B6', + '\u2F1C': '\u53C8', + '\u2F1D': '\u53E3', + '\u2F1E': '\u56D7', + '\u2F1F': '\u571F', + '\u2F20': '\u58EB', + '\u2F21': '\u5902', + '\u2F22': '\u590A', + '\u2F23': '\u5915', + '\u2F24': '\u5927', + '\u2F25': '\u5973', + '\u2F26': '\u5B50', + '\u2F27': '\u5B80', + '\u2F28': '\u5BF8', + '\u2F29': '\u5C0F', + '\u2F2A': '\u5C22', + '\u2F2B': '\u5C38', + '\u2F2C': '\u5C6E', + '\u2F2D': '\u5C71', + '\u2F2E': '\u5DDB', + '\u2F2F': '\u5DE5', + '\u2F30': '\u5DF1', + '\u2F31': '\u5DFE', + '\u2F32': '\u5E72', + '\u2F33': '\u5E7A', + '\u2F34': '\u5E7F', + '\u2F35': '\u5EF4', + '\u2F36': '\u5EFE', + '\u2F37': '\u5F0B', + '\u2F38': '\u5F13', + '\u2F39': '\u5F50', + '\u2F3A': '\u5F61', + '\u2F3B': '\u5F73', + '\u2F3C': '\u5FC3', + '\u2F3D': '\u6208', + '\u2F3E': '\u6236', + '\u2F3F': '\u624B', + '\u2F40': '\u652F', + '\u2F41': '\u6534', + '\u2F42': '\u6587', + '\u2F43': '\u6597', + '\u2F44': '\u65A4', + '\u2F45': '\u65B9', + '\u2F46': '\u65E0', + '\u2F47': '\u65E5', + '\u2F48': '\u66F0', + '\u2F49': '\u6708', + '\u2F4A': '\u6728', + '\u2F4B': '\u6B20', + '\u2F4C': '\u6B62', + '\u2F4D': '\u6B79', + '\u2F4E': '\u6BB3', + '\u2F4F': '\u6BCB', + '\u2F50': '\u6BD4', + '\u2F51': '\u6BDB', + '\u2F52': '\u6C0F', + '\u2F53': '\u6C14', + '\u2F54': '\u6C34', + '\u2F55': '\u706B', + '\u2F56': '\u722A', + '\u2F57': '\u7236', + '\u2F58': '\u723B', + '\u2F59': '\u723F', + '\u2F5A': '\u7247', + '\u2F5B': '\u7259', + '\u2F5C': '\u725B', + '\u2F5D': '\u72AC', + '\u2F5E': '\u7384', + '\u2F5F': '\u7389', + '\u2F60': '\u74DC', + '\u2F61': '\u74E6', + '\u2F62': '\u7518', + '\u2F63': '\u751F', + '\u2F64': '\u7528', + '\u2F65': '\u7530', + '\u2F66': '\u758B', + '\u2F67': '\u7592', + '\u2F68': '\u7676', + '\u2F69': '\u767D', + '\u2F6A': '\u76AE', + '\u2F6B': '\u76BF', + '\u2F6C': '\u76EE', + '\u2F6D': '\u77DB', + '\u2F6E': '\u77E2', + '\u2F6F': '\u77F3', + '\u2F70': '\u793A', + '\u2F71': '\u79B8', + '\u2F72': '\u79BE', + '\u2F73': '\u7A74', + '\u2F74': '\u7ACB', + '\u2F75': '\u7AF9', + '\u2F76': '\u7C73', + '\u2F77': '\u7CF8', + '\u2F78': '\u7F36', + '\u2F79': '\u7F51', + '\u2F7A': '\u7F8A', + '\u2F7B': '\u7FBD', + '\u2F7C': '\u8001', + '\u2F7D': '\u800C', + '\u2F7E': '\u8012', + '\u2F7F': '\u8033', + '\u2F80': '\u807F', + '\u2F81': '\u8089', + '\u2F82': '\u81E3', + '\u2F83': '\u81EA', + '\u2F84': '\u81F3', + '\u2F85': '\u81FC', + '\u2F86': '\u820C', + '\u2F87': '\u821B', + '\u2F88': '\u821F', + '\u2F89': '\u826E', + '\u2F8A': '\u8272', + '\u2F8B': '\u8278', + '\u2F8C': '\u864D', + '\u2F8D': '\u866B', + '\u2F8E': '\u8840', + '\u2F8F': '\u884C', + '\u2F90': '\u8863', + '\u2F91': '\u897E', + '\u2F92': '\u898B', + '\u2F93': '\u89D2', + '\u2F94': '\u8A00', + '\u2F95': '\u8C37', + '\u2F96': '\u8C46', + '\u2F97': '\u8C55', + '\u2F98': '\u8C78', + '\u2F99': '\u8C9D', + '\u2F9A': '\u8D64', + '\u2F9B': '\u8D70', + '\u2F9C': '\u8DB3', + '\u2F9D': '\u8EAB', + '\u2F9E': '\u8ECA', + '\u2F9F': '\u8F9B', + '\u2FA0': '\u8FB0', + '\u2FA1': '\u8FB5', + '\u2FA2': '\u9091', + '\u2FA3': '\u9149', + '\u2FA4': '\u91C6', + '\u2FA5': '\u91CC', + '\u2FA6': '\u91D1', + '\u2FA7': '\u9577', + '\u2FA8': '\u9580', + '\u2FA9': '\u961C', + '\u2FAA': '\u96B6', + '\u2FAB': '\u96B9', + '\u2FAC': '\u96E8', + '\u2FAD': '\u9751', + '\u2FAE': '\u975E', + '\u2FAF': '\u9762', + '\u2FB0': '\u9769', + '\u2FB1': '\u97CB', + '\u2FB2': '\u97ED', + '\u2FB3': '\u97F3', + '\u2FB4': '\u9801', + '\u2FB5': '\u98A8', + '\u2FB6': '\u98DB', + '\u2FB7': '\u98DF', + '\u2FB8': '\u9996', + '\u2FB9': '\u9999', + '\u2FBA': '\u99AC', + '\u2FBB': '\u9AA8', + '\u2FBC': '\u9AD8', + '\u2FBD': '\u9ADF', + '\u2FBE': '\u9B25', + '\u2FBF': '\u9B2F', + '\u2FC0': '\u9B32', + '\u2FC1': '\u9B3C', + '\u2FC2': '\u9B5A', + '\u2FC3': '\u9CE5', + '\u2FC4': '\u9E75', + '\u2FC5': '\u9E7F', + '\u2FC6': '\u9EA5', + '\u2FC7': '\u9EBB', + '\u2FC8': '\u9EC3', + '\u2FC9': '\u9ECD', + '\u2FCA': '\u9ED1', + '\u2FCB': '\u9EF9', + '\u2FCC': '\u9EFD', + '\u2FCD': '\u9F0E', + '\u2FCE': '\u9F13', + '\u2FCF': '\u9F20', + '\u2FD0': '\u9F3B', + '\u2FD1': '\u9F4A', + '\u2FD2': '\u9F52', + '\u2FD3': '\u9F8D', + '\u2FD4': '\u9F9C', + '\u2FD5': '\u9FA0', + '\u3036': '\u3012', + '\u3038': '\u5341', + '\u3039': '\u5344', + '\u303A': '\u5345', + '\u309B': '\u0020\u3099', + '\u309C': '\u0020\u309A', + '\u3131': '\u1100', + '\u3132': '\u1101', + '\u3133': '\u11AA', + '\u3134': '\u1102', + '\u3135': '\u11AC', + '\u3136': '\u11AD', + '\u3137': '\u1103', + '\u3138': '\u1104', + '\u3139': '\u1105', + '\u313A': '\u11B0', + '\u313B': '\u11B1', + '\u313C': '\u11B2', + '\u313D': '\u11B3', + '\u313E': '\u11B4', + '\u313F': '\u11B5', + '\u3140': '\u111A', + '\u3141': '\u1106', + '\u3142': '\u1107', + '\u3143': '\u1108', + '\u3144': '\u1121', + '\u3145': '\u1109', + '\u3146': '\u110A', + '\u3147': '\u110B', + '\u3148': '\u110C', + '\u3149': '\u110D', + '\u314A': '\u110E', + '\u314B': '\u110F', + '\u314C': '\u1110', + '\u314D': '\u1111', + '\u314E': '\u1112', + '\u314F': '\u1161', + '\u3150': '\u1162', + '\u3151': '\u1163', + '\u3152': '\u1164', + '\u3153': '\u1165', + '\u3154': '\u1166', + '\u3155': '\u1167', + '\u3156': '\u1168', + '\u3157': '\u1169', + '\u3158': '\u116A', + '\u3159': '\u116B', + '\u315A': '\u116C', + '\u315B': '\u116D', + '\u315C': '\u116E', + '\u315D': '\u116F', + '\u315E': '\u1170', + '\u315F': '\u1171', + '\u3160': '\u1172', + '\u3161': '\u1173', + '\u3162': '\u1174', + '\u3163': '\u1175', + '\u3164': '\u1160', + '\u3165': '\u1114', + '\u3166': '\u1115', + '\u3167': '\u11C7', + '\u3168': '\u11C8', + '\u3169': '\u11CC', + '\u316A': '\u11CE', + '\u316B': '\u11D3', + '\u316C': '\u11D7', + '\u316D': '\u11D9', + '\u316E': '\u111C', + '\u316F': '\u11DD', + '\u3170': '\u11DF', + '\u3171': '\u111D', + '\u3172': '\u111E', + '\u3173': '\u1120', + '\u3174': '\u1122', + '\u3175': '\u1123', + '\u3176': '\u1127', + '\u3177': '\u1129', + '\u3178': '\u112B', + '\u3179': '\u112C', + '\u317A': '\u112D', + '\u317B': '\u112E', + '\u317C': '\u112F', + '\u317D': '\u1132', + '\u317E': '\u1136', + '\u317F': '\u1140', + '\u3180': '\u1147', + '\u3181': '\u114C', + '\u3182': '\u11F1', + '\u3183': '\u11F2', + '\u3184': '\u1157', + '\u3185': '\u1158', + '\u3186': '\u1159', + '\u3187': '\u1184', + '\u3188': '\u1185', + '\u3189': '\u1188', + '\u318A': '\u1191', + '\u318B': '\u1192', + '\u318C': '\u1194', + '\u318D': '\u119E', + '\u318E': '\u11A1', + '\u3200': '\u0028\u1100\u0029', + '\u3201': '\u0028\u1102\u0029', + '\u3202': '\u0028\u1103\u0029', + '\u3203': '\u0028\u1105\u0029', + '\u3204': '\u0028\u1106\u0029', + '\u3205': '\u0028\u1107\u0029', + '\u3206': '\u0028\u1109\u0029', + '\u3207': '\u0028\u110B\u0029', + '\u3208': '\u0028\u110C\u0029', + '\u3209': '\u0028\u110E\u0029', + '\u320A': '\u0028\u110F\u0029', + '\u320B': '\u0028\u1110\u0029', + '\u320C': '\u0028\u1111\u0029', + '\u320D': '\u0028\u1112\u0029', + '\u320E': '\u0028\u1100\u1161\u0029', + '\u320F': '\u0028\u1102\u1161\u0029', + '\u3210': '\u0028\u1103\u1161\u0029', + '\u3211': '\u0028\u1105\u1161\u0029', + '\u3212': '\u0028\u1106\u1161\u0029', + '\u3213': '\u0028\u1107\u1161\u0029', + '\u3214': '\u0028\u1109\u1161\u0029', + '\u3215': '\u0028\u110B\u1161\u0029', + '\u3216': '\u0028\u110C\u1161\u0029', + '\u3217': '\u0028\u110E\u1161\u0029', + '\u3218': '\u0028\u110F\u1161\u0029', + '\u3219': '\u0028\u1110\u1161\u0029', + '\u321A': '\u0028\u1111\u1161\u0029', + '\u321B': '\u0028\u1112\u1161\u0029', + '\u321C': '\u0028\u110C\u116E\u0029', + '\u321D': '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029', + '\u321E': '\u0028\u110B\u1169\u1112\u116E\u0029', + '\u3220': '\u0028\u4E00\u0029', + '\u3221': '\u0028\u4E8C\u0029', + '\u3222': '\u0028\u4E09\u0029', + '\u3223': '\u0028\u56DB\u0029', + '\u3224': '\u0028\u4E94\u0029', + '\u3225': '\u0028\u516D\u0029', + '\u3226': '\u0028\u4E03\u0029', + '\u3227': '\u0028\u516B\u0029', + '\u3228': '\u0028\u4E5D\u0029', + '\u3229': '\u0028\u5341\u0029', + '\u322A': '\u0028\u6708\u0029', + '\u322B': '\u0028\u706B\u0029', + '\u322C': '\u0028\u6C34\u0029', + '\u322D': '\u0028\u6728\u0029', + '\u322E': '\u0028\u91D1\u0029', + '\u322F': '\u0028\u571F\u0029', + '\u3230': '\u0028\u65E5\u0029', + '\u3231': '\u0028\u682A\u0029', + '\u3232': '\u0028\u6709\u0029', + '\u3233': '\u0028\u793E\u0029', + '\u3234': '\u0028\u540D\u0029', + '\u3235': '\u0028\u7279\u0029', + '\u3236': '\u0028\u8CA1\u0029', + '\u3237': '\u0028\u795D\u0029', + '\u3238': '\u0028\u52B4\u0029', + '\u3239': '\u0028\u4EE3\u0029', + '\u323A': '\u0028\u547C\u0029', + '\u323B': '\u0028\u5B66\u0029', + '\u323C': '\u0028\u76E3\u0029', + '\u323D': '\u0028\u4F01\u0029', + '\u323E': '\u0028\u8CC7\u0029', + '\u323F': '\u0028\u5354\u0029', + '\u3240': '\u0028\u796D\u0029', + '\u3241': '\u0028\u4F11\u0029', + '\u3242': '\u0028\u81EA\u0029', + '\u3243': '\u0028\u81F3\u0029', + '\u32C0': '\u0031\u6708', + '\u32C1': '\u0032\u6708', + '\u32C2': '\u0033\u6708', + '\u32C3': '\u0034\u6708', + '\u32C4': '\u0035\u6708', + '\u32C5': '\u0036\u6708', + '\u32C6': '\u0037\u6708', + '\u32C7': '\u0038\u6708', + '\u32C8': '\u0039\u6708', + '\u32C9': '\u0031\u0030\u6708', + '\u32CA': '\u0031\u0031\u6708', + '\u32CB': '\u0031\u0032\u6708', + '\u3358': '\u0030\u70B9', + '\u3359': '\u0031\u70B9', + '\u335A': '\u0032\u70B9', + '\u335B': '\u0033\u70B9', + '\u335C': '\u0034\u70B9', + '\u335D': '\u0035\u70B9', + '\u335E': '\u0036\u70B9', + '\u335F': '\u0037\u70B9', + '\u3360': '\u0038\u70B9', + '\u3361': '\u0039\u70B9', + '\u3362': '\u0031\u0030\u70B9', + '\u3363': '\u0031\u0031\u70B9', + '\u3364': '\u0031\u0032\u70B9', + '\u3365': '\u0031\u0033\u70B9', + '\u3366': '\u0031\u0034\u70B9', + '\u3367': '\u0031\u0035\u70B9', + '\u3368': '\u0031\u0036\u70B9', + '\u3369': '\u0031\u0037\u70B9', + '\u336A': '\u0031\u0038\u70B9', + '\u336B': '\u0031\u0039\u70B9', + '\u336C': '\u0032\u0030\u70B9', + '\u336D': '\u0032\u0031\u70B9', + '\u336E': '\u0032\u0032\u70B9', + '\u336F': '\u0032\u0033\u70B9', + '\u3370': '\u0032\u0034\u70B9', + '\u33E0': '\u0031\u65E5', + '\u33E1': '\u0032\u65E5', + '\u33E2': '\u0033\u65E5', + '\u33E3': '\u0034\u65E5', + '\u33E4': '\u0035\u65E5', + '\u33E5': '\u0036\u65E5', + '\u33E6': '\u0037\u65E5', + '\u33E7': '\u0038\u65E5', + '\u33E8': '\u0039\u65E5', + '\u33E9': '\u0031\u0030\u65E5', + '\u33EA': '\u0031\u0031\u65E5', + '\u33EB': '\u0031\u0032\u65E5', + '\u33EC': '\u0031\u0033\u65E5', + '\u33ED': '\u0031\u0034\u65E5', + '\u33EE': '\u0031\u0035\u65E5', + '\u33EF': '\u0031\u0036\u65E5', + '\u33F0': '\u0031\u0037\u65E5', + '\u33F1': '\u0031\u0038\u65E5', + '\u33F2': '\u0031\u0039\u65E5', + '\u33F3': '\u0032\u0030\u65E5', + '\u33F4': '\u0032\u0031\u65E5', + '\u33F5': '\u0032\u0032\u65E5', + '\u33F6': '\u0032\u0033\u65E5', + '\u33F7': '\u0032\u0034\u65E5', + '\u33F8': '\u0032\u0035\u65E5', + '\u33F9': '\u0032\u0036\u65E5', + '\u33FA': '\u0032\u0037\u65E5', + '\u33FB': '\u0032\u0038\u65E5', + '\u33FC': '\u0032\u0039\u65E5', + '\u33FD': '\u0033\u0030\u65E5', + '\u33FE': '\u0033\u0031\u65E5', + '\uFB00': '\u0066\u0066', + '\uFB01': '\u0066\u0069', + '\uFB02': '\u0066\u006C', + '\uFB03': '\u0066\u0066\u0069', + '\uFB04': '\u0066\u0066\u006C', + '\uFB05': '\u017F\u0074', + '\uFB06': '\u0073\u0074', + '\uFB13': '\u0574\u0576', + '\uFB14': '\u0574\u0565', + '\uFB15': '\u0574\u056B', + '\uFB16': '\u057E\u0576', + '\uFB17': '\u0574\u056D', + '\uFB4F': '\u05D0\u05DC', + '\uFB50': '\u0671', + '\uFB51': '\u0671', + '\uFB52': '\u067B', + '\uFB53': '\u067B', + '\uFB54': '\u067B', + '\uFB55': '\u067B', + '\uFB56': '\u067E', + '\uFB57': '\u067E', + '\uFB58': '\u067E', + '\uFB59': '\u067E', + '\uFB5A': '\u0680', + '\uFB5B': '\u0680', + '\uFB5C': '\u0680', + '\uFB5D': '\u0680', + '\uFB5E': '\u067A', + '\uFB5F': '\u067A', + '\uFB60': '\u067A', + '\uFB61': '\u067A', + '\uFB62': '\u067F', + '\uFB63': '\u067F', + '\uFB64': '\u067F', + '\uFB65': '\u067F', + '\uFB66': '\u0679', + '\uFB67': '\u0679', + '\uFB68': '\u0679', + '\uFB69': '\u0679', + '\uFB6A': '\u06A4', + '\uFB6B': '\u06A4', + '\uFB6C': '\u06A4', + '\uFB6D': '\u06A4', + '\uFB6E': '\u06A6', + '\uFB6F': '\u06A6', + '\uFB70': '\u06A6', + '\uFB71': '\u06A6', + '\uFB72': '\u0684', + '\uFB73': '\u0684', + '\uFB74': '\u0684', + '\uFB75': '\u0684', + '\uFB76': '\u0683', + '\uFB77': '\u0683', + '\uFB78': '\u0683', + '\uFB79': '\u0683', + '\uFB7A': '\u0686', + '\uFB7B': '\u0686', + '\uFB7C': '\u0686', + '\uFB7D': '\u0686', + '\uFB7E': '\u0687', + '\uFB7F': '\u0687', + '\uFB80': '\u0687', + '\uFB81': '\u0687', + '\uFB82': '\u068D', + '\uFB83': '\u068D', + '\uFB84': '\u068C', + '\uFB85': '\u068C', + '\uFB86': '\u068E', + '\uFB87': '\u068E', + '\uFB88': '\u0688', + '\uFB89': '\u0688', + '\uFB8A': '\u0698', + '\uFB8B': '\u0698', + '\uFB8C': '\u0691', + '\uFB8D': '\u0691', + '\uFB8E': '\u06A9', + '\uFB8F': '\u06A9', + '\uFB90': '\u06A9', + '\uFB91': '\u06A9', + '\uFB92': '\u06AF', + '\uFB93': '\u06AF', + '\uFB94': '\u06AF', + '\uFB95': '\u06AF', + '\uFB96': '\u06B3', + '\uFB97': '\u06B3', + '\uFB98': '\u06B3', + '\uFB99': '\u06B3', + '\uFB9A': '\u06B1', + '\uFB9B': '\u06B1', + '\uFB9C': '\u06B1', + '\uFB9D': '\u06B1', + '\uFB9E': '\u06BA', + '\uFB9F': '\u06BA', + '\uFBA0': '\u06BB', + '\uFBA1': '\u06BB', + '\uFBA2': '\u06BB', + '\uFBA3': '\u06BB', + '\uFBA4': '\u06C0', + '\uFBA5': '\u06C0', + '\uFBA6': '\u06C1', + '\uFBA7': '\u06C1', + '\uFBA8': '\u06C1', + '\uFBA9': '\u06C1', + '\uFBAA': '\u06BE', + '\uFBAB': '\u06BE', + '\uFBAC': '\u06BE', + '\uFBAD': '\u06BE', + '\uFBAE': '\u06D2', + '\uFBAF': '\u06D2', + '\uFBB0': '\u06D3', + '\uFBB1': '\u06D3', + '\uFBD3': '\u06AD', + '\uFBD4': '\u06AD', + '\uFBD5': '\u06AD', + '\uFBD6': '\u06AD', + '\uFBD7': '\u06C7', + '\uFBD8': '\u06C7', + '\uFBD9': '\u06C6', + '\uFBDA': '\u06C6', + '\uFBDB': '\u06C8', + '\uFBDC': '\u06C8', + '\uFBDD': '\u0677', + '\uFBDE': '\u06CB', + '\uFBDF': '\u06CB', + '\uFBE0': '\u06C5', + '\uFBE1': '\u06C5', + '\uFBE2': '\u06C9', + '\uFBE3': '\u06C9', + '\uFBE4': '\u06D0', + '\uFBE5': '\u06D0', + '\uFBE6': '\u06D0', + '\uFBE7': '\u06D0', + '\uFBE8': '\u0649', + '\uFBE9': '\u0649', + '\uFBEA': '\u0626\u0627', + '\uFBEB': '\u0626\u0627', + '\uFBEC': '\u0626\u06D5', + '\uFBED': '\u0626\u06D5', + '\uFBEE': '\u0626\u0648', + '\uFBEF': '\u0626\u0648', + '\uFBF0': '\u0626\u06C7', + '\uFBF1': '\u0626\u06C7', + '\uFBF2': '\u0626\u06C6', + '\uFBF3': '\u0626\u06C6', + '\uFBF4': '\u0626\u06C8', + '\uFBF5': '\u0626\u06C8', + '\uFBF6': '\u0626\u06D0', + '\uFBF7': '\u0626\u06D0', + '\uFBF8': '\u0626\u06D0', + '\uFBF9': '\u0626\u0649', + '\uFBFA': '\u0626\u0649', + '\uFBFB': '\u0626\u0649', + '\uFBFC': '\u06CC', + '\uFBFD': '\u06CC', + '\uFBFE': '\u06CC', + '\uFBFF': '\u06CC', + '\uFC00': '\u0626\u062C', + '\uFC01': '\u0626\u062D', + '\uFC02': '\u0626\u0645', + '\uFC03': '\u0626\u0649', + '\uFC04': '\u0626\u064A', + '\uFC05': '\u0628\u062C', + '\uFC06': '\u0628\u062D', + '\uFC07': '\u0628\u062E', + '\uFC08': '\u0628\u0645', + '\uFC09': '\u0628\u0649', + '\uFC0A': '\u0628\u064A', + '\uFC0B': '\u062A\u062C', + '\uFC0C': '\u062A\u062D', + '\uFC0D': '\u062A\u062E', + '\uFC0E': '\u062A\u0645', + '\uFC0F': '\u062A\u0649', + '\uFC10': '\u062A\u064A', + '\uFC11': '\u062B\u062C', + '\uFC12': '\u062B\u0645', + '\uFC13': '\u062B\u0649', + '\uFC14': '\u062B\u064A', + '\uFC15': '\u062C\u062D', + '\uFC16': '\u062C\u0645', + '\uFC17': '\u062D\u062C', + '\uFC18': '\u062D\u0645', + '\uFC19': '\u062E\u062C', + '\uFC1A': '\u062E\u062D', + '\uFC1B': '\u062E\u0645', + '\uFC1C': '\u0633\u062C', + '\uFC1D': '\u0633\u062D', + '\uFC1E': '\u0633\u062E', + '\uFC1F': '\u0633\u0645', + '\uFC20': '\u0635\u062D', + '\uFC21': '\u0635\u0645', + '\uFC22': '\u0636\u062C', + '\uFC23': '\u0636\u062D', + '\uFC24': '\u0636\u062E', + '\uFC25': '\u0636\u0645', + '\uFC26': '\u0637\u062D', + '\uFC27': '\u0637\u0645', + '\uFC28': '\u0638\u0645', + '\uFC29': '\u0639\u062C', + '\uFC2A': '\u0639\u0645', + '\uFC2B': '\u063A\u062C', + '\uFC2C': '\u063A\u0645', + '\uFC2D': '\u0641\u062C', + '\uFC2E': '\u0641\u062D', + '\uFC2F': '\u0641\u062E', + '\uFC30': '\u0641\u0645', + '\uFC31': '\u0641\u0649', + '\uFC32': '\u0641\u064A', + '\uFC33': '\u0642\u062D', + '\uFC34': '\u0642\u0645', + '\uFC35': '\u0642\u0649', + '\uFC36': '\u0642\u064A', + '\uFC37': '\u0643\u0627', + '\uFC38': '\u0643\u062C', + '\uFC39': '\u0643\u062D', + '\uFC3A': '\u0643\u062E', + '\uFC3B': '\u0643\u0644', + '\uFC3C': '\u0643\u0645', + '\uFC3D': '\u0643\u0649', + '\uFC3E': '\u0643\u064A', + '\uFC3F': '\u0644\u062C', + '\uFC40': '\u0644\u062D', + '\uFC41': '\u0644\u062E', + '\uFC42': '\u0644\u0645', + '\uFC43': '\u0644\u0649', + '\uFC44': '\u0644\u064A', + '\uFC45': '\u0645\u062C', + '\uFC46': '\u0645\u062D', + '\uFC47': '\u0645\u062E', + '\uFC48': '\u0645\u0645', + '\uFC49': '\u0645\u0649', + '\uFC4A': '\u0645\u064A', + '\uFC4B': '\u0646\u062C', + '\uFC4C': '\u0646\u062D', + '\uFC4D': '\u0646\u062E', + '\uFC4E': '\u0646\u0645', + '\uFC4F': '\u0646\u0649', + '\uFC50': '\u0646\u064A', + '\uFC51': '\u0647\u062C', + '\uFC52': '\u0647\u0645', + '\uFC53': '\u0647\u0649', + '\uFC54': '\u0647\u064A', + '\uFC55': '\u064A\u062C', + '\uFC56': '\u064A\u062D', + '\uFC57': '\u064A\u062E', + '\uFC58': '\u064A\u0645', + '\uFC59': '\u064A\u0649', + '\uFC5A': '\u064A\u064A', + '\uFC5B': '\u0630\u0670', + '\uFC5C': '\u0631\u0670', + '\uFC5D': '\u0649\u0670', + '\uFC5E': '\u0020\u064C\u0651', + '\uFC5F': '\u0020\u064D\u0651', + '\uFC60': '\u0020\u064E\u0651', + '\uFC61': '\u0020\u064F\u0651', + '\uFC62': '\u0020\u0650\u0651', + '\uFC63': '\u0020\u0651\u0670', + '\uFC64': '\u0626\u0631', + '\uFC65': '\u0626\u0632', + '\uFC66': '\u0626\u0645', + '\uFC67': '\u0626\u0646', + '\uFC68': '\u0626\u0649', + '\uFC69': '\u0626\u064A', + '\uFC6A': '\u0628\u0631', + '\uFC6B': '\u0628\u0632', + '\uFC6C': '\u0628\u0645', + '\uFC6D': '\u0628\u0646', + '\uFC6E': '\u0628\u0649', + '\uFC6F': '\u0628\u064A', + '\uFC70': '\u062A\u0631', + '\uFC71': '\u062A\u0632', + '\uFC72': '\u062A\u0645', + '\uFC73': '\u062A\u0646', + '\uFC74': '\u062A\u0649', + '\uFC75': '\u062A\u064A', + '\uFC76': '\u062B\u0631', + '\uFC77': '\u062B\u0632', + '\uFC78': '\u062B\u0645', + '\uFC79': '\u062B\u0646', + '\uFC7A': '\u062B\u0649', + '\uFC7B': '\u062B\u064A', + '\uFC7C': '\u0641\u0649', + '\uFC7D': '\u0641\u064A', + '\uFC7E': '\u0642\u0649', + '\uFC7F': '\u0642\u064A', + '\uFC80': '\u0643\u0627', + '\uFC81': '\u0643\u0644', + '\uFC82': '\u0643\u0645', + '\uFC83': '\u0643\u0649', + '\uFC84': '\u0643\u064A', + '\uFC85': '\u0644\u0645', + '\uFC86': '\u0644\u0649', + '\uFC87': '\u0644\u064A', + '\uFC88': '\u0645\u0627', + '\uFC89': '\u0645\u0645', + '\uFC8A': '\u0646\u0631', + '\uFC8B': '\u0646\u0632', + '\uFC8C': '\u0646\u0645', + '\uFC8D': '\u0646\u0646', + '\uFC8E': '\u0646\u0649', + '\uFC8F': '\u0646\u064A', + '\uFC90': '\u0649\u0670', + '\uFC91': '\u064A\u0631', + '\uFC92': '\u064A\u0632', + '\uFC93': '\u064A\u0645', + '\uFC94': '\u064A\u0646', + '\uFC95': '\u064A\u0649', + '\uFC96': '\u064A\u064A', + '\uFC97': '\u0626\u062C', + '\uFC98': '\u0626\u062D', + '\uFC99': '\u0626\u062E', + '\uFC9A': '\u0626\u0645', + '\uFC9B': '\u0626\u0647', + '\uFC9C': '\u0628\u062C', + '\uFC9D': '\u0628\u062D', + '\uFC9E': '\u0628\u062E', + '\uFC9F': '\u0628\u0645', + '\uFCA0': '\u0628\u0647', + '\uFCA1': '\u062A\u062C', + '\uFCA2': '\u062A\u062D', + '\uFCA3': '\u062A\u062E', + '\uFCA4': '\u062A\u0645', + '\uFCA5': '\u062A\u0647', + '\uFCA6': '\u062B\u0645', + '\uFCA7': '\u062C\u062D', + '\uFCA8': '\u062C\u0645', + '\uFCA9': '\u062D\u062C', + '\uFCAA': '\u062D\u0645', + '\uFCAB': '\u062E\u062C', + '\uFCAC': '\u062E\u0645', + '\uFCAD': '\u0633\u062C', + '\uFCAE': '\u0633\u062D', + '\uFCAF': '\u0633\u062E', + '\uFCB0': '\u0633\u0645', + '\uFCB1': '\u0635\u062D', + '\uFCB2': '\u0635\u062E', + '\uFCB3': '\u0635\u0645', + '\uFCB4': '\u0636\u062C', + '\uFCB5': '\u0636\u062D', + '\uFCB6': '\u0636\u062E', + '\uFCB7': '\u0636\u0645', + '\uFCB8': '\u0637\u062D', + '\uFCB9': '\u0638\u0645', + '\uFCBA': '\u0639\u062C', + '\uFCBB': '\u0639\u0645', + '\uFCBC': '\u063A\u062C', + '\uFCBD': '\u063A\u0645', + '\uFCBE': '\u0641\u062C', + '\uFCBF': '\u0641\u062D', + '\uFCC0': '\u0641\u062E', + '\uFCC1': '\u0641\u0645', + '\uFCC2': '\u0642\u062D', + '\uFCC3': '\u0642\u0645', + '\uFCC4': '\u0643\u062C', + '\uFCC5': '\u0643\u062D', + '\uFCC6': '\u0643\u062E', + '\uFCC7': '\u0643\u0644', + '\uFCC8': '\u0643\u0645', + '\uFCC9': '\u0644\u062C', + '\uFCCA': '\u0644\u062D', + '\uFCCB': '\u0644\u062E', + '\uFCCC': '\u0644\u0645', + '\uFCCD': '\u0644\u0647', + '\uFCCE': '\u0645\u062C', + '\uFCCF': '\u0645\u062D', + '\uFCD0': '\u0645\u062E', + '\uFCD1': '\u0645\u0645', + '\uFCD2': '\u0646\u062C', + '\uFCD3': '\u0646\u062D', + '\uFCD4': '\u0646\u062E', + '\uFCD5': '\u0646\u0645', + '\uFCD6': '\u0646\u0647', + '\uFCD7': '\u0647\u062C', + '\uFCD8': '\u0647\u0645', + '\uFCD9': '\u0647\u0670', + '\uFCDA': '\u064A\u062C', + '\uFCDB': '\u064A\u062D', + '\uFCDC': '\u064A\u062E', + '\uFCDD': '\u064A\u0645', + '\uFCDE': '\u064A\u0647', + '\uFCDF': '\u0626\u0645', + '\uFCE0': '\u0626\u0647', + '\uFCE1': '\u0628\u0645', + '\uFCE2': '\u0628\u0647', + '\uFCE3': '\u062A\u0645', + '\uFCE4': '\u062A\u0647', + '\uFCE5': '\u062B\u0645', + '\uFCE6': '\u062B\u0647', + '\uFCE7': '\u0633\u0645', + '\uFCE8': '\u0633\u0647', + '\uFCE9': '\u0634\u0645', + '\uFCEA': '\u0634\u0647', + '\uFCEB': '\u0643\u0644', + '\uFCEC': '\u0643\u0645', + '\uFCED': '\u0644\u0645', + '\uFCEE': '\u0646\u0645', + '\uFCEF': '\u0646\u0647', + '\uFCF0': '\u064A\u0645', + '\uFCF1': '\u064A\u0647', + '\uFCF2': '\u0640\u064E\u0651', + '\uFCF3': '\u0640\u064F\u0651', + '\uFCF4': '\u0640\u0650\u0651', + '\uFCF5': '\u0637\u0649', + '\uFCF6': '\u0637\u064A', + '\uFCF7': '\u0639\u0649', + '\uFCF8': '\u0639\u064A', + '\uFCF9': '\u063A\u0649', + '\uFCFA': '\u063A\u064A', + '\uFCFB': '\u0633\u0649', + '\uFCFC': '\u0633\u064A', + '\uFCFD': '\u0634\u0649', + '\uFCFE': '\u0634\u064A', + '\uFCFF': '\u062D\u0649', + '\uFD00': '\u062D\u064A', + '\uFD01': '\u062C\u0649', + '\uFD02': '\u062C\u064A', + '\uFD03': '\u062E\u0649', + '\uFD04': '\u062E\u064A', + '\uFD05': '\u0635\u0649', + '\uFD06': '\u0635\u064A', + '\uFD07': '\u0636\u0649', + '\uFD08': '\u0636\u064A', + '\uFD09': '\u0634\u062C', + '\uFD0A': '\u0634\u062D', + '\uFD0B': '\u0634\u062E', + '\uFD0C': '\u0634\u0645', + '\uFD0D': '\u0634\u0631', + '\uFD0E': '\u0633\u0631', + '\uFD0F': '\u0635\u0631', + '\uFD10': '\u0636\u0631', + '\uFD11': '\u0637\u0649', + '\uFD12': '\u0637\u064A', + '\uFD13': '\u0639\u0649', + '\uFD14': '\u0639\u064A', + '\uFD15': '\u063A\u0649', + '\uFD16': '\u063A\u064A', + '\uFD17': '\u0633\u0649', + '\uFD18': '\u0633\u064A', + '\uFD19': '\u0634\u0649', + '\uFD1A': '\u0634\u064A', + '\uFD1B': '\u062D\u0649', + '\uFD1C': '\u062D\u064A', + '\uFD1D': '\u062C\u0649', + '\uFD1E': '\u062C\u064A', + '\uFD1F': '\u062E\u0649', + '\uFD20': '\u062E\u064A', + '\uFD21': '\u0635\u0649', + '\uFD22': '\u0635\u064A', + '\uFD23': '\u0636\u0649', + '\uFD24': '\u0636\u064A', + '\uFD25': '\u0634\u062C', + '\uFD26': '\u0634\u062D', + '\uFD27': '\u0634\u062E', + '\uFD28': '\u0634\u0645', + '\uFD29': '\u0634\u0631', + '\uFD2A': '\u0633\u0631', + '\uFD2B': '\u0635\u0631', + '\uFD2C': '\u0636\u0631', + '\uFD2D': '\u0634\u062C', + '\uFD2E': '\u0634\u062D', + '\uFD2F': '\u0634\u062E', + '\uFD30': '\u0634\u0645', + '\uFD31': '\u0633\u0647', + '\uFD32': '\u0634\u0647', + '\uFD33': '\u0637\u0645', + '\uFD34': '\u0633\u062C', + '\uFD35': '\u0633\u062D', + '\uFD36': '\u0633\u062E', + '\uFD37': '\u0634\u062C', + '\uFD38': '\u0634\u062D', + '\uFD39': '\u0634\u062E', + '\uFD3A': '\u0637\u0645', + '\uFD3B': '\u0638\u0645', + '\uFD3C': '\u0627\u064B', + '\uFD3D': '\u0627\u064B', + '\uFD50': '\u062A\u062C\u0645', + '\uFD51': '\u062A\u062D\u062C', + '\uFD52': '\u062A\u062D\u062C', + '\uFD53': '\u062A\u062D\u0645', + '\uFD54': '\u062A\u062E\u0645', + '\uFD55': '\u062A\u0645\u062C', + '\uFD56': '\u062A\u0645\u062D', + '\uFD57': '\u062A\u0645\u062E', + '\uFD58': '\u062C\u0645\u062D', + '\uFD59': '\u062C\u0645\u062D', + '\uFD5A': '\u062D\u0645\u064A', + '\uFD5B': '\u062D\u0645\u0649', + '\uFD5C': '\u0633\u062D\u062C', + '\uFD5D': '\u0633\u062C\u062D', + '\uFD5E': '\u0633\u062C\u0649', + '\uFD5F': '\u0633\u0645\u062D', + '\uFD60': '\u0633\u0645\u062D', + '\uFD61': '\u0633\u0645\u062C', + '\uFD62': '\u0633\u0645\u0645', + '\uFD63': '\u0633\u0645\u0645', + '\uFD64': '\u0635\u062D\u062D', + '\uFD65': '\u0635\u062D\u062D', + '\uFD66': '\u0635\u0645\u0645', + '\uFD67': '\u0634\u062D\u0645', + '\uFD68': '\u0634\u062D\u0645', + '\uFD69': '\u0634\u062C\u064A', + '\uFD6A': '\u0634\u0645\u062E', + '\uFD6B': '\u0634\u0645\u062E', + '\uFD6C': '\u0634\u0645\u0645', + '\uFD6D': '\u0634\u0645\u0645', + '\uFD6E': '\u0636\u062D\u0649', + '\uFD6F': '\u0636\u062E\u0645', + '\uFD70': '\u0636\u062E\u0645', + '\uFD71': '\u0637\u0645\u062D', + '\uFD72': '\u0637\u0645\u062D', + '\uFD73': '\u0637\u0645\u0645', + '\uFD74': '\u0637\u0645\u064A', + '\uFD75': '\u0639\u062C\u0645', + '\uFD76': '\u0639\u0645\u0645', + '\uFD77': '\u0639\u0645\u0645', + '\uFD78': '\u0639\u0645\u0649', + '\uFD79': '\u063A\u0645\u0645', + '\uFD7A': '\u063A\u0645\u064A', + '\uFD7B': '\u063A\u0645\u0649', + '\uFD7C': '\u0641\u062E\u0645', + '\uFD7D': '\u0641\u062E\u0645', + '\uFD7E': '\u0642\u0645\u062D', + '\uFD7F': '\u0642\u0645\u0645', + '\uFD80': '\u0644\u062D\u0645', + '\uFD81': '\u0644\u062D\u064A', + '\uFD82': '\u0644\u062D\u0649', + '\uFD83': '\u0644\u062C\u062C', + '\uFD84': '\u0644\u062C\u062C', + '\uFD85': '\u0644\u062E\u0645', + '\uFD86': '\u0644\u062E\u0645', + '\uFD87': '\u0644\u0645\u062D', + '\uFD88': '\u0644\u0645\u062D', + '\uFD89': '\u0645\u062D\u062C', + '\uFD8A': '\u0645\u062D\u0645', + '\uFD8B': '\u0645\u062D\u064A', + '\uFD8C': '\u0645\u062C\u062D', + '\uFD8D': '\u0645\u062C\u0645', + '\uFD8E': '\u0645\u062E\u062C', + '\uFD8F': '\u0645\u062E\u0645', + '\uFD92': '\u0645\u062C\u062E', + '\uFD93': '\u0647\u0645\u062C', + '\uFD94': '\u0647\u0645\u0645', + '\uFD95': '\u0646\u062D\u0645', + '\uFD96': '\u0646\u062D\u0649', + '\uFD97': '\u0646\u062C\u0645', + '\uFD98': '\u0646\u062C\u0645', + '\uFD99': '\u0646\u062C\u0649', + '\uFD9A': '\u0646\u0645\u064A', + '\uFD9B': '\u0646\u0645\u0649', + '\uFD9C': '\u064A\u0645\u0645', + '\uFD9D': '\u064A\u0645\u0645', + '\uFD9E': '\u0628\u062E\u064A', + '\uFD9F': '\u062A\u062C\u064A', + '\uFDA0': '\u062A\u062C\u0649', + '\uFDA1': '\u062A\u062E\u064A', + '\uFDA2': '\u062A\u062E\u0649', + '\uFDA3': '\u062A\u0645\u064A', + '\uFDA4': '\u062A\u0645\u0649', + '\uFDA5': '\u062C\u0645\u064A', + '\uFDA6': '\u062C\u062D\u0649', + '\uFDA7': '\u062C\u0645\u0649', + '\uFDA8': '\u0633\u062E\u0649', + '\uFDA9': '\u0635\u062D\u064A', + '\uFDAA': '\u0634\u062D\u064A', + '\uFDAB': '\u0636\u062D\u064A', + '\uFDAC': '\u0644\u062C\u064A', + '\uFDAD': '\u0644\u0645\u064A', + '\uFDAE': '\u064A\u062D\u064A', + '\uFDAF': '\u064A\u062C\u064A', + '\uFDB0': '\u064A\u0645\u064A', + '\uFDB1': '\u0645\u0645\u064A', + '\uFDB2': '\u0642\u0645\u064A', + '\uFDB3': '\u0646\u062D\u064A', + '\uFDB4': '\u0642\u0645\u062D', + '\uFDB5': '\u0644\u062D\u0645', + '\uFDB6': '\u0639\u0645\u064A', + '\uFDB7': '\u0643\u0645\u064A', + '\uFDB8': '\u0646\u062C\u062D', + '\uFDB9': '\u0645\u062E\u064A', + '\uFDBA': '\u0644\u062C\u0645', + '\uFDBB': '\u0643\u0645\u0645', + '\uFDBC': '\u0644\u062C\u0645', + '\uFDBD': '\u0646\u062C\u062D', + '\uFDBE': '\u062C\u062D\u064A', + '\uFDBF': '\u062D\u062C\u064A', + '\uFDC0': '\u0645\u062C\u064A', + '\uFDC1': '\u0641\u0645\u064A', + '\uFDC2': '\u0628\u062D\u064A', + '\uFDC3': '\u0643\u0645\u0645', + '\uFDC4': '\u0639\u062C\u0645', + '\uFDC5': '\u0635\u0645\u0645', + '\uFDC6': '\u0633\u062E\u064A', + '\uFDC7': '\u0646\u062C\u064A', + '\uFE49': '\u203E', + '\uFE4A': '\u203E', + '\uFE4B': '\u203E', + '\uFE4C': '\u203E', + '\uFE4D': '\u005F', + '\uFE4E': '\u005F', + '\uFE4F': '\u005F', + '\uFE80': '\u0621', + '\uFE81': '\u0622', + '\uFE82': '\u0622', + '\uFE83': '\u0623', + '\uFE84': '\u0623', + '\uFE85': '\u0624', + '\uFE86': '\u0624', + '\uFE87': '\u0625', + '\uFE88': '\u0625', + '\uFE89': '\u0626', + '\uFE8A': '\u0626', + '\uFE8B': '\u0626', + '\uFE8C': '\u0626', + '\uFE8D': '\u0627', + '\uFE8E': '\u0627', + '\uFE8F': '\u0628', + '\uFE90': '\u0628', + '\uFE91': '\u0628', + '\uFE92': '\u0628', + '\uFE93': '\u0629', + '\uFE94': '\u0629', + '\uFE95': '\u062A', + '\uFE96': '\u062A', + '\uFE97': '\u062A', + '\uFE98': '\u062A', + '\uFE99': '\u062B', + '\uFE9A': '\u062B', + '\uFE9B': '\u062B', + '\uFE9C': '\u062B', + '\uFE9D': '\u062C', + '\uFE9E': '\u062C', + '\uFE9F': '\u062C', + '\uFEA0': '\u062C', + '\uFEA1': '\u062D', + '\uFEA2': '\u062D', + '\uFEA3': '\u062D', + '\uFEA4': '\u062D', + '\uFEA5': '\u062E', + '\uFEA6': '\u062E', + '\uFEA7': '\u062E', + '\uFEA8': '\u062E', + '\uFEA9': '\u062F', + '\uFEAA': '\u062F', + '\uFEAB': '\u0630', + '\uFEAC': '\u0630', + '\uFEAD': '\u0631', + '\uFEAE': '\u0631', + '\uFEAF': '\u0632', + '\uFEB0': '\u0632', + '\uFEB1': '\u0633', + '\uFEB2': '\u0633', + '\uFEB3': '\u0633', + '\uFEB4': '\u0633', + '\uFEB5': '\u0634', + '\uFEB6': '\u0634', + '\uFEB7': '\u0634', + '\uFEB8': '\u0634', + '\uFEB9': '\u0635', + '\uFEBA': '\u0635', + '\uFEBB': '\u0635', + '\uFEBC': '\u0635', + '\uFEBD': '\u0636', + '\uFEBE': '\u0636', + '\uFEBF': '\u0636', + '\uFEC0': '\u0636', + '\uFEC1': '\u0637', + '\uFEC2': '\u0637', + '\uFEC3': '\u0637', + '\uFEC4': '\u0637', + '\uFEC5': '\u0638', + '\uFEC6': '\u0638', + '\uFEC7': '\u0638', + '\uFEC8': '\u0638', + '\uFEC9': '\u0639', + '\uFECA': '\u0639', + '\uFECB': '\u0639', + '\uFECC': '\u0639', + '\uFECD': '\u063A', + '\uFECE': '\u063A', + '\uFECF': '\u063A', + '\uFED0': '\u063A', + '\uFED1': '\u0641', + '\uFED2': '\u0641', + '\uFED3': '\u0641', + '\uFED4': '\u0641', + '\uFED5': '\u0642', + '\uFED6': '\u0642', + '\uFED7': '\u0642', + '\uFED8': '\u0642', + '\uFED9': '\u0643', + '\uFEDA': '\u0643', + '\uFEDB': '\u0643', + '\uFEDC': '\u0643', + '\uFEDD': '\u0644', + '\uFEDE': '\u0644', + '\uFEDF': '\u0644', + '\uFEE0': '\u0644', + '\uFEE1': '\u0645', + '\uFEE2': '\u0645', + '\uFEE3': '\u0645', + '\uFEE4': '\u0645', + '\uFEE5': '\u0646', + '\uFEE6': '\u0646', + '\uFEE7': '\u0646', + '\uFEE8': '\u0646', + '\uFEE9': '\u0647', + '\uFEEA': '\u0647', + '\uFEEB': '\u0647', + '\uFEEC': '\u0647', + '\uFEED': '\u0648', + '\uFEEE': '\u0648', + '\uFEEF': '\u0649', + '\uFEF0': '\u0649', + '\uFEF1': '\u064A', + '\uFEF2': '\u064A', + '\uFEF3': '\u064A', + '\uFEF4': '\u064A', + '\uFEF5': '\u0644\u0622', + '\uFEF6': '\u0644\u0622', + '\uFEF7': '\u0644\u0623', + '\uFEF8': '\u0644\u0623', + '\uFEF9': '\u0644\u0625', + '\uFEFA': '\u0644\u0625', + '\uFEFB': '\u0644\u0627', + '\uFEFC': '\u0644\u0627' +}; + +function reverseIfRtl(chars) { + var charsLength = chars.length; + //reverse an arabic ligature + if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) { + return chars; + } + var s = ''; + for (var ii = charsLength - 1; ii >= 0; ii--) { + s += chars[ii]; + } + return s; +} + +function adjustWidths(properties) { + if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) { + return; + } + // adjusting width to fontMatrix scale + var scale = 0.001 / properties.fontMatrix[0]; + var glyphsWidths = properties.widths; + for (var glyph in glyphsWidths) { + glyphsWidths[glyph] *= scale; + } + properties.defaultWidth *= scale; +} + +function getFontType(type, subtype) { + switch (type) { + case 'Type1': + return subtype === 'Type1C' ? FontType.TYPE1C : FontType.TYPE1; + case 'CIDFontType0': + return subtype === 'CIDFontType0C' ? FontType.CIDFONTTYPE0C : + FontType.CIDFONTTYPE0; + case 'OpenType': + return FontType.OPENTYPE; + case 'TrueType': + return FontType.TRUETYPE; + case 'CIDFontType2': + return FontType.CIDFONTTYPE2; + case 'MMType1': + return FontType.MMTYPE1; + case 'Type0': + return FontType.TYPE0; + default: + return FontType.UNKNOWN; + } +} + +var Glyph = (function GlyphClosure() { + function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId) { + this.fontChar = fontChar; + this.unicode = unicode; + this.accent = accent; + this.width = width; + this.vmetric = vmetric; + this.operatorListId = operatorListId; + } + + Glyph.prototype.matchesForCache = + function(fontChar, unicode, accent, width, vmetric, operatorListId) { + return this.fontChar === fontChar && + this.unicode === unicode && + this.accent === accent && + this.width === width && + this.vmetric === vmetric && + this.operatorListId === operatorListId; + }; + + return Glyph; +})(); + +var ToUnicodeMap = (function ToUnicodeMapClosure() { + function ToUnicodeMap(cmap) { + // The elements of this._map can be integers or strings, depending on how + // |cmap| was created. + this._map = cmap; + } + + ToUnicodeMap.prototype = { + get length() { + return this._map.length; + }, + + forEach: function(callback) { + for (var charCode in this._map) { + callback(charCode, this._map[charCode].charCodeAt(0)); + } + }, + + has: function(i) { + return this._map[i] !== undefined; + }, + + get: function(i) { + return this._map[i]; + }, + + charCodeOf: function(v) { + return this._map.indexOf(v); + } + }; + + return ToUnicodeMap; +})(); + +var IdentityToUnicodeMap = (function IdentityToUnicodeMapClosure() { + function IdentityToUnicodeMap(firstChar, lastChar) { + this.firstChar = firstChar; + this.lastChar = lastChar; + } + + IdentityToUnicodeMap.prototype = { + get length() { + return (this.lastChar + 1) - this.firstChar; + }, + + forEach: function (callback) { + for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) { + callback(i, i); + } + }, + + has: function (i) { + return this.firstChar <= i && i <= this.lastChar; + }, + + get: function (i) { + if (this.firstChar <= i && i <= this.lastChar) { + return String.fromCharCode(i); + } + return undefined; + }, + + charCodeOf: function (v) { + error('should not call .charCodeOf'); + } + }; + + return IdentityToUnicodeMap; +})(); + +var OpenTypeFileBuilder = (function OpenTypeFileBuilderClosure() { + function writeInt16(dest, offset, num) { + dest[offset] = (num >> 8) & 0xFF; + dest[offset + 1] = num & 0xFF; + } + + function writeInt32(dest, offset, num) { + dest[offset] = (num >> 24) & 0xFF; + dest[offset + 1] = (num >> 16) & 0xFF; + dest[offset + 2] = (num >> 8) & 0xFF; + dest[offset + 3] = num & 0xFF; + } + + function writeData(dest, offset, data) { + var i, ii; + if (data instanceof Uint8Array) { + dest.set(data, offset); + } else if (typeof data === 'string') { + for (i = 0, ii = data.length; i < ii; i++) { + dest[offset++] = data.charCodeAt(i) & 0xFF; + } + } else { + // treating everything else as array + for (i = 0, ii = data.length; i < ii; i++) { + dest[offset++] = data[i] & 0xFF; + } + } + } + + function OpenTypeFileBuilder(sfnt) { + this.sfnt = sfnt; + this.tables = Object.create(null); + } + + OpenTypeFileBuilder.getSearchParams = + function OpenTypeFileBuilder_getSearchParams(entriesCount, entrySize) { + var maxPower2 = 1, log2 = 0; + while ((maxPower2 ^ entriesCount) > maxPower2) { + maxPower2 <<= 1; + log2++; + } + var searchRange = maxPower2 * entrySize; + return { + range: searchRange, + entry: log2, + rangeShift: entrySize * entriesCount - searchRange + }; + }; + + var OTF_HEADER_SIZE = 12; + var OTF_TABLE_ENTRY_SIZE = 16; + + OpenTypeFileBuilder.prototype = { + toArray: function OpenTypeFileBuilder_toArray() { + var sfnt = this.sfnt; + + // Tables needs to be written by ascendant alphabetic order + var tables = this.tables; + var tablesNames = Object.keys(tables); + tablesNames.sort(); + var numTables = tablesNames.length; + + var i, j, jj, table, tableName; + // layout the tables data + var offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE; + var tableOffsets = [offset]; + for (i = 0; i < numTables; i++) { + table = tables[tablesNames[i]]; + var paddedLength = ((table.length + 3) & ~3) >>> 0; + offset += paddedLength; + tableOffsets.push(offset); + } + + var file = new Uint8Array(offset); + // write the table data first (mostly for checksum) + for (i = 0; i < numTables; i++) { + table = tables[tablesNames[i]]; + writeData(file, tableOffsets[i], table); + } + + // sfnt version (4 bytes) + if (sfnt === 'true') { + // Windows hates the Mac TrueType sfnt version number + sfnt = string32(0x00010000); + } + file[0] = sfnt.charCodeAt(0) & 0xFF; + file[1] = sfnt.charCodeAt(1) & 0xFF; + file[2] = sfnt.charCodeAt(2) & 0xFF; + file[3] = sfnt.charCodeAt(3) & 0xFF; + + // numTables (2 bytes) + writeInt16(file, 4, numTables); + + var searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16); + + // searchRange (2 bytes) + writeInt16(file, 6, searchParams.range); + // entrySelector (2 bytes) + writeInt16(file, 8, searchParams.entry); + // rangeShift (2 bytes) + writeInt16(file, 10, searchParams.rangeShift); + + offset = OTF_HEADER_SIZE; + // writing table entries + for (i = 0; i < numTables; i++) { + tableName = tablesNames[i]; + file[offset] = tableName.charCodeAt(0) & 0xFF; + file[offset + 1] = tableName.charCodeAt(1) & 0xFF; + file[offset + 2] = tableName.charCodeAt(2) & 0xFF; + file[offset + 3] = tableName.charCodeAt(3) & 0xFF; + + // checksum + var checksum = 0; + for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) { + var quad = (file[j] << 24) + (file[j + 1] << 16) + + (file[j + 2] << 8) + file[j + 3]; + checksum = (checksum + quad) | 0; + } + writeInt32(file, offset + 4, checksum); + + // offset + writeInt32(file, offset + 8, tableOffsets[i]); + // length + writeInt32(file, offset + 12, tables[tableName].length); + + offset += OTF_TABLE_ENTRY_SIZE; + } + return file; + }, + + addTable: function OpenTypeFileBuilder_addTable(tag, data) { + if (tag in this.tables) { + throw new Error('Table ' + tag + ' already exists'); + } + this.tables[tag] = data; + } + }; + + return OpenTypeFileBuilder; +})(); + +/** + * 'Font' is the class the outside world should use, it encapsulate all the font + * decoding logics whatever type it is (assuming the font type is supported). + * + * For example to read a Type1 font and to attach it to the document: + * var type1Font = new Font("MyFontName", binaryFile, propertiesObject); + * type1Font.bind(); + */ +var Font = (function FontClosure() { + function Font(name, file, properties) { + var charCode, glyphName, fontChar; + + this.name = name; + this.loadedName = properties.loadedName; + this.isType3Font = properties.isType3Font; + this.sizes = []; + + this.glyphCache = {}; + + var names = name.split('+'); + names = names.length > 1 ? names[1] : names[0]; + names = names.split(/[-,_]/g)[0]; + this.isSerifFont = !!(properties.flags & FontFlags.Serif); + this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + this.isMonospace = !!(properties.flags & FontFlags.FixedPitch); + + var type = properties.type; + var subtype = properties.subtype; + this.type = type; + + this.fallbackName = (this.isMonospace ? 'monospace' : + (this.isSerifFont ? 'serif' : 'sans-serif')); + + this.differences = properties.differences; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.composite = properties.composite; + this.wideChars = properties.wideChars; + this.cMap = properties.cMap; + this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS; + this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS; + this.fontMatrix = properties.fontMatrix; + this.bbox = properties.bbox; + + this.toUnicode = properties.toUnicode = this.buildToUnicode(properties); + + this.toFontChar = []; + + if (properties.type === 'Type3') { + for (charCode = 0; charCode < 256; charCode++) { + this.toFontChar[charCode] = (this.differences[charCode] || + properties.defaultEncoding[charCode]); + } + this.fontType = FontType.TYPE3; + return; + } + + this.cidEncoding = properties.cidEncoding; + this.vertical = properties.vertical; + if (this.vertical) { + this.vmetrics = properties.vmetrics; + this.defaultVMetrics = properties.defaultVMetrics; + } + + if (!file || file.isEmpty) { + if (file) { + // Some bad PDF generators will include empty font files, + // attempting to recover by assuming that no file exists. + warn('Font file is empty in "' + name + '" (' + this.loadedName + ')'); + } + + this.missingFile = true; + // The file data is not specified. Trying to fix the font name + // to be used with the canvas.font. + var fontName = name.replace(/[,_]/g, '-'); + var isStandardFont = !!stdFontMap[fontName] || + !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]); + fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; + + this.bold = (fontName.search(/bold/gi) !== -1); + this.italic = ((fontName.search(/oblique/gi) !== -1) || + (fontName.search(/italic/gi) !== -1)); + + // Use 'name' instead of 'fontName' here because the original + // name ArialBlack for example will be replaced by Helvetica. + this.black = (name.search(/Black/g) !== -1); + + // if at least one width is present, remeasure all chars when exists + this.remeasure = Object.keys(this.widths).length > 0; + if (isStandardFont && type === 'CIDFontType2' && + properties.cidEncoding.indexOf('Identity-') === 0) { + // Standard fonts might be embedded as CID font without glyph mapping. + // Building one based on GlyphMapForStandardFonts. + var map = []; + for (var code in GlyphMapForStandardFonts) { + map[+code] = GlyphMapForStandardFonts[code]; + } + var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap; + if (!isIdentityUnicode) { + this.toUnicode.forEach(function(charCode, unicodeCharCode) { + map[+charCode] = unicodeCharCode; + }); + } + this.toFontChar = map; + this.toUnicode = new ToUnicodeMap(map); + } else if (/Symbol/i.test(fontName)) { + var symbols = Encodings.SymbolSetEncoding; + for (charCode in symbols) { + fontChar = GlyphsUnicode[symbols[charCode]]; + if (!fontChar) { + continue; + } + this.toFontChar[charCode] = fontChar; + } + for (charCode in properties.differences) { + fontChar = GlyphsUnicode[properties.differences[charCode]]; + if (!fontChar) { + continue; + } + this.toFontChar[charCode] = fontChar; + } + } else if (/Dingbats/i.test(fontName)) { + if (/Wingdings/i.test(name)) { + warn('Wingdings font without embedded font file, ' + + 'falling back to the ZapfDingbats encoding.'); + } + var dingbats = Encodings.ZapfDingbatsEncoding; + for (charCode in dingbats) { + fontChar = DingbatsGlyphsUnicode[dingbats[charCode]]; + if (!fontChar) { + continue; + } + this.toFontChar[charCode] = fontChar; + } + for (charCode in properties.differences) { + fontChar = DingbatsGlyphsUnicode[properties.differences[charCode]]; + if (!fontChar) { + continue; + } + this.toFontChar[charCode] = fontChar; + } + } else if (isStandardFont) { + this.toFontChar = []; + for (charCode in properties.defaultEncoding) { + glyphName = (properties.differences[charCode] || + properties.defaultEncoding[charCode]); + this.toFontChar[charCode] = GlyphsUnicode[glyphName]; + } + } else { + var unicodeCharCode, notCidFont = (type.indexOf('CIDFontType') === -1); + this.toUnicode.forEach(function(charCode, unicodeCharCode) { + if (notCidFont) { + glyphName = (properties.differences[charCode] || + properties.defaultEncoding[charCode]); + unicodeCharCode = (GlyphsUnicode[glyphName] || unicodeCharCode); + } + this.toFontChar[charCode] = unicodeCharCode; + }.bind(this)); + } + this.loadedName = fontName.split('-')[0]; + this.loading = false; + this.fontType = getFontType(type, subtype); + return; + } + + // Some fonts might use wrong font types for Type1C or CIDFontType0C + if (subtype === 'Type1C' && (type !== 'Type1' && type !== 'MMType1')) { + // Some TrueType fonts by mistake claim Type1C + if (isTrueTypeFile(file)) { + subtype = 'TrueType'; + } else { + type = 'Type1'; + } + } + if (subtype === 'CIDFontType0C' && type !== 'CIDFontType0') { + type = 'CIDFontType0'; + } + if (subtype === 'OpenType') { + type = 'OpenType'; + } + // Some CIDFontType0C fonts by mistake claim CIDFontType0. + if (type === 'CIDFontType0') { + subtype = isType1File(file) ? 'CIDFontType0' : 'CIDFontType0C'; + } + + var data; + switch (type) { + case 'MMType1': + info('MMType1 font (' + name + '), falling back to Type1.'); + /* falls through */ + case 'Type1': + case 'CIDFontType0': + this.mimetype = 'font/opentype'; + + var cff = (subtype === 'Type1C' || subtype === 'CIDFontType0C') ? + new CFFFont(file, properties) : new Type1Font(name, file, properties); + + adjustWidths(properties); + + // Wrap the CFF data inside an OTF font file + data = this.convert(name, cff, properties); + break; + + case 'OpenType': + case 'TrueType': + case 'CIDFontType2': + this.mimetype = 'font/opentype'; + + // Repair the TrueType file. It is can be damaged in the point of + // view of the sanitizer + data = this.checkAndRepair(name, file, properties); + if (this.isOpenType) { + type = 'OpenType'; + } + break; + + default: + error('Font ' + type + ' is not supported'); + break; + } + + this.data = data; + this.fontType = getFontType(type, subtype); + + // Transfer some properties again that could change during font conversion + this.fontMatrix = properties.fontMatrix; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.encoding = properties.baseEncoding; + this.seacMap = properties.seacMap; + + this.loading = true; + } + + Font.getFontID = (function () { + var ID = 1; + return function Font_getFontID() { + return String(ID++); + }; + })(); + + function int16(b0, b1) { + return (b0 << 8) + b1; + } + + function int32(b0, b1, b2, b3) { + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + } + + function string16(value) { + return String.fromCharCode((value >> 8) & 0xff, value & 0xff); + } + + function safeString16(value) { + // clamp value to the 16-bit int range + value = (value > 0x7FFF ? 0x7FFF : (value < -0x8000 ? -0x8000 : value)); + return String.fromCharCode((value >> 8) & 0xff, value & 0xff); + } + + function isTrueTypeFile(file) { + var header = file.peekBytes(4); + return readUint32(header, 0) === 0x00010000; + } + + function isType1File(file) { + var header = file.peekBytes(2); + // All Type1 font programs must begin with the comment '%!' (0x25 + 0x21). + if (header[0] === 0x25 && header[1] === 0x21) { + return true; + } + // ... obviously some fonts violate that part of the specification, + // please refer to the comment in |Type1Font| below. + if (header[0] === 0x80 && header[1] === 0x01) { // pfb file header. + return true; + } + return false; + } + + /** + * Helper function for |adjustMapping|. + * @return {boolean} + */ + function isProblematicUnicodeLocation(code) { + if (code <= 0x1F) { // Control chars + return true; + } + if (code >= 0x80 && code <= 0x9F) { // Control chars + return true; + } + if ((code >= 0x2000 && code <= 0x200F) || // General punctuation chars + (code >= 0x2028 && code <= 0x202F) || + (code >= 0x2060 && code <= 0x206F)) { + return true; + } + if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials Unicode block + return true; + } + switch (code) { + case 0x7F: // Control char + case 0xA0: // Non breaking space + case 0xAD: // Soft hyphen + case 0x0E33: // Thai character SARA AM + case 0x2011: // Non breaking hyphen + case 0x205F: // Medium mathematical space + case 0x25CC: // Dotted circle (combining mark) + return true; + } + return false; + } + + /** + * Rebuilds the char code to glyph ID map by trying to replace the char codes + * with their unicode value. It also moves char codes that are in known + * problematic locations. + * @return {Object} Two properties: + * 'toFontChar' - maps original char codes(the value that will be read + * from commands such as show text) to the char codes that will be used in the + * font that we build + * 'charCodeToGlyphId' - maps the new font char codes to glyph ids + */ + function adjustMapping(charCodeToGlyphId, properties) { + var toUnicode = properties.toUnicode; + var isSymbolic = !!(properties.flags & FontFlags.Symbolic); + var isIdentityUnicode = + properties.toUnicode instanceof IdentityToUnicodeMap; + var newMap = Object.create(null); + var toFontChar = []; + var usedFontCharCodes = []; + var nextAvailableFontCharCode = PRIVATE_USE_OFFSET_START; + for (var originalCharCode in charCodeToGlyphId) { + originalCharCode |= 0; + var glyphId = charCodeToGlyphId[originalCharCode]; + var fontCharCode = originalCharCode; + // First try to map the value to a unicode position if a non identity map + // was created. + if (!isIdentityUnicode && toUnicode.has(originalCharCode)) { + var unicode = toUnicode.get(fontCharCode); + // TODO: Try to map ligatures to the correct spot. + if (unicode.length === 1) { + fontCharCode = unicode.charCodeAt(0); + } + } + // Try to move control characters, special characters and already mapped + // characters to the private use area since they will not be drawn by + // canvas if left in their current position. Also, move characters if the + // font was symbolic and there is only an identity unicode map since the + // characters probably aren't in the correct position (fixes an issue + // with firefox and thuluthfont). + if ((usedFontCharCodes[fontCharCode] !== undefined || + isProblematicUnicodeLocation(fontCharCode) || + (isSymbolic && isIdentityUnicode)) && + nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) { // Room left. + // Loop to try and find a free spot in the private use area. + do { + fontCharCode = nextAvailableFontCharCode++; + + if (SKIP_PRIVATE_USE_RANGE_F000_TO_F01F && fontCharCode === 0xF000) { + fontCharCode = 0xF020; + nextAvailableFontCharCode = fontCharCode + 1; + } + + } while (usedFontCharCodes[fontCharCode] !== undefined && + nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END); + } + + newMap[fontCharCode] = glyphId; + toFontChar[originalCharCode] = fontCharCode; + usedFontCharCodes[fontCharCode] = true; + } + return { + toFontChar: toFontChar, + charCodeToGlyphId: newMap, + nextAvailableFontCharCode: nextAvailableFontCharCode + }; + } + + function getRanges(glyphs) { + // Array.sort() sorts by characters, not numerically, so convert to an + // array of characters. + var codes = []; + for (var charCode in glyphs) { + codes.push({ fontCharCode: charCode | 0, glyphId: glyphs[charCode] }); + } + codes.sort(function fontGetRangesSort(a, b) { + return a.fontCharCode - b.fontCharCode; + }); + + // Split the sorted codes into ranges. + var ranges = []; + var length = codes.length; + for (var n = 0; n < length; ) { + var start = codes[n].fontCharCode; + var codeIndices = [codes[n].glyphId]; + ++n; + var end = start; + while (n < length && end + 1 === codes[n].fontCharCode) { + codeIndices.push(codes[n].glyphId); + ++end; + ++n; + if (end === 0xFFFF) { + break; + } + } + ranges.push([start, end, codeIndices]); + } + + return ranges; + } + + function createCmapTable(glyphs) { + var ranges = getRanges(glyphs); + var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1; + var cmap = '\x00\x00' + // version + string16(numTables) + // numTables + '\x00\x03' + // platformID + '\x00\x01' + // encodingID + string32(4 + numTables * 8); // start of the table record + + var i, ii, j, jj; + for (i = ranges.length - 1; i >= 0; --i) { + if (ranges[i][0] <= 0xFFFF) { break; } + } + var bmpLength = i + 1; + + if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) { + ranges[i][1] = 0xFFFE; + } + var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0; + var segCount = bmpLength + trailingRangesCount; + var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2); + + // Fill up the 4 parallel arrays describing the segments. + var startCount = ''; + var endCount = ''; + var idDeltas = ''; + var idRangeOffsets = ''; + var glyphsIds = ''; + var bias = 0; + + var range, start, end, codes; + for (i = 0, ii = bmpLength; i < ii; i++) { + range = ranges[i]; + start = range[0]; + end = range[1]; + startCount += string16(start); + endCount += string16(end); + codes = range[2]; + var contiguous = true; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + contiguous = false; + break; + } + } + if (!contiguous) { + var offset = (segCount - i) * 2 + bias * 2; + bias += (end - start + 1); + + idDeltas += string16(0); + idRangeOffsets += string16(offset); + + for (j = 0, jj = codes.length; j < jj; ++j) { + glyphsIds += string16(codes[j]); + } + } else { + var startCode = codes[0]; + + idDeltas += string16((startCode - start) & 0xFFFF); + idRangeOffsets += string16(0); + } + } + + if (trailingRangesCount > 0) { + endCount += '\xFF\xFF'; + startCount += '\xFF\xFF'; + idDeltas += '\x00\x01'; + idRangeOffsets += '\x00\x00'; + } + + var format314 = '\x00\x00' + // language + string16(2 * segCount) + + string16(searchParams.range) + + string16(searchParams.entry) + + string16(searchParams.rangeShift) + + endCount + '\x00\x00' + startCount + + idDeltas + idRangeOffsets + glyphsIds; + + var format31012 = ''; + var header31012 = ''; + if (numTables > 1) { + cmap += '\x00\x03' + // platformID + '\x00\x0A' + // encodingID + string32(4 + numTables * 8 + + 4 + format314.length); // start of the table record + format31012 = ''; + for (i = 0, ii = ranges.length; i < ii; i++) { + range = ranges[i]; + start = range[0]; + codes = range[2]; + var code = codes[0]; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + end = range[0] + j - 1; + format31012 += string32(start) + // startCharCode + string32(end) + // endCharCode + string32(code); // startGlyphID + start = end + 1; + code = codes[j]; + } + } + format31012 += string32(start) + // startCharCode + string32(range[1]) + // endCharCode + string32(code); // startGlyphID + } + header31012 = '\x00\x0C' + // format + '\x00\x00' + // reserved + string32(format31012.length + 16) + // length + '\x00\x00\x00\x00' + // language + string32(format31012.length / 12); // nGroups + } + + return cmap + '\x00\x04' + // format + string16(format314.length + 4) + // length + format314 + header31012 + format31012; + } + + function validateOS2Table(os2) { + var stream = new Stream(os2.data); + var version = stream.getUint16(); + // TODO verify all OS/2 tables fields, but currently we validate only those + // that give us issues + stream.getBytes(60); // skipping type, misc sizes, panose, unicode ranges + var selection = stream.getUint16(); + if (version < 4 && (selection & 0x0300)) { + return false; + } + var firstChar = stream.getUint16(); + var lastChar = stream.getUint16(); + if (firstChar > lastChar) { + return false; + } + stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap + var usWinAscent = stream.getUint16(); + if (usWinAscent === 0) { // makes font unreadable by windows + return false; + } + + // OS/2 appears to be valid, resetting some fields + os2.data[8] = os2.data[9] = 0; // IE rejects fonts if fsType != 0 + return true; + } + + function createOS2Table(properties, charstrings, override) { + override = override || { + unitsPerEm: 0, + yMax: 0, + yMin: 0, + ascent: 0, + descent: 0 + }; + + var ulUnicodeRange1 = 0; + var ulUnicodeRange2 = 0; + var ulUnicodeRange3 = 0; + var ulUnicodeRange4 = 0; + + var firstCharIndex = null; + var lastCharIndex = 0; + + if (charstrings) { + for (var code in charstrings) { + code |= 0; + if (firstCharIndex > code || !firstCharIndex) { + firstCharIndex = code; + } + if (lastCharIndex < code) { + lastCharIndex = code; + } + + var position = getUnicodeRangeFor(code); + if (position < 32) { + ulUnicodeRange1 |= 1 << position; + } else if (position < 64) { + ulUnicodeRange2 |= 1 << position - 32; + } else if (position < 96) { + ulUnicodeRange3 |= 1 << position - 64; + } else if (position < 123) { + ulUnicodeRange4 |= 1 << position - 96; + } else { + error('Unicode ranges Bits > 123 are reserved for internal usage'); + } + } + } else { + // TODO + firstCharIndex = 0; + lastCharIndex = 255; + } + + var bbox = properties.bbox || [0, 0, 0, 0]; + var unitsPerEm = (override.unitsPerEm || + 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]); + + // if the font units differ to the PDF glyph space units + // then scale up the values + var scale = (properties.ascentScaled ? 1.0 : + unitsPerEm / PDF_GLYPH_SPACE_UNITS); + + var typoAscent = (override.ascent || + Math.round(scale * (properties.ascent || bbox[3]))); + var typoDescent = (override.descent || + Math.round(scale * (properties.descent || bbox[1]))); + if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) { + typoDescent = -typoDescent; // fixing incorrect descent + } + var winAscent = override.yMax || typoAscent; + var winDescent = -override.yMin || -typoDescent; + + return '\x00\x03' + // version + '\x02\x24' + // xAvgCharWidth + '\x01\xF4' + // usWeightClass + '\x00\x05' + // usWidthClass + '\x00\x00' + // fstype (0 to let the font loads via font-face on IE) + '\x02\x8A' + // ySubscriptXSize + '\x02\xBB' + // ySubscriptYSize + '\x00\x00' + // ySubscriptXOffset + '\x00\x8C' + // ySubscriptYOffset + '\x02\x8A' + // ySuperScriptXSize + '\x02\xBB' + // ySuperScriptYSize + '\x00\x00' + // ySuperScriptXOffset + '\x01\xDF' + // ySuperScriptYOffset + '\x00\x31' + // yStrikeOutSize + '\x01\x02' + // yStrikeOutPosition + '\x00\x00' + // sFamilyClass + '\x00\x00\x06' + + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + + '\x00\x00\x00\x00\x00\x00' + // Panose + string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31) + string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63) + string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95) + string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127) + '\x2A\x32\x31\x2A' + // achVendID + string16(properties.italicAngle ? 1 : 0) + // fsSelection + string16(firstCharIndex || + properties.firstChar) + // usFirstCharIndex + string16(lastCharIndex || properties.lastChar) + // usLastCharIndex + string16(typoAscent) + // sTypoAscender + string16(typoDescent) + // sTypoDescender + '\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value) + string16(winAscent) + // usWinAscent + string16(winDescent) + // usWinDescent + '\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31) + '\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63) + string16(properties.xHeight) + // sxHeight + string16(properties.capHeight) + // sCapHeight + string16(0) + // usDefaultChar + string16(firstCharIndex || properties.firstChar) + // usBreakChar + '\x00\x03'; // usMaxContext + } + + function createPostTable(properties) { + var angle = Math.floor(properties.italicAngle * (Math.pow(2, 16))); + return ('\x00\x03\x00\x00' + // Version number + string32(angle) + // italicAngle + '\x00\x00' + // underlinePosition + '\x00\x00' + // underlineThickness + string32(properties.fixedPitch) + // isFixedPitch + '\x00\x00\x00\x00' + // minMemType42 + '\x00\x00\x00\x00' + // maxMemType42 + '\x00\x00\x00\x00' + // minMemType1 + '\x00\x00\x00\x00'); // maxMemType1 + } + + function createNameTable(name, proto) { + if (!proto) { + proto = [[], []]; // no strings and unicode strings + } + + var strings = [ + proto[0][0] || 'Original licence', // 0.Copyright + proto[0][1] || name, // 1.Font family + proto[0][2] || 'Unknown', // 2.Font subfamily (font weight) + proto[0][3] || 'uniqueID', // 3.Unique ID + proto[0][4] || name, // 4.Full font name + proto[0][5] || 'Version 0.11', // 5.Version + proto[0][6] || '', // 6.Postscript name + proto[0][7] || 'Unknown', // 7.Trademark + proto[0][8] || 'Unknown', // 8.Manufacturer + proto[0][9] || 'Unknown' // 9.Designer + ]; + + // Mac want 1-byte per character strings while Windows want + // 2-bytes per character, so duplicate the names table + var stringsUnicode = []; + var i, ii, j, jj, str; + for (i = 0, ii = strings.length; i < ii; i++) { + str = proto[1][i] || strings[i]; + + var strBufUnicode = []; + for (j = 0, jj = str.length; j < jj; j++) { + strBufUnicode.push(string16(str.charCodeAt(j))); + } + stringsUnicode.push(strBufUnicode.join('')); + } + + var names = [strings, stringsUnicode]; + var platforms = ['\x00\x01', '\x00\x03']; + var encodings = ['\x00\x00', '\x00\x01']; + var languages = ['\x00\x00', '\x04\x09']; + + var namesRecordCount = strings.length * platforms.length; + var nameTable = + '\x00\x00' + // format + string16(namesRecordCount) + // Number of names Record + string16(namesRecordCount * 12 + 6); // Storage + + // Build the name records field + var strOffset = 0; + for (i = 0, ii = platforms.length; i < ii; i++) { + var strs = names[i]; + for (j = 0, jj = strs.length; j < jj; j++) { + str = strs[j]; + var nameRecord = + platforms[i] + // platform ID + encodings[i] + // encoding ID + languages[i] + // language ID + string16(j) + // name ID + string16(str.length) + + string16(strOffset); + nameTable += nameRecord; + strOffset += str.length; + } + } + + nameTable += strings.join('') + stringsUnicode.join(''); + return nameTable; + } + + Font.prototype = { + name: null, + font: null, + mimetype: null, + encoding: null, + get renderer() { + var renderer = FontRendererFactory.create(this); + return shadow(this, 'renderer', renderer); + }, + + exportData: function Font_exportData() { + var data = {}; + for (var i in this) { + if (this.hasOwnProperty(i)) { + data[i] = this[i]; + } + } + return data; + }, + + checkAndRepair: function Font_checkAndRepair(name, font, properties) { + function readTableEntry(file) { + var tag = bytesToString(file.getBytes(4)); + + var checksum = file.getInt32(); + var offset = file.getInt32() >>> 0; + var length = file.getInt32() >>> 0; + + // Read the table associated data + var previousPosition = file.pos; + file.pos = file.start ? file.start : 0; + file.skip(offset); + var data = file.getBytes(length); + file.pos = previousPosition; + + if (tag === 'head') { + // clearing checksum adjustment + data[8] = data[9] = data[10] = data[11] = 0; + data[17] |= 0x20; //Set font optimized for cleartype flag + } + + return { + tag: tag, + checksum: checksum, + length: length, + offset: offset, + data: data + }; + } + + function readOpenTypeHeader(ttf) { + return { + version: bytesToString(ttf.getBytes(4)), + numTables: ttf.getUint16(), + searchRange: ttf.getUint16(), + entrySelector: ttf.getUint16(), + rangeShift: ttf.getUint16() + }; + } + + /** + * Read the appropriate subtable from the cmap according to 9.6.6.4 from + * PDF spec + */ + function readCmapTable(cmap, font, isSymbolicFont) { + var segment; + var start = (font.start ? font.start : 0) + cmap.offset; + font.pos = start; + + var version = font.getUint16(); + var numTables = font.getUint16(); + + var potentialTable; + var canBreak = false; + // There's an order of preference in terms of which cmap subtable to + // use: + // - non-symbolic fonts the preference is a 3,1 table then a 1,0 table + // - symbolic fonts the preference is a 3,0 table then a 1,0 table + // The following takes advantage of the fact that the tables are sorted + // to work. + for (var i = 0; i < numTables; i++) { + var platformId = font.getUint16(); + var encodingId = font.getUint16(); + var offset = font.getInt32() >>> 0; + var useTable = false; + + if (platformId === 0 && encodingId === 0) { + useTable = true; + // Continue the loop since there still may be a higher priority + // table. + } else if (platformId === 1 && encodingId === 0) { + useTable = true; + // Continue the loop since there still may be a higher priority + // table. + } else if (platformId === 3 && encodingId === 1 && + (!isSymbolicFont || !potentialTable)) { + useTable = true; + if (!isSymbolicFont) { + canBreak = true; + } + } else if (isSymbolicFont && platformId === 3 && encodingId === 0) { + useTable = true; + canBreak = true; + } + + if (useTable) { + potentialTable = { + platformId: platformId, + encodingId: encodingId, + offset: offset + }; + } + if (canBreak) { + break; + } + } + + if (potentialTable) { + font.pos = start + potentialTable.offset; + } + if (!potentialTable || font.peekByte() === -1) { + warn('Could not find a preferred cmap table.'); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + + var format = font.getUint16(); + var length = font.getUint16(); + var language = font.getUint16(); + + var hasShortCmap = false; + var mappings = []; + var j, glyphId; + + // TODO(mack): refactor this cmap subtable reading logic out + if (format === 0) { + for (j = 0; j < 256; j++) { + var index = font.getByte(); + if (!index) { + continue; + } + mappings.push({ + charCode: j, + glyphId: index + }); + } + hasShortCmap = true; + } else if (format === 4) { + // re-creating the table in format 4 since the encoding + // might be changed + var segCount = (font.getUint16() >> 1); + font.getBytes(6); // skipping range fields + var segIndex, segments = []; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments.push({ end: font.getUint16() }); + } + font.getUint16(); + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].start = font.getUint16(); + } + + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].delta = font.getUint16(); + } + + var offsetsCount = 0; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + var rangeOffset = font.getUint16(); + if (!rangeOffset) { + segment.offsetIndex = -1; + continue; + } + + var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex); + segment.offsetIndex = offsetIndex; + offsetsCount = Math.max(offsetsCount, offsetIndex + + segment.end - segment.start + 1); + } + + var offsets = []; + for (j = 0; j < offsetsCount; j++) { + offsets.push(font.getUint16()); + } + + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + start = segment.start; + var end = segment.end; + var delta = segment.delta; + offsetIndex = segment.offsetIndex; + + for (j = start; j <= end; j++) { + if (j === 0xFFFF) { + continue; + } + + glyphId = (offsetIndex < 0 ? + j : offsets[offsetIndex + j - start]); + glyphId = (glyphId + delta) & 0xFFFF; + if (glyphId === 0) { + continue; + } + mappings.push({ + charCode: j, + glyphId: glyphId + }); + } + } + } else if (format === 6) { + // Format 6 is a 2-bytes dense mapping, which means the font data + // lives glue together even if they are pretty far in the unicode + // table. (This looks weird, so I can have missed something), this + // works on Linux but seems to fails on Mac so let's rewrite the + // cmap table to a 3-1-4 style + var firstCode = font.getUint16(); + var entryCount = font.getUint16(); + + for (j = 0; j < entryCount; j++) { + glyphId = font.getUint16(); + var charCode = firstCode + j; + + mappings.push({ + charCode: charCode, + glyphId: glyphId + }); + } + } else { + error('cmap table has unsupported format: ' + format); + } + + // removing duplicate entries + mappings.sort(function (a, b) { + return a.charCode - b.charCode; + }); + for (i = 1; i < mappings.length; i++) { + if (mappings[i - 1].charCode === mappings[i].charCode) { + mappings.splice(i, 1); + i--; + } + } + + return { + platformId: potentialTable.platformId, + encodingId: potentialTable.encodingId, + mappings: mappings, + hasShortCmap: hasShortCmap + }; + } + + function sanitizeMetrics(font, header, metrics, numGlyphs) { + if (!header) { + if (metrics) { + metrics.data = null; + } + return; + } + + font.pos = (font.start ? font.start : 0) + header.offset; + font.pos += header.length - 2; + var numOfMetrics = font.getUint16(); + + if (numOfMetrics > numGlyphs) { + info('The numOfMetrics (' + numOfMetrics + ') should not be ' + + 'greater than the numGlyphs (' + numGlyphs + ')'); + // Reduce numOfMetrics if it is greater than numGlyphs + numOfMetrics = numGlyphs; + header.data[34] = (numOfMetrics & 0xff00) >> 8; + header.data[35] = numOfMetrics & 0x00ff; + } + + var numOfSidebearings = numGlyphs - numOfMetrics; + var numMissing = numOfSidebearings - + ((metrics.length - numOfMetrics * 4) >> 1); + + if (numMissing > 0) { + // For each missing glyph, we set both the width and lsb to 0 (zero). + // Since we need to add two properties for each glyph, this explains + // the use of |numMissing * 2| when initializing the typed array. + var entries = new Uint8Array(metrics.length + numMissing * 2); + entries.set(metrics.data); + metrics.data = entries; + } + } + + function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, + hintsValid) { + if (sourceEnd - sourceStart <= 12) { + // glyph with data less than 12 is invalid one + return 0; + } + var glyf = source.subarray(sourceStart, sourceEnd); + var contoursCount = (glyf[0] << 8) | glyf[1]; + if (contoursCount & 0x8000) { + // complex glyph, writing as is + dest.set(glyf, destStart); + return glyf.length; + } + + var i, j = 10, flagsCount = 0; + for (i = 0; i < contoursCount; i++) { + var endPoint = (glyf[j] << 8) | glyf[j + 1]; + flagsCount = endPoint + 1; + j += 2; + } + // skipping instructions + var instructionsStart = j; + var instructionsLength = (glyf[j] << 8) | glyf[j + 1]; + j += 2 + instructionsLength; + var instructionsEnd = j; + // validating flags + var coordinatesLength = 0; + for (i = 0; i < flagsCount; i++) { + var flag = glyf[j++]; + if (flag & 0xC0) { + // reserved flags must be zero, cleaning up + glyf[j - 1] = flag & 0x3F; + } + var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) + + ((flag & 4) ? 1 : (flag & 32) ? 0 : 2); + coordinatesLength += xyLength; + if (flag & 8) { + var repeat = glyf[j++]; + i += repeat; + coordinatesLength += repeat * xyLength; + } + } + // glyph without coordinates will be rejected + if (coordinatesLength === 0) { + return 0; + } + var glyphDataLength = j + coordinatesLength; + if (glyphDataLength > glyf.length) { + // not enough data for coordinates + return 0; + } + if (!hintsValid && instructionsLength > 0) { + dest.set(glyf.subarray(0, instructionsStart), destStart); + dest.set([0, 0], destStart + instructionsStart); + dest.set(glyf.subarray(instructionsEnd, glyphDataLength), + destStart + instructionsStart + 2); + glyphDataLength -= instructionsLength; + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = (glyphDataLength + 3) & ~3; + } + return glyphDataLength; + } + if (glyf.length - glyphDataLength > 3) { + // truncating and aligning to 4 bytes the long glyph data + glyphDataLength = (glyphDataLength + 3) & ~3; + dest.set(glyf.subarray(0, glyphDataLength), destStart); + return glyphDataLength; + } + // glyph data is fine + dest.set(glyf, destStart); + return glyf.length; + } + + function sanitizeHead(head, numGlyphs, locaLength) { + var data = head.data; + + // Validate version: + // Should always be 0x00010000 + var version = int32(data[0], data[1], data[2], data[3]); + if (version >> 16 !== 1) { + info('Attempting to fix invalid version in head table: ' + version); + data[0] = 0; + data[1] = 1; + data[2] = 0; + data[3] = 0; + } + + var indexToLocFormat = int16(data[50], data[51]); + if (indexToLocFormat < 0 || indexToLocFormat > 1) { + info('Attempting to fix invalid indexToLocFormat in head table: ' + + indexToLocFormat); + + // The value of indexToLocFormat should be 0 if the loca table + // consists of short offsets, and should be 1 if the loca table + // consists of long offsets. + // + // The number of entries in the loca table should be numGlyphs + 1. + // + // Using this information, we can work backwards to deduce if the + // size of each offset in the loca table, and thus figure out the + // appropriate value for indexToLocFormat. + + var numGlyphsPlusOne = numGlyphs + 1; + if (locaLength === numGlyphsPlusOne << 1) { + // 0x0000 indicates the loca table consists of short offsets + data[50] = 0; + data[51] = 0; + } else if (locaLength === numGlyphsPlusOne << 2) { + // 0x0001 indicates the loca table consists of long offsets + data[50] = 0; + data[51] = 1; + } else { + warn('Could not fix indexToLocFormat: ' + indexToLocFormat); + } + } + } + + function sanitizeGlyphLocations(loca, glyf, numGlyphs, + isGlyphLocationsLong, hintsValid, + dupFirstEntry) { + var itemSize, itemDecode, itemEncode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + }; + itemEncode = function fontItemEncodeLong(data, offset, value) { + data[offset] = (value >>> 24) & 0xFF; + data[offset + 1] = (value >> 16) & 0xFF; + data[offset + 2] = (value >> 8) & 0xFF; + data[offset + 3] = value & 0xFF; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return (data[offset] << 9) | (data[offset + 1] << 1); + }; + itemEncode = function fontItemEncode(data, offset, value) { + data[offset] = (value >> 9) & 0xFF; + data[offset + 1] = (value >> 1) & 0xFF; + }; + } + var locaData = loca.data; + var locaDataSize = itemSize * (1 + numGlyphs); + // is loca.data too short or long? + if (locaData.length !== locaDataSize) { + locaData = new Uint8Array(locaDataSize); + locaData.set(loca.data.subarray(0, locaDataSize)); + loca.data = locaData; + } + // removing the invalid glyphs + var oldGlyfData = glyf.data; + var oldGlyfDataLength = oldGlyfData.length; + var newGlyfData = new Uint8Array(oldGlyfDataLength); + var startOffset = itemDecode(locaData, 0); + var writeOffset = 0; + var missingGlyphData = {}; + itemEncode(locaData, 0, writeOffset); + var i, j; + for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { + var endOffset = itemDecode(locaData, j); + if (endOffset > oldGlyfDataLength && + ((oldGlyfDataLength + 3) & ~3) === endOffset) { + // Aspose breaks fonts by aligning the glyphs to the qword, but not + // the glyf table size, which makes last glyph out of range. + endOffset = oldGlyfDataLength; + } + if (endOffset > oldGlyfDataLength) { + // glyph end offset points outside glyf data, rejecting the glyph + itemEncode(locaData, j, writeOffset); + startOffset = endOffset; + continue; + } + + if (startOffset === endOffset) { + missingGlyphData[i] = true; + } + + var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, + newGlyfData, writeOffset, hintsValid); + writeOffset += newLength; + itemEncode(locaData, j, writeOffset); + startOffset = endOffset; + } + + if (writeOffset === 0) { + // glyf table cannot be empty -- redoing the glyf and loca tables + // to have single glyph with one point + var simpleGlyph = new Uint8Array( + [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]); + for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { + itemEncode(locaData, j, simpleGlyph.length); + } + glyf.data = simpleGlyph; + return missingGlyphData; + } + + if (dupFirstEntry) { + var firstEntryLength = itemDecode(locaData, itemSize); + if (newGlyfData.length > firstEntryLength + writeOffset) { + glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); + } else { + glyf.data = new Uint8Array(firstEntryLength + writeOffset); + glyf.data.set(newGlyfData.subarray(0, writeOffset)); + } + glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset); + itemEncode(loca.data, locaData.length - itemSize, + writeOffset + firstEntryLength); + } else { + glyf.data = newGlyfData.subarray(0, writeOffset); + } + return missingGlyphData; + } + + function readPostScriptTable(post, properties, maxpNumGlyphs) { + var start = (font.start ? font.start : 0) + post.offset; + font.pos = start; + + var length = post.length, end = start + length; + var version = font.getInt32(); + // skip rest to the tables + font.getBytes(28); + + var glyphNames; + var valid = true; + var i; + + switch (version) { + case 0x00010000: + glyphNames = MacStandardGlyphOrdering; + break; + case 0x00020000: + var numGlyphs = font.getUint16(); + if (numGlyphs !== maxpNumGlyphs) { + valid = false; + break; + } + var glyphNameIndexes = []; + for (i = 0; i < numGlyphs; ++i) { + var index = font.getUint16(); + if (index >= 32768) { + valid = false; + break; + } + glyphNameIndexes.push(index); + } + if (!valid) { + break; + } + var customNames = []; + var strBuf = []; + while (font.pos < end) { + var stringLength = font.getByte(); + strBuf.length = stringLength; + for (i = 0; i < stringLength; ++i) { + strBuf[i] = String.fromCharCode(font.getByte()); + } + customNames.push(strBuf.join('')); + } + glyphNames = []; + for (i = 0; i < numGlyphs; ++i) { + var j = glyphNameIndexes[i]; + if (j < 258) { + glyphNames.push(MacStandardGlyphOrdering[j]); + continue; + } + glyphNames.push(customNames[j - 258]); + } + break; + case 0x00030000: + break; + default: + warn('Unknown/unsupported post table version ' + version); + valid = false; + if (properties.defaultEncoding) { + glyphNames = properties.defaultEncoding; + } + break; + } + properties.glyphNames = glyphNames; + return valid; + } + + function readNameTable(nameTable) { + var start = (font.start ? font.start : 0) + nameTable.offset; + font.pos = start; + + var names = [[], []]; + var length = nameTable.length, end = start + length; + var format = font.getUint16(); + var FORMAT_0_HEADER_LENGTH = 6; + if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) { + // unsupported name table format or table "too" small + return names; + } + var numRecords = font.getUint16(); + var stringsStart = font.getUint16(); + var records = []; + var NAME_RECORD_LENGTH = 12; + var i, ii; + + for (i = 0; i < numRecords && + font.pos + NAME_RECORD_LENGTH <= end; i++) { + var r = { + platform: font.getUint16(), + encoding: font.getUint16(), + language: font.getUint16(), + name: font.getUint16(), + length: font.getUint16(), + offset: font.getUint16() + }; + // using only Macintosh and Windows platform/encoding names + if ((r.platform === 1 && r.encoding === 0 && r.language === 0) || + (r.platform === 3 && r.encoding === 1 && r.language === 0x409)) { + records.push(r); + } + } + for (i = 0, ii = records.length; i < ii; i++) { + var record = records[i]; + var pos = start + stringsStart + record.offset; + if (pos + record.length > end) { + continue; // outside of name table, ignoring + } + font.pos = pos; + var nameIndex = record.name; + if (record.encoding) { + // unicode + var str = ''; + for (var j = 0, jj = record.length; j < jj; j += 2) { + str += String.fromCharCode(font.getUint16()); + } + names[1][nameIndex] = str; + } else { + names[0][nameIndex] = bytesToString(font.getBytes(record.length)); + } + } + return names; + } + + var TTOpsStackDeltas = [ + 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, + -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, + 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, + 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, + 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, + -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, + -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, + -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2]; + // 0xC0-DF == -1 and 0xE0-FF == -2 + + function sanitizeTTProgram(table, ttContext) { + var data = table.data; + var i = 0, j, n, b, funcId, pc, lastEndf = 0, lastDeff = 0; + var stack = []; + var callstack = []; + var functionsCalled = []; + var tooComplexToFollowFunctions = + ttContext.tooComplexToFollowFunctions; + var inFDEF = false, ifLevel = 0, inELSE = 0; + for (var ii = data.length; i < ii;) { + var op = data[i++]; + // The TrueType instruction set docs can be found at + // https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html + if (op === 0x40) { // NPUSHB - pushes n bytes + n = data[i++]; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if (op === 0x41) { // NPUSHW - pushes n words + n = data[i++]; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b = data[i++]; + stack.push((b << 8) | data[i++]); + } + } + } else if ((op & 0xF8) === 0xB0) { // PUSHB - pushes bytes + n = op - 0xB0 + 1; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if ((op & 0xF8) === 0xB8) { // PUSHW - pushes words + n = op - 0xB8 + 1; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b = data[i++]; + stack.push((b << 8) | data[i++]); + } + } + } else if (op === 0x2B && !tooComplexToFollowFunctions) { // CALL + if (!inFDEF && !inELSE) { + // collecting inforamtion about which functions are used + funcId = stack[stack.length - 1]; + ttContext.functionsUsed[funcId] = true; + if (funcId in ttContext.functionsStackDeltas) { + stack.length += ttContext.functionsStackDeltas[funcId]; + } else if (funcId in ttContext.functionsDefined && + functionsCalled.indexOf(funcId) < 0) { + callstack.push({data: data, i: i, stackTop: stack.length - 1}); + functionsCalled.push(funcId); + pc = ttContext.functionsDefined[funcId]; + if (!pc) { + warn('TT: CALL non-existent function'); + ttContext.hintsValid = false; + return; + } + data = pc.data; + i = pc.i; + } + } + } else if (op === 0x2C && !tooComplexToFollowFunctions) { // FDEF + if (inFDEF || inELSE) { + warn('TT: nested FDEFs not allowed'); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + // collecting inforamtion about which functions are defined + lastDeff = i; + funcId = stack.pop(); + ttContext.functionsDefined[funcId] = {data: data, i: i}; + } else if (op === 0x2D) { // ENDF - end of function + if (inFDEF) { + inFDEF = false; + lastEndf = i; + } else { + pc = callstack.pop(); + if (!pc) { + warn('TT: ENDF bad stack'); + ttContext.hintsValid = false; + return; + } + funcId = functionsCalled.pop(); + data = pc.data; + i = pc.i; + ttContext.functionsStackDeltas[funcId] = + stack.length - pc.stackTop; + } + } else if (op === 0x89) { // IDEF - instruction definition + if (inFDEF || inELSE) { + warn('TT: nested IDEFs not allowed'); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + // recording it as a function to track ENDF + lastDeff = i; + } else if (op === 0x58) { // IF + ++ifLevel; + } else if (op === 0x1B) { // ELSE + inELSE = ifLevel; + } else if (op === 0x59) { // EIF + if (inELSE === ifLevel) { + inELSE = 0; + } + --ifLevel; + } else if (op === 0x1C) { // JMPR + if (!inFDEF && !inELSE) { + var offset = stack[stack.length - 1]; + // only jumping forward to prevent infinite loop + if (offset > 0) { + i += offset - 1; + } + } + } + // Adjusting stack not extactly, but just enough to get function id + if (!inFDEF && !inELSE) { + var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : + op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0; + if (op >= 0x71 && op <= 0x75) { + n = stack.pop(); + if (n === n) { + stackDelta = -n * 2; + } + } + while (stackDelta < 0 && stack.length > 0) { + stack.pop(); + stackDelta++; + } + while (stackDelta > 0) { + stack.push(NaN); // pushing any number into stack + stackDelta--; + } + } + } + ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions; + var content = [data]; + if (i > data.length) { + content.push(new Uint8Array(i - data.length)); + } + if (lastDeff > lastEndf) { + warn('TT: complementing a missing function tail'); + // new function definition started, but not finished + // complete function by [CLEAR, ENDF] + content.push(new Uint8Array([0x22, 0x2D])); + } + foldTTTable(table, content); + } + + function checkInvalidFunctions(ttContext, maxFunctionDefs) { + if (ttContext.tooComplexToFollowFunctions) { + return; + } + if (ttContext.functionsDefined.length > maxFunctionDefs) { + warn('TT: more functions defined than expected'); + ttContext.hintsValid = false; + return; + } + for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) { + if (j > maxFunctionDefs) { + warn('TT: invalid function id: ' + j); + ttContext.hintsValid = false; + return; + } + if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) { + warn('TT: undefined function: ' + j); + ttContext.hintsValid = false; + return; + } + } + } + + function foldTTTable(table, content) { + if (content.length > 1) { + // concatenating the content items + var newLength = 0; + var j, jj; + for (j = 0, jj = content.length; j < jj; j++) { + newLength += content[j].length; + } + newLength = (newLength + 3) & ~3; + var result = new Uint8Array(newLength); + var pos = 0; + for (j = 0, jj = content.length; j < jj; j++) { + result.set(content[j], pos); + pos += content[j].length; + } + table.data = result; + table.length = newLength; + } + } + + function sanitizeTTPrograms(fpgm, prep, cvt) { + var ttContext = { + functionsDefined: [], + functionsUsed: [], + functionsStackDeltas: [], + tooComplexToFollowFunctions: false, + hintsValid: true + }; + if (fpgm) { + sanitizeTTProgram(fpgm, ttContext); + } + if (prep) { + sanitizeTTProgram(prep, ttContext); + } + if (fpgm) { + checkInvalidFunctions(ttContext, maxFunctionDefs); + } + if (cvt && (cvt.length & 1)) { + var cvtData = new Uint8Array(cvt.length + 1); + cvtData.set(cvt.data); + cvt.data = cvtData; + } + return ttContext.hintsValid; + } + + // The following steps modify the original font data, making copy + font = new Stream(new Uint8Array(font.getBytes())); + + var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp', + 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF ']; + + var header = readOpenTypeHeader(font); + var numTables = header.numTables; + var cff, cffFile; + + var tables = { 'OS/2': null, cmap: null, head: null, hhea: null, + hmtx: null, maxp: null, name: null, post: null }; + var table; + for (var i = 0; i < numTables; i++) { + table = readTableEntry(font); + if (VALID_TABLES.indexOf(table.tag) < 0) { + continue; // skipping table if it's not a required or optional table + } + if (table.length === 0) { + continue; // skipping empty tables + } + tables[table.tag] = table; + } + + var isTrueType = !tables['CFF ']; + if (!isTrueType) { + // OpenType font + if (header.version === 'OTTO' || + !tables.head || !tables.hhea || !tables.maxp || !tables.post) { + // no major tables: throwing everything at CFFFont + cffFile = new Stream(tables['CFF '].data); + cff = new CFFFont(cffFile, properties); + + return this.convert(name, cff, properties); + } + + delete tables.glyf; + delete tables.loca; + delete tables.fpgm; + delete tables.prep; + delete tables['cvt ']; + this.isOpenType = true; + } else { + if (!tables.glyf || !tables.loca) { + error('Required "glyf" or "loca" tables are not found'); + } + this.isOpenType = false; + } + + if (!tables.maxp) { + error('Required "maxp" table is not found'); + } + + font.pos = (font.start || 0) + tables.maxp.offset; + var version = font.getInt32(); + var numGlyphs = font.getUint16(); + var maxFunctionDefs = 0; + if (version >= 0x00010000 && tables.maxp.length >= 22) { + // maxZones can be invalid + font.pos += 8; + var maxZones = font.getUint16(); + if (maxZones > 2) { // reset to 2 if font has invalid maxZones + tables.maxp.data[14] = 0; + tables.maxp.data[15] = 2; + } + font.pos += 4; + maxFunctionDefs = font.getUint16(); + } + + var dupFirstEntry = false; + if (properties.type === 'CIDFontType2' && properties.toUnicode && + properties.toUnicode.get(0) > '\u0000') { + // oracle's defect (see 3427), duplicating first entry + dupFirstEntry = true; + numGlyphs++; + tables.maxp.data[4] = numGlyphs >> 8; + tables.maxp.data[5] = numGlyphs & 255; + } + + var hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, + tables['cvt '], maxFunctionDefs); + if (!hintsValid) { + delete tables.fpgm; + delete tables.prep; + delete tables['cvt ']; + } + + // Ensure the hmtx table contains the advance width and + // sidebearings information for numGlyphs in the maxp table + sanitizeMetrics(font, tables.hhea, tables.hmtx, numGlyphs); + + if (!tables.head) { + error('Required "head" table is not found'); + } + + sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); + + var missingGlyphs = {}; + if (isTrueType) { + var isGlyphLocationsLong = int16(tables.head.data[50], + tables.head.data[51]); + missingGlyphs = sanitizeGlyphLocations(tables.loca, tables.glyf, + numGlyphs, isGlyphLocationsLong, + hintsValid, dupFirstEntry); + } + + if (!tables.hhea) { + error('Required "hhea" table is not found'); + } + + // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth + // Sometimes it's 0. That needs to be fixed + if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) { + tables.hhea.data[10] = 0xFF; + tables.hhea.data[11] = 0xFF; + } + + // The 'post' table has glyphs names. + if (tables.post) { + var valid = readPostScriptTable(tables.post, properties, numGlyphs); + if (!valid) { + tables.post = null; + } + } + + var charCodeToGlyphId = [], charCode, toUnicode = properties.toUnicode; + + function hasGlyph(glyphId, charCode) { + if (!missingGlyphs[glyphId]) { + return true; + } + if (charCode >= 0 && toUnicode.has(charCode)) { + return true; + } + return false; + } + + if (properties.type === 'CIDFontType2') { + var cidToGidMap = properties.cidToGidMap || []; + var isCidToGidMapEmpty = cidToGidMap.length === 0; + + properties.cMap.forEach(function(charCode, cid) { + assert(cid <= 0xffff, 'Max size of CID is 65,535'); + var glyphId = -1; + if (isCidToGidMapEmpty) { + glyphId = charCode; + } else if (cidToGidMap[cid] !== undefined) { + glyphId = cidToGidMap[cid]; + } + + if (glyphId >= 0 && glyphId < numGlyphs && + hasGlyph(glyphId, charCode)) { + charCodeToGlyphId[charCode] = glyphId; + } + }); + if (dupFirstEntry) { + charCodeToGlyphId[0] = numGlyphs - 1; + } + } else { + // Most of the following logic in this code branch is based on the + // 9.6.6.4 of the PDF spec. + var cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont); + var cmapPlatformId = cmapTable.platformId; + var cmapEncodingId = cmapTable.encodingId; + var cmapMappings = cmapTable.mappings; + var cmapMappingsLength = cmapMappings.length; + var hasEncoding = properties.differences.length || + !!properties.baseEncodingName; + + // The spec seems to imply that if the font is symbolic the encoding + // should be ignored, this doesn't appear to work for 'preistabelle.pdf' + // where the the font is symbolic and it has an encoding. + if (hasEncoding && + (cmapPlatformId === 3 && cmapEncodingId === 1 || + cmapPlatformId === 1 && cmapEncodingId === 0) || + (cmapPlatformId === -1 && cmapEncodingId === -1 && // Temporary hack + !!Encodings[properties.baseEncodingName])) { // Temporary hack + // When no preferred cmap table was found and |baseEncodingName| is + // one of the predefined encodings, we seem to obtain a better + // |charCodeToGlyphId| map from the code below (fixes bug 1057544). + // TODO: Note that this is a hack which should be removed as soon as + // we have proper support for more exotic cmap tables. + + var baseEncoding = []; + if (properties.baseEncodingName === 'MacRomanEncoding' || + properties.baseEncodingName === 'WinAnsiEncoding') { + baseEncoding = Encodings[properties.baseEncodingName]; + } + for (charCode = 0; charCode < 256; charCode++) { + var glyphName; + if (this.differences && charCode in this.differences) { + glyphName = this.differences[charCode]; + } else if (charCode in baseEncoding && + baseEncoding[charCode] !== '') { + glyphName = baseEncoding[charCode]; + } else { + glyphName = Encodings.StandardEncoding[charCode]; + } + if (!glyphName) { + continue; + } + var unicodeOrCharCode; + if (cmapPlatformId === 3 && cmapEncodingId === 1) { + unicodeOrCharCode = GlyphsUnicode[glyphName]; + } else if (cmapPlatformId === 1 && cmapEncodingId === 0) { + // TODO: the encoding needs to be updated with mac os table. + unicodeOrCharCode = Encodings.MacRomanEncoding.indexOf(glyphName); + } + + var found = false; + for (i = 0; i < cmapMappingsLength; ++i) { + if (cmapMappings[i].charCode === unicodeOrCharCode && + hasGlyph(cmapMappings[i].glyphId, unicodeOrCharCode)) { + charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; + found = true; + break; + } + } + if (!found && properties.glyphNames) { + // Try to map using the post table. There are currently no known + // pdfs that this fixes. + var glyphId = properties.glyphNames.indexOf(glyphName); + if (glyphId > 0 && hasGlyph(glyphId, -1)) { + charCodeToGlyphId[charCode] = glyphId; + } + } + } + } else if (cmapPlatformId === 0 && cmapEncodingId === 0) { + // Default Unicode semantics, use the charcodes as is. + for (i = 0; i < cmapMappingsLength; ++i) { + charCodeToGlyphId[cmapMappings[i].charCode] = + cmapMappings[i].glyphId; + } + } else { + // For (3, 0) cmap tables: + // The charcode key being stored in charCodeToGlyphId is the lower + // byte of the two-byte charcodes of the cmap table since according to + // the spec: 'each byte from the string shall be prepended with the + // high byte of the range [of charcodes in the cmap table], to form + // a two-byte character, which shall be used to select the + // associated glyph description from the subtable'. + // + // For (1, 0) cmap tables: + // 'single bytes from the string shall be used to look up the + // associated glyph descriptions from the subtable'. This means + // charcodes in the cmap will be single bytes, so no-op since + // glyph.charCode & 0xFF === glyph.charCode + for (i = 0; i < cmapMappingsLength; ++i) { + charCode = cmapMappings[i].charCode & 0xFF; + charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; + } + } + } + + if (charCodeToGlyphId.length === 0) { + // defines at least one glyph + charCodeToGlyphId[0] = 0; + } + + // Converting glyphs and ids into font's cmap table + var newMapping = adjustMapping(charCodeToGlyphId, properties); + this.toFontChar = newMapping.toFontChar; + tables.cmap = { + tag: 'cmap', + data: createCmapTable(newMapping.charCodeToGlyphId) + }; + + if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) { + // extract some more font properties from the OpenType head and + // hhea tables; yMin and descent value are always negative + var override = { + unitsPerEm: int16(tables.head.data[18], tables.head.data[19]), + yMax: int16(tables.head.data[42], tables.head.data[43]), + yMin: int16(tables.head.data[38], tables.head.data[39]) - 0x10000, + ascent: int16(tables.hhea.data[4], tables.hhea.data[5]), + descent: int16(tables.hhea.data[6], tables.hhea.data[7]) - 0x10000 + }; + + tables['OS/2'] = { + tag: 'OS/2', + data: createOS2Table(properties, newMapping.charCodeToGlyphId, + override) + }; + } + + // Rewrite the 'post' table if needed + if (!tables.post) { + tables.post = { + tag: 'post', + data: createPostTable(properties) + }; + } + + if (!isTrueType) { + try { + // Trying to repair CFF file + cffFile = new Stream(tables['CFF '].data); + var parser = new CFFParser(cffFile, properties); + cff = parser.parse(); + var compiler = new CFFCompiler(cff); + tables['CFF '].data = compiler.compile(); + } catch (e) { + warn('Failed to compile font ' + properties.loadedName); + } + } + + // Re-creating 'name' table + if (!tables.name) { + tables.name = { + tag: 'name', + data: createNameTable(this.name) + }; + } else { + // ... using existing 'name' table as prototype + var namePrototype = readNameTable(tables.name); + tables.name.data = createNameTable(name, namePrototype); + } + + var builder = new OpenTypeFileBuilder(header.version); + for (var tableTag in tables) { + builder.addTable(tableTag, tables[tableTag].data); + } + return builder.toArray(); + }, + + convert: function Font_convert(fontName, font, properties) { + // TODO: Check the charstring widths to determine this. + properties.fixedPitch = false; + + var mapping = font.getGlyphMapping(properties); + var newMapping = adjustMapping(mapping, properties); + this.toFontChar = newMapping.toFontChar; + var numGlyphs = font.numGlyphs; + + function getCharCodes(charCodeToGlyphId, glyphId) { + var charCodes = null; + for (var charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + if (!charCodes) { + charCodes = []; + } + charCodes.push(charCode | 0); + } + } + return charCodes; + } + + function createCharCode(charCodeToGlyphId, glyphId) { + for (var charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + return charCode | 0; + } + } + newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = + glyphId; + return newMapping.nextAvailableFontCharCode++; + } + + var seacs = font.seacs; + if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) { + var matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX; + var charset = font.getCharset(); + var seacMap = Object.create(null); + for (var glyphId in seacs) { + glyphId |= 0; + var seac = seacs[glyphId]; + var baseGlyphName = Encodings.StandardEncoding[seac[2]]; + var accentGlyphName = Encodings.StandardEncoding[seac[3]]; + var baseGlyphId = charset.indexOf(baseGlyphName); + var accentGlyphId = charset.indexOf(accentGlyphName); + if (baseGlyphId < 0 || accentGlyphId < 0) { + continue; + } + var accentOffset = { + x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4], + y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5] + }; + + var charCodes = getCharCodes(mapping, glyphId); + if (!charCodes) { + // There's no point in mapping it if the char code was never mapped + // to begin with. + continue; + } + for (var i = 0, ii = charCodes.length; i < ii; i++) { + var charCode = charCodes[i]; + // Find a fontCharCode that maps to the base and accent glyphs. + // If one doesn't exists, create it. + var charCodeToGlyphId = newMapping.charCodeToGlyphId; + var baseFontCharCode = createCharCode(charCodeToGlyphId, + baseGlyphId); + var accentFontCharCode = createCharCode(charCodeToGlyphId, + accentGlyphId); + seacMap[charCode] = { + baseFontCharCode: baseFontCharCode, + accentFontCharCode: accentFontCharCode, + accentOffset: accentOffset + }; + } + } + properties.seacMap = seacMap; + } + + var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]; + + var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F'); + // PostScript Font Program + builder.addTable('CFF ', font.data); + // OS/2 and Windows Specific metrics + builder.addTable('OS/2', createOS2Table(properties, + newMapping.charCodeToGlyphId)); + // Character to glyphs mapping + builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId)); + // Font header + builder.addTable('head', + '\x00\x01\x00\x00' + // Version number + '\x00\x00\x10\x00' + // fontRevision + '\x00\x00\x00\x00' + // checksumAdjustement + '\x5F\x0F\x3C\xF5' + // magicNumber + '\x00\x00' + // Flags + safeString16(unitsPerEm) + // unitsPerEM + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date + '\x00\x00' + // xMin + safeString16(properties.descent) + // yMin + '\x0F\xFF' + // xMax + safeString16(properties.ascent) + // yMax + string16(properties.italicAngle ? 2 : 0) + // macStyle + '\x00\x11' + // lowestRecPPEM + '\x00\x00' + // fontDirectionHint + '\x00\x00' + // indexToLocFormat + '\x00\x00'); // glyphDataFormat + + // Horizontal header + builder.addTable('hhea', + '\x00\x01\x00\x00' + // Version number + safeString16(properties.ascent) + // Typographic Ascent + safeString16(properties.descent) + // Typographic Descent + '\x00\x00' + // Line Gap + '\xFF\xFF' + // advanceWidthMax + '\x00\x00' + // minLeftSidebearing + '\x00\x00' + // minRightSidebearing + '\x00\x00' + // xMaxExtent + safeString16(properties.capHeight) + // caretSlopeRise + safeString16(Math.tan(properties.italicAngle) * + properties.xHeight) + // caretSlopeRun + '\x00\x00' + // caretOffset + '\x00\x00' + // -reserved- + '\x00\x00' + // -reserved- + '\x00\x00' + // -reserved- + '\x00\x00' + // -reserved- + '\x00\x00' + // metricDataFormat + string16(numGlyphs)); // Number of HMetrics + + // Horizontal metrics + builder.addTable('hmtx', (function fontFieldsHmtx() { + var charstrings = font.charstrings; + var cffWidths = font.cff ? font.cff.widths : null; + var hmtx = '\x00\x00\x00\x00'; // Fake .notdef + for (var i = 1, ii = numGlyphs; i < ii; i++) { + var width = 0; + if (charstrings) { + var charstring = charstrings[i - 1]; + width = 'width' in charstring ? charstring.width : 0; + } else if (cffWidths) { + width = Math.ceil(cffWidths[i] || 0); + } + hmtx += string16(width) + string16(0); + } + return hmtx; + })()); + + // Maximum profile + builder.addTable('maxp', + '\x00\x00\x50\x00' + // Version number + string16(numGlyphs)); // Num of glyphs + + // Naming tables + builder.addTable('name', createNameTable(fontName)); + + // PostScript informations + builder.addTable('post', createPostTable(properties)); + + return builder.toArray(); + }, + + /** + * Builds a char code to unicode map based on section 9.10 of the spec. + * @param {Object} properties Font properties object. + * @return {Object} A ToUnicodeMap object. + */ + buildToUnicode: function Font_buildToUnicode(properties) { + // Section 9.10.2 Mapping Character Codes to Unicode Values + if (properties.toUnicode && properties.toUnicode.length !== 0) { + return properties.toUnicode; + } + // According to the spec if the font is a simple font we should only map + // to unicode if the base encoding is MacRoman, MacExpert, or WinAnsi or + // the differences array only contains adobe standard or symbol set names, + // in pratice it seems better to always try to create a toUnicode + // map based of the default encoding. + var toUnicode, charcode; + if (!properties.composite /* is simple font */) { + toUnicode = []; + var encoding = properties.defaultEncoding.slice(); + var baseEncodingName = properties.baseEncodingName; + // Merge in the differences array. + var differences = properties.differences; + for (charcode in differences) { + encoding[charcode] = differences[charcode]; + } + for (charcode in encoding) { + // a) Map the character code to a character name. + var glyphName = encoding[charcode]; + // b) Look up the character name in the Adobe Glyph List (see the + // Bibliography) to obtain the corresponding Unicode value. + if (glyphName === '') { + continue; + } else if (GlyphsUnicode[glyphName] === undefined) { + // (undocumented) c) Few heuristics to recognize unknown glyphs + // NOTE: Adobe Reader does not do this step, but OSX Preview does + var code = 0; + switch (glyphName[0]) { + case 'G': // Gxx glyph + if (glyphName.length === 3) { + code = parseInt(glyphName.substr(1), 16); + } + break; + case 'g': // g00xx glyph + if (glyphName.length === 5) { + code = parseInt(glyphName.substr(1), 16); + } + break; + case 'C': // Cddd glyph + case 'c': // cddd glyph + if (glyphName.length >= 3) { + code = +glyphName.substr(1); + } + break; + } + if (code) { + // If |baseEncodingName| is one the predefined encodings, + // and |code| equals |charcode|, using the glyph defined in the + // baseEncoding seems to yield a better |toUnicode| mapping + // (fixes issue 5070). + if (baseEncodingName && code === +charcode) { + var baseEncoding = Encodings[baseEncodingName]; + if (baseEncoding && (glyphName = baseEncoding[charcode])) { + toUnicode[charcode] = + String.fromCharCode(GlyphsUnicode[glyphName]); + continue; + } + } + toUnicode[charcode] = String.fromCharCode(code); + } + continue; + } + toUnicode[charcode] = String.fromCharCode(GlyphsUnicode[glyphName]); + } + return new ToUnicodeMap(toUnicode); + } + // If the font is a composite font that uses one of the predefined CMaps + // listed in Table 118 (except Identity–H and Identity–V) or whose + // descendant CIDFont uses the Adobe-GB1, Adobe-CNS1, Adobe-Japan1, or + // Adobe-Korea1 character collection: + if (properties.composite && ( + (properties.cMap.builtInCMap && + !(properties.cMap instanceof IdentityCMap)) || + (properties.cidSystemInfo.registry === 'Adobe' && + (properties.cidSystemInfo.ordering === 'GB1' || + properties.cidSystemInfo.ordering === 'CNS1' || + properties.cidSystemInfo.ordering === 'Japan1' || + properties.cidSystemInfo.ordering === 'Korea1')))) { + // Then: + // a) Map the character code to a character identifier (CID) according + // to the font’s CMap. + // b) Obtain the registry and ordering of the character collection used + // by the font’s CMap (for example, Adobe and Japan1) from its + // CIDSystemInfo dictionary. + var registry = properties.cidSystemInfo.registry; + var ordering = properties.cidSystemInfo.ordering; + // c) Construct a second CMap name by concatenating the registry and + // ordering obtained in step (b) in the format registry–ordering–UCS2 + // (for example, Adobe–Japan1–UCS2). + var ucs2CMapName = new Name(registry + '-' + ordering + '-UCS2'); + // d) Obtain the CMap with the name constructed in step (c) (available + // from the ASN Web site; see the Bibliography). + var ucs2CMap = CMapFactory.create(ucs2CMapName, + { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); + var cMap = properties.cMap; + toUnicode = []; + cMap.forEach(function(charcode, cid) { + assert(cid <= 0xffff, 'Max size of CID is 65,535'); + // e) Map the CID obtained in step (a) according to the CMap obtained + // in step (d), producing a Unicode value. + var ucs2 = ucs2CMap.lookup(cid); + if (ucs2) { + toUnicode[charcode] = + String.fromCharCode((ucs2.charCodeAt(0) << 8) + + ucs2.charCodeAt(1)); + } + }); + return new ToUnicodeMap(toUnicode); + } + + // The viewer's choice, just use an identity map. + return new IdentityToUnicodeMap(properties.firstChar, + properties.lastChar); + }, + + get spaceWidth() { + if ('_shadowWidth' in this) { + return this._shadowWidth; + } + + // trying to estimate space character width + var possibleSpaceReplacements = ['space', 'minus', 'one', 'i']; + var width; + for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) { + var glyphName = possibleSpaceReplacements[i]; + // if possible, getting width by glyph name + if (glyphName in this.widths) { + width = this.widths[glyphName]; + break; + } + var glyphUnicode = GlyphsUnicode[glyphName]; + // finding the charcode via unicodeToCID map + var charcode = 0; + if (this.composite) { + if (this.cMap.contains(glyphUnicode)) { + charcode = this.cMap.lookup(glyphUnicode); + } + } + // ... via toUnicode map + if (!charcode && 'toUnicode' in this) { + charcode = this.toUnicode.charCodeOf(glyphUnicode); + } + // setting it to unicode if negative or undefined + if (charcode <= 0) { + charcode = glyphUnicode; + } + // trying to get width via charcode + width = this.widths[charcode]; + if (width) { + break; // the non-zero width found + } + } + width = width || this.defaultWidth; + // Do not shadow the property here. See discussion: + // https://github.com/mozilla/pdf.js/pull/2127#discussion_r1662280 + this._shadowWidth = width; + return width; + }, + + charToGlyph: function Font_charToGlyph(charcode) { + var fontCharCode, width, operatorListId; + + var widthCode = charcode; + if (this.cMap && this.cMap.contains(charcode)) { + widthCode = this.cMap.lookup(charcode); + } + width = this.widths[widthCode]; + width = isNum(width) ? width : this.defaultWidth; + var vmetric = this.vmetrics && this.vmetrics[widthCode]; + + var unicode = this.toUnicode.get(charcode) || charcode; + if (typeof unicode === 'number') { + unicode = String.fromCharCode(unicode); + } + + // First try the toFontChar map, if it's not there then try falling + // back to the char code. + fontCharCode = this.toFontChar[charcode] || charcode; + if (this.missingFile) { + fontCharCode = mapSpecialUnicodeValues(fontCharCode); + } + + if (this.isType3Font) { + // Font char code in this case is actually a glyph name. + operatorListId = fontCharCode; + } + + var accent = null; + if (this.seacMap && this.seacMap[charcode]) { + var seac = this.seacMap[charcode]; + fontCharCode = seac.baseFontCharCode; + accent = { + fontChar: String.fromCharCode(seac.accentFontCharCode), + offset: seac.accentOffset + }; + } + + var fontChar = String.fromCharCode(fontCharCode); + + var glyph = this.glyphCache[charcode]; + if (!glyph || + !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric, + operatorListId)) { + glyph = new Glyph(fontChar, unicode, accent, width, vmetric, + operatorListId); + this.glyphCache[charcode] = glyph; + } + return glyph; + }, + + charsToGlyphs: function Font_charsToGlyphs(chars) { + var charsCache = this.charsCache; + var glyphs, glyph, charcode; + + // if we translated this string before, just grab it from the cache + if (charsCache) { + glyphs = charsCache[chars]; + if (glyphs) { + return glyphs; + } + } + + // lazily create the translation cache + if (!charsCache) { + charsCache = this.charsCache = Object.create(null); + } + + glyphs = []; + var charsCacheKey = chars; + var i = 0, ii; + + if (this.cMap) { + // composite fonts have multi-byte strings convert the string from + // single-byte to multi-byte + var c = {}; + while (i < chars.length) { + this.cMap.readCharCode(chars, i, c); + charcode = c.charcode; + var length = c.length; + i += length; + glyph = this.charToGlyph(charcode); + glyphs.push(glyph); + // placing null after each word break charcode (ASCII SPACE) + // Ignore occurences of 0x20 in multiple-byte codes. + if (length === 1 && chars.charCodeAt(i - 1) === 0x20) { + glyphs.push(null); + } + } + } else { + for (i = 0, ii = chars.length; i < ii; ++i) { + charcode = chars.charCodeAt(i); + glyph = this.charToGlyph(charcode); + glyphs.push(glyph); + if (charcode === 0x20) { + glyphs.push(null); + } + } + } + + // Enter the translated string into the cache + return (charsCache[charsCacheKey] = glyphs); + } + }; + + return Font; +})(); + +var ErrorFont = (function ErrorFontClosure() { + function ErrorFont(error) { + this.error = error; + this.loadedName = 'g_font_error'; + this.loading = false; + } + + ErrorFont.prototype = { + charsToGlyphs: function ErrorFont_charsToGlyphs() { + return []; + }, + exportData: function ErrorFont_exportData() { + return {error: this.error}; + } + }; + + return ErrorFont; +})(); + +/** + * Shared logic for building a char code to glyph id mapping for Type1 and + * simple CFF fonts. See section 9.6.6.2 of the spec. + * @param {Object} properties Font properties object. + * @param {Object} builtInEncoding The encoding contained within the actual font + * data. + * @param {Array} Array of glyph names where the index is the glyph ID. + * @returns {Object} A char code to glyph ID map. + */ +function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) { + var charCodeToGlyphId = Object.create(null); + var glyphId, charCode, baseEncoding; + + if (properties.baseEncodingName) { + // If a valid base encoding name was used, the mapping is initialized with + // that. + baseEncoding = Encodings[properties.baseEncodingName]; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; // notdef + } + } + } else if (!!(properties.flags & FontFlags.Symbolic)) { + // For a symbolic font the encoding should be the fonts built-in + // encoding. + for (charCode in builtInEncoding) { + charCodeToGlyphId[charCode] = builtInEncoding[charCode]; + } + } else { + // For non-symbolic fonts that don't have a base encoding the standard + // encoding should be used. + baseEncoding = Encodings.StandardEncoding; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; // notdef + } + } + } + + // Lastly, merge in the differences. + var differences = properties.differences; + if (differences) { + for (charCode in differences) { + var glyphName = differences[charCode]; + glyphId = glyphNames.indexOf(glyphName); + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; // notdef + } + } + } + return charCodeToGlyphId; +} + +/* + * CharStrings are encoded following the the CharString Encoding sequence + * describe in Chapter 6 of the "Adobe Type1 Font Format" specification. + * The value in a byte indicates a command, a number, or subsequent bytes + * that are to be interpreted in a special way. + * + * CharString Number Encoding: + * A CharString byte containing the values from 32 through 255 inclusive + * indicate an integer. These values are decoded in four ranges. + * + * 1. A CharString byte containing a value, v, between 32 and 246 inclusive, + * indicate the integer v - 139. Thus, the integer values from -107 through + * 107 inclusive may be encoded in single byte. + * + * 2. A CharString byte containing a value, v, between 247 and 250 inclusive, + * indicates an integer involving the next byte, w, according to the formula: + * [(v - 247) x 256] + w + 108 + * + * 3. A CharString byte containing a value, v, between 251 and 254 inclusive, + * indicates an integer involving the next byte, w, according to the formula: + * -[(v - 251) * 256] - w - 108 + * + * 4. A CharString containing the value 255 indicates that the next 4 bytes + * are a two complement signed integer. The first of these bytes contains the + * highest order bits, the second byte contains the next higher order bits + * and the fourth byte contain the lowest order bits. + * + * + * CharString Command Encoding: + * CharStrings commands are encoded in 1 or 2 bytes. + * + * Single byte commands are encoded in 1 byte that contains a value between + * 0 and 31 inclusive. + * If a command byte contains the value 12, then the value in the next byte + * indicates a command. This "escape" mechanism allows many extra commands + * to be encoded and this encoding technique helps to minimize the length of + * the charStrings. + */ +var Type1CharString = (function Type1CharStringClosure() { + var COMMAND_MAP = { + 'hstem': [1], + 'vstem': [3], + 'vmoveto': [4], + 'rlineto': [5], + 'hlineto': [6], + 'vlineto': [7], + 'rrcurveto': [8], + 'callsubr': [10], + 'flex': [12, 35], + 'drop' : [12, 18], + 'endchar': [14], + 'rmoveto': [21], + 'hmoveto': [22], + 'vhcurveto': [30], + 'hvcurveto': [31] + }; + + function Type1CharString() { + this.width = 0; + this.lsb = 0; + this.flexing = false; + this.output = []; + this.stack = []; + } + + Type1CharString.prototype = { + convert: function Type1CharString_convert(encoded, subrs) { + var count = encoded.length; + var error = false; + var wx, sbx, subrNumber; + for (var i = 0; i < count; i++) { + var value = encoded[i]; + if (value < 32) { + if (value === 12) { + value = (value << 8) + encoded[++i]; + } + switch (value) { + case 1: // hstem + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case 3: // vstem + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case 4: // vmoveto + if (this.flexing) { + if (this.stack.length < 1) { + error = true; + break; + } + // Add the dx for flex and but also swap the values so they are + // the right order. + var dy = this.stack.pop(); + this.stack.push(0, dy); + break; + } + error = this.executeCommand(1, COMMAND_MAP.vmoveto); + break; + case 5: // rlineto + error = this.executeCommand(2, COMMAND_MAP.rlineto); + break; + case 6: // hlineto + error = this.executeCommand(1, COMMAND_MAP.hlineto); + break; + case 7: // vlineto + error = this.executeCommand(1, COMMAND_MAP.vlineto); + break; + case 8: // rrcurveto + error = this.executeCommand(6, COMMAND_MAP.rrcurveto); + break; + case 9: // closepath + // closepath is a Type1 command that does not take argument and is + // useless in Type2 and it can simply be ignored. + this.stack = []; + break; + case 10: // callsubr + if (this.stack.length < 1) { + error = true; + break; + } + subrNumber = this.stack.pop(); + error = this.convert(subrs[subrNumber], subrs); + break; + case 11: // return + return error; + case 13: // hsbw + if (this.stack.length < 2) { + error = true; + break; + } + // To convert to type2 we have to move the width value to the + // first part of the charstring and then use hmoveto with lsb. + wx = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx); + error = this.executeCommand(2, COMMAND_MAP.hmoveto); + break; + case 14: // endchar + this.output.push(COMMAND_MAP.endchar[0]); + break; + case 21: // rmoveto + if (this.flexing) { + break; + } + error = this.executeCommand(2, COMMAND_MAP.rmoveto); + break; + case 22: // hmoveto + if (this.flexing) { + // Add the dy for flex. + this.stack.push(0); + break; + } + error = this.executeCommand(1, COMMAND_MAP.hmoveto); + break; + case 30: // vhcurveto + error = this.executeCommand(4, COMMAND_MAP.vhcurveto); + break; + case 31: // hvcurveto + error = this.executeCommand(4, COMMAND_MAP.hvcurveto); + break; + case (12 << 8) + 0: // dotsection + // dotsection is a Type1 command to specify some hinting feature + // for dots that do not take a parameter and it can safely be + // ignored for Type2. + this.stack = []; + break; + case (12 << 8) + 1: // vstem3 + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + // [vh]stem3 are Type1 only and Type2 supports [vh]stem with + // multiple parameters, so instead of returning [vh]stem3 take a + // shortcut and return [vhstem] instead. + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case (12 << 8) + 2: // hstem3 + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + // See vstem3. + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case (12 << 8) + 6: // seac + // seac is like type 2's special endchar but it doesn't use the + // first argument asb, so remove it. + if (SEAC_ANALYSIS_ENABLED) { + this.seac = this.stack.splice(-4, 4); + error = this.executeCommand(0, COMMAND_MAP.endchar); + } else { + error = this.executeCommand(4, COMMAND_MAP.endchar); + } + break; + case (12 << 8) + 7: // sbw + if (this.stack.length < 4) { + error = true; + break; + } + // To convert to type2 we have to move the width value to the + // first part of the charstring and then use rmoveto with + // (dx, dy). The height argument will not be used for vmtx and + // vhea tables reconstruction -- ignoring it. + var wy = this.stack.pop(); + wx = this.stack.pop(); + var sby = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx, sby); + error = this.executeCommand(3, COMMAND_MAP.rmoveto); + break; + case (12 << 8) + 12: // div + if (this.stack.length < 2) { + error = true; + break; + } + var num2 = this.stack.pop(); + var num1 = this.stack.pop(); + this.stack.push(num1 / num2); + break; + case (12 << 8) + 16: // callothersubr + if (this.stack.length < 2) { + error = true; + break; + } + subrNumber = this.stack.pop(); + var numArgs = this.stack.pop(); + if (subrNumber === 0 && numArgs === 3) { + var flexArgs = this.stack.splice(this.stack.length - 17, 17); + this.stack.push( + flexArgs[2] + flexArgs[0], // bcp1x + rpx + flexArgs[3] + flexArgs[1], // bcp1y + rpy + flexArgs[4], // bcp2x + flexArgs[5], // bcp2y + flexArgs[6], // p2x + flexArgs[7], // p2y + flexArgs[8], // bcp3x + flexArgs[9], // bcp3y + flexArgs[10], // bcp4x + flexArgs[11], // bcp4y + flexArgs[12], // p3x + flexArgs[13], // p3y + flexArgs[14] // flexDepth + // 15 = finalx unused by flex + // 16 = finaly unused by flex + ); + error = this.executeCommand(13, COMMAND_MAP.flex, true); + this.flexing = false; + this.stack.push(flexArgs[15], flexArgs[16]); + } else if (subrNumber === 1 && numArgs === 0) { + this.flexing = true; + } + break; + case (12 << 8) + 17: // pop + // Ignore this since it is only used with othersubr. + break; + case (12 << 8) + 33: // setcurrentpoint + // Ignore for now. + this.stack = []; + break; + default: + warn('Unknown type 1 charstring command of "' + value + '"'); + break; + } + if (error) { + break; + } + continue; + } else if (value <= 246) { + value = value - 139; + } else if (value <= 250) { + value = ((value - 247) * 256) + encoded[++i] + 108; + } else if (value <= 254) { + value = -((value - 251) * 256) - encoded[++i] - 108; + } else { + value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | + (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0; + } + this.stack.push(value); + } + return error; + }, + + executeCommand: function(howManyArgs, command, keepStack) { + var stackLength = this.stack.length; + if (howManyArgs > stackLength) { + return true; + } + var start = stackLength - howManyArgs; + for (var i = start; i < stackLength; i++) { + var value = this.stack[i]; + if (value === (value | 0)) { // int + this.output.push(28, (value >> 8) & 0xff, value & 0xff); + } else { // fixed point + value = (65536 * value) | 0; + this.output.push(255, + (value >> 24) & 0xFF, + (value >> 16) & 0xFF, + (value >> 8) & 0xFF, + value & 0xFF); + } + } + this.output.push.apply(this.output, command); + if (keepStack) { + this.stack.splice(start, howManyArgs); + } else { + this.stack.length = 0; + } + return false; + } + }; + + return Type1CharString; +})(); + +/* + * Type1Parser encapsulate the needed code for parsing a Type1 font + * program. Some of its logic depends on the Type2 charstrings + * structure. + * Note: this doesn't really parse the font since that would require evaluation + * of PostScript, but it is possible in most cases to extract what we need + * without a full parse. + */ +var Type1Parser = (function Type1ParserClosure() { + /* + * Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence + * of Plaintext Bytes. The function took a key as a parameter which can be + * for decrypting the eexec block of for decoding charStrings. + */ + var EEXEC_ENCRYPT_KEY = 55665; + var CHAR_STRS_ENCRYPT_KEY = 4330; + + function isHexDigit(code) { + return code >= 48 && code <= 57 || // '0'-'9' + code >= 65 && code <= 70 || // 'A'-'F' + code >= 97 && code <= 102; // 'a'-'f' + } + + function decrypt(data, key, discardNumber) { + var r = key | 0, c1 = 52845, c2 = 22719; + var count = data.length; + var decrypted = new Uint8Array(count); + for (var i = 0; i < count; i++) { + var value = data[i]; + decrypted[i] = value ^ (r >> 8); + r = ((value + r) * c1 + c2) & ((1 << 16) - 1); + } + return Array.prototype.slice.call(decrypted, discardNumber); + } + + function decryptAscii(data, key, discardNumber) { + var r = key | 0, c1 = 52845, c2 = 22719; + var count = data.length, maybeLength = count >>> 1; + var decrypted = new Uint8Array(maybeLength); + var i, j; + for (i = 0, j = 0; i < count; i++) { + var digit1 = data[i]; + if (!isHexDigit(digit1)) { + continue; + } + i++; + var digit2; + while (i < count && !isHexDigit(digit2 = data[i])) { + i++; + } + if (i < count) { + var value = parseInt(String.fromCharCode(digit1, digit2), 16); + decrypted[j++] = value ^ (r >> 8); + r = ((value + r) * c1 + c2) & ((1 << 16) - 1); + } + } + return Array.prototype.slice.call(decrypted, discardNumber, j); + } + + function isSpecial(c) { + return c === 0x2F || // '/' + c === 0x5B || c === 0x5D || // '[', ']' + c === 0x7B || c === 0x7D || // '{', '}' + c === 0x28 || c === 0x29; // '(', ')' + } + + function Type1Parser(stream, encrypted) { + if (encrypted) { + var data = stream.getBytes(); + var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) && + isHexDigit(data[2]) && isHexDigit(data[3])); + stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : + decryptAscii(data, EEXEC_ENCRYPT_KEY, 4)); + } + this.stream = stream; + this.nextChar(); + } + + Type1Parser.prototype = { + readNumberArray: function Type1Parser_readNumberArray() { + this.getToken(); // read '[' or '{' (arrays can start with either) + var array = []; + while (true) { + var token = this.getToken(); + if (token === null || token === ']' || token === '}') { + break; + } + array.push(parseFloat(token || 0)); + } + return array; + }, + + readNumber: function Type1Parser_readNumber() { + var token = this.getToken(); + return parseFloat(token || 0); + }, + + readInt: function Type1Parser_readInt() { + // Use '| 0' to prevent setting a double into length such as the double + // does not flow into the loop variable. + var token = this.getToken(); + return parseInt(token || 0, 10) | 0; + }, + + readBoolean: function Type1Parser_readBoolean() { + var token = this.getToken(); + + // Use 1 and 0 since that's what type2 charstrings use. + return token === 'true' ? 1 : 0; + }, + + nextChar : function Type1_nextChar() { + return (this.currentChar = this.stream.getByte()); + }, + + getToken: function Type1Parser_getToken() { + // Eat whitespace and comments. + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch === -1) { + return null; + } + + if (comment) { + if (ch === 0x0A || ch === 0x0D) { + comment = false; + } + } else if (ch === 0x25) { // '%' + comment = true; + } else if (!Lexer.isSpace(ch)) { + break; + } + ch = this.nextChar(); + } + if (isSpecial(ch)) { + this.nextChar(); + return String.fromCharCode(ch); + } + var token = ''; + do { + token += String.fromCharCode(ch); + ch = this.nextChar(); + } while (ch >= 0 && !Lexer.isSpace(ch) && !isSpecial(ch)); + return token; + }, + + /* + * Returns an object containing a Subrs array and a CharStrings + * array extracted from and eexec encrypted block of data + */ + extractFontProgram: function Type1Parser_extractFontProgram() { + var stream = this.stream; + + var subrs = [], charstrings = []; + var program = { + subrs: [], + charstrings: [], + properties: { + 'privateData': { + 'lenIV': 4 + } + } + }; + var token, length, data, lenIV, encoded; + while ((token = this.getToken()) !== null) { + if (token !== '/') { + continue; + } + token = this.getToken(); + switch (token) { + case 'CharStrings': + // The number immediately following CharStrings must be greater or + // equal to the number of CharStrings. + this.getToken(); + this.getToken(); // read in 'dict' + this.getToken(); // read in 'dup' + this.getToken(); // read in 'begin' + while(true) { + token = this.getToken(); + if (token === null || token === 'end') { + break; + } + + if (token !== '/') { + continue; + } + var glyph = this.getToken(); + length = this.readInt(); + this.getToken(); // read in 'RD' or '-|' + data = stream.makeSubStream(stream.pos, length); + lenIV = program.properties.privateData['lenIV']; + encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV); + // Skip past the required space and binary data. + stream.skip(length); + this.nextChar(); + token = this.getToken(); // read in 'ND' or '|-' + if (token === 'noaccess') { + this.getToken(); // read in 'def' + } + charstrings.push({ + glyph: glyph, + encoded: encoded + }); + } + break; + case 'Subrs': + var num = this.readInt(); + this.getToken(); // read in 'array' + while ((token = this.getToken()) === 'dup') { + var index = this.readInt(); + length = this.readInt(); + this.getToken(); // read in 'RD' or '-|' + data = stream.makeSubStream(stream.pos, length); + lenIV = program.properties.privateData['lenIV']; + encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV); + // Skip past the required space and binary data. + stream.skip(length); + this.nextChar(); + token = this.getToken(); // read in 'NP' or '|' + if (token === 'noaccess') { + this.getToken(); // read in 'put' + } + subrs[index] = encoded; + } + break; + case 'BlueValues': + case 'OtherBlues': + case 'FamilyBlues': + case 'FamilyOtherBlues': + var blueArray = this.readNumberArray(); + // *Blue* values may contain invalid data: disables reading of + // those values when hinting is disabled. + if (blueArray.length > 0 && (blueArray.length % 2) === 0 && + HINTING_ENABLED) { + program.properties.privateData[token] = blueArray; + } + break; + case 'StemSnapH': + case 'StemSnapV': + program.properties.privateData[token] = this.readNumberArray(); + break; + case 'StdHW': + case 'StdVW': + program.properties.privateData[token] = + this.readNumberArray()[0]; + break; + case 'BlueShift': + case 'lenIV': + case 'BlueFuzz': + case 'BlueScale': + case 'LanguageGroup': + case 'ExpansionFactor': + program.properties.privateData[token] = this.readNumber(); + break; + case 'ForceBold': + program.properties.privateData[token] = this.readBoolean(); + break; + } + } + + for (var i = 0; i < charstrings.length; i++) { + glyph = charstrings[i].glyph; + encoded = charstrings[i].encoded; + var charString = new Type1CharString(); + var error = charString.convert(encoded, subrs); + var output = charString.output; + if (error) { + // It seems when FreeType encounters an error while evaluating a glyph + // that it completely ignores the glyph so we'll mimic that behaviour + // here and put an endchar to make the validator happy. + output = [14]; + } + program.charstrings.push({ + glyphName: glyph, + charstring: output, + width: charString.width, + lsb: charString.lsb, + seac: charString.seac + }); + } + + return program; + }, + + extractFontHeader: function Type1Parser_extractFontHeader(properties) { + var token; + while ((token = this.getToken()) !== null) { + if (token !== '/') { + continue; + } + token = this.getToken(); + switch (token) { + case 'FontMatrix': + var matrix = this.readNumberArray(); + properties.fontMatrix = matrix; + break; + case 'Encoding': + var encodingArg = this.getToken(); + var encoding; + if (!/^\d+$/.test(encodingArg)) { + // encoding name is specified + encoding = Encodings[encodingArg]; + } else { + encoding = []; + var size = parseInt(encodingArg, 10) | 0; + this.getToken(); // read in 'array' + + for (var j = 0; j < size; j++) { + token = this.getToken(); + // skipping till first dup or def (e.g. ignoring for statement) + while (token !== 'dup' && token !== 'def') { + token = this.getToken(); + if (token === null) { + return; // invalid header + } + } + if (token === 'def') { + break; // read all array data + } + var index = this.readInt(); + this.getToken(); // read in '/' + var glyph = this.getToken(); + encoding[index] = glyph; + this.getToken(); // read the in 'put' + } + } + properties.builtInEncoding = encoding; + break; + case 'FontBBox': + var fontBBox = this.readNumberArray(); + // adjusting ascent/descent + properties.ascent = fontBBox[3]; + properties.descent = fontBBox[1]; + properties.ascentScaled = true; + break; + } + } + } + }; + + return Type1Parser; +})(); + +/** + * The CFF class takes a Type1 file and wrap it into a + * 'Compact Font Format' which itself embed Type2 charstrings. + */ +var CFFStandardStrings = [ + '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', + 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', + 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', + 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', + 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', + 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', + 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', + 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', + 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', + 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', + 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', + 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', + 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', + 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', + 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', + 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', + 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', + 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', + 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', + 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', + 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', + 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', + 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', + 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', + 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', + 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', + 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', + 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', + 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', + 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', + 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', + 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', + 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', + 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', + 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', + 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', + 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', + 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth', + 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', + 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', + 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', + 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', + 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', + 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', + 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', + 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', + 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', + 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', + 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', + 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', + 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', + 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003', + 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold' +]; + +// Type1Font is also a CIDFontType0. +var Type1Font = function Type1Font(name, file, properties) { + // Some bad generators embed pfb file as is, we have to strip 6-byte headers. + // Also, length1 and length2 might be off by 6 bytes as well. + // http://www.math.ubc.ca/~cass/piscript/type1.pdf + var PFB_HEADER_SIZE = 6; + var headerBlockLength = properties.length1; + var eexecBlockLength = properties.length2; + var pfbHeader = file.peekBytes(PFB_HEADER_SIZE); + var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01; + if (pfbHeaderPresent) { + file.skip(PFB_HEADER_SIZE); + headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) | + (pfbHeader[3] << 8) | pfbHeader[2]; + } + + // Get the data block containing glyphs and subrs informations + var headerBlock = new Stream(file.getBytes(headerBlockLength)); + var headerBlockParser = new Type1Parser(headerBlock); + headerBlockParser.extractFontHeader(properties); + + if (pfbHeaderPresent) { + pfbHeader = file.getBytes(PFB_HEADER_SIZE); + eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) | + (pfbHeader[3] << 8) | pfbHeader[2]; + } + + // Decrypt the data blocks and retrieve it's content + var eexecBlock = new Stream(file.getBytes(eexecBlockLength)); + var eexecBlockParser = new Type1Parser(eexecBlock, true); + var data = eexecBlockParser.extractFontProgram(); + for (var info in data.properties) { + properties[info] = data.properties[info]; + } + + var charstrings = data.charstrings; + var type2Charstrings = this.getType2Charstrings(charstrings); + var subrs = this.getType2Subrs(data.subrs); + + this.charstrings = charstrings; + this.data = this.wrap(name, type2Charstrings, this.charstrings, + subrs, properties); + this.seacs = this.getSeacs(data.charstrings); +}; + +Type1Font.prototype = { + get numGlyphs() { + return this.charstrings.length + 1; + }, + + getCharset: function Type1Font_getCharset() { + var charset = ['.notdef']; + var charstrings = this.charstrings; + for (var glyphId = 0; glyphId < charstrings.length; glyphId++) { + charset.push(charstrings[glyphId].glyphName); + } + return charset; + }, + + getGlyphMapping: function Type1Font_getGlyphMapping(properties) { + var charstrings = this.charstrings; + var glyphNames = ['.notdef'], glyphId; + for (glyphId = 0; glyphId < charstrings.length; glyphId++) { + glyphNames.push(charstrings[glyphId].glyphName); + } + var encoding = properties.builtInEncoding; + if (encoding) { + var builtInEncoding = {}; + for (var charCode in encoding) { + glyphId = glyphNames.indexOf(encoding[charCode]); + if (glyphId >= 0) { + builtInEncoding[charCode] = glyphId; + } + } + } + + return type1FontGlyphMapping(properties, builtInEncoding, glyphNames); + }, + + getSeacs: function Type1Font_getSeacs(charstrings) { + var i, ii; + var seacMap = []; + for (i = 0, ii = charstrings.length; i < ii; i++) { + var charstring = charstrings[i]; + if (charstring.seac) { + // Offset by 1 for .notdef + seacMap[i + 1] = charstring.seac; + } + } + return seacMap; + }, + + getType2Charstrings: function Type1Font_getType2Charstrings( + type1Charstrings) { + var type2Charstrings = []; + for (var i = 0, ii = type1Charstrings.length; i < ii; i++) { + type2Charstrings.push(type1Charstrings[i].charstring); + } + return type2Charstrings; + }, + + getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) { + var bias = 0; + var count = type1Subrs.length; + if (count < 1133) { + bias = 107; + } else if (count < 33769) { + bias = 1131; + } else { + bias = 32768; + } + + // Add a bunch of empty subrs to deal with the Type2 bias + var type2Subrs = []; + var i; + for (i = 0; i < bias; i++) { + type2Subrs.push([0x0B]); + } + + for (i = 0; i < count; i++) { + type2Subrs.push(type1Subrs[i]); + } + + return type2Subrs; + }, + + wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) { + var cff = new CFF(); + cff.header = new CFFHeader(1, 0, 4, 4); + + cff.names = [name]; + + var topDict = new CFFTopDict(); + // CFF strings IDs 0...390 are predefined names, so refering + // to entries in our own String INDEX starts at SID 391. + topDict.setByName('version', 391); + topDict.setByName('Notice', 392); + topDict.setByName('FullName', 393); + topDict.setByName('FamilyName', 394); + topDict.setByName('Weight', 395); + topDict.setByName('Encoding', null); // placeholder + topDict.setByName('FontMatrix', properties.fontMatrix); + topDict.setByName('FontBBox', properties.bbox); + topDict.setByName('charset', null); // placeholder + topDict.setByName('CharStrings', null); // placeholder + topDict.setByName('Private', null); // placeholder + cff.topDict = topDict; + + var strings = new CFFStrings(); + strings.add('Version 0.11'); // Version + strings.add('See original notice'); // Notice + strings.add(name); // FullName + strings.add(name); // FamilyName + strings.add('Medium'); // Weight + cff.strings = strings; + + cff.globalSubrIndex = new CFFIndex(); + + var count = glyphs.length; + var charsetArray = [0]; + var i, ii; + for (i = 0; i < count; i++) { + var index = CFFStandardStrings.indexOf(charstrings[i].glyphName); + // TODO: Insert the string and correctly map it. Previously it was + // thought mapping names that aren't in the standard strings to .notdef + // was fine, however in issue818 when mapping them all to .notdef the + // adieresis glyph no longer worked. + if (index === -1) { + index = 0; + } + charsetArray.push((index >> 8) & 0xff, index & 0xff); + } + cff.charset = new CFFCharset(false, 0, [], charsetArray); + + var charStringsIndex = new CFFIndex(); + charStringsIndex.add([0x8B, 0x0E]); // .notdef + for (i = 0; i < count; i++) { + charStringsIndex.add(glyphs[i]); + } + cff.charStrings = charStringsIndex; + + var privateDict = new CFFPrivateDict(); + privateDict.setByName('Subrs', null); // placeholder + var fields = [ + 'BlueValues', + 'OtherBlues', + 'FamilyBlues', + 'FamilyOtherBlues', + 'StemSnapH', + 'StemSnapV', + 'BlueShift', + 'BlueFuzz', + 'BlueScale', + 'LanguageGroup', + 'ExpansionFactor', + 'ForceBold', + 'StdHW', + 'StdVW' + ]; + for (i = 0, ii = fields.length; i < ii; i++) { + var field = fields[i]; + if (!properties.privateData.hasOwnProperty(field)) { + continue; + } + var value = properties.privateData[field]; + if (isArray(value)) { + // All of the private dictionary array data in CFF must be stored as + // "delta-encoded" numbers. + for (var j = value.length - 1; j > 0; j--) { + value[j] -= value[j - 1]; // ... difference from previous value + } + } + privateDict.setByName(field, value); + } + cff.topDict.privateDict = privateDict; + + var subrIndex = new CFFIndex(); + for (i = 0, ii = subrs.length; i < ii; i++) { + subrIndex.add(subrs[i]); + } + privateDict.subrsIndex = subrIndex; + + var compiler = new CFFCompiler(cff); + return compiler.compile(); + } +}; + +var CFFFont = (function CFFFontClosure() { + function CFFFont(file, properties) { + this.properties = properties; + + var parser = new CFFParser(file, properties); + this.cff = parser.parse(); + var compiler = new CFFCompiler(this.cff); + this.seacs = this.cff.seacs; + try { + this.data = compiler.compile(); + } catch (e) { + warn('Failed to compile font ' + properties.loadedName); + // There may have just been an issue with the compiler, set the data + // anyway and hope the font loaded. + this.data = file; + } + } + + CFFFont.prototype = { + get numGlyphs() { + return this.cff.charStrings.count; + }, + getCharset: function CFFFont_getCharset() { + return this.cff.charset.charset; + }, + getGlyphMapping: function CFFFont_getGlyphMapping() { + var cff = this.cff; + var properties = this.properties; + var charsets = cff.charset.charset; + var charCodeToGlyphId; + var glyphId; + + if (properties.composite) { + charCodeToGlyphId = Object.create(null); + if (cff.isCIDFont) { + // If the font is actually a CID font then we should use the charset + // to map CIDs to GIDs. + for (glyphId = 0; glyphId < charsets.length; glyphId++) { + var cid = charsets[glyphId]; + var charCode = properties.cMap.charCodeOf(cid); + charCodeToGlyphId[charCode] = glyphId; + } + } else { + // If it is NOT actually a CID font then CIDs should be mapped + // directly to GIDs. + for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) { + charCodeToGlyphId[glyphId] = glyphId; + } + } + return charCodeToGlyphId; + } + + var encoding = cff.encoding ? cff.encoding.encoding : null; + charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets); + return charCodeToGlyphId; + } + }; + + return CFFFont; +})(); + +var CFFParser = (function CFFParserClosure() { + var CharstringValidationData = [ + null, + { id: 'hstem', min: 2, stackClearing: true, stem: true }, + null, + { id: 'vstem', min: 2, stackClearing: true, stem: true }, + { id: 'vmoveto', min: 1, stackClearing: true }, + { id: 'rlineto', min: 2, resetStack: true }, + { id: 'hlineto', min: 1, resetStack: true }, + { id: 'vlineto', min: 1, resetStack: true }, + { id: 'rrcurveto', min: 6, resetStack: true }, + null, + { id: 'callsubr', min: 1, undefStack: true }, + { id: 'return', min: 0, undefStack: true }, + null, // 12 + null, + { id: 'endchar', min: 0, stackClearing: true }, + null, + null, + null, + { id: 'hstemhm', min: 2, stackClearing: true, stem: true }, + { id: 'hintmask', min: 0, stackClearing: true }, + { id: 'cntrmask', min: 0, stackClearing: true }, + { id: 'rmoveto', min: 2, stackClearing: true }, + { id: 'hmoveto', min: 1, stackClearing: true }, + { id: 'vstemhm', min: 2, stackClearing: true, stem: true }, + { id: 'rcurveline', min: 8, resetStack: true }, + { id: 'rlinecurve', min: 8, resetStack: true }, + { id: 'vvcurveto', min: 4, resetStack: true }, + { id: 'hhcurveto', min: 4, resetStack: true }, + null, // shortint + { id: 'callgsubr', min: 1, undefStack: true }, + { id: 'vhcurveto', min: 4, resetStack: true }, + { id: 'hvcurveto', min: 4, resetStack: true } + ]; + var CharstringValidationData12 = [ + null, + null, + null, + { id: 'and', min: 2, stackDelta: -1 }, + { id: 'or', min: 2, stackDelta: -1 }, + { id: 'not', min: 1, stackDelta: 0 }, + null, + null, + null, + { id: 'abs', min: 1, stackDelta: 0 }, + { id: 'add', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] + stack[index - 1]; + } + }, + { id: 'sub', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] - stack[index - 1]; + } + }, + { id: 'div', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] / stack[index - 1]; + } + }, + null, + { id: 'neg', min: 1, stackDelta: 0, + stackFn: function stack_div(stack, index) { + stack[index - 1] = -stack[index - 1]; + } + }, + { id: 'eq', min: 2, stackDelta: -1 }, + null, + null, + { id: 'drop', min: 1, stackDelta: -1 }, + null, + { id: 'put', min: 2, stackDelta: -2 }, + { id: 'get', min: 1, stackDelta: 0 }, + { id: 'ifelse', min: 4, stackDelta: -3 }, + { id: 'random', min: 0, stackDelta: 1 }, + { id: 'mul', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] * stack[index - 1]; + } + }, + null, + { id: 'sqrt', min: 1, stackDelta: 0 }, + { id: 'dup', min: 1, stackDelta: 1 }, + { id: 'exch', min: 2, stackDelta: 0 }, + { id: 'index', min: 2, stackDelta: 0 }, + { id: 'roll', min: 3, stackDelta: -2 }, + null, + null, + null, + { id: 'hflex', min: 7, resetStack: true }, + { id: 'flex', min: 13, resetStack: true }, + { id: 'hflex1', min: 9, resetStack: true }, + { id: 'flex1', min: 11, resetStack: true } + ]; + + function CFFParser(file, properties) { + this.bytes = file.getBytes(); + this.properties = properties; + } + CFFParser.prototype = { + parse: function CFFParser_parse() { + var properties = this.properties; + var cff = new CFF(); + this.cff = cff; + + // The first five sections must be in order, all the others are reached + // via offsets contained in one of the below. + var header = this.parseHeader(); + var nameIndex = this.parseIndex(header.endPos); + var topDictIndex = this.parseIndex(nameIndex.endPos); + var stringIndex = this.parseIndex(topDictIndex.endPos); + var globalSubrIndex = this.parseIndex(stringIndex.endPos); + + var topDictParsed = this.parseDict(topDictIndex.obj.get(0)); + var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings); + + cff.header = header.obj; + cff.names = this.parseNameIndex(nameIndex.obj); + cff.strings = this.parseStringIndex(stringIndex.obj); + cff.topDict = topDict; + cff.globalSubrIndex = globalSubrIndex.obj; + + this.parsePrivateDict(cff.topDict); + + cff.isCIDFont = topDict.hasName('ROS'); + + var charStringOffset = topDict.getByName('CharStrings'); + var charStringsAndSeacs = this.parseCharStrings(charStringOffset); + cff.charStrings = charStringsAndSeacs.charStrings; + cff.seacs = charStringsAndSeacs.seacs; + cff.widths = charStringsAndSeacs.widths; + + var fontMatrix = topDict.getByName('FontMatrix'); + if (fontMatrix) { + properties.fontMatrix = fontMatrix; + } + + var fontBBox = topDict.getByName('FontBBox'); + if (fontBBox) { + // adjusting ascent/descent + properties.ascent = fontBBox[3]; + properties.descent = fontBBox[1]; + properties.ascentScaled = true; + } + + var charset, encoding; + if (cff.isCIDFont) { + var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj; + for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) { + var dictRaw = fdArrayIndex.get(i); + var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), + cff.strings); + this.parsePrivateDict(fontDict); + cff.fdArray.push(fontDict); + } + // cid fonts don't have an encoding + encoding = null; + charset = this.parseCharsets(topDict.getByName('charset'), + cff.charStrings.count, cff.strings, true); + cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), + cff.charStrings.count); + } else { + charset = this.parseCharsets(topDict.getByName('charset'), + cff.charStrings.count, cff.strings, false); + encoding = this.parseEncoding(topDict.getByName('Encoding'), + properties, + cff.strings, charset.charset); + } + cff.charset = charset; + cff.encoding = encoding; + + return cff; + }, + parseHeader: function CFFParser_parseHeader() { + var bytes = this.bytes; + var bytesLength = bytes.length; + var offset = 0; + + // Prevent an infinite loop, by checking that the offset is within the + // bounds of the bytes array. Necessary in empty, or invalid, font files. + while (offset < bytesLength && bytes[offset] !== 1) { + ++offset; + } + if (offset >= bytesLength) { + error('Invalid CFF header'); + } else if (offset !== 0) { + info('cff data is shifted'); + bytes = bytes.subarray(offset); + this.bytes = bytes; + } + var major = bytes[0]; + var minor = bytes[1]; + var hdrSize = bytes[2]; + var offSize = bytes[3]; + var header = new CFFHeader(major, minor, hdrSize, offSize); + return { obj: header, endPos: hdrSize }; + }, + parseDict: function CFFParser_parseDict(dict) { + var pos = 0; + + function parseOperand() { + var value = dict[pos++]; + if (value === 30) { + return parseFloatOperand(pos); + } else if (value === 28) { + value = dict[pos++]; + value = ((value << 24) | (dict[pos++] << 16)) >> 16; + return value; + } else if (value === 29) { + value = dict[pos++]; + value = (value << 8) | dict[pos++]; + value = (value << 8) | dict[pos++]; + value = (value << 8) | dict[pos++]; + return value; + } else if (value >= 32 && value <= 246) { + return value - 139; + } else if (value >= 247 && value <= 250) { + return ((value - 247) * 256) + dict[pos++] + 108; + } else if (value >= 251 && value <= 254) { + return -((value - 251) * 256) - dict[pos++] - 108; + } else { + error('255 is not a valid DICT command'); + } + return -1; + } + + function parseFloatOperand() { + var str = ''; + var eof = 15; + var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', '.', 'E', 'E-', null, '-']; + var length = dict.length; + while (pos < length) { + var b = dict[pos++]; + var b1 = b >> 4; + var b2 = b & 15; + + if (b1 === eof) { + break; + } + str += lookup[b1]; + + if (b2 === eof) { + break; + } + str += lookup[b2]; + } + return parseFloat(str); + } + + var operands = []; + var entries = []; + + pos = 0; + var end = dict.length; + while (pos < end) { + var b = dict[pos]; + if (b <= 21) { + if (b === 12) { + b = (b << 8) | dict[++pos]; + } + entries.push([b, operands]); + operands = []; + ++pos; + } else { + operands.push(parseOperand()); + } + } + return entries; + }, + parseIndex: function CFFParser_parseIndex(pos) { + var cffIndex = new CFFIndex(); + var bytes = this.bytes; + var count = (bytes[pos++] << 8) | bytes[pos++]; + var offsets = []; + var end = pos; + var i, ii; + + if (count !== 0) { + var offsetSize = bytes[pos++]; + // add 1 for offset to determine size of last object + var startPos = pos + ((count + 1) * offsetSize) - 1; + + for (i = 0, ii = count + 1; i < ii; ++i) { + var offset = 0; + for (var j = 0; j < offsetSize; ++j) { + offset <<= 8; + offset += bytes[pos++]; + } + offsets.push(startPos + offset); + } + end = offsets[count]; + } + for (i = 0, ii = offsets.length - 1; i < ii; ++i) { + var offsetStart = offsets[i]; + var offsetEnd = offsets[i + 1]; + cffIndex.add(bytes.subarray(offsetStart, offsetEnd)); + } + return {obj: cffIndex, endPos: end}; + }, + parseNameIndex: function CFFParser_parseNameIndex(index) { + var names = []; + for (var i = 0, ii = index.count; i < ii; ++i) { + var name = index.get(i); + // OTS doesn't allow names to be over 127 characters. + var length = Math.min(name.length, 127); + var data = []; + // OTS also only permits certain characters in the name. + for (var j = 0; j < length; ++j) { + var c = name[j]; + if (j === 0 && c === 0) { + data[j] = c; + continue; + } + if ((c < 33 || c > 126) || c === 91 /* [ */ || c === 93 /* ] */ || + c === 40 /* ( */ || c === 41 /* ) */ || c === 123 /* { */ || + c === 125 /* } */ || c === 60 /* < */ || c === 62 /* > */ || + c === 47 /* / */ || c === 37 /* % */ || c === 35 /* # */) { + data[j] = 95; + continue; + } + data[j] = c; + } + names.push(bytesToString(data)); + } + return names; + }, + parseStringIndex: function CFFParser_parseStringIndex(index) { + var strings = new CFFStrings(); + for (var i = 0, ii = index.count; i < ii; ++i) { + var data = index.get(i); + strings.add(bytesToString(data)); + } + return strings; + }, + createDict: function CFFParser_createDict(Type, dict, strings) { + var cffDict = new Type(strings); + for (var i = 0, ii = dict.length; i < ii; ++i) { + var pair = dict[i]; + var key = pair[0]; + var value = pair[1]; + cffDict.setByKey(key, value); + } + return cffDict; + }, + parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) { + var charStrings = this.parseIndex(charStringOffset).obj; + var seacs = []; + var widths = []; + var count = charStrings.count; + for (var i = 0; i < count; i++) { + var charstring = charStrings.get(i); + + var stackSize = 0; + var stack = []; + var undefStack = true; + var hints = 0; + var valid = true; + var data = charstring; + var length = data.length; + var firstStackClearing = true; + for (var j = 0; j < length;) { + var value = data[j++]; + var validationCommand = null; + if (value === 12) { + var q = data[j++]; + if (q === 0) { + // The CFF specification state that the 'dotsection' command + // (12, 0) is deprecated and treated as a no-op, but all Type2 + // charstrings processors should support them. Unfortunately + // the font sanitizer don't. As a workaround the sequence (12, 0) + // is replaced by a useless (0, hmoveto). + data[j - 2] = 139; + data[j - 1] = 22; + stackSize = 0; + } else { + validationCommand = CharstringValidationData12[q]; + } + } else if (value === 28) { // number (16 bit) + stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16; + j += 2; + stackSize++; + } else if (value === 14) { + if (stackSize >= 4) { + stackSize -= 4; + if (SEAC_ANALYSIS_ENABLED) { + seacs[i] = stack.slice(stackSize, stackSize + 4); + valid = false; + } + } + validationCommand = CharstringValidationData[value]; + } else if (value >= 32 && value <= 246) { // number + stack[stackSize] = value - 139; + stackSize++; + } else if (value >= 247 && value <= 254) { // number (+1 bytes) + stack[stackSize] = (value < 251 ? + ((value - 247) << 8) + data[j] + 108 : + -((value - 251) << 8) - data[j] - 108); + j++; + stackSize++; + } else if (value === 255) { // number (32 bit) + stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) | + (data[j + 2] << 8) | data[j + 3]) / 65536; + j += 4; + stackSize++; + } else if (value === 19 || value === 20) { + hints += stackSize >> 1; + j += (hints + 7) >> 3; // skipping right amount of hints flag data + stackSize %= 2; + validationCommand = CharstringValidationData[value]; + } else { + validationCommand = CharstringValidationData[value]; + } + if (validationCommand) { + if (validationCommand.stem) { + hints += stackSize >> 1; + } + if ('min' in validationCommand) { + if (!undefStack && stackSize < validationCommand.min) { + warn('Not enough parameters for ' + validationCommand.id + + '; actual: ' + stackSize + + ', expected: ' + validationCommand.min); + valid = false; + break; + } + } + if (firstStackClearing && validationCommand.stackClearing) { + firstStackClearing = false; + // the optional character width can be found before the first + // stack-clearing command arguments + stackSize -= validationCommand.min; + if (stackSize >= 2 && validationCommand.stem) { + // there are even amount of arguments for stem commands + stackSize %= 2; + } else if (stackSize > 1) { + warn('Found too many parameters for stack-clearing command'); + } + if (stackSize > 0 && stack[stackSize - 1] >= 0) { + widths[i] = stack[stackSize - 1]; + } + } + if ('stackDelta' in validationCommand) { + if ('stackFn' in validationCommand) { + validationCommand.stackFn(stack, stackSize); + } + stackSize += validationCommand.stackDelta; + } else if (validationCommand.stackClearing) { + stackSize = 0; + } else if (validationCommand.resetStack) { + stackSize = 0; + undefStack = false; + } else if (validationCommand.undefStack) { + stackSize = 0; + undefStack = true; + firstStackClearing = false; + } + } + } + if (!valid) { + // resetting invalid charstring to single 'endchar' + charStrings.set(i, new Uint8Array([14])); + } + } + return { charStrings: charStrings, seacs: seacs, widths: widths }; + }, + emptyPrivateDictionary: + function CFFParser_emptyPrivateDictionary(parentDict) { + var privateDict = this.createDict(CFFPrivateDict, [], + parentDict.strings); + parentDict.setByKey(18, [0, 0]); + parentDict.privateDict = privateDict; + }, + parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) { + // no private dict, do nothing + if (!parentDict.hasName('Private')) { + this.emptyPrivateDictionary(parentDict); + return; + } + var privateOffset = parentDict.getByName('Private'); + // make sure the params are formatted correctly + if (!isArray(privateOffset) || privateOffset.length !== 2) { + parentDict.removeByName('Private'); + return; + } + var size = privateOffset[0]; + var offset = privateOffset[1]; + // remove empty dicts or ones that refer to invalid location + if (size === 0 || offset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + + var privateDictEnd = offset + size; + var dictData = this.bytes.subarray(offset, privateDictEnd); + var dict = this.parseDict(dictData); + var privateDict = this.createDict(CFFPrivateDict, dict, + parentDict.strings); + parentDict.privateDict = privateDict; + + // Parse the Subrs index also since it's relative to the private dict. + if (!privateDict.getByName('Subrs')) { + return; + } + var subrsOffset = privateDict.getByName('Subrs'); + var relativeOffset = offset + subrsOffset; + // Validate the offset. + if (subrsOffset === 0 || relativeOffset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + var subrsIndex = this.parseIndex(relativeOffset); + privateDict.subrsIndex = subrsIndex.obj; + }, + parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) { + if (pos === 0) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, + ISOAdobeCharset); + } else if (pos === 1) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, + ExpertCharset); + } else if (pos === 2) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, + ExpertSubsetCharset); + } + + var bytes = this.bytes; + var start = pos; + var format = bytes[pos++]; + var charset = ['.notdef']; + var id, count, i; + + // subtract 1 for the .notdef glyph + length -= 1; + + switch (format) { + case 0: + for (i = 0; i < length; i++) { + id = (bytes[pos++] << 8) | bytes[pos++]; + charset.push(cid ? id : strings.get(id)); + } + break; + case 1: + while (charset.length <= length) { + id = (bytes[pos++] << 8) | bytes[pos++]; + count = bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + case 2: + while (charset.length <= length) { + id = (bytes[pos++] << 8) | bytes[pos++]; + count = (bytes[pos++] << 8) | bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + default: + error('Unknown charset format'); + } + // Raw won't be needed if we actually compile the charset. + var end = pos; + var raw = bytes.subarray(start, end); + + return new CFFCharset(false, format, charset, raw); + }, + parseEncoding: function CFFParser_parseEncoding(pos, + properties, + strings, + charset) { + var encoding = {}; + var bytes = this.bytes; + var predefined = false; + var hasSupplement = false; + var format, i, ii; + var raw = null; + + function readSupplement() { + var supplementsCount = bytes[pos++]; + for (i = 0; i < supplementsCount; i++) { + var code = bytes[pos++]; + var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff); + encoding[code] = charset.indexOf(strings.get(sid)); + } + } + + if (pos === 0 || pos === 1) { + predefined = true; + format = pos; + var baseEncoding = pos ? Encodings.ExpertEncoding : + Encodings.StandardEncoding; + for (i = 0, ii = charset.length; i < ii; i++) { + var index = baseEncoding.indexOf(charset[i]); + if (index !== -1) { + encoding[index] = i; + } + } + } else { + var dataStart = pos; + format = bytes[pos++]; + switch (format & 0x7f) { + case 0: + var glyphsCount = bytes[pos++]; + for (i = 1; i <= glyphsCount; i++) { + encoding[bytes[pos++]] = i; + } + break; + + case 1: + var rangesCount = bytes[pos++]; + var gid = 1; + for (i = 0; i < rangesCount; i++) { + var start = bytes[pos++]; + var left = bytes[pos++]; + for (var j = start; j <= start + left; j++) { + encoding[j] = gid++; + } + } + break; + + default: + error('Unknow encoding format: ' + format + ' in CFF'); + break; + } + var dataEnd = pos; + if (format & 0x80) { + // The font sanitizer does not support CFF encoding with a + // supplement, since the encoding is not really used to map + // between gid to glyph, let's overwrite what is declared in + // the top dictionary to let the sanitizer think the font use + // StandardEncoding, that's a lie but that's ok. + bytes[dataStart] &= 0x7f; + readSupplement(); + hasSupplement = true; + } + raw = bytes.subarray(dataStart, dataEnd); + } + format = format & 0x7f; + return new CFFEncoding(predefined, format, encoding, raw); + }, + parseFDSelect: function CFFParser_parseFDSelect(pos, length) { + var start = pos; + var bytes = this.bytes; + var format = bytes[pos++]; + var fdSelect = []; + var i; + + switch (format) { + case 0: + for (i = 0; i < length; ++i) { + var id = bytes[pos++]; + fdSelect.push(id); + } + break; + case 3: + var rangesCount = (bytes[pos++] << 8) | bytes[pos++]; + for (i = 0; i < rangesCount; ++i) { + var first = (bytes[pos++] << 8) | bytes[pos++]; + var fdIndex = bytes[pos++]; + var next = (bytes[pos] << 8) | bytes[pos + 1]; + for (var j = first; j < next; ++j) { + fdSelect.push(fdIndex); + } + } + // Advance past the sentinel(next). + pos += 2; + break; + default: + error('Unknown fdselect format ' + format); + break; + } + var end = pos; + return new CFFFDSelect(fdSelect, bytes.subarray(start, end)); + } + }; + return CFFParser; +})(); + +// Compact Font Format +var CFF = (function CFFClosure() { + function CFF() { + this.header = null; + this.names = []; + this.topDict = null; + this.strings = new CFFStrings(); + this.globalSubrIndex = null; + + // The following could really be per font, but since we only have one font + // store them here. + this.encoding = null; + this.charset = null; + this.charStrings = null; + this.fdArray = []; + this.fdSelect = null; + + this.isCIDFont = false; + } + return CFF; +})(); + +var CFFHeader = (function CFFHeaderClosure() { + function CFFHeader(major, minor, hdrSize, offSize) { + this.major = major; + this.minor = minor; + this.hdrSize = hdrSize; + this.offSize = offSize; + } + return CFFHeader; +})(); + +var CFFStrings = (function CFFStringsClosure() { + function CFFStrings() { + this.strings = []; + } + CFFStrings.prototype = { + get: function CFFStrings_get(index) { + if (index >= 0 && index <= 390) { + return CFFStandardStrings[index]; + } + if (index - 391 <= this.strings.length) { + return this.strings[index - 391]; + } + return CFFStandardStrings[0]; + }, + add: function CFFStrings_add(value) { + this.strings.push(value); + }, + get count() { + return this.strings.length; + } + }; + return CFFStrings; +})(); + +var CFFIndex = (function CFFIndexClosure() { + function CFFIndex() { + this.objects = []; + this.length = 0; + } + CFFIndex.prototype = { + add: function CFFIndex_add(data) { + this.length += data.length; + this.objects.push(data); + }, + set: function CFFIndex_set(index, data) { + this.length += data.length - this.objects[index].length; + this.objects[index] = data; + }, + get: function CFFIndex_get(index) { + return this.objects[index]; + }, + get count() { + return this.objects.length; + } + }; + return CFFIndex; +})(); + +var CFFDict = (function CFFDictClosure() { + function CFFDict(tables, strings) { + this.keyToNameMap = tables.keyToNameMap; + this.nameToKeyMap = tables.nameToKeyMap; + this.defaults = tables.defaults; + this.types = tables.types; + this.opcodes = tables.opcodes; + this.order = tables.order; + this.strings = strings; + this.values = {}; + } + CFFDict.prototype = { + // value should always be an array + setByKey: function CFFDict_setByKey(key, value) { + if (!(key in this.keyToNameMap)) { + return false; + } + // ignore empty values + if (value.length === 0) { + return true; + } + var type = this.types[key]; + // remove the array wrapping these types of values + if (type === 'num' || type === 'sid' || type === 'offset') { + value = value[0]; + } + this.values[key] = value; + return true; + }, + setByName: function CFFDict_setByName(name, value) { + if (!(name in this.nameToKeyMap)) { + error('Invalid dictionary name "' + name + '"'); + } + this.values[this.nameToKeyMap[name]] = value; + }, + hasName: function CFFDict_hasName(name) { + return this.nameToKeyMap[name] in this.values; + }, + getByName: function CFFDict_getByName(name) { + if (!(name in this.nameToKeyMap)) { + error('Invalid dictionary name "' + name + '"'); + } + var key = this.nameToKeyMap[name]; + if (!(key in this.values)) { + return this.defaults[key]; + } + return this.values[key]; + }, + removeByName: function CFFDict_removeByName(name) { + delete this.values[this.nameToKeyMap[name]]; + } + }; + CFFDict.createTables = function CFFDict_createTables(layout) { + var tables = { + keyToNameMap: {}, + nameToKeyMap: {}, + defaults: {}, + types: {}, + opcodes: {}, + order: [] + }; + for (var i = 0, ii = layout.length; i < ii; ++i) { + var entry = layout[i]; + var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0]; + tables.keyToNameMap[key] = entry[1]; + tables.nameToKeyMap[entry[1]] = key; + tables.types[key] = entry[2]; + tables.defaults[key] = entry[3]; + tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]]; + tables.order.push(key); + } + return tables; + }; + return CFFDict; +})(); + +var CFFTopDict = (function CFFTopDictClosure() { + var layout = [ + [[12, 30], 'ROS', ['sid', 'sid', 'num'], null], + [[12, 20], 'SyntheticBase', 'num', null], + [0, 'version', 'sid', null], + [1, 'Notice', 'sid', null], + [[12, 0], 'Copyright', 'sid', null], + [2, 'FullName', 'sid', null], + [3, 'FamilyName', 'sid', null], + [4, 'Weight', 'sid', null], + [[12, 1], 'isFixedPitch', 'num', 0], + [[12, 2], 'ItalicAngle', 'num', 0], + [[12, 3], 'UnderlinePosition', 'num', -100], + [[12, 4], 'UnderlineThickness', 'num', 50], + [[12, 5], 'PaintType', 'num', 0], + [[12, 6], 'CharstringType', 'num', 2], + [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'], + [0.001, 0, 0, 0.001, 0, 0]], + [13, 'UniqueID', 'num', null], + [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]], + [[12, 8], 'StrokeWidth', 'num', 0], + [14, 'XUID', 'array', null], + [15, 'charset', 'offset', 0], + [16, 'Encoding', 'offset', 0], + [17, 'CharStrings', 'offset', 0], + [18, 'Private', ['offset', 'offset'], null], + [[12, 21], 'PostScript', 'sid', null], + [[12, 22], 'BaseFontName', 'sid', null], + [[12, 23], 'BaseFontBlend', 'delta', null], + [[12, 31], 'CIDFontVersion', 'num', 0], + [[12, 32], 'CIDFontRevision', 'num', 0], + [[12, 33], 'CIDFontType', 'num', 0], + [[12, 34], 'CIDCount', 'num', 8720], + [[12, 35], 'UIDBase', 'num', null], + // XXX: CID Fonts on DirectWrite 6.1 only seem to work if FDSelect comes + // before FDArray. + [[12, 37], 'FDSelect', 'offset', null], + [[12, 36], 'FDArray', 'offset', null], + [[12, 38], 'FontName', 'sid', null] + ]; + var tables = null; + function CFFTopDict(strings) { + if (tables === null) { + tables = CFFDict.createTables(layout); + } + CFFDict.call(this, tables, strings); + this.privateDict = null; + } + CFFTopDict.prototype = Object.create(CFFDict.prototype); + return CFFTopDict; +})(); + +var CFFPrivateDict = (function CFFPrivateDictClosure() { + var layout = [ + [6, 'BlueValues', 'delta', null], + [7, 'OtherBlues', 'delta', null], + [8, 'FamilyBlues', 'delta', null], + [9, 'FamilyOtherBlues', 'delta', null], + [[12, 9], 'BlueScale', 'num', 0.039625], + [[12, 10], 'BlueShift', 'num', 7], + [[12, 11], 'BlueFuzz', 'num', 1], + [10, 'StdHW', 'num', null], + [11, 'StdVW', 'num', null], + [[12, 12], 'StemSnapH', 'delta', null], + [[12, 13], 'StemSnapV', 'delta', null], + [[12, 14], 'ForceBold', 'num', 0], + [[12, 17], 'LanguageGroup', 'num', 0], + [[12, 18], 'ExpansionFactor', 'num', 0.06], + [[12, 19], 'initialRandomSeed', 'num', 0], + [20, 'defaultWidthX', 'num', 0], + [21, 'nominalWidthX', 'num', 0], + [19, 'Subrs', 'offset', null] + ]; + var tables = null; + function CFFPrivateDict(strings) { + if (tables === null) { + tables = CFFDict.createTables(layout); + } + CFFDict.call(this, tables, strings); + this.subrsIndex = null; + } + CFFPrivateDict.prototype = Object.create(CFFDict.prototype); + return CFFPrivateDict; +})(); + +var CFFCharsetPredefinedTypes = { + ISO_ADOBE: 0, + EXPERT: 1, + EXPERT_SUBSET: 2 +}; +var CFFCharset = (function CFFCharsetClosure() { + function CFFCharset(predefined, format, charset, raw) { + this.predefined = predefined; + this.format = format; + this.charset = charset; + this.raw = raw; + } + return CFFCharset; +})(); + +var CFFEncoding = (function CFFEncodingClosure() { + function CFFEncoding(predefined, format, encoding, raw) { + this.predefined = predefined; + this.format = format; + this.encoding = encoding; + this.raw = raw; + } + return CFFEncoding; +})(); + +var CFFFDSelect = (function CFFFDSelectClosure() { + function CFFFDSelect(fdSelect, raw) { + this.fdSelect = fdSelect; + this.raw = raw; + } + return CFFFDSelect; +})(); + +// Helper class to keep track of where an offset is within the data and helps +// filling in that offset once it's known. +var CFFOffsetTracker = (function CFFOffsetTrackerClosure() { + function CFFOffsetTracker() { + this.offsets = {}; + } + CFFOffsetTracker.prototype = { + isTracking: function CFFOffsetTracker_isTracking(key) { + return key in this.offsets; + }, + track: function CFFOffsetTracker_track(key, location) { + if (key in this.offsets) { + error('Already tracking location of ' + key); + } + this.offsets[key] = location; + }, + offset: function CFFOffsetTracker_offset(value) { + for (var key in this.offsets) { + this.offsets[key] += value; + } + }, + setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, + values, + output) { + if (!(key in this.offsets)) { + error('Not tracking location of ' + key); + } + var data = output.data; + var dataOffset = this.offsets[key]; + var size = 5; + for (var i = 0, ii = values.length; i < ii; ++i) { + var offset0 = i * size + dataOffset; + var offset1 = offset0 + 1; + var offset2 = offset0 + 2; + var offset3 = offset0 + 3; + var offset4 = offset0 + 4; + // It's easy to screw up offsets so perform this sanity check. + if (data[offset0] !== 0x1d || data[offset1] !== 0 || + data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) { + error('writing to an offset that is not empty'); + } + var value = values[i]; + data[offset0] = 0x1d; + data[offset1] = (value >> 24) & 0xFF; + data[offset2] = (value >> 16) & 0xFF; + data[offset3] = (value >> 8) & 0xFF; + data[offset4] = value & 0xFF; + } + } + }; + return CFFOffsetTracker; +})(); + +// Takes a CFF and converts it to the binary representation. +var CFFCompiler = (function CFFCompilerClosure() { + function CFFCompiler(cff) { + this.cff = cff; + } + CFFCompiler.prototype = { + compile: function CFFCompiler_compile() { + var cff = this.cff; + var output = { + data: [], + length: 0, + add: function CFFCompiler_add(data) { + this.data = this.data.concat(data); + this.length = this.data.length; + } + }; + + // Compile the five entries that must be in order. + var header = this.compileHeader(cff.header); + output.add(header); + + var nameIndex = this.compileNameIndex(cff.names); + output.add(nameIndex); + + if (cff.isCIDFont) { + // The spec is unclear on how font matrices should relate to each other + // when there is one in the main top dict and the sub top dicts. + // Windows handles this differently than linux and osx so we have to + // normalize to work on all. + // Rules based off of some mailing list discussions: + // - If main font has a matrix and subfont doesn't, use the main matrix. + // - If no main font matrix and there is a subfont matrix, use the + // subfont matrix. + // - If both have matrices, concat together. + // - If neither have matrices, use default. + // To make this work on all platforms we move the top matrix into each + // sub top dict and concat if necessary. + if (cff.topDict.hasName('FontMatrix')) { + var base = cff.topDict.getByName('FontMatrix'); + cff.topDict.removeByName('FontMatrix'); + for (var i = 0, ii = cff.fdArray.length; i < ii; i++) { + var subDict = cff.fdArray[i]; + var matrix = base.slice(0); + if (subDict.hasName('FontMatrix')) { + matrix = Util.transform(matrix, subDict.getByName('FontMatrix')); + } + subDict.setByName('FontMatrix', matrix); + } + } + } + + var compiled = this.compileTopDicts([cff.topDict], + output.length, + cff.isCIDFont); + output.add(compiled.output); + var topDictTracker = compiled.trackers[0]; + + var stringIndex = this.compileStringIndex(cff.strings.strings); + output.add(stringIndex); + + var globalSubrIndex = this.compileIndex(cff.globalSubrIndex); + output.add(globalSubrIndex); + + // Now start on the other entries that have no specfic order. + if (cff.encoding && cff.topDict.hasName('Encoding')) { + if (cff.encoding.predefined) { + topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], + output); + } else { + var encoding = this.compileEncoding(cff.encoding); + topDictTracker.setEntryLocation('Encoding', [output.length], output); + output.add(encoding); + } + } + + if (cff.charset && cff.topDict.hasName('charset')) { + if (cff.charset.predefined) { + topDictTracker.setEntryLocation('charset', [cff.charset.format], + output); + } else { + var charset = this.compileCharset(cff.charset); + topDictTracker.setEntryLocation('charset', [output.length], output); + output.add(charset); + } + } + + var charStrings = this.compileCharStrings(cff.charStrings); + topDictTracker.setEntryLocation('CharStrings', [output.length], output); + output.add(charStrings); + + if (cff.isCIDFont) { + // For some reason FDSelect must be in front of FDArray on windows. OSX + // and linux don't seem to care. + topDictTracker.setEntryLocation('FDSelect', [output.length], output); + var fdSelect = this.compileFDSelect(cff.fdSelect.raw); + output.add(fdSelect); + // It is unclear if the sub font dictionary can have CID related + // dictionary keys, but the sanitizer doesn't like them so remove them. + compiled = this.compileTopDicts(cff.fdArray, output.length, true); + topDictTracker.setEntryLocation('FDArray', [output.length], output); + output.add(compiled.output); + var fontDictTrackers = compiled.trackers; + + this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output); + } + + this.compilePrivateDicts([cff.topDict], [topDictTracker], output); + + // If the font data ends with INDEX whose object data is zero-length, + // the sanitizer will bail out. Add a dummy byte to avoid that. + output.add([0]); + + return output.data; + }, + encodeNumber: function CFFCompiler_encodeNumber(value) { + if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) { // isInt + return this.encodeInteger(value); + } else { + return this.encodeFloat(value); + } + }, + encodeFloat: function CFFCompiler_encodeFloat(num) { + var value = num.toString(); + + // rounding inaccurate doubles + var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value); + if (m) { + var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length)); + value = (Math.round(num * epsilon) / epsilon).toString(); + } + + var nibbles = ''; + var i, ii; + for (i = 0, ii = value.length; i < ii; ++i) { + var a = value[i]; + if (a === 'e') { + nibbles += value[++i] === '-' ? 'c' : 'b'; + } else if (a === '.') { + nibbles += 'a'; + } else if (a === '-') { + nibbles += 'e'; + } else { + nibbles += a; + } + } + nibbles += (nibbles.length & 1) ? 'f' : 'ff'; + var out = [30]; + for (i = 0, ii = nibbles.length; i < ii; i += 2) { + out.push(parseInt(nibbles.substr(i, 2), 16)); + } + return out; + }, + encodeInteger: function CFFCompiler_encodeInteger(value) { + var code; + if (value >= -107 && value <= 107) { + code = [value + 139]; + } else if (value >= 108 && value <= 1131) { + value = [value - 108]; + code = [(value >> 8) + 247, value & 0xFF]; + } else if (value >= -1131 && value <= -108) { + value = -value - 108; + code = [(value >> 8) + 251, value & 0xFF]; + } else if (value >= -32768 && value <= 32767) { + code = [0x1c, (value >> 8) & 0xFF, value & 0xFF]; + } else { + code = [0x1d, + (value >> 24) & 0xFF, + (value >> 16) & 0xFF, + (value >> 8) & 0xFF, + value & 0xFF]; + } + return code; + }, + compileHeader: function CFFCompiler_compileHeader(header) { + return [ + header.major, + header.minor, + header.hdrSize, + header.offSize + ]; + }, + compileNameIndex: function CFFCompiler_compileNameIndex(names) { + var nameIndex = new CFFIndex(); + for (var i = 0, ii = names.length; i < ii; ++i) { + nameIndex.add(stringToBytes(names[i])); + } + return this.compileIndex(nameIndex); + }, + compileTopDicts: function CFFCompiler_compileTopDicts(dicts, + length, + removeCidKeys) { + var fontDictTrackers = []; + var fdArrayIndex = new CFFIndex(); + for (var i = 0, ii = dicts.length; i < ii; ++i) { + var fontDict = dicts[i]; + if (removeCidKeys) { + fontDict.removeByName('CIDFontVersion'); + fontDict.removeByName('CIDFontRevision'); + fontDict.removeByName('CIDFontType'); + fontDict.removeByName('CIDCount'); + fontDict.removeByName('UIDBase'); + } + var fontDictTracker = new CFFOffsetTracker(); + var fontDictData = this.compileDict(fontDict, fontDictTracker); + fontDictTrackers.push(fontDictTracker); + fdArrayIndex.add(fontDictData); + fontDictTracker.offset(length); + } + fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers); + return { + trackers: fontDictTrackers, + output: fdArrayIndex + }; + }, + compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, + trackers, + output) { + for (var i = 0, ii = dicts.length; i < ii; ++i) { + var fontDict = dicts[i]; + assert(fontDict.privateDict && fontDict.hasName('Private'), + 'There must be an private dictionary.'); + var privateDict = fontDict.privateDict; + var privateDictTracker = new CFFOffsetTracker(); + var privateDictData = this.compileDict(privateDict, privateDictTracker); + + var outputLength = output.length; + privateDictTracker.offset(outputLength); + if (!privateDictData.length) { + // The private dictionary was empty, set the output length to zero to + // ensure the offset length isn't out of bounds in the eyes of the + // sanitizer. + outputLength = 0; + } + + trackers[i].setEntryLocation('Private', + [privateDictData.length, outputLength], + output); + output.add(privateDictData); + + if (privateDict.subrsIndex && privateDict.hasName('Subrs')) { + var subrs = this.compileIndex(privateDict.subrsIndex); + privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], + output); + output.add(subrs); + } + } + }, + compileDict: function CFFCompiler_compileDict(dict, offsetTracker) { + var out = []; + // The dictionary keys must be in a certain order. + var order = dict.order; + for (var i = 0; i < order.length; ++i) { + var key = order[i]; + if (!(key in dict.values)) { + continue; + } + var values = dict.values[key]; + var types = dict.types[key]; + if (!isArray(types)) { + types = [types]; + } + if (!isArray(values)) { + values = [values]; + } + + // Remove any empty dict values. + if (values.length === 0) { + continue; + } + + for (var j = 0, jj = types.length; j < jj; ++j) { + var type = types[j]; + var value = values[j]; + switch (type) { + case 'num': + case 'sid': + out = out.concat(this.encodeNumber(value)); + break; + case 'offset': + // For offsets we just insert a 32bit integer so we don't have to + // deal with figuring out the length of the offset when it gets + // replaced later on by the compiler. + var name = dict.keyToNameMap[key]; + // Some offsets have the offset and the length, so just record the + // position of the first one. + if (!offsetTracker.isTracking(name)) { + offsetTracker.track(name, out.length); + } + out = out.concat([0x1d, 0, 0, 0, 0]); + break; + case 'array': + case 'delta': + out = out.concat(this.encodeNumber(value)); + for (var k = 1, kk = values.length; k < kk; ++k) { + out = out.concat(this.encodeNumber(values[k])); + } + break; + default: + error('Unknown data type of ' + type); + break; + } + } + out = out.concat(dict.opcodes[key]); + } + return out; + }, + compileStringIndex: function CFFCompiler_compileStringIndex(strings) { + var stringIndex = new CFFIndex(); + for (var i = 0, ii = strings.length; i < ii; ++i) { + stringIndex.add(stringToBytes(strings[i])); + } + return this.compileIndex(stringIndex); + }, + compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() { + var globalSubrIndex = this.cff.globalSubrIndex; + this.out.writeByteArray(this.compileIndex(globalSubrIndex)); + }, + compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) { + return this.compileIndex(charStrings); + }, + compileCharset: function CFFCompiler_compileCharset(charset) { + return this.compileTypedArray(charset.raw); + }, + compileEncoding: function CFFCompiler_compileEncoding(encoding) { + return this.compileTypedArray(encoding.raw); + }, + compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) { + return this.compileTypedArray(fdSelect); + }, + compileTypedArray: function CFFCompiler_compileTypedArray(data) { + var out = []; + for (var i = 0, ii = data.length; i < ii; ++i) { + out[i] = data[i]; + } + return out; + }, + compileIndex: function CFFCompiler_compileIndex(index, trackers) { + trackers = trackers || []; + var objects = index.objects; + // First 2 bytes contains the number of objects contained into this index + var count = objects.length; + + // If there is no object, just create an index. This technically + // should just be [0, 0] but OTS has an issue with that. + if (count === 0) { + return [0, 0, 0]; + } + + var data = [(count >> 8) & 0xFF, count & 0xff]; + + var lastOffset = 1, i; + for (i = 0; i < count; ++i) { + lastOffset += objects[i].length; + } + + var offsetSize; + if (lastOffset < 0x100) { + offsetSize = 1; + } else if (lastOffset < 0x10000) { + offsetSize = 2; + } else if (lastOffset < 0x1000000) { + offsetSize = 3; + } else { + offsetSize = 4; + } + + // Next byte contains the offset size use to reference object in the file + data.push(offsetSize); + + // Add another offset after this one because we need a new offset + var relativeOffset = 1; + for (i = 0; i < count + 1; i++) { + if (offsetSize === 1) { + data.push(relativeOffset & 0xFF); + } else if (offsetSize === 2) { + data.push((relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } else if (offsetSize === 3) { + data.push((relativeOffset >> 16) & 0xFF, + (relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } else { + data.push((relativeOffset >>> 24) & 0xFF, + (relativeOffset >> 16) & 0xFF, + (relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } + + if (objects[i]) { + relativeOffset += objects[i].length; + } + } + + for (i = 0; i < count; i++) { + // Notify the tracker where the object will be offset in the data. + if (trackers[i]) { + trackers[i].offset(data.length); + } + for (var j = 0, jj = objects[i].length; j < jj; j++) { + data.push(objects[i][j]); + } + } + return data; + } + }; + return CFFCompiler; +})(); + +// Workaround for seac on Windows. +(function checkSeacSupport() { + if (/Windows/.test(navigator.userAgent)) { + SEAC_ANALYSIS_ENABLED = true; + } +})(); + +// Workaround for Private Use Area characters in Chrome on Windows +// http://code.google.com/p/chromium/issues/detail?id=122465 +// https://github.com/mozilla/pdf.js/issues/1689 +(function checkChromeWindows() { + if (/Windows.*Chrome/.test(navigator.userAgent)) { + SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = true; + } +})(); + + +var FontRendererFactory = (function FontRendererFactoryClosure() { + function getLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + } + + function getUshort(data, offset) { + return (data[offset] << 8) | data[offset + 1]; + } + + function parseCmap(data, start, end) { + var offset = (getUshort(data, start + 2) === 1 ? + getLong(data, start + 8) : getLong(data, start + 16)); + var format = getUshort(data, start + offset); + var length, ranges, p, i; + if (format === 4) { + length = getUshort(data, start + offset + 2); + var segCount = getUshort(data, start + offset + 6) >> 1; + p = start + offset + 14; + ranges = []; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i] = {end: getUshort(data, p)}; + } + p += 2; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].start = getUshort(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].idDelta = getUshort(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + var idOffset = getUshort(data, p); + if (idOffset === 0) { + continue; + } + ranges[i].ids = []; + for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) { + ranges[i].ids[j] = getUshort(data, p + idOffset); + idOffset += 2; + } + } + return ranges; + } else if (format === 12) { + length = getLong(data, start + offset + 4); + var groups = getLong(data, start + offset + 12); + p = start + offset + 16; + ranges = []; + for (i = 0; i < groups; i++) { + ranges.push({ + start: getLong(data, p), + end: getLong(data, p + 4), + idDelta: getLong(data, p + 8) - getLong(data, p) + }); + p += 12; + } + return ranges; + } + error('not supported cmap: ' + format); + } + + function parseCff(data, start, end) { + var properties = {}; + var parser = new CFFParser(new Stream(data, start, end - start), + properties); + var cff = parser.parse(); + return { + glyphs: cff.charStrings.objects, + subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && + cff.topDict.privateDict.subrsIndex.objects), + gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects + }; + } + + function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { + var itemSize, itemDecode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return (data[offset] << 9) | (data[offset + 1] << 1); + }; + } + var glyphs = []; + var startOffset = itemDecode(loca, 0); + for (var j = itemSize; j < loca.length; j += itemSize) { + var endOffset = itemDecode(loca, j); + glyphs.push(glyf.subarray(startOffset, endOffset)); + startOffset = endOffset; + } + return glyphs; + } + + function lookupCmap(ranges, unicode) { + var code = unicode.charCodeAt(0); + var l = 0, r = ranges.length - 1; + while (l < r) { + var c = (l + r + 1) >> 1; + if (code < ranges[c].start) { + r = c - 1; + } else { + l = c; + } + } + if (ranges[l].start <= code && code <= ranges[l].end) { + return (ranges[l].idDelta + (ranges[l].ids ? + ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF; + } + return 0; + } + + function compileGlyf(code, js, font) { + function moveTo(x, y) { + js.push('c.moveTo(' + x + ',' + y + ');'); + } + function lineTo(x, y) { + js.push('c.lineTo(' + x + ',' + y + ');'); + } + function quadraticCurveTo(xa, ya, x, y) { + js.push('c.quadraticCurveTo(' + xa + ',' + ya + ',' + + x + ',' + y + ');'); + } + + var i = 0; + var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + var flags; + var x = 0, y = 0; + i += 10; + if (numberOfContours < 0) { + // composite glyph + do { + flags = (code[i] << 8) | code[i + 1]; + var glyphIndex = (code[i + 2] << 8) | code[i + 3]; + i += 4; + var arg1, arg2; + if ((flags & 0x01)) { + arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16; + i += 4; + } else { + arg1 = code[i++]; arg2 = code[i++]; + } + if ((flags & 0x02)) { + x = arg1; + y = arg2; + } else { + x = 0; y = 0; // TODO "they are points" ? + } + var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0; + if ((flags & 0x08)) { + scaleX = + scaleY = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + i += 2; + } else if ((flags & 0x40)) { + scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824; + i += 4; + } else if ((flags & 0x80)) { + scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + scale01 = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824; + scale10 = ((code[i + 4] << 24) | (code[i + 5] << 16)) / 1073741824; + scaleY = ((code[i + 6] << 24) | (code[i + 7] << 16)) / 1073741824; + i += 8; + } + var subglyph = font.glyphs[glyphIndex]; + if (subglyph) { + js.push('c.save();'); + js.push('c.transform(' + scaleX + ',' + scale01 + ',' + + scale10 + ',' + scaleY + ',' + x + ',' + y + ');'); + compileGlyf(subglyph, js, font); + js.push('c.restore();'); + } + } while ((flags & 0x20)); + } else { + // simple glyph + var endPtsOfContours = []; + var j, jj; + for (j = 0; j < numberOfContours; j++) { + endPtsOfContours.push((code[i] << 8) | code[i + 1]); + i += 2; + } + var instructionLength = (code[i] << 8) | code[i + 1]; + i += 2 + instructionLength; // skipping the instructions + var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1; + var points = []; + while (points.length < numberOfPoints) { + flags = code[i++]; + var repeat = 1; + if ((flags & 0x08)) { + repeat += code[i++]; + } + while (repeat-- > 0) { + points.push({flags: flags}); + } + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x12) { + case 0x00: + x += ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + i += 2; + break; + case 0x02: + x -= code[i++]; + break; + case 0x12: + x += code[i++]; + break; + } + points[j].x = x; + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x24) { + case 0x00: + y += ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + i += 2; + break; + case 0x04: + y -= code[i++]; + break; + case 0x24: + y += code[i++]; + break; + } + points[j].y = y; + } + + var startPoint = 0; + for (i = 0; i < numberOfContours; i++) { + var endPoint = endPtsOfContours[i]; + // contours might have implicit points, which is located in the middle + // between two neighboring off-curve points + var contour = points.slice(startPoint, endPoint + 1); + if ((contour[0].flags & 1)) { + contour.push(contour[0]); // using start point at the contour end + } else if ((contour[contour.length - 1].flags & 1)) { + // first is off-curve point, trying to use one from the end + contour.unshift(contour[contour.length - 1]); + } else { + // start and end are off-curve points, creating implicit one + var p = { + flags: 1, + x: (contour[0].x + contour[contour.length - 1].x) / 2, + y: (contour[0].y + contour[contour.length - 1].y) / 2 + }; + contour.unshift(p); + contour.push(p); + } + moveTo(contour[0].x, contour[0].y); + for (j = 1, jj = contour.length; j < jj; j++) { + if ((contour[j].flags & 1)) { + lineTo(contour[j].x, contour[j].y); + } else if ((contour[j + 1].flags & 1)){ + quadraticCurveTo(contour[j].x, contour[j].y, + contour[j + 1].x, contour[j + 1].y); + j++; + } else { + quadraticCurveTo(contour[j].x, contour[j].y, + (contour[j].x + contour[j + 1].x) / 2, + (contour[j].y + contour[j + 1].y) / 2); + } + } + startPoint = endPoint + 1; + } + } + } + + function compileCharString(code, js, font) { + var stack = []; + var x = 0, y = 0; + var stems = 0; + + function moveTo(x, y) { + js.push('c.moveTo(' + x + ',' + y + ');'); + } + function lineTo(x, y) { + js.push('c.lineTo(' + x + ',' + y + ');'); + } + function bezierCurveTo(x1, y1, x2, y2, x, y) { + js.push('c.bezierCurveTo(' + x1 + ',' + y1 + ',' + x2 + ',' + y2 + ',' + + x + ',' + y + ');'); + } + + function parse(code) { + var i = 0; + while (i < code.length) { + var stackClean = false; + var v = code[i++]; + var xa, xb, ya, yb, y1, y2, y3, n, subrCode; + switch (v) { + case 1: // hstem + stems += stack.length >> 1; + stackClean = true; + break; + case 3: // vstem + stems += stack.length >> 1; + stackClean = true; + break; + case 4: // vmoveto + y += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 5: // rlineto + while (stack.length > 0) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + break; + case 6: // hlineto + while (stack.length > 0) { + x += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + y += stack.shift(); + lineTo(x, y); + } + break; + case 7: // vlineto + while (stack.length > 0) { + y += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + x += stack.shift(); + lineTo(x, y); + } + break; + case 8: // rrcurveto + while (stack.length > 0) { + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 10: // callsubr + n = stack.pop() + font.subrsBias; + subrCode = font.subrs[n]; + if (subrCode) { + parse(subrCode); + } + break; + case 11: // return + return; + case 12: + v = code[i++]; + switch (v) { + case 34: // flex + xa = x + stack.shift(); + xb = xa + stack.shift(); y1 = y + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y, xb, y1, x, y1); + xa = x + stack.shift(); + xb = xa + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y, x, y); + break; + case 35: // flex + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + stack.pop(); // fd + break; + case 36: // hflex1 + xa = x + stack.shift(); y1 = y + stack.shift(); + xb = xa + stack.shift(); y2 = y1 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y2, x, y2); + xa = x + stack.shift(); + xb = xa + stack.shift(); y3 = y2 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y2, xb, y3, x, y); + break; + case 37: // flex1 + var x0 = x, y0 = y; + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb; y = yb; + if (Math.abs(x - x0) > Math.abs(y - y0)) { + x += stack.shift(); + } else { + y += stack.shift(); + } + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + default: + error('unknown operator: 12 ' + v); + } + break; + case 14: // endchar + if (stack.length >= 4) { + var achar = stack.pop(); + var bchar = stack.pop(); + y = stack.pop(); + x = stack.pop(); + js.push('c.save();'); + js.push('c.translate('+ x + ',' + y + ');'); + var gid = lookupCmap(font.cmap, String.fromCharCode( + font.glyphNameMap[Encodings.StandardEncoding[achar]])); + compileCharString(font.glyphs[gid], js, font); + js.push('c.restore();'); + + gid = lookupCmap(font.cmap, String.fromCharCode( + font.glyphNameMap[Encodings.StandardEncoding[bchar]])); + compileCharString(font.glyphs[gid], js, font); + } + return; + case 18: // hstemhm + stems += stack.length >> 1; + stackClean = true; + break; + case 19: // hintmask + stems += stack.length >> 1; + i += (stems + 7) >> 3; + stackClean = true; + break; + case 20: // cntrmask + stems += stack.length >> 1; + i += (stems + 7) >> 3; + stackClean = true; + break; + case 21: // rmoveto + y += stack.pop(); + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 22: // hmoveto + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 23: // vstemhm + stems += stack.length >> 1; + stackClean = true; + break; + case 24: // rcurveline + while (stack.length > 2) { + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + break; + case 25: // rlinecurve + while (stack.length > 6) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + case 26: // vvcurveto + if (stack.length % 2) { + x += stack.shift(); + } + while (stack.length > 0) { + xa = x; ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb; y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 27: // hhcurveto + if (stack.length % 2) { + y += stack.shift(); + } + while (stack.length > 0) { + xa = x + stack.shift(); ya = y; + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb; + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 28: + stack.push(((code[i] << 24) | (code[i + 1] << 16)) >> 16); + i += 2; + break; + case 29: // callgsubr + n = stack.pop() + font.gsubrsBias; + subrCode = font.gsubrs[n]; + if (subrCode) { + parse(subrCode); + } + break; + case 30: // vhcurveto + while (stack.length > 0) { + xa = x; ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + + xa = x + stack.shift(); ya = y; + xb = xa + stack.shift(); yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 31: // hvcurveto + while (stack.length > 0) { + xa = x + stack.shift(); ya = y; + xb = xa + stack.shift(); yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + + xa = x; ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + default: + if (v < 32) { + error('unknown operator: ' + v); + } + if (v < 247) { + stack.push(v - 139); + } else if (v < 251) { + stack.push((v - 247) * 256 + code[i++] + 108); + } else if (v < 255) { + stack.push(-(v - 251) * 256 - code[i++] - 108); + } else { + stack.push(((code[i] << 24) | (code[i + 1] << 16) | + (code[i + 2] << 8) | code[i + 3]) / 65536); + i += 4; + } + break; + } + if (stackClean) { + stack.length = 0; + } + } + } + parse(code); + } + + var noop = ''; + + function CompiledFont(fontMatrix) { + this.compiledGlyphs = {}; + this.fontMatrix = fontMatrix; + } + CompiledFont.prototype = { + getPathJs: function (unicode) { + var gid = lookupCmap(this.cmap, unicode); + var fn = this.compiledGlyphs[gid]; + if (!fn) { + this.compiledGlyphs[gid] = fn = this.compileGlyph(this.glyphs[gid]); + } + return fn; + }, + + compileGlyph: function (code) { + if (!code || code.length === 0 || code[0] === 14) { + return noop; + } + + var js = []; + js.push('c.save();'); + js.push('c.transform(' + this.fontMatrix.join(',') + ');'); + js.push('c.scale(size, -size);'); + + this.compileGlyphImpl(code, js); + + js.push('c.restore();'); + + return js.join('\n'); + }, + + compileGlyphImpl: function () { + error('Children classes should implement this.'); + }, + + hasBuiltPath: function (unicode) { + var gid = lookupCmap(this.cmap, unicode); + return gid in this.compiledGlyphs; + } + }; + + function TrueTypeCompiled(glyphs, cmap, fontMatrix) { + fontMatrix = fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]; + CompiledFont.call(this, fontMatrix); + + this.glyphs = glyphs; + this.cmap = cmap; + + this.compiledGlyphs = []; + } + + Util.inherit(TrueTypeCompiled, CompiledFont, { + compileGlyphImpl: function (code, js) { + compileGlyf(code, js, this); + } + }); + + function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) { + fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0]; + CompiledFont.call(this, fontMatrix); + this.glyphs = cffInfo.glyphs; + this.gsubrs = cffInfo.gsubrs || []; + this.subrs = cffInfo.subrs || []; + this.cmap = cmap; + this.glyphNameMap = glyphNameMap || GlyphsUnicode; + + this.compiledGlyphs = []; + this.gsubrsBias = (this.gsubrs.length < 1240 ? + 107 : (this.gsubrs.length < 33900 ? 1131 : 32768)); + this.subrsBias = (this.subrs.length < 1240 ? + 107 : (this.subrs.length < 33900 ? 1131 : 32768)); + } + + Util.inherit(Type2Compiled, CompiledFont, { + compileGlyphImpl: function (code, js) { + compileCharString(code, js, this); + } + }); + + + return { + create: function FontRendererFactory_create(font) { + var data = new Uint8Array(font.data); + var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; + var numTables = getUshort(data, 4); + for (var i = 0, p = 12; i < numTables; i++, p += 16) { + var tag = bytesToString(data.subarray(p, p + 4)); + var offset = getLong(data, p + 8); + var length = getLong(data, p + 12); + switch (tag) { + case 'cmap': + cmap = parseCmap(data, offset, offset + length); + break; + case 'glyf': + glyf = data.subarray(offset, offset + length); + break; + case 'loca': + loca = data.subarray(offset, offset + length); + break; + case 'head': + unitsPerEm = getUshort(data, offset + 18); + indexToLocFormat = getUshort(data, offset + 50); + break; + case 'CFF ': + cff = parseCff(data, offset, offset + length); + break; + } + } + + if (glyf) { + var fontMatrix = (!unitsPerEm ? font.fontMatrix : + [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]); + return new TrueTypeCompiled( + parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); + } else { + return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap); + } + } + }; +})(); + + +var GlyphsUnicode = { + A: 0x0041, + AE: 0x00C6, + AEacute: 0x01FC, + AEmacron: 0x01E2, + AEsmall: 0xF7E6, + Aacute: 0x00C1, + Aacutesmall: 0xF7E1, + Abreve: 0x0102, + Abreveacute: 0x1EAE, + Abrevecyrillic: 0x04D0, + Abrevedotbelow: 0x1EB6, + Abrevegrave: 0x1EB0, + Abrevehookabove: 0x1EB2, + Abrevetilde: 0x1EB4, + Acaron: 0x01CD, + Acircle: 0x24B6, + Acircumflex: 0x00C2, + Acircumflexacute: 0x1EA4, + Acircumflexdotbelow: 0x1EAC, + Acircumflexgrave: 0x1EA6, + Acircumflexhookabove: 0x1EA8, + Acircumflexsmall: 0xF7E2, + Acircumflextilde: 0x1EAA, + Acute: 0xF6C9, + Acutesmall: 0xF7B4, + Acyrillic: 0x0410, + Adblgrave: 0x0200, + Adieresis: 0x00C4, + Adieresiscyrillic: 0x04D2, + Adieresismacron: 0x01DE, + Adieresissmall: 0xF7E4, + Adotbelow: 0x1EA0, + Adotmacron: 0x01E0, + Agrave: 0x00C0, + Agravesmall: 0xF7E0, + Ahookabove: 0x1EA2, + Aiecyrillic: 0x04D4, + Ainvertedbreve: 0x0202, + Alpha: 0x0391, + Alphatonos: 0x0386, + Amacron: 0x0100, + Amonospace: 0xFF21, + Aogonek: 0x0104, + Aring: 0x00C5, + Aringacute: 0x01FA, + Aringbelow: 0x1E00, + Aringsmall: 0xF7E5, + Asmall: 0xF761, + Atilde: 0x00C3, + Atildesmall: 0xF7E3, + Aybarmenian: 0x0531, + B: 0x0042, + Bcircle: 0x24B7, + Bdotaccent: 0x1E02, + Bdotbelow: 0x1E04, + Becyrillic: 0x0411, + Benarmenian: 0x0532, + Beta: 0x0392, + Bhook: 0x0181, + Blinebelow: 0x1E06, + Bmonospace: 0xFF22, + Brevesmall: 0xF6F4, + Bsmall: 0xF762, + Btopbar: 0x0182, + C: 0x0043, + Caarmenian: 0x053E, + Cacute: 0x0106, + Caron: 0xF6CA, + Caronsmall: 0xF6F5, + Ccaron: 0x010C, + Ccedilla: 0x00C7, + Ccedillaacute: 0x1E08, + Ccedillasmall: 0xF7E7, + Ccircle: 0x24B8, + Ccircumflex: 0x0108, + Cdot: 0x010A, + Cdotaccent: 0x010A, + Cedillasmall: 0xF7B8, + Chaarmenian: 0x0549, + Cheabkhasiancyrillic: 0x04BC, + Checyrillic: 0x0427, + Chedescenderabkhasiancyrillic: 0x04BE, + Chedescendercyrillic: 0x04B6, + Chedieresiscyrillic: 0x04F4, + Cheharmenian: 0x0543, + Chekhakassiancyrillic: 0x04CB, + Cheverticalstrokecyrillic: 0x04B8, + Chi: 0x03A7, + Chook: 0x0187, + Circumflexsmall: 0xF6F6, + Cmonospace: 0xFF23, + Coarmenian: 0x0551, + Csmall: 0xF763, + D: 0x0044, + DZ: 0x01F1, + DZcaron: 0x01C4, + Daarmenian: 0x0534, + Dafrican: 0x0189, + Dcaron: 0x010E, + Dcedilla: 0x1E10, + Dcircle: 0x24B9, + Dcircumflexbelow: 0x1E12, + Dcroat: 0x0110, + Ddotaccent: 0x1E0A, + Ddotbelow: 0x1E0C, + Decyrillic: 0x0414, + Deicoptic: 0x03EE, + Delta: 0x2206, + Deltagreek: 0x0394, + Dhook: 0x018A, + Dieresis: 0xF6CB, + DieresisAcute: 0xF6CC, + DieresisGrave: 0xF6CD, + Dieresissmall: 0xF7A8, + Digammagreek: 0x03DC, + Djecyrillic: 0x0402, + Dlinebelow: 0x1E0E, + Dmonospace: 0xFF24, + Dotaccentsmall: 0xF6F7, + Dslash: 0x0110, + Dsmall: 0xF764, + Dtopbar: 0x018B, + Dz: 0x01F2, + Dzcaron: 0x01C5, + Dzeabkhasiancyrillic: 0x04E0, + Dzecyrillic: 0x0405, + Dzhecyrillic: 0x040F, + E: 0x0045, + Eacute: 0x00C9, + Eacutesmall: 0xF7E9, + Ebreve: 0x0114, + Ecaron: 0x011A, + Ecedillabreve: 0x1E1C, + Echarmenian: 0x0535, + Ecircle: 0x24BA, + Ecircumflex: 0x00CA, + Ecircumflexacute: 0x1EBE, + Ecircumflexbelow: 0x1E18, + Ecircumflexdotbelow: 0x1EC6, + Ecircumflexgrave: 0x1EC0, + Ecircumflexhookabove: 0x1EC2, + Ecircumflexsmall: 0xF7EA, + Ecircumflextilde: 0x1EC4, + Ecyrillic: 0x0404, + Edblgrave: 0x0204, + Edieresis: 0x00CB, + Edieresissmall: 0xF7EB, + Edot: 0x0116, + Edotaccent: 0x0116, + Edotbelow: 0x1EB8, + Efcyrillic: 0x0424, + Egrave: 0x00C8, + Egravesmall: 0xF7E8, + Eharmenian: 0x0537, + Ehookabove: 0x1EBA, + Eightroman: 0x2167, + Einvertedbreve: 0x0206, + Eiotifiedcyrillic: 0x0464, + Elcyrillic: 0x041B, + Elevenroman: 0x216A, + Emacron: 0x0112, + Emacronacute: 0x1E16, + Emacrongrave: 0x1E14, + Emcyrillic: 0x041C, + Emonospace: 0xFF25, + Encyrillic: 0x041D, + Endescendercyrillic: 0x04A2, + Eng: 0x014A, + Enghecyrillic: 0x04A4, + Enhookcyrillic: 0x04C7, + Eogonek: 0x0118, + Eopen: 0x0190, + Epsilon: 0x0395, + Epsilontonos: 0x0388, + Ercyrillic: 0x0420, + Ereversed: 0x018E, + Ereversedcyrillic: 0x042D, + Escyrillic: 0x0421, + Esdescendercyrillic: 0x04AA, + Esh: 0x01A9, + Esmall: 0xF765, + Eta: 0x0397, + Etarmenian: 0x0538, + Etatonos: 0x0389, + Eth: 0x00D0, + Ethsmall: 0xF7F0, + Etilde: 0x1EBC, + Etildebelow: 0x1E1A, + Euro: 0x20AC, + Ezh: 0x01B7, + Ezhcaron: 0x01EE, + Ezhreversed: 0x01B8, + F: 0x0046, + Fcircle: 0x24BB, + Fdotaccent: 0x1E1E, + Feharmenian: 0x0556, + Feicoptic: 0x03E4, + Fhook: 0x0191, + Fitacyrillic: 0x0472, + Fiveroman: 0x2164, + Fmonospace: 0xFF26, + Fourroman: 0x2163, + Fsmall: 0xF766, + G: 0x0047, + GBsquare: 0x3387, + Gacute: 0x01F4, + Gamma: 0x0393, + Gammaafrican: 0x0194, + Gangiacoptic: 0x03EA, + Gbreve: 0x011E, + Gcaron: 0x01E6, + Gcedilla: 0x0122, + Gcircle: 0x24BC, + Gcircumflex: 0x011C, + Gcommaaccent: 0x0122, + Gdot: 0x0120, + Gdotaccent: 0x0120, + Gecyrillic: 0x0413, + Ghadarmenian: 0x0542, + Ghemiddlehookcyrillic: 0x0494, + Ghestrokecyrillic: 0x0492, + Gheupturncyrillic: 0x0490, + Ghook: 0x0193, + Gimarmenian: 0x0533, + Gjecyrillic: 0x0403, + Gmacron: 0x1E20, + Gmonospace: 0xFF27, + Grave: 0xF6CE, + Gravesmall: 0xF760, + Gsmall: 0xF767, + Gsmallhook: 0x029B, + Gstroke: 0x01E4, + H: 0x0048, + H18533: 0x25CF, + H18543: 0x25AA, + H18551: 0x25AB, + H22073: 0x25A1, + HPsquare: 0x33CB, + Haabkhasiancyrillic: 0x04A8, + Hadescendercyrillic: 0x04B2, + Hardsigncyrillic: 0x042A, + Hbar: 0x0126, + Hbrevebelow: 0x1E2A, + Hcedilla: 0x1E28, + Hcircle: 0x24BD, + Hcircumflex: 0x0124, + Hdieresis: 0x1E26, + Hdotaccent: 0x1E22, + Hdotbelow: 0x1E24, + Hmonospace: 0xFF28, + Hoarmenian: 0x0540, + Horicoptic: 0x03E8, + Hsmall: 0xF768, + Hungarumlaut: 0xF6CF, + Hungarumlautsmall: 0xF6F8, + Hzsquare: 0x3390, + I: 0x0049, + IAcyrillic: 0x042F, + IJ: 0x0132, + IUcyrillic: 0x042E, + Iacute: 0x00CD, + Iacutesmall: 0xF7ED, + Ibreve: 0x012C, + Icaron: 0x01CF, + Icircle: 0x24BE, + Icircumflex: 0x00CE, + Icircumflexsmall: 0xF7EE, + Icyrillic: 0x0406, + Idblgrave: 0x0208, + Idieresis: 0x00CF, + Idieresisacute: 0x1E2E, + Idieresiscyrillic: 0x04E4, + Idieresissmall: 0xF7EF, + Idot: 0x0130, + Idotaccent: 0x0130, + Idotbelow: 0x1ECA, + Iebrevecyrillic: 0x04D6, + Iecyrillic: 0x0415, + Ifraktur: 0x2111, + Igrave: 0x00CC, + Igravesmall: 0xF7EC, + Ihookabove: 0x1EC8, + Iicyrillic: 0x0418, + Iinvertedbreve: 0x020A, + Iishortcyrillic: 0x0419, + Imacron: 0x012A, + Imacroncyrillic: 0x04E2, + Imonospace: 0xFF29, + Iniarmenian: 0x053B, + Iocyrillic: 0x0401, + Iogonek: 0x012E, + Iota: 0x0399, + Iotaafrican: 0x0196, + Iotadieresis: 0x03AA, + Iotatonos: 0x038A, + Ismall: 0xF769, + Istroke: 0x0197, + Itilde: 0x0128, + Itildebelow: 0x1E2C, + Izhitsacyrillic: 0x0474, + Izhitsadblgravecyrillic: 0x0476, + J: 0x004A, + Jaarmenian: 0x0541, + Jcircle: 0x24BF, + Jcircumflex: 0x0134, + Jecyrillic: 0x0408, + Jheharmenian: 0x054B, + Jmonospace: 0xFF2A, + Jsmall: 0xF76A, + K: 0x004B, + KBsquare: 0x3385, + KKsquare: 0x33CD, + Kabashkircyrillic: 0x04A0, + Kacute: 0x1E30, + Kacyrillic: 0x041A, + Kadescendercyrillic: 0x049A, + Kahookcyrillic: 0x04C3, + Kappa: 0x039A, + Kastrokecyrillic: 0x049E, + Kaverticalstrokecyrillic: 0x049C, + Kcaron: 0x01E8, + Kcedilla: 0x0136, + Kcircle: 0x24C0, + Kcommaaccent: 0x0136, + Kdotbelow: 0x1E32, + Keharmenian: 0x0554, + Kenarmenian: 0x053F, + Khacyrillic: 0x0425, + Kheicoptic: 0x03E6, + Khook: 0x0198, + Kjecyrillic: 0x040C, + Klinebelow: 0x1E34, + Kmonospace: 0xFF2B, + Koppacyrillic: 0x0480, + Koppagreek: 0x03DE, + Ksicyrillic: 0x046E, + Ksmall: 0xF76B, + L: 0x004C, + LJ: 0x01C7, + LL: 0xF6BF, + Lacute: 0x0139, + Lambda: 0x039B, + Lcaron: 0x013D, + Lcedilla: 0x013B, + Lcircle: 0x24C1, + Lcircumflexbelow: 0x1E3C, + Lcommaaccent: 0x013B, + Ldot: 0x013F, + Ldotaccent: 0x013F, + Ldotbelow: 0x1E36, + Ldotbelowmacron: 0x1E38, + Liwnarmenian: 0x053C, + Lj: 0x01C8, + Ljecyrillic: 0x0409, + Llinebelow: 0x1E3A, + Lmonospace: 0xFF2C, + Lslash: 0x0141, + Lslashsmall: 0xF6F9, + Lsmall: 0xF76C, + M: 0x004D, + MBsquare: 0x3386, + Macron: 0xF6D0, + Macronsmall: 0xF7AF, + Macute: 0x1E3E, + Mcircle: 0x24C2, + Mdotaccent: 0x1E40, + Mdotbelow: 0x1E42, + Menarmenian: 0x0544, + Mmonospace: 0xFF2D, + Msmall: 0xF76D, + Mturned: 0x019C, + Mu: 0x039C, + N: 0x004E, + NJ: 0x01CA, + Nacute: 0x0143, + Ncaron: 0x0147, + Ncedilla: 0x0145, + Ncircle: 0x24C3, + Ncircumflexbelow: 0x1E4A, + Ncommaaccent: 0x0145, + Ndotaccent: 0x1E44, + Ndotbelow: 0x1E46, + Nhookleft: 0x019D, + Nineroman: 0x2168, + Nj: 0x01CB, + Njecyrillic: 0x040A, + Nlinebelow: 0x1E48, + Nmonospace: 0xFF2E, + Nowarmenian: 0x0546, + Nsmall: 0xF76E, + Ntilde: 0x00D1, + Ntildesmall: 0xF7F1, + Nu: 0x039D, + O: 0x004F, + OE: 0x0152, + OEsmall: 0xF6FA, + Oacute: 0x00D3, + Oacutesmall: 0xF7F3, + Obarredcyrillic: 0x04E8, + Obarreddieresiscyrillic: 0x04EA, + Obreve: 0x014E, + Ocaron: 0x01D1, + Ocenteredtilde: 0x019F, + Ocircle: 0x24C4, + Ocircumflex: 0x00D4, + Ocircumflexacute: 0x1ED0, + Ocircumflexdotbelow: 0x1ED8, + Ocircumflexgrave: 0x1ED2, + Ocircumflexhookabove: 0x1ED4, + Ocircumflexsmall: 0xF7F4, + Ocircumflextilde: 0x1ED6, + Ocyrillic: 0x041E, + Odblacute: 0x0150, + Odblgrave: 0x020C, + Odieresis: 0x00D6, + Odieresiscyrillic: 0x04E6, + Odieresissmall: 0xF7F6, + Odotbelow: 0x1ECC, + Ogoneksmall: 0xF6FB, + Ograve: 0x00D2, + Ogravesmall: 0xF7F2, + Oharmenian: 0x0555, + Ohm: 0x2126, + Ohookabove: 0x1ECE, + Ohorn: 0x01A0, + Ohornacute: 0x1EDA, + Ohorndotbelow: 0x1EE2, + Ohorngrave: 0x1EDC, + Ohornhookabove: 0x1EDE, + Ohorntilde: 0x1EE0, + Ohungarumlaut: 0x0150, + Oi: 0x01A2, + Oinvertedbreve: 0x020E, + Omacron: 0x014C, + Omacronacute: 0x1E52, + Omacrongrave: 0x1E50, + Omega: 0x2126, + Omegacyrillic: 0x0460, + Omegagreek: 0x03A9, + Omegaroundcyrillic: 0x047A, + Omegatitlocyrillic: 0x047C, + Omegatonos: 0x038F, + Omicron: 0x039F, + Omicrontonos: 0x038C, + Omonospace: 0xFF2F, + Oneroman: 0x2160, + Oogonek: 0x01EA, + Oogonekmacron: 0x01EC, + Oopen: 0x0186, + Oslash: 0x00D8, + Oslashacute: 0x01FE, + Oslashsmall: 0xF7F8, + Osmall: 0xF76F, + Ostrokeacute: 0x01FE, + Otcyrillic: 0x047E, + Otilde: 0x00D5, + Otildeacute: 0x1E4C, + Otildedieresis: 0x1E4E, + Otildesmall: 0xF7F5, + P: 0x0050, + Pacute: 0x1E54, + Pcircle: 0x24C5, + Pdotaccent: 0x1E56, + Pecyrillic: 0x041F, + Peharmenian: 0x054A, + Pemiddlehookcyrillic: 0x04A6, + Phi: 0x03A6, + Phook: 0x01A4, + Pi: 0x03A0, + Piwrarmenian: 0x0553, + Pmonospace: 0xFF30, + Psi: 0x03A8, + Psicyrillic: 0x0470, + Psmall: 0xF770, + Q: 0x0051, + Qcircle: 0x24C6, + Qmonospace: 0xFF31, + Qsmall: 0xF771, + R: 0x0052, + Raarmenian: 0x054C, + Racute: 0x0154, + Rcaron: 0x0158, + Rcedilla: 0x0156, + Rcircle: 0x24C7, + Rcommaaccent: 0x0156, + Rdblgrave: 0x0210, + Rdotaccent: 0x1E58, + Rdotbelow: 0x1E5A, + Rdotbelowmacron: 0x1E5C, + Reharmenian: 0x0550, + Rfraktur: 0x211C, + Rho: 0x03A1, + Ringsmall: 0xF6FC, + Rinvertedbreve: 0x0212, + Rlinebelow: 0x1E5E, + Rmonospace: 0xFF32, + Rsmall: 0xF772, + Rsmallinverted: 0x0281, + Rsmallinvertedsuperior: 0x02B6, + S: 0x0053, + SF010000: 0x250C, + SF020000: 0x2514, + SF030000: 0x2510, + SF040000: 0x2518, + SF050000: 0x253C, + SF060000: 0x252C, + SF070000: 0x2534, + SF080000: 0x251C, + SF090000: 0x2524, + SF100000: 0x2500, + SF110000: 0x2502, + SF190000: 0x2561, + SF200000: 0x2562, + SF210000: 0x2556, + SF220000: 0x2555, + SF230000: 0x2563, + SF240000: 0x2551, + SF250000: 0x2557, + SF260000: 0x255D, + SF270000: 0x255C, + SF280000: 0x255B, + SF360000: 0x255E, + SF370000: 0x255F, + SF380000: 0x255A, + SF390000: 0x2554, + SF400000: 0x2569, + SF410000: 0x2566, + SF420000: 0x2560, + SF430000: 0x2550, + SF440000: 0x256C, + SF450000: 0x2567, + SF460000: 0x2568, + SF470000: 0x2564, + SF480000: 0x2565, + SF490000: 0x2559, + SF500000: 0x2558, + SF510000: 0x2552, + SF520000: 0x2553, + SF530000: 0x256B, + SF540000: 0x256A, + Sacute: 0x015A, + Sacutedotaccent: 0x1E64, + Sampigreek: 0x03E0, + Scaron: 0x0160, + Scarondotaccent: 0x1E66, + Scaronsmall: 0xF6FD, + Scedilla: 0x015E, + Schwa: 0x018F, + Schwacyrillic: 0x04D8, + Schwadieresiscyrillic: 0x04DA, + Scircle: 0x24C8, + Scircumflex: 0x015C, + Scommaaccent: 0x0218, + Sdotaccent: 0x1E60, + Sdotbelow: 0x1E62, + Sdotbelowdotaccent: 0x1E68, + Seharmenian: 0x054D, + Sevenroman: 0x2166, + Shaarmenian: 0x0547, + Shacyrillic: 0x0428, + Shchacyrillic: 0x0429, + Sheicoptic: 0x03E2, + Shhacyrillic: 0x04BA, + Shimacoptic: 0x03EC, + Sigma: 0x03A3, + Sixroman: 0x2165, + Smonospace: 0xFF33, + Softsigncyrillic: 0x042C, + Ssmall: 0xF773, + Stigmagreek: 0x03DA, + T: 0x0054, + Tau: 0x03A4, + Tbar: 0x0166, + Tcaron: 0x0164, + Tcedilla: 0x0162, + Tcircle: 0x24C9, + Tcircumflexbelow: 0x1E70, + Tcommaaccent: 0x0162, + Tdotaccent: 0x1E6A, + Tdotbelow: 0x1E6C, + Tecyrillic: 0x0422, + Tedescendercyrillic: 0x04AC, + Tenroman: 0x2169, + Tetsecyrillic: 0x04B4, + Theta: 0x0398, + Thook: 0x01AC, + Thorn: 0x00DE, + Thornsmall: 0xF7FE, + Threeroman: 0x2162, + Tildesmall: 0xF6FE, + Tiwnarmenian: 0x054F, + Tlinebelow: 0x1E6E, + Tmonospace: 0xFF34, + Toarmenian: 0x0539, + Tonefive: 0x01BC, + Tonesix: 0x0184, + Tonetwo: 0x01A7, + Tretroflexhook: 0x01AE, + Tsecyrillic: 0x0426, + Tshecyrillic: 0x040B, + Tsmall: 0xF774, + Twelveroman: 0x216B, + Tworoman: 0x2161, + U: 0x0055, + Uacute: 0x00DA, + Uacutesmall: 0xF7FA, + Ubreve: 0x016C, + Ucaron: 0x01D3, + Ucircle: 0x24CA, + Ucircumflex: 0x00DB, + Ucircumflexbelow: 0x1E76, + Ucircumflexsmall: 0xF7FB, + Ucyrillic: 0x0423, + Udblacute: 0x0170, + Udblgrave: 0x0214, + Udieresis: 0x00DC, + Udieresisacute: 0x01D7, + Udieresisbelow: 0x1E72, + Udieresiscaron: 0x01D9, + Udieresiscyrillic: 0x04F0, + Udieresisgrave: 0x01DB, + Udieresismacron: 0x01D5, + Udieresissmall: 0xF7FC, + Udotbelow: 0x1EE4, + Ugrave: 0x00D9, + Ugravesmall: 0xF7F9, + Uhookabove: 0x1EE6, + Uhorn: 0x01AF, + Uhornacute: 0x1EE8, + Uhorndotbelow: 0x1EF0, + Uhorngrave: 0x1EEA, + Uhornhookabove: 0x1EEC, + Uhorntilde: 0x1EEE, + Uhungarumlaut: 0x0170, + Uhungarumlautcyrillic: 0x04F2, + Uinvertedbreve: 0x0216, + Ukcyrillic: 0x0478, + Umacron: 0x016A, + Umacroncyrillic: 0x04EE, + Umacrondieresis: 0x1E7A, + Umonospace: 0xFF35, + Uogonek: 0x0172, + Upsilon: 0x03A5, + Upsilon1: 0x03D2, + Upsilonacutehooksymbolgreek: 0x03D3, + Upsilonafrican: 0x01B1, + Upsilondieresis: 0x03AB, + Upsilondieresishooksymbolgreek: 0x03D4, + Upsilonhooksymbol: 0x03D2, + Upsilontonos: 0x038E, + Uring: 0x016E, + Ushortcyrillic: 0x040E, + Usmall: 0xF775, + Ustraightcyrillic: 0x04AE, + Ustraightstrokecyrillic: 0x04B0, + Utilde: 0x0168, + Utildeacute: 0x1E78, + Utildebelow: 0x1E74, + V: 0x0056, + Vcircle: 0x24CB, + Vdotbelow: 0x1E7E, + Vecyrillic: 0x0412, + Vewarmenian: 0x054E, + Vhook: 0x01B2, + Vmonospace: 0xFF36, + Voarmenian: 0x0548, + Vsmall: 0xF776, + Vtilde: 0x1E7C, + W: 0x0057, + Wacute: 0x1E82, + Wcircle: 0x24CC, + Wcircumflex: 0x0174, + Wdieresis: 0x1E84, + Wdotaccent: 0x1E86, + Wdotbelow: 0x1E88, + Wgrave: 0x1E80, + Wmonospace: 0xFF37, + Wsmall: 0xF777, + X: 0x0058, + Xcircle: 0x24CD, + Xdieresis: 0x1E8C, + Xdotaccent: 0x1E8A, + Xeharmenian: 0x053D, + Xi: 0x039E, + Xmonospace: 0xFF38, + Xsmall: 0xF778, + Y: 0x0059, + Yacute: 0x00DD, + Yacutesmall: 0xF7FD, + Yatcyrillic: 0x0462, + Ycircle: 0x24CE, + Ycircumflex: 0x0176, + Ydieresis: 0x0178, + Ydieresissmall: 0xF7FF, + Ydotaccent: 0x1E8E, + Ydotbelow: 0x1EF4, + Yericyrillic: 0x042B, + Yerudieresiscyrillic: 0x04F8, + Ygrave: 0x1EF2, + Yhook: 0x01B3, + Yhookabove: 0x1EF6, + Yiarmenian: 0x0545, + Yicyrillic: 0x0407, + Yiwnarmenian: 0x0552, + Ymonospace: 0xFF39, + Ysmall: 0xF779, + Ytilde: 0x1EF8, + Yusbigcyrillic: 0x046A, + Yusbigiotifiedcyrillic: 0x046C, + Yuslittlecyrillic: 0x0466, + Yuslittleiotifiedcyrillic: 0x0468, + Z: 0x005A, + Zaarmenian: 0x0536, + Zacute: 0x0179, + Zcaron: 0x017D, + Zcaronsmall: 0xF6FF, + Zcircle: 0x24CF, + Zcircumflex: 0x1E90, + Zdot: 0x017B, + Zdotaccent: 0x017B, + Zdotbelow: 0x1E92, + Zecyrillic: 0x0417, + Zedescendercyrillic: 0x0498, + Zedieresiscyrillic: 0x04DE, + Zeta: 0x0396, + Zhearmenian: 0x053A, + Zhebrevecyrillic: 0x04C1, + Zhecyrillic: 0x0416, + Zhedescendercyrillic: 0x0496, + Zhedieresiscyrillic: 0x04DC, + Zlinebelow: 0x1E94, + Zmonospace: 0xFF3A, + Zsmall: 0xF77A, + Zstroke: 0x01B5, + a: 0x0061, + aabengali: 0x0986, + aacute: 0x00E1, + aadeva: 0x0906, + aagujarati: 0x0A86, + aagurmukhi: 0x0A06, + aamatragurmukhi: 0x0A3E, + aarusquare: 0x3303, + aavowelsignbengali: 0x09BE, + aavowelsigndeva: 0x093E, + aavowelsigngujarati: 0x0ABE, + abbreviationmarkarmenian: 0x055F, + abbreviationsigndeva: 0x0970, + abengali: 0x0985, + abopomofo: 0x311A, + abreve: 0x0103, + abreveacute: 0x1EAF, + abrevecyrillic: 0x04D1, + abrevedotbelow: 0x1EB7, + abrevegrave: 0x1EB1, + abrevehookabove: 0x1EB3, + abrevetilde: 0x1EB5, + acaron: 0x01CE, + acircle: 0x24D0, + acircumflex: 0x00E2, + acircumflexacute: 0x1EA5, + acircumflexdotbelow: 0x1EAD, + acircumflexgrave: 0x1EA7, + acircumflexhookabove: 0x1EA9, + acircumflextilde: 0x1EAB, + acute: 0x00B4, + acutebelowcmb: 0x0317, + acutecmb: 0x0301, + acutecomb: 0x0301, + acutedeva: 0x0954, + acutelowmod: 0x02CF, + acutetonecmb: 0x0341, + acyrillic: 0x0430, + adblgrave: 0x0201, + addakgurmukhi: 0x0A71, + adeva: 0x0905, + adieresis: 0x00E4, + adieresiscyrillic: 0x04D3, + adieresismacron: 0x01DF, + adotbelow: 0x1EA1, + adotmacron: 0x01E1, + ae: 0x00E6, + aeacute: 0x01FD, + aekorean: 0x3150, + aemacron: 0x01E3, + afii00208: 0x2015, + afii08941: 0x20A4, + afii10017: 0x0410, + afii10018: 0x0411, + afii10019: 0x0412, + afii10020: 0x0413, + afii10021: 0x0414, + afii10022: 0x0415, + afii10023: 0x0401, + afii10024: 0x0416, + afii10025: 0x0417, + afii10026: 0x0418, + afii10027: 0x0419, + afii10028: 0x041A, + afii10029: 0x041B, + afii10030: 0x041C, + afii10031: 0x041D, + afii10032: 0x041E, + afii10033: 0x041F, + afii10034: 0x0420, + afii10035: 0x0421, + afii10036: 0x0422, + afii10037: 0x0423, + afii10038: 0x0424, + afii10039: 0x0425, + afii10040: 0x0426, + afii10041: 0x0427, + afii10042: 0x0428, + afii10043: 0x0429, + afii10044: 0x042A, + afii10045: 0x042B, + afii10046: 0x042C, + afii10047: 0x042D, + afii10048: 0x042E, + afii10049: 0x042F, + afii10050: 0x0490, + afii10051: 0x0402, + afii10052: 0x0403, + afii10053: 0x0404, + afii10054: 0x0405, + afii10055: 0x0406, + afii10056: 0x0407, + afii10057: 0x0408, + afii10058: 0x0409, + afii10059: 0x040A, + afii10060: 0x040B, + afii10061: 0x040C, + afii10062: 0x040E, + afii10063: 0xF6C4, + afii10064: 0xF6C5, + afii10065: 0x0430, + afii10066: 0x0431, + afii10067: 0x0432, + afii10068: 0x0433, + afii10069: 0x0434, + afii10070: 0x0435, + afii10071: 0x0451, + afii10072: 0x0436, + afii10073: 0x0437, + afii10074: 0x0438, + afii10075: 0x0439, + afii10076: 0x043A, + afii10077: 0x043B, + afii10078: 0x043C, + afii10079: 0x043D, + afii10080: 0x043E, + afii10081: 0x043F, + afii10082: 0x0440, + afii10083: 0x0441, + afii10084: 0x0442, + afii10085: 0x0443, + afii10086: 0x0444, + afii10087: 0x0445, + afii10088: 0x0446, + afii10089: 0x0447, + afii10090: 0x0448, + afii10091: 0x0449, + afii10092: 0x044A, + afii10093: 0x044B, + afii10094: 0x044C, + afii10095: 0x044D, + afii10096: 0x044E, + afii10097: 0x044F, + afii10098: 0x0491, + afii10099: 0x0452, + afii10100: 0x0453, + afii10101: 0x0454, + afii10102: 0x0455, + afii10103: 0x0456, + afii10104: 0x0457, + afii10105: 0x0458, + afii10106: 0x0459, + afii10107: 0x045A, + afii10108: 0x045B, + afii10109: 0x045C, + afii10110: 0x045E, + afii10145: 0x040F, + afii10146: 0x0462, + afii10147: 0x0472, + afii10148: 0x0474, + afii10192: 0xF6C6, + afii10193: 0x045F, + afii10194: 0x0463, + afii10195: 0x0473, + afii10196: 0x0475, + afii10831: 0xF6C7, + afii10832: 0xF6C8, + afii10846: 0x04D9, + afii299: 0x200E, + afii300: 0x200F, + afii301: 0x200D, + afii57381: 0x066A, + afii57388: 0x060C, + afii57392: 0x0660, + afii57393: 0x0661, + afii57394: 0x0662, + afii57395: 0x0663, + afii57396: 0x0664, + afii57397: 0x0665, + afii57398: 0x0666, + afii57399: 0x0667, + afii57400: 0x0668, + afii57401: 0x0669, + afii57403: 0x061B, + afii57407: 0x061F, + afii57409: 0x0621, + afii57410: 0x0622, + afii57411: 0x0623, + afii57412: 0x0624, + afii57413: 0x0625, + afii57414: 0x0626, + afii57415: 0x0627, + afii57416: 0x0628, + afii57417: 0x0629, + afii57418: 0x062A, + afii57419: 0x062B, + afii57420: 0x062C, + afii57421: 0x062D, + afii57422: 0x062E, + afii57423: 0x062F, + afii57424: 0x0630, + afii57425: 0x0631, + afii57426: 0x0632, + afii57427: 0x0633, + afii57428: 0x0634, + afii57429: 0x0635, + afii57430: 0x0636, + afii57431: 0x0637, + afii57432: 0x0638, + afii57433: 0x0639, + afii57434: 0x063A, + afii57440: 0x0640, + afii57441: 0x0641, + afii57442: 0x0642, + afii57443: 0x0643, + afii57444: 0x0644, + afii57445: 0x0645, + afii57446: 0x0646, + afii57448: 0x0648, + afii57449: 0x0649, + afii57450: 0x064A, + afii57451: 0x064B, + afii57452: 0x064C, + afii57453: 0x064D, + afii57454: 0x064E, + afii57455: 0x064F, + afii57456: 0x0650, + afii57457: 0x0651, + afii57458: 0x0652, + afii57470: 0x0647, + afii57505: 0x06A4, + afii57506: 0x067E, + afii57507: 0x0686, + afii57508: 0x0698, + afii57509: 0x06AF, + afii57511: 0x0679, + afii57512: 0x0688, + afii57513: 0x0691, + afii57514: 0x06BA, + afii57519: 0x06D2, + afii57534: 0x06D5, + afii57636: 0x20AA, + afii57645: 0x05BE, + afii57658: 0x05C3, + afii57664: 0x05D0, + afii57665: 0x05D1, + afii57666: 0x05D2, + afii57667: 0x05D3, + afii57668: 0x05D4, + afii57669: 0x05D5, + afii57670: 0x05D6, + afii57671: 0x05D7, + afii57672: 0x05D8, + afii57673: 0x05D9, + afii57674: 0x05DA, + afii57675: 0x05DB, + afii57676: 0x05DC, + afii57677: 0x05DD, + afii57678: 0x05DE, + afii57679: 0x05DF, + afii57680: 0x05E0, + afii57681: 0x05E1, + afii57682: 0x05E2, + afii57683: 0x05E3, + afii57684: 0x05E4, + afii57685: 0x05E5, + afii57686: 0x05E6, + afii57687: 0x05E7, + afii57688: 0x05E8, + afii57689: 0x05E9, + afii57690: 0x05EA, + afii57694: 0xFB2A, + afii57695: 0xFB2B, + afii57700: 0xFB4B, + afii57705: 0xFB1F, + afii57716: 0x05F0, + afii57717: 0x05F1, + afii57718: 0x05F2, + afii57723: 0xFB35, + afii57793: 0x05B4, + afii57794: 0x05B5, + afii57795: 0x05B6, + afii57796: 0x05BB, + afii57797: 0x05B8, + afii57798: 0x05B7, + afii57799: 0x05B0, + afii57800: 0x05B2, + afii57801: 0x05B1, + afii57802: 0x05B3, + afii57803: 0x05C2, + afii57804: 0x05C1, + afii57806: 0x05B9, + afii57807: 0x05BC, + afii57839: 0x05BD, + afii57841: 0x05BF, + afii57842: 0x05C0, + afii57929: 0x02BC, + afii61248: 0x2105, + afii61289: 0x2113, + afii61352: 0x2116, + afii61573: 0x202C, + afii61574: 0x202D, + afii61575: 0x202E, + afii61664: 0x200C, + afii63167: 0x066D, + afii64937: 0x02BD, + agrave: 0x00E0, + agujarati: 0x0A85, + agurmukhi: 0x0A05, + ahiragana: 0x3042, + ahookabove: 0x1EA3, + aibengali: 0x0990, + aibopomofo: 0x311E, + aideva: 0x0910, + aiecyrillic: 0x04D5, + aigujarati: 0x0A90, + aigurmukhi: 0x0A10, + aimatragurmukhi: 0x0A48, + ainarabic: 0x0639, + ainfinalarabic: 0xFECA, + aininitialarabic: 0xFECB, + ainmedialarabic: 0xFECC, + ainvertedbreve: 0x0203, + aivowelsignbengali: 0x09C8, + aivowelsigndeva: 0x0948, + aivowelsigngujarati: 0x0AC8, + akatakana: 0x30A2, + akatakanahalfwidth: 0xFF71, + akorean: 0x314F, + alef: 0x05D0, + alefarabic: 0x0627, + alefdageshhebrew: 0xFB30, + aleffinalarabic: 0xFE8E, + alefhamzaabovearabic: 0x0623, + alefhamzaabovefinalarabic: 0xFE84, + alefhamzabelowarabic: 0x0625, + alefhamzabelowfinalarabic: 0xFE88, + alefhebrew: 0x05D0, + aleflamedhebrew: 0xFB4F, + alefmaddaabovearabic: 0x0622, + alefmaddaabovefinalarabic: 0xFE82, + alefmaksuraarabic: 0x0649, + alefmaksurafinalarabic: 0xFEF0, + alefmaksurainitialarabic: 0xFEF3, + alefmaksuramedialarabic: 0xFEF4, + alefpatahhebrew: 0xFB2E, + alefqamatshebrew: 0xFB2F, + aleph: 0x2135, + allequal: 0x224C, + alpha: 0x03B1, + alphatonos: 0x03AC, + amacron: 0x0101, + amonospace: 0xFF41, + ampersand: 0x0026, + ampersandmonospace: 0xFF06, + ampersandsmall: 0xF726, + amsquare: 0x33C2, + anbopomofo: 0x3122, + angbopomofo: 0x3124, + angbracketleft: 0x3008, // This glyph is missing from Adobe's original list. + angbracketright: 0x3009, // This glyph is missing from Adobe's original list. + angkhankhuthai: 0x0E5A, + angle: 0x2220, + anglebracketleft: 0x3008, + anglebracketleftvertical: 0xFE3F, + anglebracketright: 0x3009, + anglebracketrightvertical: 0xFE40, + angleleft: 0x2329, + angleright: 0x232A, + angstrom: 0x212B, + anoteleia: 0x0387, + anudattadeva: 0x0952, + anusvarabengali: 0x0982, + anusvaradeva: 0x0902, + anusvaragujarati: 0x0A82, + aogonek: 0x0105, + apaatosquare: 0x3300, + aparen: 0x249C, + apostrophearmenian: 0x055A, + apostrophemod: 0x02BC, + apple: 0xF8FF, + approaches: 0x2250, + approxequal: 0x2248, + approxequalorimage: 0x2252, + approximatelyequal: 0x2245, + araeaekorean: 0x318E, + araeakorean: 0x318D, + arc: 0x2312, + arighthalfring: 0x1E9A, + aring: 0x00E5, + aringacute: 0x01FB, + aringbelow: 0x1E01, + arrowboth: 0x2194, + arrowdashdown: 0x21E3, + arrowdashleft: 0x21E0, + arrowdashright: 0x21E2, + arrowdashup: 0x21E1, + arrowdblboth: 0x21D4, + arrowdbldown: 0x21D3, + arrowdblleft: 0x21D0, + arrowdblright: 0x21D2, + arrowdblup: 0x21D1, + arrowdown: 0x2193, + arrowdownleft: 0x2199, + arrowdownright: 0x2198, + arrowdownwhite: 0x21E9, + arrowheaddownmod: 0x02C5, + arrowheadleftmod: 0x02C2, + arrowheadrightmod: 0x02C3, + arrowheadupmod: 0x02C4, + arrowhorizex: 0xF8E7, + arrowleft: 0x2190, + arrowleftdbl: 0x21D0, + arrowleftdblstroke: 0x21CD, + arrowleftoverright: 0x21C6, + arrowleftwhite: 0x21E6, + arrowright: 0x2192, + arrowrightdblstroke: 0x21CF, + arrowrightheavy: 0x279E, + arrowrightoverleft: 0x21C4, + arrowrightwhite: 0x21E8, + arrowtableft: 0x21E4, + arrowtabright: 0x21E5, + arrowup: 0x2191, + arrowupdn: 0x2195, + arrowupdnbse: 0x21A8, + arrowupdownbase: 0x21A8, + arrowupleft: 0x2196, + arrowupleftofdown: 0x21C5, + arrowupright: 0x2197, + arrowupwhite: 0x21E7, + arrowvertex: 0xF8E6, + asciicircum: 0x005E, + asciicircummonospace: 0xFF3E, + asciitilde: 0x007E, + asciitildemonospace: 0xFF5E, + ascript: 0x0251, + ascriptturned: 0x0252, + asmallhiragana: 0x3041, + asmallkatakana: 0x30A1, + asmallkatakanahalfwidth: 0xFF67, + asterisk: 0x002A, + asteriskaltonearabic: 0x066D, + asteriskarabic: 0x066D, + asteriskmath: 0x2217, + asteriskmonospace: 0xFF0A, + asterisksmall: 0xFE61, + asterism: 0x2042, + asuperior: 0xF6E9, + asymptoticallyequal: 0x2243, + at: 0x0040, + atilde: 0x00E3, + atmonospace: 0xFF20, + atsmall: 0xFE6B, + aturned: 0x0250, + aubengali: 0x0994, + aubopomofo: 0x3120, + audeva: 0x0914, + augujarati: 0x0A94, + augurmukhi: 0x0A14, + aulengthmarkbengali: 0x09D7, + aumatragurmukhi: 0x0A4C, + auvowelsignbengali: 0x09CC, + auvowelsigndeva: 0x094C, + auvowelsigngujarati: 0x0ACC, + avagrahadeva: 0x093D, + aybarmenian: 0x0561, + ayin: 0x05E2, + ayinaltonehebrew: 0xFB20, + ayinhebrew: 0x05E2, + b: 0x0062, + babengali: 0x09AC, + backslash: 0x005C, + backslashmonospace: 0xFF3C, + badeva: 0x092C, + bagujarati: 0x0AAC, + bagurmukhi: 0x0A2C, + bahiragana: 0x3070, + bahtthai: 0x0E3F, + bakatakana: 0x30D0, + bar: 0x007C, + barmonospace: 0xFF5C, + bbopomofo: 0x3105, + bcircle: 0x24D1, + bdotaccent: 0x1E03, + bdotbelow: 0x1E05, + beamedsixteenthnotes: 0x266C, + because: 0x2235, + becyrillic: 0x0431, + beharabic: 0x0628, + behfinalarabic: 0xFE90, + behinitialarabic: 0xFE91, + behiragana: 0x3079, + behmedialarabic: 0xFE92, + behmeeminitialarabic: 0xFC9F, + behmeemisolatedarabic: 0xFC08, + behnoonfinalarabic: 0xFC6D, + bekatakana: 0x30D9, + benarmenian: 0x0562, + bet: 0x05D1, + beta: 0x03B2, + betasymbolgreek: 0x03D0, + betdagesh: 0xFB31, + betdageshhebrew: 0xFB31, + bethebrew: 0x05D1, + betrafehebrew: 0xFB4C, + bhabengali: 0x09AD, + bhadeva: 0x092D, + bhagujarati: 0x0AAD, + bhagurmukhi: 0x0A2D, + bhook: 0x0253, + bihiragana: 0x3073, + bikatakana: 0x30D3, + bilabialclick: 0x0298, + bindigurmukhi: 0x0A02, + birusquare: 0x3331, + blackcircle: 0x25CF, + blackdiamond: 0x25C6, + blackdownpointingtriangle: 0x25BC, + blackleftpointingpointer: 0x25C4, + blackleftpointingtriangle: 0x25C0, + blacklenticularbracketleft: 0x3010, + blacklenticularbracketleftvertical: 0xFE3B, + blacklenticularbracketright: 0x3011, + blacklenticularbracketrightvertical: 0xFE3C, + blacklowerlefttriangle: 0x25E3, + blacklowerrighttriangle: 0x25E2, + blackrectangle: 0x25AC, + blackrightpointingpointer: 0x25BA, + blackrightpointingtriangle: 0x25B6, + blacksmallsquare: 0x25AA, + blacksmilingface: 0x263B, + blacksquare: 0x25A0, + blackstar: 0x2605, + blackupperlefttriangle: 0x25E4, + blackupperrighttriangle: 0x25E5, + blackuppointingsmalltriangle: 0x25B4, + blackuppointingtriangle: 0x25B2, + blank: 0x2423, + blinebelow: 0x1E07, + block: 0x2588, + bmonospace: 0xFF42, + bobaimaithai: 0x0E1A, + bohiragana: 0x307C, + bokatakana: 0x30DC, + bparen: 0x249D, + bqsquare: 0x33C3, + braceex: 0xF8F4, + braceleft: 0x007B, + braceleftbt: 0xF8F3, + braceleftmid: 0xF8F2, + braceleftmonospace: 0xFF5B, + braceleftsmall: 0xFE5B, + bracelefttp: 0xF8F1, + braceleftvertical: 0xFE37, + braceright: 0x007D, + bracerightbt: 0xF8FE, + bracerightmid: 0xF8FD, + bracerightmonospace: 0xFF5D, + bracerightsmall: 0xFE5C, + bracerighttp: 0xF8FC, + bracerightvertical: 0xFE38, + bracketleft: 0x005B, + bracketleftbt: 0xF8F0, + bracketleftex: 0xF8EF, + bracketleftmonospace: 0xFF3B, + bracketlefttp: 0xF8EE, + bracketright: 0x005D, + bracketrightbt: 0xF8FB, + bracketrightex: 0xF8FA, + bracketrightmonospace: 0xFF3D, + bracketrighttp: 0xF8F9, + breve: 0x02D8, + brevebelowcmb: 0x032E, + brevecmb: 0x0306, + breveinvertedbelowcmb: 0x032F, + breveinvertedcmb: 0x0311, + breveinverteddoublecmb: 0x0361, + bridgebelowcmb: 0x032A, + bridgeinvertedbelowcmb: 0x033A, + brokenbar: 0x00A6, + bstroke: 0x0180, + bsuperior: 0xF6EA, + btopbar: 0x0183, + buhiragana: 0x3076, + bukatakana: 0x30D6, + bullet: 0x2022, + bulletinverse: 0x25D8, + bulletoperator: 0x2219, + bullseye: 0x25CE, + c: 0x0063, + caarmenian: 0x056E, + cabengali: 0x099A, + cacute: 0x0107, + cadeva: 0x091A, + cagujarati: 0x0A9A, + cagurmukhi: 0x0A1A, + calsquare: 0x3388, + candrabindubengali: 0x0981, + candrabinducmb: 0x0310, + candrabindudeva: 0x0901, + candrabindugujarati: 0x0A81, + capslock: 0x21EA, + careof: 0x2105, + caron: 0x02C7, + caronbelowcmb: 0x032C, + caroncmb: 0x030C, + carriagereturn: 0x21B5, + cbopomofo: 0x3118, + ccaron: 0x010D, + ccedilla: 0x00E7, + ccedillaacute: 0x1E09, + ccircle: 0x24D2, + ccircumflex: 0x0109, + ccurl: 0x0255, + cdot: 0x010B, + cdotaccent: 0x010B, + cdsquare: 0x33C5, + cedilla: 0x00B8, + cedillacmb: 0x0327, + cent: 0x00A2, + centigrade: 0x2103, + centinferior: 0xF6DF, + centmonospace: 0xFFE0, + centoldstyle: 0xF7A2, + centsuperior: 0xF6E0, + chaarmenian: 0x0579, + chabengali: 0x099B, + chadeva: 0x091B, + chagujarati: 0x0A9B, + chagurmukhi: 0x0A1B, + chbopomofo: 0x3114, + cheabkhasiancyrillic: 0x04BD, + checkmark: 0x2713, + checyrillic: 0x0447, + chedescenderabkhasiancyrillic: 0x04BF, + chedescendercyrillic: 0x04B7, + chedieresiscyrillic: 0x04F5, + cheharmenian: 0x0573, + chekhakassiancyrillic: 0x04CC, + cheverticalstrokecyrillic: 0x04B9, + chi: 0x03C7, + chieuchacirclekorean: 0x3277, + chieuchaparenkorean: 0x3217, + chieuchcirclekorean: 0x3269, + chieuchkorean: 0x314A, + chieuchparenkorean: 0x3209, + chochangthai: 0x0E0A, + chochanthai: 0x0E08, + chochingthai: 0x0E09, + chochoethai: 0x0E0C, + chook: 0x0188, + cieucacirclekorean: 0x3276, + cieucaparenkorean: 0x3216, + cieuccirclekorean: 0x3268, + cieuckorean: 0x3148, + cieucparenkorean: 0x3208, + cieucuparenkorean: 0x321C, + circle: 0x25CB, + circlecopyrt: 0x00A9, // This glyph is missing from Adobe's original list. + circlemultiply: 0x2297, + circleot: 0x2299, + circleplus: 0x2295, + circlepostalmark: 0x3036, + circlewithlefthalfblack: 0x25D0, + circlewithrighthalfblack: 0x25D1, + circumflex: 0x02C6, + circumflexbelowcmb: 0x032D, + circumflexcmb: 0x0302, + clear: 0x2327, + clickalveolar: 0x01C2, + clickdental: 0x01C0, + clicklateral: 0x01C1, + clickretroflex: 0x01C3, + club: 0x2663, + clubsuitblack: 0x2663, + clubsuitwhite: 0x2667, + cmcubedsquare: 0x33A4, + cmonospace: 0xFF43, + cmsquaredsquare: 0x33A0, + coarmenian: 0x0581, + colon: 0x003A, + colonmonetary: 0x20A1, + colonmonospace: 0xFF1A, + colonsign: 0x20A1, + colonsmall: 0xFE55, + colontriangularhalfmod: 0x02D1, + colontriangularmod: 0x02D0, + comma: 0x002C, + commaabovecmb: 0x0313, + commaaboverightcmb: 0x0315, + commaaccent: 0xF6C3, + commaarabic: 0x060C, + commaarmenian: 0x055D, + commainferior: 0xF6E1, + commamonospace: 0xFF0C, + commareversedabovecmb: 0x0314, + commareversedmod: 0x02BD, + commasmall: 0xFE50, + commasuperior: 0xF6E2, + commaturnedabovecmb: 0x0312, + commaturnedmod: 0x02BB, + compass: 0x263C, + congruent: 0x2245, + contourintegral: 0x222E, + control: 0x2303, + controlACK: 0x0006, + controlBEL: 0x0007, + controlBS: 0x0008, + controlCAN: 0x0018, + controlCR: 0x000D, + controlDC1: 0x0011, + controlDC2: 0x0012, + controlDC3: 0x0013, + controlDC4: 0x0014, + controlDEL: 0x007F, + controlDLE: 0x0010, + controlEM: 0x0019, + controlENQ: 0x0005, + controlEOT: 0x0004, + controlESC: 0x001B, + controlETB: 0x0017, + controlETX: 0x0003, + controlFF: 0x000C, + controlFS: 0x001C, + controlGS: 0x001D, + controlHT: 0x0009, + controlLF: 0x000A, + controlNAK: 0x0015, + controlRS: 0x001E, + controlSI: 0x000F, + controlSO: 0x000E, + controlSOT: 0x0002, + controlSTX: 0x0001, + controlSUB: 0x001A, + controlSYN: 0x0016, + controlUS: 0x001F, + controlVT: 0x000B, + copyright: 0x00A9, + copyrightsans: 0xF8E9, + copyrightserif: 0xF6D9, + cornerbracketleft: 0x300C, + cornerbracketlefthalfwidth: 0xFF62, + cornerbracketleftvertical: 0xFE41, + cornerbracketright: 0x300D, + cornerbracketrighthalfwidth: 0xFF63, + cornerbracketrightvertical: 0xFE42, + corporationsquare: 0x337F, + cosquare: 0x33C7, + coverkgsquare: 0x33C6, + cparen: 0x249E, + cruzeiro: 0x20A2, + cstretched: 0x0297, + curlyand: 0x22CF, + curlyor: 0x22CE, + currency: 0x00A4, + cyrBreve: 0xF6D1, + cyrFlex: 0xF6D2, + cyrbreve: 0xF6D4, + cyrflex: 0xF6D5, + d: 0x0064, + daarmenian: 0x0564, + dabengali: 0x09A6, + dadarabic: 0x0636, + dadeva: 0x0926, + dadfinalarabic: 0xFEBE, + dadinitialarabic: 0xFEBF, + dadmedialarabic: 0xFEC0, + dagesh: 0x05BC, + dageshhebrew: 0x05BC, + dagger: 0x2020, + daggerdbl: 0x2021, + dagujarati: 0x0AA6, + dagurmukhi: 0x0A26, + dahiragana: 0x3060, + dakatakana: 0x30C0, + dalarabic: 0x062F, + dalet: 0x05D3, + daletdagesh: 0xFB33, + daletdageshhebrew: 0xFB33, + dalethebrew: 0x05D3, + dalfinalarabic: 0xFEAA, + dammaarabic: 0x064F, + dammalowarabic: 0x064F, + dammatanaltonearabic: 0x064C, + dammatanarabic: 0x064C, + danda: 0x0964, + dargahebrew: 0x05A7, + dargalefthebrew: 0x05A7, + dasiapneumatacyrilliccmb: 0x0485, + dblGrave: 0xF6D3, + dblanglebracketleft: 0x300A, + dblanglebracketleftvertical: 0xFE3D, + dblanglebracketright: 0x300B, + dblanglebracketrightvertical: 0xFE3E, + dblarchinvertedbelowcmb: 0x032B, + dblarrowleft: 0x21D4, + dblarrowright: 0x21D2, + dbldanda: 0x0965, + dblgrave: 0xF6D6, + dblgravecmb: 0x030F, + dblintegral: 0x222C, + dbllowline: 0x2017, + dbllowlinecmb: 0x0333, + dbloverlinecmb: 0x033F, + dblprimemod: 0x02BA, + dblverticalbar: 0x2016, + dblverticallineabovecmb: 0x030E, + dbopomofo: 0x3109, + dbsquare: 0x33C8, + dcaron: 0x010F, + dcedilla: 0x1E11, + dcircle: 0x24D3, + dcircumflexbelow: 0x1E13, + dcroat: 0x0111, + ddabengali: 0x09A1, + ddadeva: 0x0921, + ddagujarati: 0x0AA1, + ddagurmukhi: 0x0A21, + ddalarabic: 0x0688, + ddalfinalarabic: 0xFB89, + dddhadeva: 0x095C, + ddhabengali: 0x09A2, + ddhadeva: 0x0922, + ddhagujarati: 0x0AA2, + ddhagurmukhi: 0x0A22, + ddotaccent: 0x1E0B, + ddotbelow: 0x1E0D, + decimalseparatorarabic: 0x066B, + decimalseparatorpersian: 0x066B, + decyrillic: 0x0434, + degree: 0x00B0, + dehihebrew: 0x05AD, + dehiragana: 0x3067, + deicoptic: 0x03EF, + dekatakana: 0x30C7, + deleteleft: 0x232B, + deleteright: 0x2326, + delta: 0x03B4, + deltaturned: 0x018D, + denominatorminusonenumeratorbengali: 0x09F8, + dezh: 0x02A4, + dhabengali: 0x09A7, + dhadeva: 0x0927, + dhagujarati: 0x0AA7, + dhagurmukhi: 0x0A27, + dhook: 0x0257, + dialytikatonos: 0x0385, + dialytikatonoscmb: 0x0344, + diamond: 0x2666, + diamondsuitwhite: 0x2662, + dieresis: 0x00A8, + dieresisacute: 0xF6D7, + dieresisbelowcmb: 0x0324, + dieresiscmb: 0x0308, + dieresisgrave: 0xF6D8, + dieresistonos: 0x0385, + dihiragana: 0x3062, + dikatakana: 0x30C2, + dittomark: 0x3003, + divide: 0x00F7, + divides: 0x2223, + divisionslash: 0x2215, + djecyrillic: 0x0452, + dkshade: 0x2593, + dlinebelow: 0x1E0F, + dlsquare: 0x3397, + dmacron: 0x0111, + dmonospace: 0xFF44, + dnblock: 0x2584, + dochadathai: 0x0E0E, + dodekthai: 0x0E14, + dohiragana: 0x3069, + dokatakana: 0x30C9, + dollar: 0x0024, + dollarinferior: 0xF6E3, + dollarmonospace: 0xFF04, + dollaroldstyle: 0xF724, + dollarsmall: 0xFE69, + dollarsuperior: 0xF6E4, + dong: 0x20AB, + dorusquare: 0x3326, + dotaccent: 0x02D9, + dotaccentcmb: 0x0307, + dotbelowcmb: 0x0323, + dotbelowcomb: 0x0323, + dotkatakana: 0x30FB, + dotlessi: 0x0131, + dotlessj: 0xF6BE, + dotlessjstrokehook: 0x0284, + dotmath: 0x22C5, + dottedcircle: 0x25CC, + doubleyodpatah: 0xFB1F, + doubleyodpatahhebrew: 0xFB1F, + downtackbelowcmb: 0x031E, + downtackmod: 0x02D5, + dparen: 0x249F, + dsuperior: 0xF6EB, + dtail: 0x0256, + dtopbar: 0x018C, + duhiragana: 0x3065, + dukatakana: 0x30C5, + dz: 0x01F3, + dzaltone: 0x02A3, + dzcaron: 0x01C6, + dzcurl: 0x02A5, + dzeabkhasiancyrillic: 0x04E1, + dzecyrillic: 0x0455, + dzhecyrillic: 0x045F, + e: 0x0065, + eacute: 0x00E9, + earth: 0x2641, + ebengali: 0x098F, + ebopomofo: 0x311C, + ebreve: 0x0115, + ecandradeva: 0x090D, + ecandragujarati: 0x0A8D, + ecandravowelsigndeva: 0x0945, + ecandravowelsigngujarati: 0x0AC5, + ecaron: 0x011B, + ecedillabreve: 0x1E1D, + echarmenian: 0x0565, + echyiwnarmenian: 0x0587, + ecircle: 0x24D4, + ecircumflex: 0x00EA, + ecircumflexacute: 0x1EBF, + ecircumflexbelow: 0x1E19, + ecircumflexdotbelow: 0x1EC7, + ecircumflexgrave: 0x1EC1, + ecircumflexhookabove: 0x1EC3, + ecircumflextilde: 0x1EC5, + ecyrillic: 0x0454, + edblgrave: 0x0205, + edeva: 0x090F, + edieresis: 0x00EB, + edot: 0x0117, + edotaccent: 0x0117, + edotbelow: 0x1EB9, + eegurmukhi: 0x0A0F, + eematragurmukhi: 0x0A47, + efcyrillic: 0x0444, + egrave: 0x00E8, + egujarati: 0x0A8F, + eharmenian: 0x0567, + ehbopomofo: 0x311D, + ehiragana: 0x3048, + ehookabove: 0x1EBB, + eibopomofo: 0x311F, + eight: 0x0038, + eightarabic: 0x0668, + eightbengali: 0x09EE, + eightcircle: 0x2467, + eightcircleinversesansserif: 0x2791, + eightdeva: 0x096E, + eighteencircle: 0x2471, + eighteenparen: 0x2485, + eighteenperiod: 0x2499, + eightgujarati: 0x0AEE, + eightgurmukhi: 0x0A6E, + eighthackarabic: 0x0668, + eighthangzhou: 0x3028, + eighthnotebeamed: 0x266B, + eightideographicparen: 0x3227, + eightinferior: 0x2088, + eightmonospace: 0xFF18, + eightoldstyle: 0xF738, + eightparen: 0x247B, + eightperiod: 0x248F, + eightpersian: 0x06F8, + eightroman: 0x2177, + eightsuperior: 0x2078, + eightthai: 0x0E58, + einvertedbreve: 0x0207, + eiotifiedcyrillic: 0x0465, + ekatakana: 0x30A8, + ekatakanahalfwidth: 0xFF74, + ekonkargurmukhi: 0x0A74, + ekorean: 0x3154, + elcyrillic: 0x043B, + element: 0x2208, + elevencircle: 0x246A, + elevenparen: 0x247E, + elevenperiod: 0x2492, + elevenroman: 0x217A, + ellipsis: 0x2026, + ellipsisvertical: 0x22EE, + emacron: 0x0113, + emacronacute: 0x1E17, + emacrongrave: 0x1E15, + emcyrillic: 0x043C, + emdash: 0x2014, + emdashvertical: 0xFE31, + emonospace: 0xFF45, + emphasismarkarmenian: 0x055B, + emptyset: 0x2205, + enbopomofo: 0x3123, + encyrillic: 0x043D, + endash: 0x2013, + endashvertical: 0xFE32, + endescendercyrillic: 0x04A3, + eng: 0x014B, + engbopomofo: 0x3125, + enghecyrillic: 0x04A5, + enhookcyrillic: 0x04C8, + enspace: 0x2002, + eogonek: 0x0119, + eokorean: 0x3153, + eopen: 0x025B, + eopenclosed: 0x029A, + eopenreversed: 0x025C, + eopenreversedclosed: 0x025E, + eopenreversedhook: 0x025D, + eparen: 0x24A0, + epsilon: 0x03B5, + epsilontonos: 0x03AD, + equal: 0x003D, + equalmonospace: 0xFF1D, + equalsmall: 0xFE66, + equalsuperior: 0x207C, + equivalence: 0x2261, + erbopomofo: 0x3126, + ercyrillic: 0x0440, + ereversed: 0x0258, + ereversedcyrillic: 0x044D, + escyrillic: 0x0441, + esdescendercyrillic: 0x04AB, + esh: 0x0283, + eshcurl: 0x0286, + eshortdeva: 0x090E, + eshortvowelsigndeva: 0x0946, + eshreversedloop: 0x01AA, + eshsquatreversed: 0x0285, + esmallhiragana: 0x3047, + esmallkatakana: 0x30A7, + esmallkatakanahalfwidth: 0xFF6A, + estimated: 0x212E, + esuperior: 0xF6EC, + eta: 0x03B7, + etarmenian: 0x0568, + etatonos: 0x03AE, + eth: 0x00F0, + etilde: 0x1EBD, + etildebelow: 0x1E1B, + etnahtafoukhhebrew: 0x0591, + etnahtafoukhlefthebrew: 0x0591, + etnahtahebrew: 0x0591, + etnahtalefthebrew: 0x0591, + eturned: 0x01DD, + eukorean: 0x3161, + euro: 0x20AC, + evowelsignbengali: 0x09C7, + evowelsigndeva: 0x0947, + evowelsigngujarati: 0x0AC7, + exclam: 0x0021, + exclamarmenian: 0x055C, + exclamdbl: 0x203C, + exclamdown: 0x00A1, + exclamdownsmall: 0xF7A1, + exclammonospace: 0xFF01, + exclamsmall: 0xF721, + existential: 0x2203, + ezh: 0x0292, + ezhcaron: 0x01EF, + ezhcurl: 0x0293, + ezhreversed: 0x01B9, + ezhtail: 0x01BA, + f: 0x0066, + fadeva: 0x095E, + fagurmukhi: 0x0A5E, + fahrenheit: 0x2109, + fathaarabic: 0x064E, + fathalowarabic: 0x064E, + fathatanarabic: 0x064B, + fbopomofo: 0x3108, + fcircle: 0x24D5, + fdotaccent: 0x1E1F, + feharabic: 0x0641, + feharmenian: 0x0586, + fehfinalarabic: 0xFED2, + fehinitialarabic: 0xFED3, + fehmedialarabic: 0xFED4, + feicoptic: 0x03E5, + female: 0x2640, + ff: 0xFB00, + ffi: 0xFB03, + ffl: 0xFB04, + fi: 0xFB01, + fifteencircle: 0x246E, + fifteenparen: 0x2482, + fifteenperiod: 0x2496, + figuredash: 0x2012, + filledbox: 0x25A0, + filledrect: 0x25AC, + finalkaf: 0x05DA, + finalkafdagesh: 0xFB3A, + finalkafdageshhebrew: 0xFB3A, + finalkafhebrew: 0x05DA, + finalmem: 0x05DD, + finalmemhebrew: 0x05DD, + finalnun: 0x05DF, + finalnunhebrew: 0x05DF, + finalpe: 0x05E3, + finalpehebrew: 0x05E3, + finaltsadi: 0x05E5, + finaltsadihebrew: 0x05E5, + firsttonechinese: 0x02C9, + fisheye: 0x25C9, + fitacyrillic: 0x0473, + five: 0x0035, + fivearabic: 0x0665, + fivebengali: 0x09EB, + fivecircle: 0x2464, + fivecircleinversesansserif: 0x278E, + fivedeva: 0x096B, + fiveeighths: 0x215D, + fivegujarati: 0x0AEB, + fivegurmukhi: 0x0A6B, + fivehackarabic: 0x0665, + fivehangzhou: 0x3025, + fiveideographicparen: 0x3224, + fiveinferior: 0x2085, + fivemonospace: 0xFF15, + fiveoldstyle: 0xF735, + fiveparen: 0x2478, + fiveperiod: 0x248C, + fivepersian: 0x06F5, + fiveroman: 0x2174, + fivesuperior: 0x2075, + fivethai: 0x0E55, + fl: 0xFB02, + florin: 0x0192, + fmonospace: 0xFF46, + fmsquare: 0x3399, + fofanthai: 0x0E1F, + fofathai: 0x0E1D, + fongmanthai: 0x0E4F, + forall: 0x2200, + four: 0x0034, + fourarabic: 0x0664, + fourbengali: 0x09EA, + fourcircle: 0x2463, + fourcircleinversesansserif: 0x278D, + fourdeva: 0x096A, + fourgujarati: 0x0AEA, + fourgurmukhi: 0x0A6A, + fourhackarabic: 0x0664, + fourhangzhou: 0x3024, + fourideographicparen: 0x3223, + fourinferior: 0x2084, + fourmonospace: 0xFF14, + fournumeratorbengali: 0x09F7, + fouroldstyle: 0xF734, + fourparen: 0x2477, + fourperiod: 0x248B, + fourpersian: 0x06F4, + fourroman: 0x2173, + foursuperior: 0x2074, + fourteencircle: 0x246D, + fourteenparen: 0x2481, + fourteenperiod: 0x2495, + fourthai: 0x0E54, + fourthtonechinese: 0x02CB, + fparen: 0x24A1, + fraction: 0x2044, + franc: 0x20A3, + g: 0x0067, + gabengali: 0x0997, + gacute: 0x01F5, + gadeva: 0x0917, + gafarabic: 0x06AF, + gaffinalarabic: 0xFB93, + gafinitialarabic: 0xFB94, + gafmedialarabic: 0xFB95, + gagujarati: 0x0A97, + gagurmukhi: 0x0A17, + gahiragana: 0x304C, + gakatakana: 0x30AC, + gamma: 0x03B3, + gammalatinsmall: 0x0263, + gammasuperior: 0x02E0, + gangiacoptic: 0x03EB, + gbopomofo: 0x310D, + gbreve: 0x011F, + gcaron: 0x01E7, + gcedilla: 0x0123, + gcircle: 0x24D6, + gcircumflex: 0x011D, + gcommaaccent: 0x0123, + gdot: 0x0121, + gdotaccent: 0x0121, + gecyrillic: 0x0433, + gehiragana: 0x3052, + gekatakana: 0x30B2, + geometricallyequal: 0x2251, + gereshaccenthebrew: 0x059C, + gereshhebrew: 0x05F3, + gereshmuqdamhebrew: 0x059D, + germandbls: 0x00DF, + gershayimaccenthebrew: 0x059E, + gershayimhebrew: 0x05F4, + getamark: 0x3013, + ghabengali: 0x0998, + ghadarmenian: 0x0572, + ghadeva: 0x0918, + ghagujarati: 0x0A98, + ghagurmukhi: 0x0A18, + ghainarabic: 0x063A, + ghainfinalarabic: 0xFECE, + ghaininitialarabic: 0xFECF, + ghainmedialarabic: 0xFED0, + ghemiddlehookcyrillic: 0x0495, + ghestrokecyrillic: 0x0493, + gheupturncyrillic: 0x0491, + ghhadeva: 0x095A, + ghhagurmukhi: 0x0A5A, + ghook: 0x0260, + ghzsquare: 0x3393, + gihiragana: 0x304E, + gikatakana: 0x30AE, + gimarmenian: 0x0563, + gimel: 0x05D2, + gimeldagesh: 0xFB32, + gimeldageshhebrew: 0xFB32, + gimelhebrew: 0x05D2, + gjecyrillic: 0x0453, + glottalinvertedstroke: 0x01BE, + glottalstop: 0x0294, + glottalstopinverted: 0x0296, + glottalstopmod: 0x02C0, + glottalstopreversed: 0x0295, + glottalstopreversedmod: 0x02C1, + glottalstopreversedsuperior: 0x02E4, + glottalstopstroke: 0x02A1, + glottalstopstrokereversed: 0x02A2, + gmacron: 0x1E21, + gmonospace: 0xFF47, + gohiragana: 0x3054, + gokatakana: 0x30B4, + gparen: 0x24A2, + gpasquare: 0x33AC, + gradient: 0x2207, + grave: 0x0060, + gravebelowcmb: 0x0316, + gravecmb: 0x0300, + gravecomb: 0x0300, + gravedeva: 0x0953, + gravelowmod: 0x02CE, + gravemonospace: 0xFF40, + gravetonecmb: 0x0340, + greater: 0x003E, + greaterequal: 0x2265, + greaterequalorless: 0x22DB, + greatermonospace: 0xFF1E, + greaterorequivalent: 0x2273, + greaterorless: 0x2277, + greateroverequal: 0x2267, + greatersmall: 0xFE65, + gscript: 0x0261, + gstroke: 0x01E5, + guhiragana: 0x3050, + guillemotleft: 0x00AB, + guillemotright: 0x00BB, + guilsinglleft: 0x2039, + guilsinglright: 0x203A, + gukatakana: 0x30B0, + guramusquare: 0x3318, + gysquare: 0x33C9, + h: 0x0068, + haabkhasiancyrillic: 0x04A9, + haaltonearabic: 0x06C1, + habengali: 0x09B9, + hadescendercyrillic: 0x04B3, + hadeva: 0x0939, + hagujarati: 0x0AB9, + hagurmukhi: 0x0A39, + haharabic: 0x062D, + hahfinalarabic: 0xFEA2, + hahinitialarabic: 0xFEA3, + hahiragana: 0x306F, + hahmedialarabic: 0xFEA4, + haitusquare: 0x332A, + hakatakana: 0x30CF, + hakatakanahalfwidth: 0xFF8A, + halantgurmukhi: 0x0A4D, + hamzaarabic: 0x0621, + hamzalowarabic: 0x0621, + hangulfiller: 0x3164, + hardsigncyrillic: 0x044A, + harpoonleftbarbup: 0x21BC, + harpoonrightbarbup: 0x21C0, + hasquare: 0x33CA, + hatafpatah: 0x05B2, + hatafpatah16: 0x05B2, + hatafpatah23: 0x05B2, + hatafpatah2f: 0x05B2, + hatafpatahhebrew: 0x05B2, + hatafpatahnarrowhebrew: 0x05B2, + hatafpatahquarterhebrew: 0x05B2, + hatafpatahwidehebrew: 0x05B2, + hatafqamats: 0x05B3, + hatafqamats1b: 0x05B3, + hatafqamats28: 0x05B3, + hatafqamats34: 0x05B3, + hatafqamatshebrew: 0x05B3, + hatafqamatsnarrowhebrew: 0x05B3, + hatafqamatsquarterhebrew: 0x05B3, + hatafqamatswidehebrew: 0x05B3, + hatafsegol: 0x05B1, + hatafsegol17: 0x05B1, + hatafsegol24: 0x05B1, + hatafsegol30: 0x05B1, + hatafsegolhebrew: 0x05B1, + hatafsegolnarrowhebrew: 0x05B1, + hatafsegolquarterhebrew: 0x05B1, + hatafsegolwidehebrew: 0x05B1, + hbar: 0x0127, + hbopomofo: 0x310F, + hbrevebelow: 0x1E2B, + hcedilla: 0x1E29, + hcircle: 0x24D7, + hcircumflex: 0x0125, + hdieresis: 0x1E27, + hdotaccent: 0x1E23, + hdotbelow: 0x1E25, + he: 0x05D4, + heart: 0x2665, + heartsuitblack: 0x2665, + heartsuitwhite: 0x2661, + hedagesh: 0xFB34, + hedageshhebrew: 0xFB34, + hehaltonearabic: 0x06C1, + heharabic: 0x0647, + hehebrew: 0x05D4, + hehfinalaltonearabic: 0xFBA7, + hehfinalalttwoarabic: 0xFEEA, + hehfinalarabic: 0xFEEA, + hehhamzaabovefinalarabic: 0xFBA5, + hehhamzaaboveisolatedarabic: 0xFBA4, + hehinitialaltonearabic: 0xFBA8, + hehinitialarabic: 0xFEEB, + hehiragana: 0x3078, + hehmedialaltonearabic: 0xFBA9, + hehmedialarabic: 0xFEEC, + heiseierasquare: 0x337B, + hekatakana: 0x30D8, + hekatakanahalfwidth: 0xFF8D, + hekutaarusquare: 0x3336, + henghook: 0x0267, + herutusquare: 0x3339, + het: 0x05D7, + hethebrew: 0x05D7, + hhook: 0x0266, + hhooksuperior: 0x02B1, + hieuhacirclekorean: 0x327B, + hieuhaparenkorean: 0x321B, + hieuhcirclekorean: 0x326D, + hieuhkorean: 0x314E, + hieuhparenkorean: 0x320D, + hihiragana: 0x3072, + hikatakana: 0x30D2, + hikatakanahalfwidth: 0xFF8B, + hiriq: 0x05B4, + hiriq14: 0x05B4, + hiriq21: 0x05B4, + hiriq2d: 0x05B4, + hiriqhebrew: 0x05B4, + hiriqnarrowhebrew: 0x05B4, + hiriqquarterhebrew: 0x05B4, + hiriqwidehebrew: 0x05B4, + hlinebelow: 0x1E96, + hmonospace: 0xFF48, + hoarmenian: 0x0570, + hohipthai: 0x0E2B, + hohiragana: 0x307B, + hokatakana: 0x30DB, + hokatakanahalfwidth: 0xFF8E, + holam: 0x05B9, + holam19: 0x05B9, + holam26: 0x05B9, + holam32: 0x05B9, + holamhebrew: 0x05B9, + holamnarrowhebrew: 0x05B9, + holamquarterhebrew: 0x05B9, + holamwidehebrew: 0x05B9, + honokhukthai: 0x0E2E, + hookabovecomb: 0x0309, + hookcmb: 0x0309, + hookpalatalizedbelowcmb: 0x0321, + hookretroflexbelowcmb: 0x0322, + hoonsquare: 0x3342, + horicoptic: 0x03E9, + horizontalbar: 0x2015, + horncmb: 0x031B, + hotsprings: 0x2668, + house: 0x2302, + hparen: 0x24A3, + hsuperior: 0x02B0, + hturned: 0x0265, + huhiragana: 0x3075, + huiitosquare: 0x3333, + hukatakana: 0x30D5, + hukatakanahalfwidth: 0xFF8C, + hungarumlaut: 0x02DD, + hungarumlautcmb: 0x030B, + hv: 0x0195, + hyphen: 0x002D, + hypheninferior: 0xF6E5, + hyphenmonospace: 0xFF0D, + hyphensmall: 0xFE63, + hyphensuperior: 0xF6E6, + hyphentwo: 0x2010, + i: 0x0069, + iacute: 0x00ED, + iacyrillic: 0x044F, + ibengali: 0x0987, + ibopomofo: 0x3127, + ibreve: 0x012D, + icaron: 0x01D0, + icircle: 0x24D8, + icircumflex: 0x00EE, + icyrillic: 0x0456, + idblgrave: 0x0209, + ideographearthcircle: 0x328F, + ideographfirecircle: 0x328B, + ideographicallianceparen: 0x323F, + ideographiccallparen: 0x323A, + ideographiccentrecircle: 0x32A5, + ideographicclose: 0x3006, + ideographiccomma: 0x3001, + ideographiccommaleft: 0xFF64, + ideographiccongratulationparen: 0x3237, + ideographiccorrectcircle: 0x32A3, + ideographicearthparen: 0x322F, + ideographicenterpriseparen: 0x323D, + ideographicexcellentcircle: 0x329D, + ideographicfestivalparen: 0x3240, + ideographicfinancialcircle: 0x3296, + ideographicfinancialparen: 0x3236, + ideographicfireparen: 0x322B, + ideographichaveparen: 0x3232, + ideographichighcircle: 0x32A4, + ideographiciterationmark: 0x3005, + ideographiclaborcircle: 0x3298, + ideographiclaborparen: 0x3238, + ideographicleftcircle: 0x32A7, + ideographiclowcircle: 0x32A6, + ideographicmedicinecircle: 0x32A9, + ideographicmetalparen: 0x322E, + ideographicmoonparen: 0x322A, + ideographicnameparen: 0x3234, + ideographicperiod: 0x3002, + ideographicprintcircle: 0x329E, + ideographicreachparen: 0x3243, + ideographicrepresentparen: 0x3239, + ideographicresourceparen: 0x323E, + ideographicrightcircle: 0x32A8, + ideographicsecretcircle: 0x3299, + ideographicselfparen: 0x3242, + ideographicsocietyparen: 0x3233, + ideographicspace: 0x3000, + ideographicspecialparen: 0x3235, + ideographicstockparen: 0x3231, + ideographicstudyparen: 0x323B, + ideographicsunparen: 0x3230, + ideographicsuperviseparen: 0x323C, + ideographicwaterparen: 0x322C, + ideographicwoodparen: 0x322D, + ideographiczero: 0x3007, + ideographmetalcircle: 0x328E, + ideographmooncircle: 0x328A, + ideographnamecircle: 0x3294, + ideographsuncircle: 0x3290, + ideographwatercircle: 0x328C, + ideographwoodcircle: 0x328D, + ideva: 0x0907, + idieresis: 0x00EF, + idieresisacute: 0x1E2F, + idieresiscyrillic: 0x04E5, + idotbelow: 0x1ECB, + iebrevecyrillic: 0x04D7, + iecyrillic: 0x0435, + ieungacirclekorean: 0x3275, + ieungaparenkorean: 0x3215, + ieungcirclekorean: 0x3267, + ieungkorean: 0x3147, + ieungparenkorean: 0x3207, + igrave: 0x00EC, + igujarati: 0x0A87, + igurmukhi: 0x0A07, + ihiragana: 0x3044, + ihookabove: 0x1EC9, + iibengali: 0x0988, + iicyrillic: 0x0438, + iideva: 0x0908, + iigujarati: 0x0A88, + iigurmukhi: 0x0A08, + iimatragurmukhi: 0x0A40, + iinvertedbreve: 0x020B, + iishortcyrillic: 0x0439, + iivowelsignbengali: 0x09C0, + iivowelsigndeva: 0x0940, + iivowelsigngujarati: 0x0AC0, + ij: 0x0133, + ikatakana: 0x30A4, + ikatakanahalfwidth: 0xFF72, + ikorean: 0x3163, + ilde: 0x02DC, + iluyhebrew: 0x05AC, + imacron: 0x012B, + imacroncyrillic: 0x04E3, + imageorapproximatelyequal: 0x2253, + imatragurmukhi: 0x0A3F, + imonospace: 0xFF49, + increment: 0x2206, + infinity: 0x221E, + iniarmenian: 0x056B, + integral: 0x222B, + integralbottom: 0x2321, + integralbt: 0x2321, + integralex: 0xF8F5, + integraltop: 0x2320, + integraltp: 0x2320, + intersection: 0x2229, + intisquare: 0x3305, + invbullet: 0x25D8, + invcircle: 0x25D9, + invsmileface: 0x263B, + iocyrillic: 0x0451, + iogonek: 0x012F, + iota: 0x03B9, + iotadieresis: 0x03CA, + iotadieresistonos: 0x0390, + iotalatin: 0x0269, + iotatonos: 0x03AF, + iparen: 0x24A4, + irigurmukhi: 0x0A72, + ismallhiragana: 0x3043, + ismallkatakana: 0x30A3, + ismallkatakanahalfwidth: 0xFF68, + issharbengali: 0x09FA, + istroke: 0x0268, + isuperior: 0xF6ED, + iterationhiragana: 0x309D, + iterationkatakana: 0x30FD, + itilde: 0x0129, + itildebelow: 0x1E2D, + iubopomofo: 0x3129, + iucyrillic: 0x044E, + ivowelsignbengali: 0x09BF, + ivowelsigndeva: 0x093F, + ivowelsigngujarati: 0x0ABF, + izhitsacyrillic: 0x0475, + izhitsadblgravecyrillic: 0x0477, + j: 0x006A, + jaarmenian: 0x0571, + jabengali: 0x099C, + jadeva: 0x091C, + jagujarati: 0x0A9C, + jagurmukhi: 0x0A1C, + jbopomofo: 0x3110, + jcaron: 0x01F0, + jcircle: 0x24D9, + jcircumflex: 0x0135, + jcrossedtail: 0x029D, + jdotlessstroke: 0x025F, + jecyrillic: 0x0458, + jeemarabic: 0x062C, + jeemfinalarabic: 0xFE9E, + jeeminitialarabic: 0xFE9F, + jeemmedialarabic: 0xFEA0, + jeharabic: 0x0698, + jehfinalarabic: 0xFB8B, + jhabengali: 0x099D, + jhadeva: 0x091D, + jhagujarati: 0x0A9D, + jhagurmukhi: 0x0A1D, + jheharmenian: 0x057B, + jis: 0x3004, + jmonospace: 0xFF4A, + jparen: 0x24A5, + jsuperior: 0x02B2, + k: 0x006B, + kabashkircyrillic: 0x04A1, + kabengali: 0x0995, + kacute: 0x1E31, + kacyrillic: 0x043A, + kadescendercyrillic: 0x049B, + kadeva: 0x0915, + kaf: 0x05DB, + kafarabic: 0x0643, + kafdagesh: 0xFB3B, + kafdageshhebrew: 0xFB3B, + kaffinalarabic: 0xFEDA, + kafhebrew: 0x05DB, + kafinitialarabic: 0xFEDB, + kafmedialarabic: 0xFEDC, + kafrafehebrew: 0xFB4D, + kagujarati: 0x0A95, + kagurmukhi: 0x0A15, + kahiragana: 0x304B, + kahookcyrillic: 0x04C4, + kakatakana: 0x30AB, + kakatakanahalfwidth: 0xFF76, + kappa: 0x03BA, + kappasymbolgreek: 0x03F0, + kapyeounmieumkorean: 0x3171, + kapyeounphieuphkorean: 0x3184, + kapyeounpieupkorean: 0x3178, + kapyeounssangpieupkorean: 0x3179, + karoriisquare: 0x330D, + kashidaautoarabic: 0x0640, + kashidaautonosidebearingarabic: 0x0640, + kasmallkatakana: 0x30F5, + kasquare: 0x3384, + kasraarabic: 0x0650, + kasratanarabic: 0x064D, + kastrokecyrillic: 0x049F, + katahiraprolongmarkhalfwidth: 0xFF70, + kaverticalstrokecyrillic: 0x049D, + kbopomofo: 0x310E, + kcalsquare: 0x3389, + kcaron: 0x01E9, + kcedilla: 0x0137, + kcircle: 0x24DA, + kcommaaccent: 0x0137, + kdotbelow: 0x1E33, + keharmenian: 0x0584, + kehiragana: 0x3051, + kekatakana: 0x30B1, + kekatakanahalfwidth: 0xFF79, + kenarmenian: 0x056F, + kesmallkatakana: 0x30F6, + kgreenlandic: 0x0138, + khabengali: 0x0996, + khacyrillic: 0x0445, + khadeva: 0x0916, + khagujarati: 0x0A96, + khagurmukhi: 0x0A16, + khaharabic: 0x062E, + khahfinalarabic: 0xFEA6, + khahinitialarabic: 0xFEA7, + khahmedialarabic: 0xFEA8, + kheicoptic: 0x03E7, + khhadeva: 0x0959, + khhagurmukhi: 0x0A59, + khieukhacirclekorean: 0x3278, + khieukhaparenkorean: 0x3218, + khieukhcirclekorean: 0x326A, + khieukhkorean: 0x314B, + khieukhparenkorean: 0x320A, + khokhaithai: 0x0E02, + khokhonthai: 0x0E05, + khokhuatthai: 0x0E03, + khokhwaithai: 0x0E04, + khomutthai: 0x0E5B, + khook: 0x0199, + khorakhangthai: 0x0E06, + khzsquare: 0x3391, + kihiragana: 0x304D, + kikatakana: 0x30AD, + kikatakanahalfwidth: 0xFF77, + kiroguramusquare: 0x3315, + kiromeetorusquare: 0x3316, + kirosquare: 0x3314, + kiyeokacirclekorean: 0x326E, + kiyeokaparenkorean: 0x320E, + kiyeokcirclekorean: 0x3260, + kiyeokkorean: 0x3131, + kiyeokparenkorean: 0x3200, + kiyeoksioskorean: 0x3133, + kjecyrillic: 0x045C, + klinebelow: 0x1E35, + klsquare: 0x3398, + kmcubedsquare: 0x33A6, + kmonospace: 0xFF4B, + kmsquaredsquare: 0x33A2, + kohiragana: 0x3053, + kohmsquare: 0x33C0, + kokaithai: 0x0E01, + kokatakana: 0x30B3, + kokatakanahalfwidth: 0xFF7A, + kooposquare: 0x331E, + koppacyrillic: 0x0481, + koreanstandardsymbol: 0x327F, + koroniscmb: 0x0343, + kparen: 0x24A6, + kpasquare: 0x33AA, + ksicyrillic: 0x046F, + ktsquare: 0x33CF, + kturned: 0x029E, + kuhiragana: 0x304F, + kukatakana: 0x30AF, + kukatakanahalfwidth: 0xFF78, + kvsquare: 0x33B8, + kwsquare: 0x33BE, + l: 0x006C, + labengali: 0x09B2, + lacute: 0x013A, + ladeva: 0x0932, + lagujarati: 0x0AB2, + lagurmukhi: 0x0A32, + lakkhangyaothai: 0x0E45, + lamaleffinalarabic: 0xFEFC, + lamalefhamzaabovefinalarabic: 0xFEF8, + lamalefhamzaaboveisolatedarabic: 0xFEF7, + lamalefhamzabelowfinalarabic: 0xFEFA, + lamalefhamzabelowisolatedarabic: 0xFEF9, + lamalefisolatedarabic: 0xFEFB, + lamalefmaddaabovefinalarabic: 0xFEF6, + lamalefmaddaaboveisolatedarabic: 0xFEF5, + lamarabic: 0x0644, + lambda: 0x03BB, + lambdastroke: 0x019B, + lamed: 0x05DC, + lameddagesh: 0xFB3C, + lameddageshhebrew: 0xFB3C, + lamedhebrew: 0x05DC, + lamfinalarabic: 0xFEDE, + lamhahinitialarabic: 0xFCCA, + laminitialarabic: 0xFEDF, + lamjeeminitialarabic: 0xFCC9, + lamkhahinitialarabic: 0xFCCB, + lamlamhehisolatedarabic: 0xFDF2, + lammedialarabic: 0xFEE0, + lammeemhahinitialarabic: 0xFD88, + lammeeminitialarabic: 0xFCCC, + largecircle: 0x25EF, + lbar: 0x019A, + lbelt: 0x026C, + lbopomofo: 0x310C, + lcaron: 0x013E, + lcedilla: 0x013C, + lcircle: 0x24DB, + lcircumflexbelow: 0x1E3D, + lcommaaccent: 0x013C, + ldot: 0x0140, + ldotaccent: 0x0140, + ldotbelow: 0x1E37, + ldotbelowmacron: 0x1E39, + leftangleabovecmb: 0x031A, + lefttackbelowcmb: 0x0318, + less: 0x003C, + lessequal: 0x2264, + lessequalorgreater: 0x22DA, + lessmonospace: 0xFF1C, + lessorequivalent: 0x2272, + lessorgreater: 0x2276, + lessoverequal: 0x2266, + lesssmall: 0xFE64, + lezh: 0x026E, + lfblock: 0x258C, + lhookretroflex: 0x026D, + lira: 0x20A4, + liwnarmenian: 0x056C, + lj: 0x01C9, + ljecyrillic: 0x0459, + ll: 0xF6C0, + lladeva: 0x0933, + llagujarati: 0x0AB3, + llinebelow: 0x1E3B, + llladeva: 0x0934, + llvocalicbengali: 0x09E1, + llvocalicdeva: 0x0961, + llvocalicvowelsignbengali: 0x09E3, + llvocalicvowelsigndeva: 0x0963, + lmiddletilde: 0x026B, + lmonospace: 0xFF4C, + lmsquare: 0x33D0, + lochulathai: 0x0E2C, + logicaland: 0x2227, + logicalnot: 0x00AC, + logicalnotreversed: 0x2310, + logicalor: 0x2228, + lolingthai: 0x0E25, + longs: 0x017F, + lowlinecenterline: 0xFE4E, + lowlinecmb: 0x0332, + lowlinedashed: 0xFE4D, + lozenge: 0x25CA, + lparen: 0x24A7, + lslash: 0x0142, + lsquare: 0x2113, + lsuperior: 0xF6EE, + ltshade: 0x2591, + luthai: 0x0E26, + lvocalicbengali: 0x098C, + lvocalicdeva: 0x090C, + lvocalicvowelsignbengali: 0x09E2, + lvocalicvowelsigndeva: 0x0962, + lxsquare: 0x33D3, + m: 0x006D, + mabengali: 0x09AE, + macron: 0x00AF, + macronbelowcmb: 0x0331, + macroncmb: 0x0304, + macronlowmod: 0x02CD, + macronmonospace: 0xFFE3, + macute: 0x1E3F, + madeva: 0x092E, + magujarati: 0x0AAE, + magurmukhi: 0x0A2E, + mahapakhhebrew: 0x05A4, + mahapakhlefthebrew: 0x05A4, + mahiragana: 0x307E, + maichattawalowleftthai: 0xF895, + maichattawalowrightthai: 0xF894, + maichattawathai: 0x0E4B, + maichattawaupperleftthai: 0xF893, + maieklowleftthai: 0xF88C, + maieklowrightthai: 0xF88B, + maiekthai: 0x0E48, + maiekupperleftthai: 0xF88A, + maihanakatleftthai: 0xF884, + maihanakatthai: 0x0E31, + maitaikhuleftthai: 0xF889, + maitaikhuthai: 0x0E47, + maitholowleftthai: 0xF88F, + maitholowrightthai: 0xF88E, + maithothai: 0x0E49, + maithoupperleftthai: 0xF88D, + maitrilowleftthai: 0xF892, + maitrilowrightthai: 0xF891, + maitrithai: 0x0E4A, + maitriupperleftthai: 0xF890, + maiyamokthai: 0x0E46, + makatakana: 0x30DE, + makatakanahalfwidth: 0xFF8F, + male: 0x2642, + mansyonsquare: 0x3347, + maqafhebrew: 0x05BE, + mars: 0x2642, + masoracirclehebrew: 0x05AF, + masquare: 0x3383, + mbopomofo: 0x3107, + mbsquare: 0x33D4, + mcircle: 0x24DC, + mcubedsquare: 0x33A5, + mdotaccent: 0x1E41, + mdotbelow: 0x1E43, + meemarabic: 0x0645, + meemfinalarabic: 0xFEE2, + meeminitialarabic: 0xFEE3, + meemmedialarabic: 0xFEE4, + meemmeeminitialarabic: 0xFCD1, + meemmeemisolatedarabic: 0xFC48, + meetorusquare: 0x334D, + mehiragana: 0x3081, + meizierasquare: 0x337E, + mekatakana: 0x30E1, + mekatakanahalfwidth: 0xFF92, + mem: 0x05DE, + memdagesh: 0xFB3E, + memdageshhebrew: 0xFB3E, + memhebrew: 0x05DE, + menarmenian: 0x0574, + merkhahebrew: 0x05A5, + merkhakefulahebrew: 0x05A6, + merkhakefulalefthebrew: 0x05A6, + merkhalefthebrew: 0x05A5, + mhook: 0x0271, + mhzsquare: 0x3392, + middledotkatakanahalfwidth: 0xFF65, + middot: 0x00B7, + mieumacirclekorean: 0x3272, + mieumaparenkorean: 0x3212, + mieumcirclekorean: 0x3264, + mieumkorean: 0x3141, + mieumpansioskorean: 0x3170, + mieumparenkorean: 0x3204, + mieumpieupkorean: 0x316E, + mieumsioskorean: 0x316F, + mihiragana: 0x307F, + mikatakana: 0x30DF, + mikatakanahalfwidth: 0xFF90, + minus: 0x2212, + minusbelowcmb: 0x0320, + minuscircle: 0x2296, + minusmod: 0x02D7, + minusplus: 0x2213, + minute: 0x2032, + miribaarusquare: 0x334A, + mirisquare: 0x3349, + mlonglegturned: 0x0270, + mlsquare: 0x3396, + mmcubedsquare: 0x33A3, + mmonospace: 0xFF4D, + mmsquaredsquare: 0x339F, + mohiragana: 0x3082, + mohmsquare: 0x33C1, + mokatakana: 0x30E2, + mokatakanahalfwidth: 0xFF93, + molsquare: 0x33D6, + momathai: 0x0E21, + moverssquare: 0x33A7, + moverssquaredsquare: 0x33A8, + mparen: 0x24A8, + mpasquare: 0x33AB, + mssquare: 0x33B3, + msuperior: 0xF6EF, + mturned: 0x026F, + mu: 0x00B5, + mu1: 0x00B5, + muasquare: 0x3382, + muchgreater: 0x226B, + muchless: 0x226A, + mufsquare: 0x338C, + mugreek: 0x03BC, + mugsquare: 0x338D, + muhiragana: 0x3080, + mukatakana: 0x30E0, + mukatakanahalfwidth: 0xFF91, + mulsquare: 0x3395, + multiply: 0x00D7, + mumsquare: 0x339B, + munahhebrew: 0x05A3, + munahlefthebrew: 0x05A3, + musicalnote: 0x266A, + musicalnotedbl: 0x266B, + musicflatsign: 0x266D, + musicsharpsign: 0x266F, + mussquare: 0x33B2, + muvsquare: 0x33B6, + muwsquare: 0x33BC, + mvmegasquare: 0x33B9, + mvsquare: 0x33B7, + mwmegasquare: 0x33BF, + mwsquare: 0x33BD, + n: 0x006E, + nabengali: 0x09A8, + nabla: 0x2207, + nacute: 0x0144, + nadeva: 0x0928, + nagujarati: 0x0AA8, + nagurmukhi: 0x0A28, + nahiragana: 0x306A, + nakatakana: 0x30CA, + nakatakanahalfwidth: 0xFF85, + napostrophe: 0x0149, + nasquare: 0x3381, + nbopomofo: 0x310B, + nbspace: 0x00A0, + ncaron: 0x0148, + ncedilla: 0x0146, + ncircle: 0x24DD, + ncircumflexbelow: 0x1E4B, + ncommaaccent: 0x0146, + ndotaccent: 0x1E45, + ndotbelow: 0x1E47, + nehiragana: 0x306D, + nekatakana: 0x30CD, + nekatakanahalfwidth: 0xFF88, + newsheqelsign: 0x20AA, + nfsquare: 0x338B, + ngabengali: 0x0999, + ngadeva: 0x0919, + ngagujarati: 0x0A99, + ngagurmukhi: 0x0A19, + ngonguthai: 0x0E07, + nhiragana: 0x3093, + nhookleft: 0x0272, + nhookretroflex: 0x0273, + nieunacirclekorean: 0x326F, + nieunaparenkorean: 0x320F, + nieuncieuckorean: 0x3135, + nieuncirclekorean: 0x3261, + nieunhieuhkorean: 0x3136, + nieunkorean: 0x3134, + nieunpansioskorean: 0x3168, + nieunparenkorean: 0x3201, + nieunsioskorean: 0x3167, + nieuntikeutkorean: 0x3166, + nihiragana: 0x306B, + nikatakana: 0x30CB, + nikatakanahalfwidth: 0xFF86, + nikhahitleftthai: 0xF899, + nikhahitthai: 0x0E4D, + nine: 0x0039, + ninearabic: 0x0669, + ninebengali: 0x09EF, + ninecircle: 0x2468, + ninecircleinversesansserif: 0x2792, + ninedeva: 0x096F, + ninegujarati: 0x0AEF, + ninegurmukhi: 0x0A6F, + ninehackarabic: 0x0669, + ninehangzhou: 0x3029, + nineideographicparen: 0x3228, + nineinferior: 0x2089, + ninemonospace: 0xFF19, + nineoldstyle: 0xF739, + nineparen: 0x247C, + nineperiod: 0x2490, + ninepersian: 0x06F9, + nineroman: 0x2178, + ninesuperior: 0x2079, + nineteencircle: 0x2472, + nineteenparen: 0x2486, + nineteenperiod: 0x249A, + ninethai: 0x0E59, + nj: 0x01CC, + njecyrillic: 0x045A, + nkatakana: 0x30F3, + nkatakanahalfwidth: 0xFF9D, + nlegrightlong: 0x019E, + nlinebelow: 0x1E49, + nmonospace: 0xFF4E, + nmsquare: 0x339A, + nnabengali: 0x09A3, + nnadeva: 0x0923, + nnagujarati: 0x0AA3, + nnagurmukhi: 0x0A23, + nnnadeva: 0x0929, + nohiragana: 0x306E, + nokatakana: 0x30CE, + nokatakanahalfwidth: 0xFF89, + nonbreakingspace: 0x00A0, + nonenthai: 0x0E13, + nonuthai: 0x0E19, + noonarabic: 0x0646, + noonfinalarabic: 0xFEE6, + noonghunnaarabic: 0x06BA, + noonghunnafinalarabic: 0xFB9F, + nooninitialarabic: 0xFEE7, + noonjeeminitialarabic: 0xFCD2, + noonjeemisolatedarabic: 0xFC4B, + noonmedialarabic: 0xFEE8, + noonmeeminitialarabic: 0xFCD5, + noonmeemisolatedarabic: 0xFC4E, + noonnoonfinalarabic: 0xFC8D, + notcontains: 0x220C, + notelement: 0x2209, + notelementof: 0x2209, + notequal: 0x2260, + notgreater: 0x226F, + notgreaternorequal: 0x2271, + notgreaternorless: 0x2279, + notidentical: 0x2262, + notless: 0x226E, + notlessnorequal: 0x2270, + notparallel: 0x2226, + notprecedes: 0x2280, + notsubset: 0x2284, + notsucceeds: 0x2281, + notsuperset: 0x2285, + nowarmenian: 0x0576, + nparen: 0x24A9, + nssquare: 0x33B1, + nsuperior: 0x207F, + ntilde: 0x00F1, + nu: 0x03BD, + nuhiragana: 0x306C, + nukatakana: 0x30CC, + nukatakanahalfwidth: 0xFF87, + nuktabengali: 0x09BC, + nuktadeva: 0x093C, + nuktagujarati: 0x0ABC, + nuktagurmukhi: 0x0A3C, + numbersign: 0x0023, + numbersignmonospace: 0xFF03, + numbersignsmall: 0xFE5F, + numeralsigngreek: 0x0374, + numeralsignlowergreek: 0x0375, + numero: 0x2116, + nun: 0x05E0, + nundagesh: 0xFB40, + nundageshhebrew: 0xFB40, + nunhebrew: 0x05E0, + nvsquare: 0x33B5, + nwsquare: 0x33BB, + nyabengali: 0x099E, + nyadeva: 0x091E, + nyagujarati: 0x0A9E, + nyagurmukhi: 0x0A1E, + o: 0x006F, + oacute: 0x00F3, + oangthai: 0x0E2D, + obarred: 0x0275, + obarredcyrillic: 0x04E9, + obarreddieresiscyrillic: 0x04EB, + obengali: 0x0993, + obopomofo: 0x311B, + obreve: 0x014F, + ocandradeva: 0x0911, + ocandragujarati: 0x0A91, + ocandravowelsigndeva: 0x0949, + ocandravowelsigngujarati: 0x0AC9, + ocaron: 0x01D2, + ocircle: 0x24DE, + ocircumflex: 0x00F4, + ocircumflexacute: 0x1ED1, + ocircumflexdotbelow: 0x1ED9, + ocircumflexgrave: 0x1ED3, + ocircumflexhookabove: 0x1ED5, + ocircumflextilde: 0x1ED7, + ocyrillic: 0x043E, + odblacute: 0x0151, + odblgrave: 0x020D, + odeva: 0x0913, + odieresis: 0x00F6, + odieresiscyrillic: 0x04E7, + odotbelow: 0x1ECD, + oe: 0x0153, + oekorean: 0x315A, + ogonek: 0x02DB, + ogonekcmb: 0x0328, + ograve: 0x00F2, + ogujarati: 0x0A93, + oharmenian: 0x0585, + ohiragana: 0x304A, + ohookabove: 0x1ECF, + ohorn: 0x01A1, + ohornacute: 0x1EDB, + ohorndotbelow: 0x1EE3, + ohorngrave: 0x1EDD, + ohornhookabove: 0x1EDF, + ohorntilde: 0x1EE1, + ohungarumlaut: 0x0151, + oi: 0x01A3, + oinvertedbreve: 0x020F, + okatakana: 0x30AA, + okatakanahalfwidth: 0xFF75, + okorean: 0x3157, + olehebrew: 0x05AB, + omacron: 0x014D, + omacronacute: 0x1E53, + omacrongrave: 0x1E51, + omdeva: 0x0950, + omega: 0x03C9, + omega1: 0x03D6, + omegacyrillic: 0x0461, + omegalatinclosed: 0x0277, + omegaroundcyrillic: 0x047B, + omegatitlocyrillic: 0x047D, + omegatonos: 0x03CE, + omgujarati: 0x0AD0, + omicron: 0x03BF, + omicrontonos: 0x03CC, + omonospace: 0xFF4F, + one: 0x0031, + onearabic: 0x0661, + onebengali: 0x09E7, + onecircle: 0x2460, + onecircleinversesansserif: 0x278A, + onedeva: 0x0967, + onedotenleader: 0x2024, + oneeighth: 0x215B, + onefitted: 0xF6DC, + onegujarati: 0x0AE7, + onegurmukhi: 0x0A67, + onehackarabic: 0x0661, + onehalf: 0x00BD, + onehangzhou: 0x3021, + oneideographicparen: 0x3220, + oneinferior: 0x2081, + onemonospace: 0xFF11, + onenumeratorbengali: 0x09F4, + oneoldstyle: 0xF731, + oneparen: 0x2474, + oneperiod: 0x2488, + onepersian: 0x06F1, + onequarter: 0x00BC, + oneroman: 0x2170, + onesuperior: 0x00B9, + onethai: 0x0E51, + onethird: 0x2153, + oogonek: 0x01EB, + oogonekmacron: 0x01ED, + oogurmukhi: 0x0A13, + oomatragurmukhi: 0x0A4B, + oopen: 0x0254, + oparen: 0x24AA, + openbullet: 0x25E6, + option: 0x2325, + ordfeminine: 0x00AA, + ordmasculine: 0x00BA, + orthogonal: 0x221F, + oshortdeva: 0x0912, + oshortvowelsigndeva: 0x094A, + oslash: 0x00F8, + oslashacute: 0x01FF, + osmallhiragana: 0x3049, + osmallkatakana: 0x30A9, + osmallkatakanahalfwidth: 0xFF6B, + ostrokeacute: 0x01FF, + osuperior: 0xF6F0, + otcyrillic: 0x047F, + otilde: 0x00F5, + otildeacute: 0x1E4D, + otildedieresis: 0x1E4F, + oubopomofo: 0x3121, + overline: 0x203E, + overlinecenterline: 0xFE4A, + overlinecmb: 0x0305, + overlinedashed: 0xFE49, + overlinedblwavy: 0xFE4C, + overlinewavy: 0xFE4B, + overscore: 0x00AF, + ovowelsignbengali: 0x09CB, + ovowelsigndeva: 0x094B, + ovowelsigngujarati: 0x0ACB, + p: 0x0070, + paampssquare: 0x3380, + paasentosquare: 0x332B, + pabengali: 0x09AA, + pacute: 0x1E55, + padeva: 0x092A, + pagedown: 0x21DF, + pageup: 0x21DE, + pagujarati: 0x0AAA, + pagurmukhi: 0x0A2A, + pahiragana: 0x3071, + paiyannoithai: 0x0E2F, + pakatakana: 0x30D1, + palatalizationcyrilliccmb: 0x0484, + palochkacyrillic: 0x04C0, + pansioskorean: 0x317F, + paragraph: 0x00B6, + parallel: 0x2225, + parenleft: 0x0028, + parenleftaltonearabic: 0xFD3E, + parenleftbt: 0xF8ED, + parenleftex: 0xF8EC, + parenleftinferior: 0x208D, + parenleftmonospace: 0xFF08, + parenleftsmall: 0xFE59, + parenleftsuperior: 0x207D, + parenlefttp: 0xF8EB, + parenleftvertical: 0xFE35, + parenright: 0x0029, + parenrightaltonearabic: 0xFD3F, + parenrightbt: 0xF8F8, + parenrightex: 0xF8F7, + parenrightinferior: 0x208E, + parenrightmonospace: 0xFF09, + parenrightsmall: 0xFE5A, + parenrightsuperior: 0x207E, + parenrighttp: 0xF8F6, + parenrightvertical: 0xFE36, + partialdiff: 0x2202, + paseqhebrew: 0x05C0, + pashtahebrew: 0x0599, + pasquare: 0x33A9, + patah: 0x05B7, + patah11: 0x05B7, + patah1d: 0x05B7, + patah2a: 0x05B7, + patahhebrew: 0x05B7, + patahnarrowhebrew: 0x05B7, + patahquarterhebrew: 0x05B7, + patahwidehebrew: 0x05B7, + pazerhebrew: 0x05A1, + pbopomofo: 0x3106, + pcircle: 0x24DF, + pdotaccent: 0x1E57, + pe: 0x05E4, + pecyrillic: 0x043F, + pedagesh: 0xFB44, + pedageshhebrew: 0xFB44, + peezisquare: 0x333B, + pefinaldageshhebrew: 0xFB43, + peharabic: 0x067E, + peharmenian: 0x057A, + pehebrew: 0x05E4, + pehfinalarabic: 0xFB57, + pehinitialarabic: 0xFB58, + pehiragana: 0x307A, + pehmedialarabic: 0xFB59, + pekatakana: 0x30DA, + pemiddlehookcyrillic: 0x04A7, + perafehebrew: 0xFB4E, + percent: 0x0025, + percentarabic: 0x066A, + percentmonospace: 0xFF05, + percentsmall: 0xFE6A, + period: 0x002E, + periodarmenian: 0x0589, + periodcentered: 0x00B7, + periodhalfwidth: 0xFF61, + periodinferior: 0xF6E7, + periodmonospace: 0xFF0E, + periodsmall: 0xFE52, + periodsuperior: 0xF6E8, + perispomenigreekcmb: 0x0342, + perpendicular: 0x22A5, + perthousand: 0x2030, + peseta: 0x20A7, + pfsquare: 0x338A, + phabengali: 0x09AB, + phadeva: 0x092B, + phagujarati: 0x0AAB, + phagurmukhi: 0x0A2B, + phi: 0x03C6, + phi1: 0x03D5, + phieuphacirclekorean: 0x327A, + phieuphaparenkorean: 0x321A, + phieuphcirclekorean: 0x326C, + phieuphkorean: 0x314D, + phieuphparenkorean: 0x320C, + philatin: 0x0278, + phinthuthai: 0x0E3A, + phisymbolgreek: 0x03D5, + phook: 0x01A5, + phophanthai: 0x0E1E, + phophungthai: 0x0E1C, + phosamphaothai: 0x0E20, + pi: 0x03C0, + pieupacirclekorean: 0x3273, + pieupaparenkorean: 0x3213, + pieupcieuckorean: 0x3176, + pieupcirclekorean: 0x3265, + pieupkiyeokkorean: 0x3172, + pieupkorean: 0x3142, + pieupparenkorean: 0x3205, + pieupsioskiyeokkorean: 0x3174, + pieupsioskorean: 0x3144, + pieupsiostikeutkorean: 0x3175, + pieupthieuthkorean: 0x3177, + pieuptikeutkorean: 0x3173, + pihiragana: 0x3074, + pikatakana: 0x30D4, + pisymbolgreek: 0x03D6, + piwrarmenian: 0x0583, + plus: 0x002B, + plusbelowcmb: 0x031F, + pluscircle: 0x2295, + plusminus: 0x00B1, + plusmod: 0x02D6, + plusmonospace: 0xFF0B, + plussmall: 0xFE62, + plussuperior: 0x207A, + pmonospace: 0xFF50, + pmsquare: 0x33D8, + pohiragana: 0x307D, + pointingindexdownwhite: 0x261F, + pointingindexleftwhite: 0x261C, + pointingindexrightwhite: 0x261E, + pointingindexupwhite: 0x261D, + pokatakana: 0x30DD, + poplathai: 0x0E1B, + postalmark: 0x3012, + postalmarkface: 0x3020, + pparen: 0x24AB, + precedes: 0x227A, + prescription: 0x211E, + primemod: 0x02B9, + primereversed: 0x2035, + product: 0x220F, + projective: 0x2305, + prolongedkana: 0x30FC, + propellor: 0x2318, + propersubset: 0x2282, + propersuperset: 0x2283, + proportion: 0x2237, + proportional: 0x221D, + psi: 0x03C8, + psicyrillic: 0x0471, + psilipneumatacyrilliccmb: 0x0486, + pssquare: 0x33B0, + puhiragana: 0x3077, + pukatakana: 0x30D7, + pvsquare: 0x33B4, + pwsquare: 0x33BA, + q: 0x0071, + qadeva: 0x0958, + qadmahebrew: 0x05A8, + qafarabic: 0x0642, + qaffinalarabic: 0xFED6, + qafinitialarabic: 0xFED7, + qafmedialarabic: 0xFED8, + qamats: 0x05B8, + qamats10: 0x05B8, + qamats1a: 0x05B8, + qamats1c: 0x05B8, + qamats27: 0x05B8, + qamats29: 0x05B8, + qamats33: 0x05B8, + qamatsde: 0x05B8, + qamatshebrew: 0x05B8, + qamatsnarrowhebrew: 0x05B8, + qamatsqatanhebrew: 0x05B8, + qamatsqatannarrowhebrew: 0x05B8, + qamatsqatanquarterhebrew: 0x05B8, + qamatsqatanwidehebrew: 0x05B8, + qamatsquarterhebrew: 0x05B8, + qamatswidehebrew: 0x05B8, + qarneyparahebrew: 0x059F, + qbopomofo: 0x3111, + qcircle: 0x24E0, + qhook: 0x02A0, + qmonospace: 0xFF51, + qof: 0x05E7, + qofdagesh: 0xFB47, + qofdageshhebrew: 0xFB47, + qofhebrew: 0x05E7, + qparen: 0x24AC, + quarternote: 0x2669, + qubuts: 0x05BB, + qubuts18: 0x05BB, + qubuts25: 0x05BB, + qubuts31: 0x05BB, + qubutshebrew: 0x05BB, + qubutsnarrowhebrew: 0x05BB, + qubutsquarterhebrew: 0x05BB, + qubutswidehebrew: 0x05BB, + question: 0x003F, + questionarabic: 0x061F, + questionarmenian: 0x055E, + questiondown: 0x00BF, + questiondownsmall: 0xF7BF, + questiongreek: 0x037E, + questionmonospace: 0xFF1F, + questionsmall: 0xF73F, + quotedbl: 0x0022, + quotedblbase: 0x201E, + quotedblleft: 0x201C, + quotedblmonospace: 0xFF02, + quotedblprime: 0x301E, + quotedblprimereversed: 0x301D, + quotedblright: 0x201D, + quoteleft: 0x2018, + quoteleftreversed: 0x201B, + quotereversed: 0x201B, + quoteright: 0x2019, + quoterightn: 0x0149, + quotesinglbase: 0x201A, + quotesingle: 0x0027, + quotesinglemonospace: 0xFF07, + r: 0x0072, + raarmenian: 0x057C, + rabengali: 0x09B0, + racute: 0x0155, + radeva: 0x0930, + radical: 0x221A, + radicalex: 0xF8E5, + radoverssquare: 0x33AE, + radoverssquaredsquare: 0x33AF, + radsquare: 0x33AD, + rafe: 0x05BF, + rafehebrew: 0x05BF, + ragujarati: 0x0AB0, + ragurmukhi: 0x0A30, + rahiragana: 0x3089, + rakatakana: 0x30E9, + rakatakanahalfwidth: 0xFF97, + ralowerdiagonalbengali: 0x09F1, + ramiddlediagonalbengali: 0x09F0, + ramshorn: 0x0264, + ratio: 0x2236, + rbopomofo: 0x3116, + rcaron: 0x0159, + rcedilla: 0x0157, + rcircle: 0x24E1, + rcommaaccent: 0x0157, + rdblgrave: 0x0211, + rdotaccent: 0x1E59, + rdotbelow: 0x1E5B, + rdotbelowmacron: 0x1E5D, + referencemark: 0x203B, + reflexsubset: 0x2286, + reflexsuperset: 0x2287, + registered: 0x00AE, + registersans: 0xF8E8, + registerserif: 0xF6DA, + reharabic: 0x0631, + reharmenian: 0x0580, + rehfinalarabic: 0xFEAE, + rehiragana: 0x308C, + rekatakana: 0x30EC, + rekatakanahalfwidth: 0xFF9A, + resh: 0x05E8, + reshdageshhebrew: 0xFB48, + reshhebrew: 0x05E8, + reversedtilde: 0x223D, + reviahebrew: 0x0597, + reviamugrashhebrew: 0x0597, + revlogicalnot: 0x2310, + rfishhook: 0x027E, + rfishhookreversed: 0x027F, + rhabengali: 0x09DD, + rhadeva: 0x095D, + rho: 0x03C1, + rhook: 0x027D, + rhookturned: 0x027B, + rhookturnedsuperior: 0x02B5, + rhosymbolgreek: 0x03F1, + rhotichookmod: 0x02DE, + rieulacirclekorean: 0x3271, + rieulaparenkorean: 0x3211, + rieulcirclekorean: 0x3263, + rieulhieuhkorean: 0x3140, + rieulkiyeokkorean: 0x313A, + rieulkiyeoksioskorean: 0x3169, + rieulkorean: 0x3139, + rieulmieumkorean: 0x313B, + rieulpansioskorean: 0x316C, + rieulparenkorean: 0x3203, + rieulphieuphkorean: 0x313F, + rieulpieupkorean: 0x313C, + rieulpieupsioskorean: 0x316B, + rieulsioskorean: 0x313D, + rieulthieuthkorean: 0x313E, + rieultikeutkorean: 0x316A, + rieulyeorinhieuhkorean: 0x316D, + rightangle: 0x221F, + righttackbelowcmb: 0x0319, + righttriangle: 0x22BF, + rihiragana: 0x308A, + rikatakana: 0x30EA, + rikatakanahalfwidth: 0xFF98, + ring: 0x02DA, + ringbelowcmb: 0x0325, + ringcmb: 0x030A, + ringhalfleft: 0x02BF, + ringhalfleftarmenian: 0x0559, + ringhalfleftbelowcmb: 0x031C, + ringhalfleftcentered: 0x02D3, + ringhalfright: 0x02BE, + ringhalfrightbelowcmb: 0x0339, + ringhalfrightcentered: 0x02D2, + rinvertedbreve: 0x0213, + rittorusquare: 0x3351, + rlinebelow: 0x1E5F, + rlongleg: 0x027C, + rlonglegturned: 0x027A, + rmonospace: 0xFF52, + rohiragana: 0x308D, + rokatakana: 0x30ED, + rokatakanahalfwidth: 0xFF9B, + roruathai: 0x0E23, + rparen: 0x24AD, + rrabengali: 0x09DC, + rradeva: 0x0931, + rragurmukhi: 0x0A5C, + rreharabic: 0x0691, + rrehfinalarabic: 0xFB8D, + rrvocalicbengali: 0x09E0, + rrvocalicdeva: 0x0960, + rrvocalicgujarati: 0x0AE0, + rrvocalicvowelsignbengali: 0x09C4, + rrvocalicvowelsigndeva: 0x0944, + rrvocalicvowelsigngujarati: 0x0AC4, + rsuperior: 0xF6F1, + rtblock: 0x2590, + rturned: 0x0279, + rturnedsuperior: 0x02B4, + ruhiragana: 0x308B, + rukatakana: 0x30EB, + rukatakanahalfwidth: 0xFF99, + rupeemarkbengali: 0x09F2, + rupeesignbengali: 0x09F3, + rupiah: 0xF6DD, + ruthai: 0x0E24, + rvocalicbengali: 0x098B, + rvocalicdeva: 0x090B, + rvocalicgujarati: 0x0A8B, + rvocalicvowelsignbengali: 0x09C3, + rvocalicvowelsigndeva: 0x0943, + rvocalicvowelsigngujarati: 0x0AC3, + s: 0x0073, + sabengali: 0x09B8, + sacute: 0x015B, + sacutedotaccent: 0x1E65, + sadarabic: 0x0635, + sadeva: 0x0938, + sadfinalarabic: 0xFEBA, + sadinitialarabic: 0xFEBB, + sadmedialarabic: 0xFEBC, + sagujarati: 0x0AB8, + sagurmukhi: 0x0A38, + sahiragana: 0x3055, + sakatakana: 0x30B5, + sakatakanahalfwidth: 0xFF7B, + sallallahoualayhewasallamarabic: 0xFDFA, + samekh: 0x05E1, + samekhdagesh: 0xFB41, + samekhdageshhebrew: 0xFB41, + samekhhebrew: 0x05E1, + saraaathai: 0x0E32, + saraaethai: 0x0E41, + saraaimaimalaithai: 0x0E44, + saraaimaimuanthai: 0x0E43, + saraamthai: 0x0E33, + saraathai: 0x0E30, + saraethai: 0x0E40, + saraiileftthai: 0xF886, + saraiithai: 0x0E35, + saraileftthai: 0xF885, + saraithai: 0x0E34, + saraothai: 0x0E42, + saraueeleftthai: 0xF888, + saraueethai: 0x0E37, + saraueleftthai: 0xF887, + sarauethai: 0x0E36, + sarauthai: 0x0E38, + sarauuthai: 0x0E39, + sbopomofo: 0x3119, + scaron: 0x0161, + scarondotaccent: 0x1E67, + scedilla: 0x015F, + schwa: 0x0259, + schwacyrillic: 0x04D9, + schwadieresiscyrillic: 0x04DB, + schwahook: 0x025A, + scircle: 0x24E2, + scircumflex: 0x015D, + scommaaccent: 0x0219, + sdotaccent: 0x1E61, + sdotbelow: 0x1E63, + sdotbelowdotaccent: 0x1E69, + seagullbelowcmb: 0x033C, + second: 0x2033, + secondtonechinese: 0x02CA, + section: 0x00A7, + seenarabic: 0x0633, + seenfinalarabic: 0xFEB2, + seeninitialarabic: 0xFEB3, + seenmedialarabic: 0xFEB4, + segol: 0x05B6, + segol13: 0x05B6, + segol1f: 0x05B6, + segol2c: 0x05B6, + segolhebrew: 0x05B6, + segolnarrowhebrew: 0x05B6, + segolquarterhebrew: 0x05B6, + segoltahebrew: 0x0592, + segolwidehebrew: 0x05B6, + seharmenian: 0x057D, + sehiragana: 0x305B, + sekatakana: 0x30BB, + sekatakanahalfwidth: 0xFF7E, + semicolon: 0x003B, + semicolonarabic: 0x061B, + semicolonmonospace: 0xFF1B, + semicolonsmall: 0xFE54, + semivoicedmarkkana: 0x309C, + semivoicedmarkkanahalfwidth: 0xFF9F, + sentisquare: 0x3322, + sentosquare: 0x3323, + seven: 0x0037, + sevenarabic: 0x0667, + sevenbengali: 0x09ED, + sevencircle: 0x2466, + sevencircleinversesansserif: 0x2790, + sevendeva: 0x096D, + seveneighths: 0x215E, + sevengujarati: 0x0AED, + sevengurmukhi: 0x0A6D, + sevenhackarabic: 0x0667, + sevenhangzhou: 0x3027, + sevenideographicparen: 0x3226, + seveninferior: 0x2087, + sevenmonospace: 0xFF17, + sevenoldstyle: 0xF737, + sevenparen: 0x247A, + sevenperiod: 0x248E, + sevenpersian: 0x06F7, + sevenroman: 0x2176, + sevensuperior: 0x2077, + seventeencircle: 0x2470, + seventeenparen: 0x2484, + seventeenperiod: 0x2498, + seventhai: 0x0E57, + sfthyphen: 0x00AD, + shaarmenian: 0x0577, + shabengali: 0x09B6, + shacyrillic: 0x0448, + shaddaarabic: 0x0651, + shaddadammaarabic: 0xFC61, + shaddadammatanarabic: 0xFC5E, + shaddafathaarabic: 0xFC60, + shaddakasraarabic: 0xFC62, + shaddakasratanarabic: 0xFC5F, + shade: 0x2592, + shadedark: 0x2593, + shadelight: 0x2591, + shademedium: 0x2592, + shadeva: 0x0936, + shagujarati: 0x0AB6, + shagurmukhi: 0x0A36, + shalshelethebrew: 0x0593, + shbopomofo: 0x3115, + shchacyrillic: 0x0449, + sheenarabic: 0x0634, + sheenfinalarabic: 0xFEB6, + sheeninitialarabic: 0xFEB7, + sheenmedialarabic: 0xFEB8, + sheicoptic: 0x03E3, + sheqel: 0x20AA, + sheqelhebrew: 0x20AA, + sheva: 0x05B0, + sheva115: 0x05B0, + sheva15: 0x05B0, + sheva22: 0x05B0, + sheva2e: 0x05B0, + shevahebrew: 0x05B0, + shevanarrowhebrew: 0x05B0, + shevaquarterhebrew: 0x05B0, + shevawidehebrew: 0x05B0, + shhacyrillic: 0x04BB, + shimacoptic: 0x03ED, + shin: 0x05E9, + shindagesh: 0xFB49, + shindageshhebrew: 0xFB49, + shindageshshindot: 0xFB2C, + shindageshshindothebrew: 0xFB2C, + shindageshsindot: 0xFB2D, + shindageshsindothebrew: 0xFB2D, + shindothebrew: 0x05C1, + shinhebrew: 0x05E9, + shinshindot: 0xFB2A, + shinshindothebrew: 0xFB2A, + shinsindot: 0xFB2B, + shinsindothebrew: 0xFB2B, + shook: 0x0282, + sigma: 0x03C3, + sigma1: 0x03C2, + sigmafinal: 0x03C2, + sigmalunatesymbolgreek: 0x03F2, + sihiragana: 0x3057, + sikatakana: 0x30B7, + sikatakanahalfwidth: 0xFF7C, + siluqhebrew: 0x05BD, + siluqlefthebrew: 0x05BD, + similar: 0x223C, + sindothebrew: 0x05C2, + siosacirclekorean: 0x3274, + siosaparenkorean: 0x3214, + sioscieuckorean: 0x317E, + sioscirclekorean: 0x3266, + sioskiyeokkorean: 0x317A, + sioskorean: 0x3145, + siosnieunkorean: 0x317B, + siosparenkorean: 0x3206, + siospieupkorean: 0x317D, + siostikeutkorean: 0x317C, + six: 0x0036, + sixarabic: 0x0666, + sixbengali: 0x09EC, + sixcircle: 0x2465, + sixcircleinversesansserif: 0x278F, + sixdeva: 0x096C, + sixgujarati: 0x0AEC, + sixgurmukhi: 0x0A6C, + sixhackarabic: 0x0666, + sixhangzhou: 0x3026, + sixideographicparen: 0x3225, + sixinferior: 0x2086, + sixmonospace: 0xFF16, + sixoldstyle: 0xF736, + sixparen: 0x2479, + sixperiod: 0x248D, + sixpersian: 0x06F6, + sixroman: 0x2175, + sixsuperior: 0x2076, + sixteencircle: 0x246F, + sixteencurrencydenominatorbengali: 0x09F9, + sixteenparen: 0x2483, + sixteenperiod: 0x2497, + sixthai: 0x0E56, + slash: 0x002F, + slashmonospace: 0xFF0F, + slong: 0x017F, + slongdotaccent: 0x1E9B, + smileface: 0x263A, + smonospace: 0xFF53, + sofpasuqhebrew: 0x05C3, + softhyphen: 0x00AD, + softsigncyrillic: 0x044C, + sohiragana: 0x305D, + sokatakana: 0x30BD, + sokatakanahalfwidth: 0xFF7F, + soliduslongoverlaycmb: 0x0338, + solidusshortoverlaycmb: 0x0337, + sorusithai: 0x0E29, + sosalathai: 0x0E28, + sosothai: 0x0E0B, + sosuathai: 0x0E2A, + space: 0x0020, + spacehackarabic: 0x0020, + spade: 0x2660, + spadesuitblack: 0x2660, + spadesuitwhite: 0x2664, + sparen: 0x24AE, + squarebelowcmb: 0x033B, + squarecc: 0x33C4, + squarecm: 0x339D, + squarediagonalcrosshatchfill: 0x25A9, + squarehorizontalfill: 0x25A4, + squarekg: 0x338F, + squarekm: 0x339E, + squarekmcapital: 0x33CE, + squareln: 0x33D1, + squarelog: 0x33D2, + squaremg: 0x338E, + squaremil: 0x33D5, + squaremm: 0x339C, + squaremsquared: 0x33A1, + squareorthogonalcrosshatchfill: 0x25A6, + squareupperlefttolowerrightfill: 0x25A7, + squareupperrighttolowerleftfill: 0x25A8, + squareverticalfill: 0x25A5, + squarewhitewithsmallblack: 0x25A3, + srsquare: 0x33DB, + ssabengali: 0x09B7, + ssadeva: 0x0937, + ssagujarati: 0x0AB7, + ssangcieuckorean: 0x3149, + ssanghieuhkorean: 0x3185, + ssangieungkorean: 0x3180, + ssangkiyeokkorean: 0x3132, + ssangnieunkorean: 0x3165, + ssangpieupkorean: 0x3143, + ssangsioskorean: 0x3146, + ssangtikeutkorean: 0x3138, + ssuperior: 0xF6F2, + sterling: 0x00A3, + sterlingmonospace: 0xFFE1, + strokelongoverlaycmb: 0x0336, + strokeshortoverlaycmb: 0x0335, + subset: 0x2282, + subsetnotequal: 0x228A, + subsetorequal: 0x2286, + succeeds: 0x227B, + suchthat: 0x220B, + suhiragana: 0x3059, + sukatakana: 0x30B9, + sukatakanahalfwidth: 0xFF7D, + sukunarabic: 0x0652, + summation: 0x2211, + sun: 0x263C, + superset: 0x2283, + supersetnotequal: 0x228B, + supersetorequal: 0x2287, + svsquare: 0x33DC, + syouwaerasquare: 0x337C, + t: 0x0074, + tabengali: 0x09A4, + tackdown: 0x22A4, + tackleft: 0x22A3, + tadeva: 0x0924, + tagujarati: 0x0AA4, + tagurmukhi: 0x0A24, + taharabic: 0x0637, + tahfinalarabic: 0xFEC2, + tahinitialarabic: 0xFEC3, + tahiragana: 0x305F, + tahmedialarabic: 0xFEC4, + taisyouerasquare: 0x337D, + takatakana: 0x30BF, + takatakanahalfwidth: 0xFF80, + tatweelarabic: 0x0640, + tau: 0x03C4, + tav: 0x05EA, + tavdages: 0xFB4A, + tavdagesh: 0xFB4A, + tavdageshhebrew: 0xFB4A, + tavhebrew: 0x05EA, + tbar: 0x0167, + tbopomofo: 0x310A, + tcaron: 0x0165, + tccurl: 0x02A8, + tcedilla: 0x0163, + tcheharabic: 0x0686, + tchehfinalarabic: 0xFB7B, + tchehinitialarabic: 0xFB7C, + tchehmedialarabic: 0xFB7D, + tcircle: 0x24E3, + tcircumflexbelow: 0x1E71, + tcommaaccent: 0x0163, + tdieresis: 0x1E97, + tdotaccent: 0x1E6B, + tdotbelow: 0x1E6D, + tecyrillic: 0x0442, + tedescendercyrillic: 0x04AD, + teharabic: 0x062A, + tehfinalarabic: 0xFE96, + tehhahinitialarabic: 0xFCA2, + tehhahisolatedarabic: 0xFC0C, + tehinitialarabic: 0xFE97, + tehiragana: 0x3066, + tehjeeminitialarabic: 0xFCA1, + tehjeemisolatedarabic: 0xFC0B, + tehmarbutaarabic: 0x0629, + tehmarbutafinalarabic: 0xFE94, + tehmedialarabic: 0xFE98, + tehmeeminitialarabic: 0xFCA4, + tehmeemisolatedarabic: 0xFC0E, + tehnoonfinalarabic: 0xFC73, + tekatakana: 0x30C6, + tekatakanahalfwidth: 0xFF83, + telephone: 0x2121, + telephoneblack: 0x260E, + telishagedolahebrew: 0x05A0, + telishaqetanahebrew: 0x05A9, + tencircle: 0x2469, + tenideographicparen: 0x3229, + tenparen: 0x247D, + tenperiod: 0x2491, + tenroman: 0x2179, + tesh: 0x02A7, + tet: 0x05D8, + tetdagesh: 0xFB38, + tetdageshhebrew: 0xFB38, + tethebrew: 0x05D8, + tetsecyrillic: 0x04B5, + tevirhebrew: 0x059B, + tevirlefthebrew: 0x059B, + thabengali: 0x09A5, + thadeva: 0x0925, + thagujarati: 0x0AA5, + thagurmukhi: 0x0A25, + thalarabic: 0x0630, + thalfinalarabic: 0xFEAC, + thanthakhatlowleftthai: 0xF898, + thanthakhatlowrightthai: 0xF897, + thanthakhatthai: 0x0E4C, + thanthakhatupperleftthai: 0xF896, + theharabic: 0x062B, + thehfinalarabic: 0xFE9A, + thehinitialarabic: 0xFE9B, + thehmedialarabic: 0xFE9C, + thereexists: 0x2203, + therefore: 0x2234, + theta: 0x03B8, + theta1: 0x03D1, + thetasymbolgreek: 0x03D1, + thieuthacirclekorean: 0x3279, + thieuthaparenkorean: 0x3219, + thieuthcirclekorean: 0x326B, + thieuthkorean: 0x314C, + thieuthparenkorean: 0x320B, + thirteencircle: 0x246C, + thirteenparen: 0x2480, + thirteenperiod: 0x2494, + thonangmonthothai: 0x0E11, + thook: 0x01AD, + thophuthaothai: 0x0E12, + thorn: 0x00FE, + thothahanthai: 0x0E17, + thothanthai: 0x0E10, + thothongthai: 0x0E18, + thothungthai: 0x0E16, + thousandcyrillic: 0x0482, + thousandsseparatorarabic: 0x066C, + thousandsseparatorpersian: 0x066C, + three: 0x0033, + threearabic: 0x0663, + threebengali: 0x09E9, + threecircle: 0x2462, + threecircleinversesansserif: 0x278C, + threedeva: 0x0969, + threeeighths: 0x215C, + threegujarati: 0x0AE9, + threegurmukhi: 0x0A69, + threehackarabic: 0x0663, + threehangzhou: 0x3023, + threeideographicparen: 0x3222, + threeinferior: 0x2083, + threemonospace: 0xFF13, + threenumeratorbengali: 0x09F6, + threeoldstyle: 0xF733, + threeparen: 0x2476, + threeperiod: 0x248A, + threepersian: 0x06F3, + threequarters: 0x00BE, + threequartersemdash: 0xF6DE, + threeroman: 0x2172, + threesuperior: 0x00B3, + threethai: 0x0E53, + thzsquare: 0x3394, + tihiragana: 0x3061, + tikatakana: 0x30C1, + tikatakanahalfwidth: 0xFF81, + tikeutacirclekorean: 0x3270, + tikeutaparenkorean: 0x3210, + tikeutcirclekorean: 0x3262, + tikeutkorean: 0x3137, + tikeutparenkorean: 0x3202, + tilde: 0x02DC, + tildebelowcmb: 0x0330, + tildecmb: 0x0303, + tildecomb: 0x0303, + tildedoublecmb: 0x0360, + tildeoperator: 0x223C, + tildeoverlaycmb: 0x0334, + tildeverticalcmb: 0x033E, + timescircle: 0x2297, + tipehahebrew: 0x0596, + tipehalefthebrew: 0x0596, + tippigurmukhi: 0x0A70, + titlocyrilliccmb: 0x0483, + tiwnarmenian: 0x057F, + tlinebelow: 0x1E6F, + tmonospace: 0xFF54, + toarmenian: 0x0569, + tohiragana: 0x3068, + tokatakana: 0x30C8, + tokatakanahalfwidth: 0xFF84, + tonebarextrahighmod: 0x02E5, + tonebarextralowmod: 0x02E9, + tonebarhighmod: 0x02E6, + tonebarlowmod: 0x02E8, + tonebarmidmod: 0x02E7, + tonefive: 0x01BD, + tonesix: 0x0185, + tonetwo: 0x01A8, + tonos: 0x0384, + tonsquare: 0x3327, + topatakthai: 0x0E0F, + tortoiseshellbracketleft: 0x3014, + tortoiseshellbracketleftsmall: 0xFE5D, + tortoiseshellbracketleftvertical: 0xFE39, + tortoiseshellbracketright: 0x3015, + tortoiseshellbracketrightsmall: 0xFE5E, + tortoiseshellbracketrightvertical: 0xFE3A, + totaothai: 0x0E15, + tpalatalhook: 0x01AB, + tparen: 0x24AF, + trademark: 0x2122, + trademarksans: 0xF8EA, + trademarkserif: 0xF6DB, + tretroflexhook: 0x0288, + triagdn: 0x25BC, + triaglf: 0x25C4, + triagrt: 0x25BA, + triagup: 0x25B2, + ts: 0x02A6, + tsadi: 0x05E6, + tsadidagesh: 0xFB46, + tsadidageshhebrew: 0xFB46, + tsadihebrew: 0x05E6, + tsecyrillic: 0x0446, + tsere: 0x05B5, + tsere12: 0x05B5, + tsere1e: 0x05B5, + tsere2b: 0x05B5, + tserehebrew: 0x05B5, + tserenarrowhebrew: 0x05B5, + tserequarterhebrew: 0x05B5, + tserewidehebrew: 0x05B5, + tshecyrillic: 0x045B, + tsuperior: 0xF6F3, + ttabengali: 0x099F, + ttadeva: 0x091F, + ttagujarati: 0x0A9F, + ttagurmukhi: 0x0A1F, + tteharabic: 0x0679, + ttehfinalarabic: 0xFB67, + ttehinitialarabic: 0xFB68, + ttehmedialarabic: 0xFB69, + tthabengali: 0x09A0, + tthadeva: 0x0920, + tthagujarati: 0x0AA0, + tthagurmukhi: 0x0A20, + tturned: 0x0287, + tuhiragana: 0x3064, + tukatakana: 0x30C4, + tukatakanahalfwidth: 0xFF82, + tusmallhiragana: 0x3063, + tusmallkatakana: 0x30C3, + tusmallkatakanahalfwidth: 0xFF6F, + twelvecircle: 0x246B, + twelveparen: 0x247F, + twelveperiod: 0x2493, + twelveroman: 0x217B, + twentycircle: 0x2473, + twentyhangzhou: 0x5344, + twentyparen: 0x2487, + twentyperiod: 0x249B, + two: 0x0032, + twoarabic: 0x0662, + twobengali: 0x09E8, + twocircle: 0x2461, + twocircleinversesansserif: 0x278B, + twodeva: 0x0968, + twodotenleader: 0x2025, + twodotleader: 0x2025, + twodotleadervertical: 0xFE30, + twogujarati: 0x0AE8, + twogurmukhi: 0x0A68, + twohackarabic: 0x0662, + twohangzhou: 0x3022, + twoideographicparen: 0x3221, + twoinferior: 0x2082, + twomonospace: 0xFF12, + twonumeratorbengali: 0x09F5, + twooldstyle: 0xF732, + twoparen: 0x2475, + twoperiod: 0x2489, + twopersian: 0x06F2, + tworoman: 0x2171, + twostroke: 0x01BB, + twosuperior: 0x00B2, + twothai: 0x0E52, + twothirds: 0x2154, + u: 0x0075, + uacute: 0x00FA, + ubar: 0x0289, + ubengali: 0x0989, + ubopomofo: 0x3128, + ubreve: 0x016D, + ucaron: 0x01D4, + ucircle: 0x24E4, + ucircumflex: 0x00FB, + ucircumflexbelow: 0x1E77, + ucyrillic: 0x0443, + udattadeva: 0x0951, + udblacute: 0x0171, + udblgrave: 0x0215, + udeva: 0x0909, + udieresis: 0x00FC, + udieresisacute: 0x01D8, + udieresisbelow: 0x1E73, + udieresiscaron: 0x01DA, + udieresiscyrillic: 0x04F1, + udieresisgrave: 0x01DC, + udieresismacron: 0x01D6, + udotbelow: 0x1EE5, + ugrave: 0x00F9, + ugujarati: 0x0A89, + ugurmukhi: 0x0A09, + uhiragana: 0x3046, + uhookabove: 0x1EE7, + uhorn: 0x01B0, + uhornacute: 0x1EE9, + uhorndotbelow: 0x1EF1, + uhorngrave: 0x1EEB, + uhornhookabove: 0x1EED, + uhorntilde: 0x1EEF, + uhungarumlaut: 0x0171, + uhungarumlautcyrillic: 0x04F3, + uinvertedbreve: 0x0217, + ukatakana: 0x30A6, + ukatakanahalfwidth: 0xFF73, + ukcyrillic: 0x0479, + ukorean: 0x315C, + umacron: 0x016B, + umacroncyrillic: 0x04EF, + umacrondieresis: 0x1E7B, + umatragurmukhi: 0x0A41, + umonospace: 0xFF55, + underscore: 0x005F, + underscoredbl: 0x2017, + underscoremonospace: 0xFF3F, + underscorevertical: 0xFE33, + underscorewavy: 0xFE4F, + union: 0x222A, + universal: 0x2200, + uogonek: 0x0173, + uparen: 0x24B0, + upblock: 0x2580, + upperdothebrew: 0x05C4, + upsilon: 0x03C5, + upsilondieresis: 0x03CB, + upsilondieresistonos: 0x03B0, + upsilonlatin: 0x028A, + upsilontonos: 0x03CD, + uptackbelowcmb: 0x031D, + uptackmod: 0x02D4, + uragurmukhi: 0x0A73, + uring: 0x016F, + ushortcyrillic: 0x045E, + usmallhiragana: 0x3045, + usmallkatakana: 0x30A5, + usmallkatakanahalfwidth: 0xFF69, + ustraightcyrillic: 0x04AF, + ustraightstrokecyrillic: 0x04B1, + utilde: 0x0169, + utildeacute: 0x1E79, + utildebelow: 0x1E75, + uubengali: 0x098A, + uudeva: 0x090A, + uugujarati: 0x0A8A, + uugurmukhi: 0x0A0A, + uumatragurmukhi: 0x0A42, + uuvowelsignbengali: 0x09C2, + uuvowelsigndeva: 0x0942, + uuvowelsigngujarati: 0x0AC2, + uvowelsignbengali: 0x09C1, + uvowelsigndeva: 0x0941, + uvowelsigngujarati: 0x0AC1, + v: 0x0076, + vadeva: 0x0935, + vagujarati: 0x0AB5, + vagurmukhi: 0x0A35, + vakatakana: 0x30F7, + vav: 0x05D5, + vavdagesh: 0xFB35, + vavdagesh65: 0xFB35, + vavdageshhebrew: 0xFB35, + vavhebrew: 0x05D5, + vavholam: 0xFB4B, + vavholamhebrew: 0xFB4B, + vavvavhebrew: 0x05F0, + vavyodhebrew: 0x05F1, + vcircle: 0x24E5, + vdotbelow: 0x1E7F, + vecyrillic: 0x0432, + veharabic: 0x06A4, + vehfinalarabic: 0xFB6B, + vehinitialarabic: 0xFB6C, + vehmedialarabic: 0xFB6D, + vekatakana: 0x30F9, + venus: 0x2640, + verticalbar: 0x007C, + verticallineabovecmb: 0x030D, + verticallinebelowcmb: 0x0329, + verticallinelowmod: 0x02CC, + verticallinemod: 0x02C8, + vewarmenian: 0x057E, + vhook: 0x028B, + vikatakana: 0x30F8, + viramabengali: 0x09CD, + viramadeva: 0x094D, + viramagujarati: 0x0ACD, + visargabengali: 0x0983, + visargadeva: 0x0903, + visargagujarati: 0x0A83, + vmonospace: 0xFF56, + voarmenian: 0x0578, + voicediterationhiragana: 0x309E, + voicediterationkatakana: 0x30FE, + voicedmarkkana: 0x309B, + voicedmarkkanahalfwidth: 0xFF9E, + vokatakana: 0x30FA, + vparen: 0x24B1, + vtilde: 0x1E7D, + vturned: 0x028C, + vuhiragana: 0x3094, + vukatakana: 0x30F4, + w: 0x0077, + wacute: 0x1E83, + waekorean: 0x3159, + wahiragana: 0x308F, + wakatakana: 0x30EF, + wakatakanahalfwidth: 0xFF9C, + wakorean: 0x3158, + wasmallhiragana: 0x308E, + wasmallkatakana: 0x30EE, + wattosquare: 0x3357, + wavedash: 0x301C, + wavyunderscorevertical: 0xFE34, + wawarabic: 0x0648, + wawfinalarabic: 0xFEEE, + wawhamzaabovearabic: 0x0624, + wawhamzaabovefinalarabic: 0xFE86, + wbsquare: 0x33DD, + wcircle: 0x24E6, + wcircumflex: 0x0175, + wdieresis: 0x1E85, + wdotaccent: 0x1E87, + wdotbelow: 0x1E89, + wehiragana: 0x3091, + weierstrass: 0x2118, + wekatakana: 0x30F1, + wekorean: 0x315E, + weokorean: 0x315D, + wgrave: 0x1E81, + whitebullet: 0x25E6, + whitecircle: 0x25CB, + whitecircleinverse: 0x25D9, + whitecornerbracketleft: 0x300E, + whitecornerbracketleftvertical: 0xFE43, + whitecornerbracketright: 0x300F, + whitecornerbracketrightvertical: 0xFE44, + whitediamond: 0x25C7, + whitediamondcontainingblacksmalldiamond: 0x25C8, + whitedownpointingsmalltriangle: 0x25BF, + whitedownpointingtriangle: 0x25BD, + whiteleftpointingsmalltriangle: 0x25C3, + whiteleftpointingtriangle: 0x25C1, + whitelenticularbracketleft: 0x3016, + whitelenticularbracketright: 0x3017, + whiterightpointingsmalltriangle: 0x25B9, + whiterightpointingtriangle: 0x25B7, + whitesmallsquare: 0x25AB, + whitesmilingface: 0x263A, + whitesquare: 0x25A1, + whitestar: 0x2606, + whitetelephone: 0x260F, + whitetortoiseshellbracketleft: 0x3018, + whitetortoiseshellbracketright: 0x3019, + whiteuppointingsmalltriangle: 0x25B5, + whiteuppointingtriangle: 0x25B3, + wihiragana: 0x3090, + wikatakana: 0x30F0, + wikorean: 0x315F, + wmonospace: 0xFF57, + wohiragana: 0x3092, + wokatakana: 0x30F2, + wokatakanahalfwidth: 0xFF66, + won: 0x20A9, + wonmonospace: 0xFFE6, + wowaenthai: 0x0E27, + wparen: 0x24B2, + wring: 0x1E98, + wsuperior: 0x02B7, + wturned: 0x028D, + wynn: 0x01BF, + x: 0x0078, + xabovecmb: 0x033D, + xbopomofo: 0x3112, + xcircle: 0x24E7, + xdieresis: 0x1E8D, + xdotaccent: 0x1E8B, + xeharmenian: 0x056D, + xi: 0x03BE, + xmonospace: 0xFF58, + xparen: 0x24B3, + xsuperior: 0x02E3, + y: 0x0079, + yaadosquare: 0x334E, + yabengali: 0x09AF, + yacute: 0x00FD, + yadeva: 0x092F, + yaekorean: 0x3152, + yagujarati: 0x0AAF, + yagurmukhi: 0x0A2F, + yahiragana: 0x3084, + yakatakana: 0x30E4, + yakatakanahalfwidth: 0xFF94, + yakorean: 0x3151, + yamakkanthai: 0x0E4E, + yasmallhiragana: 0x3083, + yasmallkatakana: 0x30E3, + yasmallkatakanahalfwidth: 0xFF6C, + yatcyrillic: 0x0463, + ycircle: 0x24E8, + ycircumflex: 0x0177, + ydieresis: 0x00FF, + ydotaccent: 0x1E8F, + ydotbelow: 0x1EF5, + yeharabic: 0x064A, + yehbarreearabic: 0x06D2, + yehbarreefinalarabic: 0xFBAF, + yehfinalarabic: 0xFEF2, + yehhamzaabovearabic: 0x0626, + yehhamzaabovefinalarabic: 0xFE8A, + yehhamzaaboveinitialarabic: 0xFE8B, + yehhamzaabovemedialarabic: 0xFE8C, + yehinitialarabic: 0xFEF3, + yehmedialarabic: 0xFEF4, + yehmeeminitialarabic: 0xFCDD, + yehmeemisolatedarabic: 0xFC58, + yehnoonfinalarabic: 0xFC94, + yehthreedotsbelowarabic: 0x06D1, + yekorean: 0x3156, + yen: 0x00A5, + yenmonospace: 0xFFE5, + yeokorean: 0x3155, + yeorinhieuhkorean: 0x3186, + yerahbenyomohebrew: 0x05AA, + yerahbenyomolefthebrew: 0x05AA, + yericyrillic: 0x044B, + yerudieresiscyrillic: 0x04F9, + yesieungkorean: 0x3181, + yesieungpansioskorean: 0x3183, + yesieungsioskorean: 0x3182, + yetivhebrew: 0x059A, + ygrave: 0x1EF3, + yhook: 0x01B4, + yhookabove: 0x1EF7, + yiarmenian: 0x0575, + yicyrillic: 0x0457, + yikorean: 0x3162, + yinyang: 0x262F, + yiwnarmenian: 0x0582, + ymonospace: 0xFF59, + yod: 0x05D9, + yoddagesh: 0xFB39, + yoddageshhebrew: 0xFB39, + yodhebrew: 0x05D9, + yodyodhebrew: 0x05F2, + yodyodpatahhebrew: 0xFB1F, + yohiragana: 0x3088, + yoikorean: 0x3189, + yokatakana: 0x30E8, + yokatakanahalfwidth: 0xFF96, + yokorean: 0x315B, + yosmallhiragana: 0x3087, + yosmallkatakana: 0x30E7, + yosmallkatakanahalfwidth: 0xFF6E, + yotgreek: 0x03F3, + yoyaekorean: 0x3188, + yoyakorean: 0x3187, + yoyakthai: 0x0E22, + yoyingthai: 0x0E0D, + yparen: 0x24B4, + ypogegrammeni: 0x037A, + ypogegrammenigreekcmb: 0x0345, + yr: 0x01A6, + yring: 0x1E99, + ysuperior: 0x02B8, + ytilde: 0x1EF9, + yturned: 0x028E, + yuhiragana: 0x3086, + yuikorean: 0x318C, + yukatakana: 0x30E6, + yukatakanahalfwidth: 0xFF95, + yukorean: 0x3160, + yusbigcyrillic: 0x046B, + yusbigiotifiedcyrillic: 0x046D, + yuslittlecyrillic: 0x0467, + yuslittleiotifiedcyrillic: 0x0469, + yusmallhiragana: 0x3085, + yusmallkatakana: 0x30E5, + yusmallkatakanahalfwidth: 0xFF6D, + yuyekorean: 0x318B, + yuyeokorean: 0x318A, + yyabengali: 0x09DF, + yyadeva: 0x095F, + z: 0x007A, + zaarmenian: 0x0566, + zacute: 0x017A, + zadeva: 0x095B, + zagurmukhi: 0x0A5B, + zaharabic: 0x0638, + zahfinalarabic: 0xFEC6, + zahinitialarabic: 0xFEC7, + zahiragana: 0x3056, + zahmedialarabic: 0xFEC8, + zainarabic: 0x0632, + zainfinalarabic: 0xFEB0, + zakatakana: 0x30B6, + zaqefgadolhebrew: 0x0595, + zaqefqatanhebrew: 0x0594, + zarqahebrew: 0x0598, + zayin: 0x05D6, + zayindagesh: 0xFB36, + zayindageshhebrew: 0xFB36, + zayinhebrew: 0x05D6, + zbopomofo: 0x3117, + zcaron: 0x017E, + zcircle: 0x24E9, + zcircumflex: 0x1E91, + zcurl: 0x0291, + zdot: 0x017C, + zdotaccent: 0x017C, + zdotbelow: 0x1E93, + zecyrillic: 0x0437, + zedescendercyrillic: 0x0499, + zedieresiscyrillic: 0x04DF, + zehiragana: 0x305C, + zekatakana: 0x30BC, + zero: 0x0030, + zeroarabic: 0x0660, + zerobengali: 0x09E6, + zerodeva: 0x0966, + zerogujarati: 0x0AE6, + zerogurmukhi: 0x0A66, + zerohackarabic: 0x0660, + zeroinferior: 0x2080, + zeromonospace: 0xFF10, + zerooldstyle: 0xF730, + zeropersian: 0x06F0, + zerosuperior: 0x2070, + zerothai: 0x0E50, + zerowidthjoiner: 0xFEFF, + zerowidthnonjoiner: 0x200C, + zerowidthspace: 0x200B, + zeta: 0x03B6, + zhbopomofo: 0x3113, + zhearmenian: 0x056A, + zhebrevecyrillic: 0x04C2, + zhecyrillic: 0x0436, + zhedescendercyrillic: 0x0497, + zhedieresiscyrillic: 0x04DD, + zihiragana: 0x3058, + zikatakana: 0x30B8, + zinorhebrew: 0x05AE, + zlinebelow: 0x1E95, + zmonospace: 0xFF5A, + zohiragana: 0x305E, + zokatakana: 0x30BE, + zparen: 0x24B5, + zretroflexhook: 0x0290, + zstroke: 0x01B6, + zuhiragana: 0x305A, + zukatakana: 0x30BA, + '.notdef': 0x0000 +}; + +var DingbatsGlyphsUnicode = { + space: 0x0020, + a1: 0x2701, + a2: 0x2702, + a202: 0x2703, + a3: 0x2704, + a4: 0x260E, + a5: 0x2706, + a119: 0x2707, + a118: 0x2708, + a117: 0x2709, + a11: 0x261B, + a12: 0x261E, + a13: 0x270C, + a14: 0x270D, + a15: 0x270E, + a16: 0x270F, + a105: 0x2710, + a17: 0x2711, + a18: 0x2712, + a19: 0x2713, + a20: 0x2714, + a21: 0x2715, + a22: 0x2716, + a23: 0x2717, + a24: 0x2718, + a25: 0x2719, + a26: 0x271A, + a27: 0x271B, + a28: 0x271C, + a6: 0x271D, + a7: 0x271E, + a8: 0x271F, + a9: 0x2720, + a10: 0x2721, + a29: 0x2722, + a30: 0x2723, + a31: 0x2724, + a32: 0x2725, + a33: 0x2726, + a34: 0x2727, + a35: 0x2605, + a36: 0x2729, + a37: 0x272A, + a38: 0x272B, + a39: 0x272C, + a40: 0x272D, + a41: 0x272E, + a42: 0x272F, + a43: 0x2730, + a44: 0x2731, + a45: 0x2732, + a46: 0x2733, + a47: 0x2734, + a48: 0x2735, + a49: 0x2736, + a50: 0x2737, + a51: 0x2738, + a52: 0x2739, + a53: 0x273A, + a54: 0x273B, + a55: 0x273C, + a56: 0x273D, + a57: 0x273E, + a58: 0x273F, + a59: 0x2740, + a60: 0x2741, + a61: 0x2742, + a62: 0x2743, + a63: 0x2744, + a64: 0x2745, + a65: 0x2746, + a66: 0x2747, + a67: 0x2748, + a68: 0x2749, + a69: 0x274A, + a70: 0x274B, + a71: 0x25CF, + a72: 0x274D, + a73: 0x25A0, + a74: 0x274F, + a203: 0x2750, + a75: 0x2751, + a204: 0x2752, + a76: 0x25B2, + a77: 0x25BC, + a78: 0x25C6, + a79: 0x2756, + a81: 0x25D7, + a82: 0x2758, + a83: 0x2759, + a84: 0x275A, + a97: 0x275B, + a98: 0x275C, + a99: 0x275D, + a100: 0x275E, + a101: 0x2761, + a102: 0x2762, + a103: 0x2763, + a104: 0x2764, + a106: 0x2765, + a107: 0x2766, + a108: 0x2767, + a112: 0x2663, + a111: 0x2666, + a110: 0x2665, + a109: 0x2660, + a120: 0x2460, + a121: 0x2461, + a122: 0x2462, + a123: 0x2463, + a124: 0x2464, + a125: 0x2465, + a126: 0x2466, + a127: 0x2467, + a128: 0x2468, + a129: 0x2469, + a130: 0x2776, + a131: 0x2777, + a132: 0x2778, + a133: 0x2779, + a134: 0x277A, + a135: 0x277B, + a136: 0x277C, + a137: 0x277D, + a138: 0x277E, + a139: 0x277F, + a140: 0x2780, + a141: 0x2781, + a142: 0x2782, + a143: 0x2783, + a144: 0x2784, + a145: 0x2785, + a146: 0x2786, + a147: 0x2787, + a148: 0x2788, + a149: 0x2789, + a150: 0x278A, + a151: 0x278B, + a152: 0x278C, + a153: 0x278D, + a154: 0x278E, + a155: 0x278F, + a156: 0x2790, + a157: 0x2791, + a158: 0x2792, + a159: 0x2793, + a160: 0x2794, + a161: 0x2192, + a163: 0x2194, + a164: 0x2195, + a196: 0x2798, + a165: 0x2799, + a192: 0x279A, + a166: 0x279B, + a167: 0x279C, + a168: 0x279D, + a169: 0x279E, + a170: 0x279F, + a171: 0x27A0, + a172: 0x27A1, + a173: 0x27A2, + a162: 0x27A3, + a174: 0x27A4, + a175: 0x27A5, + a176: 0x27A6, + a177: 0x27A7, + a178: 0x27A8, + a179: 0x27A9, + a193: 0x27AA, + a180: 0x27AB, + a199: 0x27AC, + a181: 0x27AD, + a200: 0x27AE, + a182: 0x27AF, + a201: 0x27B1, + a183: 0x27B2, + a184: 0x27B3, + a197: 0x27B4, + a185: 0x27B5, + a194: 0x27B6, + a198: 0x27B7, + a186: 0x27B8, + a195: 0x27B9, + a187: 0x27BA, + a188: 0x27BB, + a189: 0x27BC, + a190: 0x27BD, + a191: 0x27BE, + a89: 0x2768, // 0xF8D7 + a90: 0x2769, // 0xF8D8 + a93: 0x276A, // 0xF8D9 + a94: 0x276B, // 0xF8DA + a91: 0x276C, // 0xF8DB + a92: 0x276D, // 0xF8DC + a205: 0x276E, // 0xF8DD + a85: 0x276F, // 0xF8DE + a206: 0x2770, // 0xF8DF + a86: 0x2771, // 0xF8E0 + a87: 0x2772, // 0xF8E1 + a88: 0x2773, // 0xF8E2 + a95: 0x2774, // 0xF8E3 + a96: 0x2775, // 0xF8E4 + '.notdef': 0x0000 +}; + + +var PDFImage = (function PDFImageClosure() { + /** + * Decode the image in the main thread if it supported. Resovles the promise + * when the image data is ready. + */ + function handleImageData(handler, xref, res, image) { + if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) { + // For natively supported jpegs send them to the main thread for decoding. + var dict = image.dict; + var colorSpace = dict.get('ColorSpace', 'CS'); + colorSpace = ColorSpace.parse(colorSpace, xref, res); + var numComps = colorSpace.numComps; + var decodePromise = handler.sendWithPromise('JpegDecode', + [image.getIR(), numComps]); + return decodePromise.then(function (message) { + var data = message.data; + return new Stream(data, 0, data.length, image.dict); + }); + } else { + return Promise.resolve(image); + } + } + + /** + * Decode and clamp a value. The formula is different from the spec because we + * don't decode to float range [0,1], we decode it in the [0,max] range. + */ + function decodeAndClamp(value, addend, coefficient, max) { + value = addend + value * coefficient; + // Clamp the value to the range + return (value < 0 ? 0 : (value > max ? max : value)); + } + + function PDFImage(xref, res, image, inline, smask, mask, isMask) { + this.image = image; + var dict = image.dict; + if (dict.has('Filter')) { + var filter = dict.get('Filter').name; + if (filter === 'JPXDecode') { + var jpxImage = new JpxImage(); + jpxImage.parseImageProperties(image.stream); + image.stream.reset(); + image.bitsPerComponent = jpxImage.bitsPerComponent; + image.numComps = jpxImage.componentsCount; + } else if (filter === 'JBIG2Decode') { + image.bitsPerComponent = 1; + image.numComps = 1; + } + } + // TODO cache rendered images? + + this.width = dict.get('Width', 'W'); + this.height = dict.get('Height', 'H'); + + if (this.width < 1 || this.height < 1) { + error('Invalid image width: ' + this.width + ' or height: ' + + this.height); + } + + this.interpolate = dict.get('Interpolate', 'I') || false; + this.imageMask = dict.get('ImageMask', 'IM') || false; + this.matte = dict.get('Matte') || false; + + var bitsPerComponent = image.bitsPerComponent; + if (!bitsPerComponent) { + bitsPerComponent = dict.get('BitsPerComponent', 'BPC'); + if (!bitsPerComponent) { + if (this.imageMask) { + bitsPerComponent = 1; + } else { + error('Bits per component missing in image: ' + this.imageMask); + } + } + } + this.bpc = bitsPerComponent; + + if (!this.imageMask) { + var colorSpace = dict.get('ColorSpace', 'CS'); + if (!colorSpace) { + info('JPX images (which do not require color spaces)'); + switch (image.numComps) { + case 1: + colorSpace = Name.get('DeviceGray'); + break; + case 3: + colorSpace = Name.get('DeviceRGB'); + break; + case 4: + colorSpace = Name.get('DeviceCMYK'); + break; + default: + error('JPX images with ' + this.numComps + + ' color components not supported.'); + } + } + this.colorSpace = ColorSpace.parse(colorSpace, xref, res); + this.numComps = this.colorSpace.numComps; + } + + this.decode = dict.get('Decode', 'D'); + this.needsDecode = false; + if (this.decode && + ((this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode)) || + (isMask && !ColorSpace.isDefaultDecode(this.decode, 1)))) { + this.needsDecode = true; + // Do some preprocessing to avoid more math. + var max = (1 << bitsPerComponent) - 1; + this.decodeCoefficients = []; + this.decodeAddends = []; + for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) { + var dmin = this.decode[i]; + var dmax = this.decode[i + 1]; + this.decodeCoefficients[j] = dmax - dmin; + this.decodeAddends[j] = max * dmin; + } + } + + if (smask) { + this.smask = new PDFImage(xref, res, smask, false); + } else if (mask) { + if (isStream(mask)) { + this.mask = new PDFImage(xref, res, mask, false, null, null, true); + } else { + // Color key mask (just an array). + this.mask = mask; + } + } + } + /** + * Handles processing of image data and returns the Promise that is resolved + * with a PDFImage when the image is ready to be used. + */ + PDFImage.buildImage = function PDFImage_buildImage(handler, xref, + res, image, inline) { + var imagePromise = handleImageData(handler, xref, res, image); + var smaskPromise; + var maskPromise; + + var smask = image.dict.get('SMask'); + var mask = image.dict.get('Mask'); + + if (smask) { + smaskPromise = handleImageData(handler, xref, res, smask); + maskPromise = Promise.resolve(null); + } else { + smaskPromise = Promise.resolve(null); + if (mask) { + if (isStream(mask)) { + maskPromise = handleImageData(handler, xref, res, mask); + } else if (isArray(mask)) { + maskPromise = Promise.resolve(mask); + } else { + warn('Unsupported mask format.'); + maskPromise = Promise.resolve(null); + } + } else { + maskPromise = Promise.resolve(null); + } + } + return Promise.all([imagePromise, smaskPromise, maskPromise]).then( + function(results) { + var imageData = results[0]; + var smaskData = results[1]; + var maskData = results[2]; + return new PDFImage(xref, res, imageData, inline, smaskData, maskData); + }); + }; + + /** + * Resize an image using the nearest neighbor algorithm. Currently only + * supports one and three component images. + * @param {TypedArray} pixels The original image with one component. + * @param {Number} bpc Number of bits per component. + * @param {Number} components Number of color components, 1 or 3 is supported. + * @param {Number} w1 Original width. + * @param {Number} h1 Original height. + * @param {Number} w2 New width. + * @param {Number} h2 New height. + * @param {TypedArray} dest (Optional) The destination buffer. + * @param {Number} alpha01 (Optional) Size reserved for the alpha channel. + * @return {TypedArray} Resized image data. + */ + PDFImage.resize = function PDFImage_resize(pixels, bpc, components, + w1, h1, w2, h2, dest, alpha01) { + + if (components !== 1 && components !== 3) { + error('Unsupported component count for resizing.'); + } + + var length = w2 * h2 * components; + var temp = dest ? dest : (bpc <= 8 ? new Uint8Array(length) : + (bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length))); + var xRatio = w1 / w2; + var yRatio = h1 / h2; + var i, j, py, newIndex = 0, oldIndex; + var xScaled = new Uint16Array(w2); + var w1Scanline = w1 * components; + if (alpha01 !== 1) { + alpha01 = 0; + } + + for (j = 0; j < w2; j++) { + xScaled[j] = Math.floor(j * xRatio) * components; + } + + if (components === 1) { + for (i = 0; i < h2; i++) { + py = Math.floor(i * yRatio) * w1Scanline; + for (j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + temp[newIndex++] = pixels[oldIndex]; + } + } + } else if (components === 3) { + for (i = 0; i < h2; i++) { + py = Math.floor(i * yRatio) * w1Scanline; + for (j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + temp[newIndex++] = pixels[oldIndex++]; + temp[newIndex++] = pixels[oldIndex++]; + temp[newIndex++] = pixels[oldIndex++]; + newIndex += alpha01; + } + } + } + return temp; + }; + + PDFImage.createMask = + function PDFImage_createMask(imgArray, width, height, + imageIsFromDecodeStream, inverseDecode) { + + // |imgArray| might not contain full data for every pixel of the mask, so + // we need to distinguish between |computedLength| and |actualLength|. + // In particular, if inverseDecode is true, then the array we return must + // have a length of |computedLength|. + + var computedLength = ((width + 7) >> 3) * height; + var actualLength = imgArray.byteLength; + var haveFullData = computedLength === actualLength; + var data, i; + + if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) { + // imgArray came from a DecodeStream and its data is in an appropriate + // form, so we can just transfer it. + data = imgArray; + } else if (!inverseDecode) { + data = new Uint8Array(actualLength); + data.set(imgArray); + } else { + data = new Uint8Array(computedLength); + data.set(imgArray); + for (i = actualLength; i < computedLength; i++) { + data[i] = 0xff; + } + } + + // If necessary, invert the original mask data (but not any extra we might + // have added above). It's safe to modify the array -- whether it's the + // original or a copy, we're about to transfer it anyway, so nothing else + // in this thread can be relying on its contents. + if (inverseDecode) { + for (i = 0; i < actualLength; i++) { + data[i] = ~data[i]; + } + } + + return {data: data, width: width, height: height}; + }; + + PDFImage.prototype = { + get drawWidth() { + return Math.max(this.width, + this.smask && this.smask.width || 0, + this.mask && this.mask.width || 0); + }, + + get drawHeight() { + return Math.max(this.height, + this.smask && this.smask.height || 0, + this.mask && this.mask.height || 0); + }, + + decodeBuffer: function PDFImage_decodeBuffer(buffer) { + var bpc = this.bpc; + var numComps = this.numComps; + + var decodeAddends = this.decodeAddends; + var decodeCoefficients = this.decodeCoefficients; + var max = (1 << bpc) - 1; + var i, ii; + + if (bpc === 1) { + // If the buffer needed decode that means it just needs to be inverted. + for (i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] = +!(buffer[i]); + } + return; + } + var index = 0; + for (i = 0, ii = this.width * this.height; i < ii; i++) { + for (var j = 0; j < numComps; j++) { + buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], + decodeCoefficients[j], max); + index++; + } + } + }, + + getComponents: function PDFImage_getComponents(buffer) { + var bpc = this.bpc; + + // This image doesn't require any extra work. + if (bpc === 8) { + return buffer; + } + + var width = this.width; + var height = this.height; + var numComps = this.numComps; + + var length = width * height * numComps; + var bufferPos = 0; + var output = (bpc <= 8 ? new Uint8Array(length) : + (bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length))); + var rowComps = width * numComps; + + var max = (1 << bpc) - 1; + var i = 0, ii, buf; + + if (bpc === 1) { + // Optimization for reading 1 bpc images. + var mask, loop1End, loop2End; + for (var j = 0; j < height; j++) { + loop1End = i + (rowComps & ~7); + loop2End = i + rowComps; + + // unroll loop for all full bytes + while (i < loop1End) { + buf = buffer[bufferPos++]; + output[i] = (buf >> 7) & 1; + output[i + 1] = (buf >> 6) & 1; + output[i + 2] = (buf >> 5) & 1; + output[i + 3] = (buf >> 4) & 1; + output[i + 4] = (buf >> 3) & 1; + output[i + 5] = (buf >> 2) & 1; + output[i + 6] = (buf >> 1) & 1; + output[i + 7] = buf & 1; + i += 8; + } + + // handle remaing bits + if (i < loop2End) { + buf = buffer[bufferPos++]; + mask = 128; + while (i < loop2End) { + output[i++] = +!!(buf & mask); + mask >>= 1; + } + } + } + } else { + // The general case that handles all other bpc values. + var bits = 0; + buf = 0; + for (i = 0, ii = length; i < ii; ++i) { + if (i % rowComps === 0) { + buf = 0; + bits = 0; + } + + while (bits < bpc) { + buf = (buf << 8) | buffer[bufferPos++]; + bits += 8; + } + + var remainingBits = bits - bpc; + var value = buf >> remainingBits; + output[i] = (value < 0 ? 0 : (value > max ? max : value)); + buf = buf & ((1 << remainingBits) - 1); + bits = remainingBits; + } + } + return output; + }, + + fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height, + actualHeight, image) { + var smask = this.smask; + var mask = this.mask; + var alphaBuf, sw, sh, i, ii, j; + + if (smask) { + sw = smask.width; + sh = smask.height; + alphaBuf = new Uint8Array(sw * sh); + smask.fillGrayBuffer(alphaBuf); + if (sw !== width || sh !== height) { + alphaBuf = PDFImage.resize(alphaBuf, smask.bpc, 1, sw, sh, width, + height); + } + } else if (mask) { + if (mask instanceof PDFImage) { + sw = mask.width; + sh = mask.height; + alphaBuf = new Uint8Array(sw * sh); + mask.numComps = 1; + mask.fillGrayBuffer(alphaBuf); + + // Need to invert values in rgbaBuf + for (i = 0, ii = sw * sh; i < ii; ++i) { + alphaBuf[i] = 255 - alphaBuf[i]; + } + + if (sw !== width || sh !== height) { + alphaBuf = PDFImage.resize(alphaBuf, mask.bpc, 1, sw, sh, width, + height); + } + } else if (isArray(mask)) { + // Color key mask: if any of the compontents are outside the range + // then they should be painted. + alphaBuf = new Uint8Array(width * height); + var numComps = this.numComps; + for (i = 0, ii = width * height; i < ii; ++i) { + var opacity = 0; + var imageOffset = i * numComps; + for (j = 0; j < numComps; ++j) { + var color = image[imageOffset + j]; + var maskOffset = j * 2; + if (color < mask[maskOffset] || color > mask[maskOffset + 1]) { + opacity = 255; + break; + } + } + alphaBuf[i] = opacity; + } + } else { + error('Unknown mask format.'); + } + } + + if (alphaBuf) { + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = alphaBuf[i]; + } + } else { + // No mask. + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = 255; + } + } + }, + + undoPreblend: function PDFImage_undoPreblend(buffer, width, height) { + var matte = this.smask && this.smask.matte; + if (!matte) { + return; + } + var matteRgb = this.colorSpace.getRgb(matte, 0); + var matteR = matteRgb[0]; + var matteG = matteRgb[1]; + var matteB = matteRgb[2]; + var length = width * height * 4; + var r, g, b; + for (var i = 0; i < length; i += 4) { + var alpha = buffer[i + 3]; + if (alpha === 0) { + // according formula we have to get Infinity in all components + // making it white (typical paper color) should be okay + buffer[i] = 255; + buffer[i + 1] = 255; + buffer[i + 2] = 255; + continue; + } + var k = 255 / alpha; + r = (buffer[i] - matteR) * k + matteR; + g = (buffer[i + 1] - matteG) * k + matteG; + b = (buffer[i + 2] - matteB) * k + matteB; + buffer[i] = r <= 0 ? 0 : r >= 255 ? 255 : r | 0; + buffer[i + 1] = g <= 0 ? 0 : g >= 255 ? 255 : g | 0; + buffer[i + 2] = b <= 0 ? 0 : b >= 255 ? 255 : b | 0; + } + }, + + createImageData: function PDFImage_createImageData(forceRGBA) { + var drawWidth = this.drawWidth; + var drawHeight = this.drawHeight; + var imgData = { // other fields are filled in below + width: drawWidth, + height: drawHeight + }; + + var numComps = this.numComps; + var originalWidth = this.width; + var originalHeight = this.height; + var bpc = this.bpc; + + // Rows start at byte boundary. + var rowBytes = (originalWidth * numComps * bpc + 7) >> 3; + var imgArray; + + if (!forceRGBA) { + // If it is a 1-bit-per-pixel grayscale (i.e. black-and-white) image + // without any complications, we pass a same-sized copy to the main + // thread rather than expanding by 32x to RGBA form. This saves *lots* + // of memory for many scanned documents. It's also much faster. + // + // Similarly, if it is a 24-bit-per pixel RGB image without any + // complications, we avoid expanding by 1.333x to RGBA form. + var kind; + if (this.colorSpace.name === 'DeviceGray' && bpc === 1) { + kind = ImageKind.GRAYSCALE_1BPP; + } else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 && + !this.needsDecode) { + kind = ImageKind.RGB_24BPP; + } + if (kind && !this.smask && !this.mask && + drawWidth === originalWidth && drawHeight === originalHeight) { + imgData.kind = kind; + + imgArray = this.getImageBytes(originalHeight * rowBytes); + // If imgArray came from a DecodeStream, we're safe to transfer it + // (and thus neuter it) because it will constitute the entire + // DecodeStream's data. But if it came from a Stream, we need to + // copy it because it'll only be a portion of the Stream's data, and + // the rest will be read later on. + if (this.image instanceof DecodeStream) { + imgData.data = imgArray; + } else { + var newArray = new Uint8Array(imgArray.length); + newArray.set(imgArray); + imgData.data = newArray; + } + if (this.needsDecode) { + // Invert the buffer (which must be grayscale if we reached here). + assert(kind === ImageKind.GRAYSCALE_1BPP); + var buffer = imgData.data; + for (var i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] ^= 0xff; + } + } + return imgData; + } + if (this.image instanceof JpegStream && !this.smask && !this.mask) { + imgData.kind = ImageKind.RGB_24BPP; + imgData.data = this.getImageBytes(originalHeight * rowBytes, + drawWidth, drawHeight, true); + return imgData; + } + } + + imgArray = this.getImageBytes(originalHeight * rowBytes); + // imgArray can be incomplete (e.g. after CCITT fax encoding). + var actualHeight = 0 | (imgArray.length / rowBytes * + drawHeight / originalHeight); + + var comps = this.getComponents(imgArray); + + // If opacity data is present, use RGBA_32BPP form. Otherwise, use the + // more compact RGB_24BPP form if allowable. + var alpha01, maybeUndoPreblend; + if (!forceRGBA && !this.smask && !this.mask) { + imgData.kind = ImageKind.RGB_24BPP; + imgData.data = new Uint8Array(drawWidth * drawHeight * 3); + alpha01 = 0; + maybeUndoPreblend = false; + } else { + imgData.kind = ImageKind.RGBA_32BPP; + imgData.data = new Uint8Array(drawWidth * drawHeight * 4); + alpha01 = 1; + maybeUndoPreblend = true; + + // Color key masking (opacity) must be performed before decoding. + this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight, + comps); + } + + if (this.needsDecode) { + this.decodeBuffer(comps); + } + this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight, + drawWidth, drawHeight, actualHeight, bpc, comps, + alpha01); + if (maybeUndoPreblend) { + this.undoPreblend(imgData.data, drawWidth, actualHeight); + } + + return imgData; + }, + + fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) { + var numComps = this.numComps; + if (numComps !== 1) { + error('Reading gray scale from a color image: ' + numComps); + } + + var width = this.width; + var height = this.height; + var bpc = this.bpc; + + // rows start at byte boundary + var rowBytes = (width * numComps * bpc + 7) >> 3; + var imgArray = this.getImageBytes(height * rowBytes); + + var comps = this.getComponents(imgArray); + var i, length; + + if (bpc === 1) { + // inline decoding (= inversion) for 1 bpc images + length = width * height; + if (this.needsDecode) { + // invert and scale to {0, 255} + for (i = 0; i < length; ++i) { + buffer[i] = (comps[i] - 1) & 255; + } + } else { + // scale to {0, 255} + for (i = 0; i < length; ++i) { + buffer[i] = (-comps[i]) & 255; + } + } + return; + } + + if (this.needsDecode) { + this.decodeBuffer(comps); + } + length = width * height; + // we aren't using a colorspace so we need to scale the value + var scale = 255 / ((1 << bpc) - 1); + for (i = 0; i < length; ++i) { + buffer[i] = (scale * comps[i]) | 0; + } + }, + + getImageBytes: function PDFImage_getImageBytes(length, + drawWidth, drawHeight, + forceRGB) { + this.image.reset(); + this.image.drawWidth = drawWidth || this.width; + this.image.drawHeight = drawHeight || this.height; + this.image.forceRGB = !!forceRGB; + return this.image.getBytes(length); + } + }; + return PDFImage; +})(); + + +// The Metrics object contains glyph widths (in glyph space units). +// As per PDF spec, for most fonts (Type 3 being an exception) a glyph +// space unit corresponds to 1/1000th of text space unit. +var Metrics = { + 'Courier': 600, + 'Courier-Bold': 600, + 'Courier-BoldOblique': 600, + 'Courier-Oblique': 600, + 'Helvetica' : { + 'space': 278, + 'exclam': 278, + 'quotedbl': 355, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 667, + 'quoteright': 222, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 278, + 'semicolon': 278, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 556, + 'at': 1015, + 'A': 667, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 500, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 278, + 'backslash': 278, + 'bracketright': 278, + 'asciicircum': 469, + 'underscore': 556, + 'quoteleft': 222, + 'a': 556, + 'b': 556, + 'c': 500, + 'd': 556, + 'e': 556, + 'f': 278, + 'g': 556, + 'h': 556, + 'i': 222, + 'j': 222, + 'k': 500, + 'l': 222, + 'm': 833, + 'n': 556, + 'o': 556, + 'p': 556, + 'q': 556, + 'r': 333, + 's': 500, + 't': 278, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 500, + 'braceleft': 334, + 'bar': 260, + 'braceright': 334, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 191, + 'quotedblleft': 333, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 537, + 'bullet': 350, + 'quotesinglbase': 222, + 'quotedblbase': 333, + 'quotedblright': 333, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 556, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 222, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 556, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 667, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 500, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 500, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 222, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 500, + 'scedilla': 500, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 556, + 'Amacron': 667, + 'rcaron': 333, + 'ccedilla': 500, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 643, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 584, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 500, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 260, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 333, + 'omacron': 556, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 222, + 'tcaron': 317, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 222, + 'Oacute': 778, + 'oacute': 556, + 'amacron': 556, + 'sacute': 500, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 556, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 299, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 556, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 556, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 556, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 556, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 556, + 'Rcommaaccent': 722, + 'Lcommaaccent': 556, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 500, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 584, + 'odieresis': 556, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 556, + 'eth': 556, + 'zcaron': 500, + 'ncommaaccent': 556, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-Bold': { + 'space': 278, + 'exclam': 333, + 'quotedbl': 474, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 722, + 'quoteright': 278, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 333, + 'semicolon': 333, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 611, + 'at': 975, + 'A': 722, + 'B': 722, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 556, + 'K': 722, + 'L': 611, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 584, + 'underscore': 556, + 'quoteleft': 278, + 'a': 556, + 'b': 611, + 'c': 556, + 'd': 611, + 'e': 556, + 'f': 333, + 'g': 611, + 'h': 611, + 'i': 278, + 'j': 278, + 'k': 556, + 'l': 278, + 'm': 889, + 'n': 611, + 'o': 611, + 'p': 611, + 'q': 611, + 'r': 389, + 's': 556, + 't': 333, + 'u': 611, + 'v': 556, + 'w': 778, + 'x': 556, + 'y': 556, + 'z': 500, + 'braceleft': 389, + 'bar': 280, + 'braceright': 389, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 238, + 'quotedblleft': 500, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 611, + 'fl': 611, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 556, + 'bullet': 350, + 'quotesinglbase': 278, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 611, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 611, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 722, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 556, + 'scommaaccent': 556, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 611, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 556, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 556, + 'scedilla': 556, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 611, + 'acircumflex': 556, + 'Amacron': 722, + 'rcaron': 389, + 'ccedilla': 556, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 743, + 'Umacron': 722, + 'uring': 611, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 584, + 'uacute': 611, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 556, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 556, + 'nacute': 611, + 'umacron': 611, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 280, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 611, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 389, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 611, + 'amacron': 556, + 'sacute': 556, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 611, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 611, + 'igrave': 278, + 'ohungarumlaut': 611, + 'Eogonek': 667, + 'dcroat': 611, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 400, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 611, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 611, + 'ntilde': 611, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 611, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 611, + 'Ccaron': 722, + 'ugrave': 611, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 611, + 'Rcommaaccent': 722, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 556, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 611, + 'tcommaaccent': 333, + 'logicalnot': 584, + 'odieresis': 611, + 'udieresis': 611, + 'notequal': 549, + 'gcommaaccent': 611, + 'eth': 611, + 'zcaron': 500, + 'ncommaaccent': 611, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-BoldOblique': { + 'space': 278, + 'exclam': 333, + 'quotedbl': 474, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 722, + 'quoteright': 278, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 333, + 'semicolon': 333, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 611, + 'at': 975, + 'A': 722, + 'B': 722, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 556, + 'K': 722, + 'L': 611, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 584, + 'underscore': 556, + 'quoteleft': 278, + 'a': 556, + 'b': 611, + 'c': 556, + 'd': 611, + 'e': 556, + 'f': 333, + 'g': 611, + 'h': 611, + 'i': 278, + 'j': 278, + 'k': 556, + 'l': 278, + 'm': 889, + 'n': 611, + 'o': 611, + 'p': 611, + 'q': 611, + 'r': 389, + 's': 556, + 't': 333, + 'u': 611, + 'v': 556, + 'w': 778, + 'x': 556, + 'y': 556, + 'z': 500, + 'braceleft': 389, + 'bar': 280, + 'braceright': 389, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 238, + 'quotedblleft': 500, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 611, + 'fl': 611, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 556, + 'bullet': 350, + 'quotesinglbase': 278, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 611, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 611, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 722, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 556, + 'scommaaccent': 556, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 611, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 556, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 556, + 'scedilla': 556, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 611, + 'acircumflex': 556, + 'Amacron': 722, + 'rcaron': 389, + 'ccedilla': 556, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 743, + 'Umacron': 722, + 'uring': 611, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 584, + 'uacute': 611, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 556, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 556, + 'nacute': 611, + 'umacron': 611, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 280, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 611, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 389, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 611, + 'amacron': 556, + 'sacute': 556, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 611, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 611, + 'igrave': 278, + 'ohungarumlaut': 611, + 'Eogonek': 667, + 'dcroat': 611, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 400, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 611, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 611, + 'ntilde': 611, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 611, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 611, + 'Ccaron': 722, + 'ugrave': 611, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 611, + 'Rcommaaccent': 722, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 556, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 611, + 'tcommaaccent': 333, + 'logicalnot': 584, + 'odieresis': 611, + 'udieresis': 611, + 'notequal': 549, + 'gcommaaccent': 611, + 'eth': 611, + 'zcaron': 500, + 'ncommaaccent': 611, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-Oblique' : { + 'space': 278, + 'exclam': 278, + 'quotedbl': 355, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 667, + 'quoteright': 222, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 278, + 'semicolon': 278, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 556, + 'at': 1015, + 'A': 667, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 500, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 278, + 'backslash': 278, + 'bracketright': 278, + 'asciicircum': 469, + 'underscore': 556, + 'quoteleft': 222, + 'a': 556, + 'b': 556, + 'c': 500, + 'd': 556, + 'e': 556, + 'f': 278, + 'g': 556, + 'h': 556, + 'i': 222, + 'j': 222, + 'k': 500, + 'l': 222, + 'm': 833, + 'n': 556, + 'o': 556, + 'p': 556, + 'q': 556, + 'r': 333, + 's': 500, + 't': 278, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 500, + 'braceleft': 334, + 'bar': 260, + 'braceright': 334, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 191, + 'quotedblleft': 333, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 537, + 'bullet': 350, + 'quotesinglbase': 222, + 'quotedblbase': 333, + 'quotedblright': 333, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 556, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 222, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 556, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 667, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 500, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 500, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 222, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 500, + 'scedilla': 500, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 556, + 'Amacron': 667, + 'rcaron': 333, + 'ccedilla': 500, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 643, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 584, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 500, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 260, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 333, + 'omacron': 556, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 222, + 'tcaron': 317, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 222, + 'Oacute': 778, + 'oacute': 556, + 'amacron': 556, + 'sacute': 500, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 556, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 299, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 556, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 556, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 556, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 556, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 556, + 'Rcommaaccent': 722, + 'Lcommaaccent': 556, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 500, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 584, + 'odieresis': 556, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 556, + 'eth': 556, + 'zcaron': 500, + 'ncommaaccent': 556, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Symbol': { + 'space': 250, + 'exclam': 333, + 'universal': 713, + 'numbersign': 500, + 'existential': 549, + 'percent': 833, + 'ampersand': 778, + 'suchthat': 439, + 'parenleft': 333, + 'parenright': 333, + 'asteriskmath': 500, + 'plus': 549, + 'comma': 250, + 'minus': 549, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 278, + 'semicolon': 278, + 'less': 549, + 'equal': 549, + 'greater': 549, + 'question': 444, + 'congruent': 549, + 'Alpha': 722, + 'Beta': 667, + 'Chi': 722, + 'Delta': 612, + 'Epsilon': 611, + 'Phi': 763, + 'Gamma': 603, + 'Eta': 722, + 'Iota': 333, + 'theta1': 631, + 'Kappa': 722, + 'Lambda': 686, + 'Mu': 889, + 'Nu': 722, + 'Omicron': 722, + 'Pi': 768, + 'Theta': 741, + 'Rho': 556, + 'Sigma': 592, + 'Tau': 611, + 'Upsilon': 690, + 'sigma1': 439, + 'Omega': 768, + 'Xi': 645, + 'Psi': 795, + 'Zeta': 611, + 'bracketleft': 333, + 'therefore': 863, + 'bracketright': 333, + 'perpendicular': 658, + 'underscore': 500, + 'radicalex': 500, + 'alpha': 631, + 'beta': 549, + 'chi': 549, + 'delta': 494, + 'epsilon': 439, + 'phi': 521, + 'gamma': 411, + 'eta': 603, + 'iota': 329, + 'phi1': 603, + 'kappa': 549, + 'lambda': 549, + 'mu': 576, + 'nu': 521, + 'omicron': 549, + 'pi': 549, + 'theta': 521, + 'rho': 549, + 'sigma': 603, + 'tau': 439, + 'upsilon': 576, + 'omega1': 713, + 'omega': 686, + 'xi': 493, + 'psi': 686, + 'zeta': 494, + 'braceleft': 480, + 'bar': 200, + 'braceright': 480, + 'similar': 549, + 'Euro': 750, + 'Upsilon1': 620, + 'minute': 247, + 'lessequal': 549, + 'fraction': 167, + 'infinity': 713, + 'florin': 500, + 'club': 753, + 'diamond': 753, + 'heart': 753, + 'spade': 753, + 'arrowboth': 1042, + 'arrowleft': 987, + 'arrowup': 603, + 'arrowright': 987, + 'arrowdown': 603, + 'degree': 400, + 'plusminus': 549, + 'second': 411, + 'greaterequal': 549, + 'multiply': 549, + 'proportional': 713, + 'partialdiff': 494, + 'bullet': 460, + 'divide': 549, + 'notequal': 549, + 'equivalence': 549, + 'approxequal': 549, + 'ellipsis': 1000, + 'arrowvertex': 603, + 'arrowhorizex': 1000, + 'carriagereturn': 658, + 'aleph': 823, + 'Ifraktur': 686, + 'Rfraktur': 795, + 'weierstrass': 987, + 'circlemultiply': 768, + 'circleplus': 768, + 'emptyset': 823, + 'intersection': 768, + 'union': 768, + 'propersuperset': 713, + 'reflexsuperset': 713, + 'notsubset': 713, + 'propersubset': 713, + 'reflexsubset': 713, + 'element': 713, + 'notelement': 713, + 'angle': 768, + 'gradient': 713, + 'registerserif': 790, + 'copyrightserif': 790, + 'trademarkserif': 890, + 'product': 823, + 'radical': 549, + 'dotmath': 250, + 'logicalnot': 713, + 'logicaland': 603, + 'logicalor': 603, + 'arrowdblboth': 1042, + 'arrowdblleft': 987, + 'arrowdblup': 603, + 'arrowdblright': 987, + 'arrowdbldown': 603, + 'lozenge': 494, + 'angleleft': 329, + 'registersans': 790, + 'copyrightsans': 790, + 'trademarksans': 786, + 'summation': 713, + 'parenlefttp': 384, + 'parenleftex': 384, + 'parenleftbt': 384, + 'bracketlefttp': 384, + 'bracketleftex': 384, + 'bracketleftbt': 384, + 'bracelefttp': 494, + 'braceleftmid': 494, + 'braceleftbt': 494, + 'braceex': 494, + 'angleright': 329, + 'integral': 274, + 'integraltp': 686, + 'integralex': 686, + 'integralbt': 686, + 'parenrighttp': 384, + 'parenrightex': 384, + 'parenrightbt': 384, + 'bracketrighttp': 384, + 'bracketrightex': 384, + 'bracketrightbt': 384, + 'bracerighttp': 494, + 'bracerightmid': 494, + 'bracerightbt': 494, + 'apple': 790 + }, + 'Times-Roman': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 408, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 564, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 278, + 'semicolon': 278, + 'less': 564, + 'equal': 564, + 'greater': 564, + 'question': 444, + 'at': 921, + 'A': 722, + 'B': 667, + 'C': 667, + 'D': 722, + 'E': 611, + 'F': 556, + 'G': 722, + 'H': 722, + 'I': 333, + 'J': 389, + 'K': 722, + 'L': 611, + 'M': 889, + 'N': 722, + 'O': 722, + 'P': 556, + 'Q': 722, + 'R': 667, + 'S': 556, + 'T': 611, + 'U': 722, + 'V': 722, + 'W': 944, + 'X': 722, + 'Y': 722, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 469, + 'underscore': 500, + 'quoteleft': 333, + 'a': 444, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 500, + 'i': 278, + 'j': 278, + 'k': 500, + 'l': 278, + 'm': 778, + 'n': 500, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 333, + 's': 389, + 't': 278, + 'u': 500, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 444, + 'braceleft': 480, + 'bar': 200, + 'braceright': 480, + 'asciitilde': 541, + 'exclamdown': 333, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 180, + 'quotedblleft': 444, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 453, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 444, + 'quotedblright': 444, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 444, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 889, + 'ordfeminine': 276, + 'Lslash': 611, + 'Oslash': 722, + 'OE': 889, + 'ordmasculine': 310, + 'ae': 667, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 500, + 'Idieresis': 333, + 'eacute': 444, + 'abreve': 444, + 'uhungarumlaut': 500, + 'ecaron': 444, + 'Ydieresis': 722, + 'divide': 564, + 'Yacute': 722, + 'Acircumflex': 722, + 'aacute': 444, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 444, + 'Uacute': 722, + 'uogonek': 500, + 'Edieresis': 611, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 760, + 'Emacron': 611, + 'ccaron': 444, + 'aring': 444, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 444, + 'Tcommaaccent': 611, + 'Cacute': 667, + 'atilde': 444, + 'Edotaccent': 611, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 667, + 'Gcommaaccent': 722, + 'ucircumflex': 500, + 'acircumflex': 444, + 'Amacron': 722, + 'rcaron': 333, + 'ccedilla': 444, + 'Zdotaccent': 611, + 'Thorn': 556, + 'Omacron': 722, + 'Racute': 667, + 'Sacute': 556, + 'dcaron': 588, + 'Umacron': 722, + 'uring': 500, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 564, + 'uacute': 500, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 611, + 'adieresis': 444, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 500, + 'umacron': 500, + 'Ncaron': 722, + 'Iacute': 333, + 'plusminus': 564, + 'brokenbar': 200, + 'registered': 760, + 'Gbreve': 722, + 'Idotaccent': 333, + 'summation': 600, + 'Egrave': 611, + 'racute': 333, + 'omacron': 500, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 326, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 444, + 'zacute': 444, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 444, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 500, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 611, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 344, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 980, + 'edotaccent': 444, + 'Igrave': 333, + 'Imacron': 333, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 500, + 'Uhungarumlaut': 722, + 'Eacute': 611, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 500, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 667, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 722, + 'zdotaccent': 444, + 'Ecaron': 611, + 'Iogonek': 333, + 'kcommaaccent': 500, + 'minus': 564, + 'Icircumflex': 333, + 'ncaron': 500, + 'tcommaaccent': 278, + 'logicalnot': 564, + 'odieresis': 500, + 'udieresis': 500, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 444, + 'ncommaaccent': 500, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-Bold': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 555, + 'numbersign': 500, + 'dollar': 500, + 'percent': 1000, + 'ampersand': 833, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 570, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 570, + 'equal': 570, + 'greater': 570, + 'question': 500, + 'at': 930, + 'A': 722, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 778, + 'I': 389, + 'J': 500, + 'K': 778, + 'L': 667, + 'M': 944, + 'N': 722, + 'O': 778, + 'P': 611, + 'Q': 778, + 'R': 722, + 'S': 556, + 'T': 667, + 'U': 722, + 'V': 722, + 'W': 1000, + 'X': 722, + 'Y': 722, + 'Z': 667, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 581, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 556, + 'c': 444, + 'd': 556, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 556, + 'i': 278, + 'j': 333, + 'k': 556, + 'l': 278, + 'm': 833, + 'n': 556, + 'o': 500, + 'p': 556, + 'q': 556, + 'r': 444, + 's': 389, + 't': 333, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 444, + 'braceleft': 394, + 'bar': 220, + 'braceright': 394, + 'asciitilde': 520, + 'exclamdown': 333, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 278, + 'quotedblleft': 500, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 540, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 300, + 'Lslash': 667, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 330, + 'ae': 722, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 556, + 'Idieresis': 389, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 556, + 'ecaron': 444, + 'Ydieresis': 722, + 'divide': 570, + 'Yacute': 722, + 'Acircumflex': 722, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 747, + 'Emacron': 667, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 667, + 'Cacute': 722, + 'atilde': 500, + 'Edotaccent': 667, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 500, + 'Amacron': 722, + 'rcaron': 444, + 'ccedilla': 444, + 'Zdotaccent': 667, + 'Thorn': 611, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 556, + 'dcaron': 672, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 300, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 570, + 'uacute': 556, + 'Tcaron': 667, + 'partialdiff': 494, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 389, + 'plusminus': 570, + 'brokenbar': 220, + 'registered': 747, + 'Gbreve': 778, + 'Idotaccent': 389, + 'summation': 600, + 'Egrave': 667, + 'racute': 444, + 'omacron': 500, + 'Zacute': 667, + 'Zcaron': 667, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 416, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 444, + 'zacute': 444, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 300, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 394, + 'Kcommaaccent': 778, + 'Lacute': 667, + 'trademark': 1000, + 'edotaccent': 444, + 'Igrave': 389, + 'Imacron': 389, + 'Lcaron': 667, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 444, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 722, + 'Lcommaaccent': 667, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 444, + 'Ecaron': 667, + 'Iogonek': 389, + 'kcommaaccent': 556, + 'minus': 570, + 'Icircumflex': 389, + 'ncaron': 556, + 'tcommaaccent': 333, + 'logicalnot': 570, + 'odieresis': 500, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 444, + 'ncommaaccent': 556, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-BoldItalic': { + 'space': 250, + 'exclam': 389, + 'quotedbl': 555, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 570, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 570, + 'equal': 570, + 'greater': 570, + 'question': 500, + 'at': 832, + 'A': 667, + 'B': 667, + 'C': 667, + 'D': 722, + 'E': 667, + 'F': 667, + 'G': 722, + 'H': 778, + 'I': 389, + 'J': 500, + 'K': 667, + 'L': 611, + 'M': 889, + 'N': 722, + 'O': 722, + 'P': 611, + 'Q': 722, + 'R': 667, + 'S': 556, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 889, + 'X': 667, + 'Y': 611, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 570, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 556, + 'i': 278, + 'j': 278, + 'k': 500, + 'l': 278, + 'm': 778, + 'n': 556, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 389, + 's': 389, + 't': 278, + 'u': 556, + 'v': 444, + 'w': 667, + 'x': 500, + 'y': 444, + 'z': 389, + 'braceleft': 348, + 'bar': 220, + 'braceright': 348, + 'asciitilde': 570, + 'exclamdown': 389, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 278, + 'quotedblleft': 500, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 500, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 944, + 'ordfeminine': 266, + 'Lslash': 611, + 'Oslash': 722, + 'OE': 944, + 'ordmasculine': 300, + 'ae': 722, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 500, + 'Idieresis': 389, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 556, + 'ecaron': 444, + 'Ydieresis': 611, + 'divide': 570, + 'Yacute': 611, + 'Acircumflex': 667, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 444, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 747, + 'Emacron': 667, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 611, + 'Cacute': 667, + 'atilde': 500, + 'Edotaccent': 667, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 667, + 'Gcommaaccent': 722, + 'ucircumflex': 556, + 'acircumflex': 500, + 'Amacron': 667, + 'rcaron': 389, + 'ccedilla': 444, + 'Zdotaccent': 611, + 'Thorn': 611, + 'Omacron': 722, + 'Racute': 667, + 'Sacute': 556, + 'dcaron': 608, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 570, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 444, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 389, + 'plusminus': 570, + 'brokenbar': 220, + 'registered': 747, + 'Gbreve': 722, + 'Idotaccent': 389, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 500, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 366, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 444, + 'zacute': 389, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 576, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 667, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 382, + 'Kcommaaccent': 667, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 444, + 'Igrave': 389, + 'Imacron': 389, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 556, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 667, + 'Lcommaaccent': 611, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 722, + 'zdotaccent': 389, + 'Ecaron': 667, + 'Iogonek': 389, + 'kcommaaccent': 500, + 'minus': 606, + 'Icircumflex': 389, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 606, + 'odieresis': 500, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 389, + 'ncommaaccent': 556, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-Italic': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 420, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 675, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 675, + 'equal': 675, + 'greater': 675, + 'question': 500, + 'at': 920, + 'A': 611, + 'B': 611, + 'C': 667, + 'D': 722, + 'E': 611, + 'F': 611, + 'G': 722, + 'H': 722, + 'I': 333, + 'J': 444, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 667, + 'O': 722, + 'P': 611, + 'Q': 722, + 'R': 611, + 'S': 500, + 'T': 556, + 'U': 722, + 'V': 611, + 'W': 833, + 'X': 611, + 'Y': 556, + 'Z': 556, + 'bracketleft': 389, + 'backslash': 278, + 'bracketright': 389, + 'asciicircum': 422, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 278, + 'g': 500, + 'h': 500, + 'i': 278, + 'j': 278, + 'k': 444, + 'l': 278, + 'm': 722, + 'n': 500, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 389, + 's': 389, + 't': 278, + 'u': 500, + 'v': 444, + 'w': 667, + 'x': 444, + 'y': 444, + 'z': 389, + 'braceleft': 400, + 'bar': 275, + 'braceright': 400, + 'asciitilde': 541, + 'exclamdown': 389, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 214, + 'quotedblleft': 556, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 523, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 556, + 'quotedblright': 556, + 'guillemotright': 500, + 'ellipsis': 889, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 889, + 'AE': 889, + 'ordfeminine': 276, + 'Lslash': 556, + 'Oslash': 722, + 'OE': 944, + 'ordmasculine': 310, + 'ae': 667, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 667, + 'germandbls': 500, + 'Idieresis': 333, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 500, + 'ecaron': 444, + 'Ydieresis': 556, + 'divide': 675, + 'Yacute': 556, + 'Acircumflex': 611, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 444, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 500, + 'Edieresis': 611, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 760, + 'Emacron': 611, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 667, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 556, + 'Cacute': 667, + 'atilde': 500, + 'Edotaccent': 611, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 611, + 'Gcommaaccent': 722, + 'ucircumflex': 500, + 'acircumflex': 500, + 'Amacron': 611, + 'rcaron': 389, + 'ccedilla': 444, + 'Zdotaccent': 556, + 'Thorn': 611, + 'Omacron': 722, + 'Racute': 611, + 'Sacute': 500, + 'dcaron': 544, + 'Umacron': 722, + 'uring': 500, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 611, + 'Abreve': 611, + 'multiply': 675, + 'uacute': 500, + 'Tcaron': 556, + 'partialdiff': 476, + 'ydieresis': 444, + 'Nacute': 667, + 'icircumflex': 278, + 'Ecircumflex': 611, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 500, + 'umacron': 500, + 'Ncaron': 667, + 'Iacute': 333, + 'plusminus': 675, + 'brokenbar': 275, + 'registered': 760, + 'Gbreve': 722, + 'Idotaccent': 333, + 'summation': 600, + 'Egrave': 611, + 'racute': 389, + 'omacron': 500, + 'Zacute': 556, + 'Zcaron': 556, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 300, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 611, + 'Adieresis': 611, + 'egrave': 444, + 'zacute': 389, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 500, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 611, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 500, + 'lcaron': 300, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 980, + 'edotaccent': 444, + 'Igrave': 333, + 'Imacron': 333, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 500, + 'Uhungarumlaut': 722, + 'Eacute': 611, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 500, + 'Scommaaccent': 500, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 500, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 667, + 'otilde': 500, + 'Rcommaaccent': 611, + 'Lcommaaccent': 556, + 'Atilde': 611, + 'Aogonek': 611, + 'Aring': 611, + 'Otilde': 722, + 'zdotaccent': 389, + 'Ecaron': 611, + 'Iogonek': 333, + 'kcommaaccent': 444, + 'minus': 675, + 'Icircumflex': 333, + 'ncaron': 500, + 'tcommaaccent': 278, + 'logicalnot': 675, + 'odieresis': 500, + 'udieresis': 500, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 389, + 'ncommaaccent': 500, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'ZapfDingbats': { + 'space': 278, + 'a1': 974, + 'a2': 961, + 'a202': 974, + 'a3': 980, + 'a4': 719, + 'a5': 789, + 'a119': 790, + 'a118': 791, + 'a117': 690, + 'a11': 960, + 'a12': 939, + 'a13': 549, + 'a14': 855, + 'a15': 911, + 'a16': 933, + 'a105': 911, + 'a17': 945, + 'a18': 974, + 'a19': 755, + 'a20': 846, + 'a21': 762, + 'a22': 761, + 'a23': 571, + 'a24': 677, + 'a25': 763, + 'a26': 760, + 'a27': 759, + 'a28': 754, + 'a6': 494, + 'a7': 552, + 'a8': 537, + 'a9': 577, + 'a10': 692, + 'a29': 786, + 'a30': 788, + 'a31': 788, + 'a32': 790, + 'a33': 793, + 'a34': 794, + 'a35': 816, + 'a36': 823, + 'a37': 789, + 'a38': 841, + 'a39': 823, + 'a40': 833, + 'a41': 816, + 'a42': 831, + 'a43': 923, + 'a44': 744, + 'a45': 723, + 'a46': 749, + 'a47': 790, + 'a48': 792, + 'a49': 695, + 'a50': 776, + 'a51': 768, + 'a52': 792, + 'a53': 759, + 'a54': 707, + 'a55': 708, + 'a56': 682, + 'a57': 701, + 'a58': 826, + 'a59': 815, + 'a60': 789, + 'a61': 789, + 'a62': 707, + 'a63': 687, + 'a64': 696, + 'a65': 689, + 'a66': 786, + 'a67': 787, + 'a68': 713, + 'a69': 791, + 'a70': 785, + 'a71': 791, + 'a72': 873, + 'a73': 761, + 'a74': 762, + 'a203': 762, + 'a75': 759, + 'a204': 759, + 'a76': 892, + 'a77': 892, + 'a78': 788, + 'a79': 784, + 'a81': 438, + 'a82': 138, + 'a83': 277, + 'a84': 415, + 'a97': 392, + 'a98': 392, + 'a99': 668, + 'a100': 668, + 'a89': 390, + 'a90': 390, + 'a93': 317, + 'a94': 317, + 'a91': 276, + 'a92': 276, + 'a205': 509, + 'a85': 509, + 'a206': 410, + 'a86': 410, + 'a87': 234, + 'a88': 234, + 'a95': 334, + 'a96': 334, + 'a101': 732, + 'a102': 544, + 'a103': 544, + 'a104': 910, + 'a106': 667, + 'a107': 760, + 'a108': 760, + 'a112': 776, + 'a111': 595, + 'a110': 694, + 'a109': 626, + 'a120': 788, + 'a121': 788, + 'a122': 788, + 'a123': 788, + 'a124': 788, + 'a125': 788, + 'a126': 788, + 'a127': 788, + 'a128': 788, + 'a129': 788, + 'a130': 788, + 'a131': 788, + 'a132': 788, + 'a133': 788, + 'a134': 788, + 'a135': 788, + 'a136': 788, + 'a137': 788, + 'a138': 788, + 'a139': 788, + 'a140': 788, + 'a141': 788, + 'a142': 788, + 'a143': 788, + 'a144': 788, + 'a145': 788, + 'a146': 788, + 'a147': 788, + 'a148': 788, + 'a149': 788, + 'a150': 788, + 'a151': 788, + 'a152': 788, + 'a153': 788, + 'a154': 788, + 'a155': 788, + 'a156': 788, + 'a157': 788, + 'a158': 788, + 'a159': 788, + 'a160': 894, + 'a161': 838, + 'a163': 1016, + 'a164': 458, + 'a196': 748, + 'a165': 924, + 'a192': 748, + 'a166': 918, + 'a167': 927, + 'a168': 928, + 'a169': 928, + 'a170': 834, + 'a171': 873, + 'a172': 828, + 'a173': 924, + 'a162': 924, + 'a174': 917, + 'a175': 930, + 'a176': 931, + 'a177': 463, + 'a178': 883, + 'a179': 836, + 'a193': 836, + 'a180': 867, + 'a199': 867, + 'a181': 696, + 'a200': 696, + 'a182': 874, + 'a201': 874, + 'a183': 760, + 'a184': 946, + 'a197': 771, + 'a185': 865, + 'a194': 771, + 'a198': 888, + 'a186': 967, + 'a195': 888, + 'a187': 831, + 'a188': 873, + 'a189': 927, + 'a190': 970, + 'a191': 918 + } +}; + + +var EOF = {}; + +function isEOF(v) { + return (v === EOF); +} + +var MAX_LENGTH_TO_CACHE = 1000; + +var Parser = (function ParserClosure() { + function Parser(lexer, allowStreams, xref) { + this.lexer = lexer; + this.allowStreams = allowStreams; + this.xref = xref; + this.imageCache = {}; + this.refill(); + } + + Parser.prototype = { + refill: function Parser_refill() { + this.buf1 = this.lexer.getObj(); + this.buf2 = this.lexer.getObj(); + }, + shift: function Parser_shift() { + if (isCmd(this.buf2, 'ID')) { + this.buf1 = this.buf2; + this.buf2 = null; + } else { + this.buf1 = this.buf2; + this.buf2 = this.lexer.getObj(); + } + }, + getObj: function Parser_getObj(cipherTransform) { + var buf1 = this.buf1; + this.shift(); + + if (buf1 instanceof Cmd) { + switch (buf1.cmd) { + case 'BI': // inline image + return this.makeInlineImage(cipherTransform); + case '[': // array + var array = []; + while (!isCmd(this.buf1, ']') && !isEOF(this.buf1)) { + array.push(this.getObj(cipherTransform)); + } + if (isEOF(this.buf1)) { + error('End of file inside array'); + } + this.shift(); + return array; + case '<<': // dictionary or stream + var dict = new Dict(this.xref); + while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) { + if (!isName(this.buf1)) { + info('Malformed dictionary: key must be a name object'); + this.shift(); + continue; + } + + var key = this.buf1.name; + this.shift(); + if (isEOF(this.buf1)) { + break; + } + dict.set(key, this.getObj(cipherTransform)); + } + if (isEOF(this.buf1)) { + error('End of file inside dictionary'); + } + + // Stream objects are not allowed inside content streams or + // object streams. + if (isCmd(this.buf2, 'stream')) { + return (this.allowStreams ? + this.makeStream(dict, cipherTransform) : dict); + } + this.shift(); + return dict; + default: // simple object + return buf1; + } + } + + if (isInt(buf1)) { // indirect reference or integer + var num = buf1; + if (isInt(this.buf1) && isCmd(this.buf2, 'R')) { + var ref = new Ref(num, this.buf1); + this.shift(); + this.shift(); + return ref; + } + return num; + } + + if (isString(buf1)) { // string + var str = buf1; + if (cipherTransform) { + str = cipherTransform.decryptString(str); + } + return str; + } + + // simple object + return buf1; + }, + /** + * Find the end of the stream by searching for the /EI\s/. + * @returns {number} The inline stream length. + */ + findDefaultInlineStreamEnd: + function Parser_findDefaultInlineStreamEnd(stream) { + var E = 0x45, I = 0x49, SPACE = 0x20, LF = 0xA, CR = 0xD; + var startPos = stream.pos, state = 0, ch, i, n, followingBytes; + while ((ch = stream.getByte()) !== -1) { + if (state === 0) { + state = (ch === E) ? 1 : 0; + } else if (state === 1) { + state = (ch === I) ? 2 : 0; + } else { + assert(state === 2); + if (ch === SPACE || ch === LF || ch === CR) { + // Let's check the next five bytes are ASCII... just be sure. + n = 5; + followingBytes = stream.peekBytes(n); + for (i = 0; i < n; i++) { + ch = followingBytes[i]; + if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) { + // Not a LF, CR, SPACE or any visible ASCII character, i.e. + // it's binary stuff. Resetting the state. + state = 0; + break; + } + } + if (state === 2) { + break; // Finished! + } + } else { + state = 0; + } + } + } + return ((stream.pos - 4) - startPos); + }, + /** + * Find the EOI (end-of-image) marker 0xFFD9 of the stream. + * @returns {number} The inline stream length. + */ + findDCTDecodeInlineStreamEnd: + function Parser_findDCTDecodeInlineStreamEnd(stream) { + var startPos = stream.pos, foundEOI = false, b, markerLength, length; + while ((b = stream.getByte()) !== -1) { + if (b !== 0xFF) { // Not a valid marker. + continue; + } + switch (stream.getByte()) { + case 0x00: // Byte stuffing. + // 0xFF00 appears to be a very common byte sequence in JPEG images. + break; + + case 0xFF: // Fill byte. + // Avoid skipping a valid marker, resetting the stream position. + stream.skip(-1); + break; + + case 0xD9: // EOI + foundEOI = true; + break; + + case 0xC0: // SOF0 + case 0xC1: // SOF1 + case 0xC2: // SOF2 + case 0xC3: // SOF3 + + case 0xC5: // SOF5 + case 0xC6: // SOF6 + case 0xC7: // SOF7 + + case 0xC9: // SOF9 + case 0xCA: // SOF10 + case 0xCB: // SOF11 + + case 0xCD: // SOF13 + case 0xCE: // SOF14 + case 0xCF: // SOF15 + + case 0xC4: // DHT + case 0xCC: // DAC + + case 0xDA: // SOS + case 0xDB: // DQT + case 0xDC: // DNL + case 0xDD: // DRI + case 0xDE: // DHP + case 0xDF: // EXP + + case 0xE0: // APP0 + case 0xE1: // APP1 + case 0xE2: // APP2 + case 0xE3: // APP3 + case 0xE4: // APP4 + case 0xE5: // APP5 + case 0xE6: // APP6 + case 0xE7: // APP7 + case 0xE8: // APP8 + case 0xE9: // APP9 + case 0xEA: // APP10 + case 0xEB: // APP11 + case 0xEC: // APP12 + case 0xED: // APP13 + case 0xEE: // APP14 + case 0xEF: // APP15 + + case 0xFE: // COM + // The marker should be followed by the length of the segment. + markerLength = stream.getUint16(); + if (markerLength > 2) { + // |markerLength| contains the byte length of the marker segment, + // including its own length (2 bytes) and excluding the marker. + stream.skip(markerLength - 2); // Jump to the next marker. + } else { + // The marker length is invalid, resetting the stream position. + stream.skip(-2); + } + break; + } + if (foundEOI) { + break; + } + } + length = stream.pos - startPos; + if (b === -1) { + warn('Inline DCTDecode image stream: ' + + 'EOI marker not found, searching for /EI/ instead.'); + stream.skip(-length); // Reset the stream position. + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + /** + * Find the EOD (end-of-data) marker '~>' (i.e. TILDE + GT) of the stream. + * @returns {number} The inline stream length. + */ + findASCII85DecodeInlineStreamEnd: + function Parser_findASCII85DecodeInlineStreamEnd(stream) { + var TILDE = 0x7E, GT = 0x3E; + var startPos = stream.pos, ch, length; + while ((ch = stream.getByte()) !== -1) { + if (ch === TILDE && stream.peekByte() === GT) { + stream.skip(); + break; + } + } + length = stream.pos - startPos; + if (ch === -1) { + warn('Inline ASCII85Decode image stream: ' + + 'EOD marker not found, searching for /EI/ instead.'); + stream.skip(-length); // Reset the stream position. + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + /** + * Find the EOD (end-of-data) marker '>' (i.e. GT) of the stream. + * @returns {number} The inline stream length. + */ + findASCIIHexDecodeInlineStreamEnd: + function Parser_findASCIIHexDecodeInlineStreamEnd(stream) { + var GT = 0x3E; + var startPos = stream.pos, ch, length; + while ((ch = stream.getByte()) !== -1) { + if (ch === GT) { + break; + } + } + length = stream.pos - startPos; + if (ch === -1) { + warn('Inline ASCIIHexDecode image stream: ' + + 'EOD marker not found, searching for /EI/ instead.'); + stream.skip(-length); // Reset the stream position. + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + /** + * Skip over the /EI/ for streams where we search for an EOD marker. + */ + inlineStreamSkipEI: function Parser_inlineStreamSkipEI(stream) { + var E = 0x45, I = 0x49; + var state = 0, ch; + while ((ch = stream.getByte()) !== -1) { + if (state === 0) { + state = (ch === E) ? 1 : 0; + } else if (state === 1) { + state = (ch === I) ? 2 : 0; + } else if (state === 2) { + break; + } + } + }, + makeInlineImage: function Parser_makeInlineImage(cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + + // Parse dictionary. + var dict = new Dict(null); + while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) { + if (!isName(this.buf1)) { + error('Dictionary key must be a name object'); + } + var key = this.buf1.name; + this.shift(); + if (isEOF(this.buf1)) { + break; + } + dict.set(key, this.getObj(cipherTransform)); + } + + // Extract the name of the first (i.e. the current) image filter. + var filter = this.fetchIfRef(dict.get('Filter', 'F')), filterName; + if (isName(filter)) { + filterName = filter.name; + } else if (isArray(filter) && isName(filter[0])) { + filterName = filter[0].name; + } + + // Parse image stream. + var startPos = stream.pos, length, i, ii; + if (filterName === 'DCTDecode' || filterName === 'DCT') { + length = this.findDCTDecodeInlineStreamEnd(stream); + } else if (filterName === 'ASCII85Decide' || filterName === 'A85') { + length = this.findASCII85DecodeInlineStreamEnd(stream); + } else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') { + length = this.findASCIIHexDecodeInlineStreamEnd(stream); + } else { + length = this.findDefaultInlineStreamEnd(stream); + } + var imageStream = stream.makeSubStream(startPos, length, dict); + + // Cache all images below the MAX_LENGTH_TO_CACHE threshold by their + // adler32 checksum. + var adler32; + if (length < MAX_LENGTH_TO_CACHE) { + var imageBytes = imageStream.getBytes(); + imageStream.reset(); + + var a = 1; + var b = 0; + for (i = 0, ii = imageBytes.length; i < ii; ++i) { + // No modulo required in the loop if imageBytes.length < 5552. + a += imageBytes[i] & 0xff; + b += a; + } + adler32 = ((b % 65521) << 16) | (a % 65521); + + if (this.imageCache.adler32 === adler32) { + this.buf2 = Cmd.get('EI'); + this.shift(); + + this.imageCache[adler32].reset(); + return this.imageCache[adler32]; + } + } + + if (cipherTransform) { + imageStream = cipherTransform.createStream(imageStream, length); + } + + imageStream = this.filter(imageStream, dict, length); + imageStream.dict = dict; + if (adler32 !== undefined) { + imageStream.cacheKey = 'inline_' + length + '_' + adler32; + this.imageCache[adler32] = imageStream; + } + + this.buf2 = Cmd.get('EI'); + this.shift(); + + return imageStream; + }, + fetchIfRef: function Parser_fetchIfRef(obj) { + // not relying on the xref.fetchIfRef -- xref might not be set + return (isRef(obj) ? this.xref.fetch(obj) : obj); + }, + makeStream: function Parser_makeStream(dict, cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + + // get stream start position + lexer.skipToNextLine(); + var pos = stream.pos - 1; + + // get length + var length = this.fetchIfRef(dict.get('Length')); + if (!isInt(length)) { + info('Bad ' + length + ' attribute in stream'); + length = 0; + } + + // skip over the stream data + stream.pos = pos + length; + lexer.nextChar(); + + this.shift(); // '>>' + this.shift(); // 'stream' + if (!isCmd(this.buf1, 'endstream')) { + // bad stream length, scanning for endstream + stream.pos = pos; + var SCAN_BLOCK_SIZE = 2048; + var ENDSTREAM_SIGNATURE_LENGTH = 9; + var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6D]; + var skipped = 0, found = false, i, j; + while (stream.pos < stream.end) { + var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE); + var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH; + if (scanLength <= 0) { + break; + } + found = false; + for (i = 0, j = 0; i < scanLength; i++) { + var b = scanBytes[i]; + if (b !== ENDSTREAM_SIGNATURE[j]) { + i -= j; + j = 0; + } else { + j++; + if (j >= ENDSTREAM_SIGNATURE_LENGTH) { + i++; + found = true; + break; + } + } + } + if (found) { + skipped += i - ENDSTREAM_SIGNATURE_LENGTH; + stream.pos += i - ENDSTREAM_SIGNATURE_LENGTH; + break; + } + skipped += scanLength; + stream.pos += scanLength; + } + if (!found) { + error('Missing endstream'); + } + length = skipped; + + lexer.nextChar(); + this.shift(); + this.shift(); + } + this.shift(); // 'endstream' + + stream = stream.makeSubStream(pos, length, dict); + if (cipherTransform) { + stream = cipherTransform.createStream(stream, length); + } + stream = this.filter(stream, dict, length); + stream.dict = dict; + return stream; + }, + filter: function Parser_filter(stream, dict, length) { + var filter = this.fetchIfRef(dict.get('Filter', 'F')); + var params = this.fetchIfRef(dict.get('DecodeParms', 'DP')); + if (isName(filter)) { + return this.makeFilter(stream, filter.name, length, params); + } + + var maybeLength = length; + if (isArray(filter)) { + var filterArray = filter; + var paramsArray = params; + for (var i = 0, ii = filterArray.length; i < ii; ++i) { + filter = filterArray[i]; + if (!isName(filter)) { + error('Bad filter name: ' + filter); + } + + params = null; + if (isArray(paramsArray) && (i in paramsArray)) { + params = paramsArray[i]; + } + stream = this.makeFilter(stream, filter.name, maybeLength, params); + // after the first stream the length variable is invalid + maybeLength = null; + } + } + return stream; + }, + makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) { + if (stream.dict.get('Length') === 0) { + return new NullStream(stream); + } + try { + if (params) { + params = this.fetchIfRef(params); + } + var xrefStreamStats = this.xref.stats.streamTypes; + if (name === 'FlateDecode' || name === 'Fl') { + xrefStreamStats[StreamType.FLATE] = true; + if (params) { + return new PredictorStream(new FlateStream(stream, maybeLength), + maybeLength, params); + } + return new FlateStream(stream, maybeLength); + } + if (name === 'LZWDecode' || name === 'LZW') { + xrefStreamStats[StreamType.LZW] = true; + var earlyChange = 1; + if (params) { + if (params.has('EarlyChange')) { + earlyChange = params.get('EarlyChange'); + } + return new PredictorStream( + new LZWStream(stream, maybeLength, earlyChange), + maybeLength, params); + } + return new LZWStream(stream, maybeLength, earlyChange); + } + if (name === 'DCTDecode' || name === 'DCT') { + xrefStreamStats[StreamType.DCT] = true; + return new JpegStream(stream, maybeLength, stream.dict, this.xref); + } + if (name === 'JPXDecode' || name === 'JPX') { + xrefStreamStats[StreamType.JPX] = true; + return new JpxStream(stream, maybeLength, stream.dict); + } + if (name === 'ASCII85Decode' || name === 'A85') { + xrefStreamStats[StreamType.A85] = true; + return new Ascii85Stream(stream, maybeLength); + } + if (name === 'ASCIIHexDecode' || name === 'AHx') { + xrefStreamStats[StreamType.AHX] = true; + return new AsciiHexStream(stream, maybeLength); + } + if (name === 'CCITTFaxDecode' || name === 'CCF') { + xrefStreamStats[StreamType.CCF] = true; + return new CCITTFaxStream(stream, maybeLength, params); + } + if (name === 'RunLengthDecode' || name === 'RL') { + xrefStreamStats[StreamType.RL] = true; + return new RunLengthStream(stream, maybeLength); + } + if (name === 'JBIG2Decode') { + xrefStreamStats[StreamType.JBIG] = true; + return new Jbig2Stream(stream, maybeLength, stream.dict); + } + warn('filter "' + name + '" not supported yet'); + return stream; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Invalid stream: \"' + ex + '\"'); + return new NullStream(stream); + } + } + }; + + return Parser; +})(); + +var Lexer = (function LexerClosure() { + function Lexer(stream, knownCommands) { + this.stream = stream; + this.nextChar(); + + // While lexing, we build up many strings one char at a time. Using += for + // this can result in lots of garbage strings. It's better to build an + // array of single-char strings and then join() them together at the end. + // And reusing a single array (i.e. |this.strBuf|) over and over for this + // purpose uses less memory than using a new array for each string. + this.strBuf = []; + + // The PDFs might have "glued" commands with other commands, operands or + // literals, e.g. "q1". The knownCommands is a dictionary of the valid + // commands and their prefixes. The prefixes are built the following way: + // if there a command that is a prefix of the other valid command or + // literal (e.g. 'f' and 'false') the following prefixes must be included, + // 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no + // other commands or literals as a prefix. The knowCommands is optional. + this.knownCommands = knownCommands; + } + + Lexer.isSpace = function Lexer_isSpace(ch) { + // Space is one of the following characters: SPACE, TAB, CR or LF. + return (ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A); + }; + + // A '1' in this array means the character is white space. A '1' or + // '2' means the character ends a name or command. + var specialChars = [ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx + ]; + + function toHexDigit(ch) { + if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' + return ch & 0x0F; + } + if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { + // 'A'-'F', 'a'-'f' + return (ch & 0x0F) + 9; + } + return -1; + } + + Lexer.prototype = { + nextChar: function Lexer_nextChar() { + return (this.currentChar = this.stream.getByte()); + }, + peekChar: function Lexer_peekChar() { + return this.stream.peekByte(); + }, + getNumber: function Lexer_getNumber() { + var ch = this.currentChar; + var eNotation = false; + var divideBy = 0; // different from 0 if it's a floating point value + var sign = 1; + + if (ch === 0x2D) { // '-' + sign = -1; + ch = this.nextChar(); + } else if (ch === 0x2B) { // '+' + ch = this.nextChar(); + } + if (ch === 0x2E) { // '.' + divideBy = 10; + ch = this.nextChar(); + } + if (ch < 0x30 || ch > 0x39) { // '0' - '9' + error('Invalid number: ' + String.fromCharCode(ch)); + return 0; + } + + var baseValue = ch - 0x30; // '0' + var powerValue = 0; + var powerValueSign = 1; + + while ((ch = this.nextChar()) >= 0) { + if (0x30 <= ch && ch <= 0x39) { // '0' - '9' + var currentDigit = ch - 0x30; // '0' + if (eNotation) { // We are after an 'e' or 'E' + powerValue = powerValue * 10 + currentDigit; + } else { + if (divideBy !== 0) { // We are after a point + divideBy *= 10; + } + baseValue = baseValue * 10 + currentDigit; + } + } else if (ch === 0x2E) { // '.' + if (divideBy === 0) { + divideBy = 1; + } else { + // A number can have only one '.' + break; + } + } else if (ch === 0x2D) { // '-' + // ignore minus signs in the middle of numbers to match + // Adobe's behavior + warn('Badly formated number'); + } else if (ch === 0x45 || ch === 0x65) { // 'E', 'e' + // 'E' can be either a scientific notation or the beginning of a new + // operator + ch = this.peekChar(); + if (ch === 0x2B || ch === 0x2D) { // '+', '-' + powerValueSign = (ch === 0x2D) ? -1 : 1; + this.nextChar(); // Consume the sign character + } else if (ch < 0x30 || ch > 0x39) { // '0' - '9' + // The 'E' must be the beginning of a new operator + break; + } + eNotation = true; + } else { + // the last character doesn't belong to us + break; + } + } + + if (divideBy !== 0) { + baseValue /= divideBy; + } + if (eNotation) { + baseValue *= Math.pow(10, powerValueSign * powerValue); + } + return sign * baseValue; + }, + getString: function Lexer_getString() { + var numParen = 1; + var done = false; + var strBuf = this.strBuf; + strBuf.length = 0; + + var ch = this.nextChar(); + while (true) { + var charBuffered = false; + switch (ch | 0) { + case -1: + warn('Unterminated string'); + done = true; + break; + case 0x28: // '(' + ++numParen; + strBuf.push('('); + break; + case 0x29: // ')' + if (--numParen === 0) { + this.nextChar(); // consume strings ')' + done = true; + } else { + strBuf.push(')'); + } + break; + case 0x5C: // '\\' + ch = this.nextChar(); + switch (ch) { + case -1: + warn('Unterminated string'); + done = true; + break; + case 0x6E: // 'n' + strBuf.push('\n'); + break; + case 0x72: // 'r' + strBuf.push('\r'); + break; + case 0x74: // 't' + strBuf.push('\t'); + break; + case 0x62: // 'b' + strBuf.push('\b'); + break; + case 0x66: // 'f' + strBuf.push('\f'); + break; + case 0x5C: // '\' + case 0x28: // '(' + case 0x29: // ')' + strBuf.push(String.fromCharCode(ch)); + break; + case 0x30: case 0x31: case 0x32: case 0x33: // '0'-'3' + case 0x34: case 0x35: case 0x36: case 0x37: // '4'-'7' + var x = ch & 0x0F; + ch = this.nextChar(); + charBuffered = true; + if (ch >= 0x30 && ch <= 0x37) { // '0'-'7' + x = (x << 3) + (ch & 0x0F); + ch = this.nextChar(); + if (ch >= 0x30 && ch <= 0x37) { // '0'-'7' + charBuffered = false; + x = (x << 3) + (ch & 0x0F); + } + } + strBuf.push(String.fromCharCode(x)); + break; + case 0x0D: // CR + if (this.peekChar() === 0x0A) { // LF + this.nextChar(); + } + break; + case 0x0A: // LF + break; + default: + strBuf.push(String.fromCharCode(ch)); + break; + } + break; + default: + strBuf.push(String.fromCharCode(ch)); + break; + } + if (done) { + break; + } + if (!charBuffered) { + ch = this.nextChar(); + } + } + return strBuf.join(''); + }, + getName: function Lexer_getName() { + var ch; + var strBuf = this.strBuf; + strBuf.length = 0; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + if (ch === 0x23) { // '#' + ch = this.nextChar(); + var x = toHexDigit(ch); + if (x !== -1) { + var x2 = toHexDigit(this.nextChar()); + if (x2 === -1) { + error('Illegal digit in hex char in name: ' + x2); + } + strBuf.push(String.fromCharCode((x << 4) | x2)); + } else { + strBuf.push('#', String.fromCharCode(ch)); + } + } else { + strBuf.push(String.fromCharCode(ch)); + } + } + if (strBuf.length > 128) { + error('Warning: name token is longer than allowed by the spec: ' + + strBuf.length); + } + return Name.get(strBuf.join('')); + }, + getHexString: function Lexer_getHexString() { + var strBuf = this.strBuf; + strBuf.length = 0; + var ch = this.currentChar; + var isFirstHex = true; + var firstDigit; + var secondDigit; + while (true) { + if (ch < 0) { + warn('Unterminated hex string'); + break; + } else if (ch === 0x3E) { // '>' + this.nextChar(); + break; + } else if (specialChars[ch] === 1) { + ch = this.nextChar(); + + } else { + if (isFirstHex) { + firstDigit = toHexDigit(ch); + if (firstDigit === -1) { + warn('Ignoring invalid character "' + ch + '" in hex string'); + ch = this.nextChar(); + continue; + } + } else { + secondDigit = toHexDigit(ch); + if (secondDigit === -1) { + warn('Ignoring invalid character "' + ch + '" in hex string'); + ch = this.nextChar(); + continue; + } + strBuf.push(String.fromCharCode((firstDigit << 4) | secondDigit)); + } + isFirstHex = !isFirstHex; + ch = this.nextChar(); + } + } + return strBuf.join(''); + }, + getObj: function Lexer_getObj() { + // skip whitespace and comments + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch < 0) { + return EOF; + } + if (comment) { + if (ch === 0x0A || ch === 0x0D) { // LF, CR + comment = false; + } + } else if (ch === 0x25) { // '%' + comment = true; + } else if (specialChars[ch] !== 1) { + break; + } + ch = this.nextChar(); + } + + // start reading token + switch (ch | 0) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4' + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9' + case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.' + return this.getNumber(); + case 0x28: // '(' + return this.getString(); + case 0x2F: // '/' + return this.getName(); + // array punctuation + case 0x5B: // '[' + this.nextChar(); + return Cmd.get('['); + case 0x5D: // ']' + this.nextChar(); + return Cmd.get(']'); + // hex string or dict punctuation + case 0x3C: // '<' + ch = this.nextChar(); + if (ch === 0x3C) { + // dict punctuation + this.nextChar(); + return Cmd.get('<<'); + } + return this.getHexString(); + // dict punctuation + case 0x3E: // '>' + ch = this.nextChar(); + if (ch === 0x3E) { + this.nextChar(); + return Cmd.get('>>'); + } + return Cmd.get('>'); + case 0x7B: // '{' + this.nextChar(); + return Cmd.get('{'); + case 0x7D: // '}' + this.nextChar(); + return Cmd.get('}'); + case 0x29: // ')' + error('Illegal character: ' + ch); + break; + } + + // command + var str = String.fromCharCode(ch); + var knownCommands = this.knownCommands; + var knownCommandFound = knownCommands && knownCommands[str] !== undefined; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + // stop if known command is found and next character does not make + // the str a command + var possibleCommand = str + String.fromCharCode(ch); + if (knownCommandFound && knownCommands[possibleCommand] === undefined) { + break; + } + if (str.length === 128) { + error('Command token too long: ' + str.length); + } + str = possibleCommand; + knownCommandFound = knownCommands && knownCommands[str] !== undefined; + } + if (str === 'true') { + return true; + } + if (str === 'false') { + return false; + } + if (str === 'null') { + return null; + } + return Cmd.get(str); + }, + skipToNextLine: function Lexer_skipToNextLine() { + var ch = this.currentChar; + while (ch >= 0) { + if (ch === 0x0D) { // CR + ch = this.nextChar(); + if (ch === 0x0A) { // LF + this.nextChar(); + } + break; + } else if (ch === 0x0A) { // LF + this.nextChar(); + break; + } + ch = this.nextChar(); + } + } + }; + + return Lexer; +})(); + +var Linearization = { + create: function LinearizationCreate(stream) { + function getInt(name, allowZeroValue) { + var obj = linDict.get(name); + if (isInt(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) { + return obj; + } + throw new Error('The "' + name + '" parameter in the linearization ' + + 'dictionary is invalid.'); + } + function getHints() { + var hints = linDict.get('H'), hintsLength, item; + if (isArray(hints) && + ((hintsLength = hints.length) === 2 || hintsLength === 4)) { + for (var index = 0; index < hintsLength; index++) { + if (!(isInt(item = hints[index]) && item > 0)) { + throw new Error('Hint (' + index + + ') in the linearization dictionary is invalid.'); + } + } + return hints; + } + throw new Error('Hint array in the linearization dictionary is invalid.'); + } + var parser = new Parser(new Lexer(stream), false, null); + var obj1 = parser.getObj(); + var obj2 = parser.getObj(); + var obj3 = parser.getObj(); + var linDict = parser.getObj(); + var obj, length; + if (!(isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') && isDict(linDict) && + isNum(obj = linDict.get('Linearized')) && obj > 0)) { + return null; // No valid linearization dictionary found. + } else if ((length = getInt('L')) !== stream.length) { + throw new Error('The "L" parameter in the linearization dictionary ' + + 'does not equal the stream length.'); + } + return { + length: length, + hints: getHints(), + objectNumberFirst: getInt('O'), + endFirst: getInt('E'), + numPages: getInt('N'), + mainXRefEntriesOffset: getInt('T'), + pageFirst: (linDict.has('P') ? getInt('P', true) : 0) + }; + } +}; + + +var PostScriptParser = (function PostScriptParserClosure() { + function PostScriptParser(lexer) { + this.lexer = lexer; + this.operators = []; + this.token = null; + this.prev = null; + } + PostScriptParser.prototype = { + nextToken: function PostScriptParser_nextToken() { + this.prev = this.token; + this.token = this.lexer.getToken(); + }, + accept: function PostScriptParser_accept(type) { + if (this.token.type === type) { + this.nextToken(); + return true; + } + return false; + }, + expect: function PostScriptParser_expect(type) { + if (this.accept(type)) { + return true; + } + error('Unexpected symbol: found ' + this.token.type + ' expected ' + + type + '.'); + }, + parse: function PostScriptParser_parse() { + this.nextToken(); + this.expect(PostScriptTokenTypes.LBRACE); + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + return this.operators; + }, + parseBlock: function PostScriptParser_parseBlock() { + while (true) { + if (this.accept(PostScriptTokenTypes.NUMBER)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.OPERATOR)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + this.parseCondition(); + } else { + return; + } + } + }, + parseCondition: function PostScriptParser_parseCondition() { + // Add two place holders that will be updated later + var conditionLocation = this.operators.length; + this.operators.push(null, null); + + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + if (this.accept(PostScriptTokenTypes.IF)) { + // The true block is right after the 'if' so it just falls through on + // true else it jumps and skips the true block. + this.operators[conditionLocation] = this.operators.length; + this.operators[conditionLocation + 1] = 'jz'; + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + var jumpLocation = this.operators.length; + this.operators.push(null, null); + var endOfTrue = this.operators.length; + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + this.expect(PostScriptTokenTypes.IFELSE); + // The jump is added at the end of the true block to skip the false + // block. + this.operators[jumpLocation] = this.operators.length; + this.operators[jumpLocation + 1] = 'j'; + + this.operators[conditionLocation] = endOfTrue; + this.operators[conditionLocation + 1] = 'jz'; + } else { + error('PS Function: error parsing conditional.'); + } + } + }; + return PostScriptParser; +})(); + +var PostScriptTokenTypes = { + LBRACE: 0, + RBRACE: 1, + NUMBER: 2, + OPERATOR: 3, + IF: 4, + IFELSE: 5 +}; + +var PostScriptToken = (function PostScriptTokenClosure() { + function PostScriptToken(type, value) { + this.type = type; + this.value = value; + } + + var opCache = {}; + + PostScriptToken.getOperator = function PostScriptToken_getOperator(op) { + var opValue = opCache[op]; + if (opValue) { + return opValue; + } + return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op); + }; + + PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE, + '{'); + PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE, + '}'); + PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF'); + PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE, + 'IFELSE'); + return PostScriptToken; +})(); + +var PostScriptLexer = (function PostScriptLexerClosure() { + function PostScriptLexer(stream) { + this.stream = stream; + this.nextChar(); + + this.strBuf = []; + } + PostScriptLexer.prototype = { + nextChar: function PostScriptLexer_nextChar() { + return (this.currentChar = this.stream.getByte()); + }, + getToken: function PostScriptLexer_getToken() { + var comment = false; + var ch = this.currentChar; + + // skip comments + while (true) { + if (ch < 0) { + return EOF; + } + + if (comment) { + if (ch === 0x0A || ch === 0x0D) { + comment = false; + } + } else if (ch === 0x25) { // '%' + comment = true; + } else if (!Lexer.isSpace(ch)) { + break; + } + ch = this.nextChar(); + } + switch (ch | 0) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4' + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9' + case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.' + return new PostScriptToken(PostScriptTokenTypes.NUMBER, + this.getNumber()); + case 0x7B: // '{' + this.nextChar(); + return PostScriptToken.LBRACE; + case 0x7D: // '}' + this.nextChar(); + return PostScriptToken.RBRACE; + } + // operator + var strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch); + + while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z' + ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) { + strBuf.push(String.fromCharCode(ch)); + } + var str = strBuf.join(''); + switch (str.toLowerCase()) { + case 'if': + return PostScriptToken.IF; + case 'ifelse': + return PostScriptToken.IFELSE; + default: + return PostScriptToken.getOperator(str); + } + }, + getNumber: function PostScriptLexer_getNumber() { + var ch = this.currentChar; + var strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch); + + while ((ch = this.nextChar()) >= 0) { + if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9' + ch === 0x2D || ch === 0x2E) { // '-', '.' + strBuf.push(String.fromCharCode(ch)); + } else { + break; + } + } + var value = parseFloat(strBuf.join('')); + if (isNaN(value)) { + error('Invalid floating point number: ' + value); + } + return value; + } + }; + return PostScriptLexer; +})(); + + +var Stream = (function StreamClosure() { + function Stream(arrayBuffer, start, length, dict) { + this.bytes = (arrayBuffer instanceof Uint8Array ? + arrayBuffer : new Uint8Array(arrayBuffer)); + this.start = start || 0; + this.pos = this.start; + this.end = (start + length) || this.bytes.length; + this.dict = dict; + } + + // required methods for a stream. if a particular stream does not + // implement these, an error should be thrown + Stream.prototype = { + get length() { + return this.end - this.start; + }, + get isEmpty() { + return this.length === 0; + }, + getByte: function Stream_getByte() { + if (this.pos >= this.end) { + return -1; + } + return this.bytes[this.pos++]; + }, + getUint16: function Stream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + getInt32: function Stream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + // returns subarray of original buffer + // should only be read + getBytes: function Stream_getBytes(length) { + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + + if (!length) { + return bytes.subarray(pos, strEnd); + } + var end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.pos = end; + return bytes.subarray(pos, end); + }, + peekByte: function Stream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + peekBytes: function Stream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + skip: function Stream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + reset: function Stream_reset() { + this.pos = this.start; + }, + moveStart: function Stream_moveStart() { + this.start = this.pos; + }, + makeSubStream: function Stream_makeSubStream(start, length, dict) { + return new Stream(this.bytes.buffer, start, length, dict); + }, + isStream: true + }; + + return Stream; +})(); + +var StringStream = (function StringStreamClosure() { + function StringStream(str) { + var length = str.length; + var bytes = new Uint8Array(length); + for (var n = 0; n < length; ++n) { + bytes[n] = str.charCodeAt(n); + } + Stream.call(this, bytes); + } + + StringStream.prototype = Stream.prototype; + + return StringStream; +})(); + +// super class for the decoding streams +var DecodeStream = (function DecodeStreamClosure() { + // Lots of DecodeStreams are created whose buffers are never used. For these + // we share a single empty buffer. This is (a) space-efficient and (b) avoids + // having special cases that would be required if we used |null| for an empty + // buffer. + var emptyBuffer = new Uint8Array(0); + + function DecodeStream(maybeMinBufferLength) { + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = emptyBuffer; + this.minBufferLength = 512; + if (maybeMinBufferLength) { + // Compute the first power of two that is as big as maybeMinBufferLength. + while (this.minBufferLength < maybeMinBufferLength) { + this.minBufferLength *= 2; + } + } + } + + DecodeStream.prototype = { + get isEmpty() { + while (!this.eof && this.bufferLength === 0) { + this.readBlock(); + } + return this.bufferLength === 0; + }, + ensureBuffer: function DecodeStream_ensureBuffer(requested) { + var buffer = this.buffer; + if (requested <= buffer.byteLength) { + return buffer; + } + var size = this.minBufferLength; + while (size < requested) { + size *= 2; + } + var buffer2 = new Uint8Array(size); + buffer2.set(buffer); + return (this.buffer = buffer2); + }, + getByte: function DecodeStream_getByte() { + var pos = this.pos; + while (this.bufferLength <= pos) { + if (this.eof) { + return -1; + } + this.readBlock(); + } + return this.buffer[this.pos++]; + }, + getUint16: function DecodeStream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + getInt32: function DecodeStream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + getBytes: function DecodeStream_getBytes(length) { + var end, pos = this.pos; + + if (length) { + this.ensureBuffer(pos + length); + end = pos + length; + + while (!this.eof && this.bufferLength < end) { + this.readBlock(); + } + var bufEnd = this.bufferLength; + if (end > bufEnd) { + end = bufEnd; + } + } else { + while (!this.eof) { + this.readBlock(); + } + end = this.bufferLength; + } + + this.pos = end; + return this.buffer.subarray(pos, end); + }, + peekByte: function DecodeStream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + peekBytes: function DecodeStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + makeSubStream: function DecodeStream_makeSubStream(start, length, dict) { + var end = start + length; + while (this.bufferLength <= end && !this.eof) { + this.readBlock(); + } + return new Stream(this.buffer, start, length, dict); + }, + skip: function DecodeStream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + reset: function DecodeStream_reset() { + this.pos = 0; + }, + getBaseStreams: function DecodeStream_getBaseStreams() { + if (this.str && this.str.getBaseStreams) { + return this.str.getBaseStreams(); + } + return []; + } + }; + + return DecodeStream; +})(); + +var StreamsSequenceStream = (function StreamsSequenceStreamClosure() { + function StreamsSequenceStream(streams) { + this.streams = streams; + DecodeStream.call(this, /* maybeLength = */ null); + } + + StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype); + + StreamsSequenceStream.prototype.readBlock = + function streamSequenceStreamReadBlock() { + + var streams = this.streams; + if (streams.length === 0) { + this.eof = true; + return; + } + var stream = streams.shift(); + var chunk = stream.getBytes(); + var bufferLength = this.bufferLength; + var newLength = bufferLength + chunk.length; + var buffer = this.ensureBuffer(newLength); + buffer.set(chunk, bufferLength); + this.bufferLength = newLength; + }; + + StreamsSequenceStream.prototype.getBaseStreams = + function StreamsSequenceStream_getBaseStreams() { + + var baseStreams = []; + for (var i = 0, ii = this.streams.length; i < ii; i++) { + var stream = this.streams[i]; + if (stream.getBaseStreams) { + Util.appendToArray(baseStreams, stream.getBaseStreams()); + } + } + return baseStreams; + }; + + return StreamsSequenceStream; +})(); + +var FlateStream = (function FlateStreamClosure() { + var codeLenCodeMap = new Int32Array([ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + ]); + + var lengthDecode = new Int32Array([ + 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, + 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, + 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, + 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102 + ]); + + var distDecode = new Int32Array([ + 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, + 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, + 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, + 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001 + ]); + + var fixedLitCodeTab = [new Int32Array([ + 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, + 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, + 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, + 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, + 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, + 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, + 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, + 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, + 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, + 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, + 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, + 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, + 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, + 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, + 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, + 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, + 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, + 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, + 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, + 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, + 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, + 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, + 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, + 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, + 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, + 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, + 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, + 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, + 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, + 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, + 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, + 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, + 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, + 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, + 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, + 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, + 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, + 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, + 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, + 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, + 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, + 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, + 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, + 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, + 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, + 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, + 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, + 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, + 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, + 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, + 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, + 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, + 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, + 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, + 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, + 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, + 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, + 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, + 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, + 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, + 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, + 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, + 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, + 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff + ]), 9]; + + var fixedDistCodeTab = [new Int32Array([ + 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, + 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, + 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, + 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 + ]), 5]; + + function FlateStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + + var cmf = str.getByte(); + var flg = str.getByte(); + if (cmf === -1 || flg === -1) { + error('Invalid header in flate stream: ' + cmf + ', ' + flg); + } + if ((cmf & 0x0f) !== 0x08) { + error('Unknown compression method in flate stream: ' + cmf + ', ' + flg); + } + if ((((cmf << 8) + flg) % 31) !== 0) { + error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg); + } + if (flg & 0x20) { + error('FDICT bit set in flate stream: ' + cmf + ', ' + flg); + } + + this.codeSize = 0; + this.codeBuf = 0; + + DecodeStream.call(this, maybeLength); + } + + FlateStream.prototype = Object.create(DecodeStream.prototype); + + FlateStream.prototype.getBits = function FlateStream_getBits(bits) { + var str = this.str; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + + var b; + while (codeSize < bits) { + if ((b = str.getByte()) === -1) { + error('Bad encoding in flate stream'); + } + codeBuf |= b << codeSize; + codeSize += 8; + } + b = codeBuf & ((1 << bits) - 1); + this.codeBuf = codeBuf >> bits; + this.codeSize = codeSize -= bits; + + return b; + }; + + FlateStream.prototype.getCode = function FlateStream_getCode(table) { + var str = this.str; + var codes = table[0]; + var maxLen = table[1]; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + + var b; + while (codeSize < maxLen) { + if ((b = str.getByte()) === -1) { + // premature end of stream. code might however still be valid. + // codeSize < codeLen check below guards against incomplete codeVal. + break; + } + codeBuf |= (b << codeSize); + codeSize += 8; + } + var code = codes[codeBuf & ((1 << maxLen) - 1)]; + var codeLen = code >> 16; + var codeVal = code & 0xffff; + if (codeLen < 1 || codeSize < codeLen) { + error('Bad encoding in flate stream'); + } + this.codeBuf = (codeBuf >> codeLen); + this.codeSize = (codeSize - codeLen); + return codeVal; + }; + + FlateStream.prototype.generateHuffmanTable = + function flateStreamGenerateHuffmanTable(lengths) { + var n = lengths.length; + + // find max code length + var maxLen = 0; + var i; + for (i = 0; i < n; ++i) { + if (lengths[i] > maxLen) { + maxLen = lengths[i]; + } + } + + // build the table + var size = 1 << maxLen; + var codes = new Int32Array(size); + for (var len = 1, code = 0, skip = 2; + len <= maxLen; + ++len, code <<= 1, skip <<= 1) { + for (var val = 0; val < n; ++val) { + if (lengths[val] === len) { + // bit-reverse the code + var code2 = 0; + var t = code; + for (i = 0; i < len; ++i) { + code2 = (code2 << 1) | (t & 1); + t >>= 1; + } + + // fill the table entries + for (i = code2; i < size; i += skip) { + codes[i] = (len << 16) | val; + } + ++code; + } + } + } + + return [codes, maxLen]; + }; + + FlateStream.prototype.readBlock = function FlateStream_readBlock() { + var buffer, len; + var str = this.str; + // read block header + var hdr = this.getBits(3); + if (hdr & 1) { + this.eof = true; + } + hdr >>= 1; + + if (hdr === 0) { // uncompressed block + var b; + + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + var blockLen = b; + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + blockLen |= (b << 8); + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + var check = b; + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + check |= (b << 8); + if (check !== (~blockLen & 0xffff) && + (blockLen !== 0 || check !== 0)) { + // Ignoring error for bad "empty" block (see issue 1277) + error('Bad uncompressed block length in flate stream'); + } + + this.codeBuf = 0; + this.codeSize = 0; + + var bufferLength = this.bufferLength; + buffer = this.ensureBuffer(bufferLength + blockLen); + var end = bufferLength + blockLen; + this.bufferLength = end; + if (blockLen === 0) { + if (str.peekByte() === -1) { + this.eof = true; + } + } else { + for (var n = bufferLength; n < end; ++n) { + if ((b = str.getByte()) === -1) { + this.eof = true; + break; + } + buffer[n] = b; + } + } + return; + } + + var litCodeTable; + var distCodeTable; + if (hdr === 1) { // compressed block, fixed codes + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr === 2) { // compressed block, dynamic codes + var numLitCodes = this.getBits(5) + 257; + var numDistCodes = this.getBits(5) + 1; + var numCodeLenCodes = this.getBits(4) + 4; + + // build the code lengths code table + var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); + + var i; + for (i = 0; i < numCodeLenCodes; ++i) { + codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3); + } + var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); + + // build the literal and distance code tables + len = 0; + i = 0; + var codes = numLitCodes + numDistCodes; + var codeLengths = new Uint8Array(codes); + var bitsLength, bitsOffset, what; + while (i < codes) { + var code = this.getCode(codeLenCodeTab); + if (code === 16) { + bitsLength = 2; bitsOffset = 3; what = len; + } else if (code === 17) { + bitsLength = 3; bitsOffset = 3; what = (len = 0); + } else if (code === 18) { + bitsLength = 7; bitsOffset = 11; what = (len = 0); + } else { + codeLengths[i++] = len = code; + continue; + } + + var repeatLength = this.getBits(bitsLength) + bitsOffset; + while (repeatLength-- > 0) { + codeLengths[i++] = what; + } + } + + litCodeTable = + this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); + distCodeTable = + this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); + } else { + error('Unknown block type in flate stream'); + } + + buffer = this.buffer; + var limit = buffer ? buffer.length : 0; + var pos = this.bufferLength; + while (true) { + var code1 = this.getCode(litCodeTable); + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + buffer[pos++] = code1; + continue; + } + if (code1 === 256) { + this.bufferLength = pos; + return; + } + code1 -= 257; + code1 = lengthDecode[code1]; + var code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + len = (code1 & 0xffff) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + var dist = (code1 & 0xffff) + code2; + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + for (var k = 0; k < len; ++k, ++pos) { + buffer[pos] = buffer[pos - dist]; + } + } + }; + + return FlateStream; +})(); + +var PredictorStream = (function PredictorStreamClosure() { + function PredictorStream(str, maybeLength, params) { + var predictor = this.predictor = params.get('Predictor') || 1; + + if (predictor <= 1) { + return str; // no prediction + } + if (predictor !== 2 && (predictor < 10 || predictor > 15)) { + error('Unsupported predictor: ' + predictor); + } + + if (predictor === 2) { + this.readBlock = this.readBlockTiff; + } else { + this.readBlock = this.readBlockPng; + } + + this.str = str; + this.dict = str.dict; + + var colors = this.colors = params.get('Colors') || 1; + var bits = this.bits = params.get('BitsPerComponent') || 8; + var columns = this.columns = params.get('Columns') || 1; + + this.pixBytes = (colors * bits + 7) >> 3; + this.rowBytes = (columns * colors * bits + 7) >> 3; + + DecodeStream.call(this, maybeLength); + return this; + } + + PredictorStream.prototype = Object.create(DecodeStream.prototype); + + PredictorStream.prototype.readBlockTiff = + function predictorStreamReadBlockTiff() { + var rowBytes = this.rowBytes; + + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + rowBytes); + + var bits = this.bits; + var colors = this.colors; + + var rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + + var inbuf = 0, outbuf = 0; + var inbits = 0, outbits = 0; + var pos = bufferLength; + var i; + + if (bits === 1) { + for (i = 0; i < rowBytes; ++i) { + var c = rawBytes[i]; + inbuf = (inbuf << 8) | c; + // bitwise addition is exclusive or + // first shift inbuf and then add + buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF; + // truncate inbuf (assumes colors < 16) + inbuf &= 0xFFFF; + } + } else if (bits === 8) { + for (i = 0; i < colors; ++i) { + buffer[pos++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[pos] = buffer[pos - colors] + rawBytes[i]; + pos++; + } + } else { + var compArray = new Uint8Array(colors + 1); + var bitMask = (1 << bits) - 1; + var j = 0, k = bufferLength; + var columns = this.columns; + for (i = 0; i < columns; ++i) { + for (var kk = 0; kk < colors; ++kk) { + if (inbits < bits) { + inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF); + inbits += 8; + } + compArray[kk] = (compArray[kk] + + (inbuf >> (inbits - bits))) & bitMask; + inbits -= bits; + outbuf = (outbuf << bits) | compArray[kk]; + outbits += bits; + if (outbits >= 8) { + buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF; + outbits -= 8; + } + } + } + if (outbits > 0) { + buffer[k++] = (outbuf << (8 - outbits)) + + (inbuf & ((1 << (8 - outbits)) - 1)); + } + } + this.bufferLength += rowBytes; + }; + + PredictorStream.prototype.readBlockPng = + function predictorStreamReadBlockPng() { + + var rowBytes = this.rowBytes; + var pixBytes = this.pixBytes; + + var predictor = this.str.getByte(); + var rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + rowBytes); + + var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); + if (prevRow.length === 0) { + prevRow = new Uint8Array(rowBytes); + } + + var i, j = bufferLength, up, c; + switch (predictor) { + case 0: + for (i = 0; i < rowBytes; ++i) { + buffer[j++] = rawBytes[i]; + } + break; + case 1: + for (i = 0; i < pixBytes; ++i) { + buffer[j++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF; + j++; + } + break; + case 2: + for (i = 0; i < rowBytes; ++i) { + buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF; + } + break; + case 3: + for (i = 0; i < pixBytes; ++i) { + buffer[j++] = (prevRow[i] >> 1) + rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) + + rawBytes[i]) & 0xFF; + j++; + } + break; + case 4: + // we need to save the up left pixels values. the simplest way + // is to create a new buffer + for (i = 0; i < pixBytes; ++i) { + up = prevRow[i]; + c = rawBytes[i]; + buffer[j++] = up + c; + } + for (; i < rowBytes; ++i) { + up = prevRow[i]; + var upLeft = prevRow[i - pixBytes]; + var left = buffer[j - pixBytes]; + var p = left + up - upLeft; + + var pa = p - left; + if (pa < 0) { + pa = -pa; + } + var pb = p - up; + if (pb < 0) { + pb = -pb; + } + var pc = p - upLeft; + if (pc < 0) { + pc = -pc; + } + + c = rawBytes[i]; + if (pa <= pb && pa <= pc) { + buffer[j++] = left + c; + } else if (pb <= pc) { + buffer[j++] = up + c; + } else { + buffer[j++] = upLeft + c; + } + } + break; + default: + error('Unsupported predictor: ' + predictor); + } + this.bufferLength += rowBytes; + }; + + return PredictorStream; +})(); + +/** + * Depending on the type of JPEG a JpegStream is handled in different ways. For + * JPEG's that are supported natively such as DeviceGray and DeviceRGB the image + * data is stored and then loaded by the browser. For unsupported JPEG's we use + * a library to decode these images and the stream behaves like all the other + * DecodeStreams. + */ +var JpegStream = (function JpegStreamClosure() { + function JpegStream(stream, maybeLength, dict, xref) { + // Some images may contain 'junk' before the SOI (start-of-image) marker. + // Note: this seems to mainly affect inline images. + var ch; + while ((ch = stream.getByte()) !== -1) { + if (ch === 0xFF) { // Find the first byte of the SOI marker (0xFFD8). + stream.skip(-1); // Reset the stream position to the SOI. + break; + } + } + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + + DecodeStream.call(this, maybeLength); + } + + JpegStream.prototype = Object.create(DecodeStream.prototype); + + Object.defineProperty(JpegStream.prototype, 'bytes', { + get: function JpegStream_bytes() { + // If this.maybeLength is null, we'll get the entire stream. + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + + JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + try { + var jpegImage = new JpegImage(); + + // checking if values needs to be transformed before conversion + if (this.forceRGB && this.dict && isArray(this.dict.get('Decode'))) { + var decodeArr = this.dict.get('Decode'); + var bitsPerComponent = this.dict.get('BitsPerComponent') || 8; + var decodeArrLength = decodeArr.length; + var transform = new Int32Array(decodeArrLength); + var transformNeeded = false; + var maxValue = (1 << bitsPerComponent) - 1; + for (var i = 0; i < decodeArrLength; i += 2) { + transform[i] = ((decodeArr[i + 1] - decodeArr[i]) * 256) | 0; + transform[i + 1] = (decodeArr[i] * maxValue) | 0; + if (transform[i] !== 256 || transform[i + 1] !== 0) { + transformNeeded = true; + } + } + if (transformNeeded) { + jpegImage.decodeTransform = transform; + } + } + + jpegImage.parse(this.bytes); + var data = jpegImage.getData(this.drawWidth, this.drawHeight, + this.forceRGB); + this.buffer = data; + this.bufferLength = data.length; + this.eof = true; + } catch (e) { + error('JPEG error: ' + e); + } + }; + + JpegStream.prototype.getBytes = function JpegStream_getBytes(length) { + this.ensureBuffer(); + return this.buffer; + }; + + JpegStream.prototype.getIR = function JpegStream_getIR() { + return PDFJS.createObjectURL(this.bytes, 'image/jpeg'); + }; + /** + * Checks if the image can be decoded and displayed by the browser without any + * further processing such as color space conversions. + */ + JpegStream.prototype.isNativelySupported = + function JpegStream_isNativelySupported(xref, res) { + var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res); + return cs.name === 'DeviceGray' || cs.name === 'DeviceRGB'; + }; + /** + * Checks if the image can be decoded by the browser. + */ + JpegStream.prototype.isNativelyDecodable = + function JpegStream_isNativelyDecodable(xref, res) { + var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res); + var numComps = cs.numComps; + return numComps === 1 || numComps === 3; + }; + + return JpegStream; +})(); + +/** + * For JPEG 2000's we use a library to decode these images and + * the stream behaves like all the other DecodeStreams. + */ +var JpxStream = (function JpxStreamClosure() { + function JpxStream(stream, maybeLength, dict) { + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + + DecodeStream.call(this, maybeLength); + } + + JpxStream.prototype = Object.create(DecodeStream.prototype); + + Object.defineProperty(JpxStream.prototype, 'bytes', { + get: function JpxStream_bytes() { + // If this.maybeLength is null, we'll get the entire stream. + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + + JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + + var jpxImage = new JpxImage(); + jpxImage.parse(this.bytes); + + var width = jpxImage.width; + var height = jpxImage.height; + var componentsCount = jpxImage.componentsCount; + var tileCount = jpxImage.tiles.length; + if (tileCount === 1) { + this.buffer = jpxImage.tiles[0].items; + } else { + var data = new Uint8Array(width * height * componentsCount); + + for (var k = 0; k < tileCount; k++) { + var tileComponents = jpxImage.tiles[k]; + var tileWidth = tileComponents.width; + var tileHeight = tileComponents.height; + var tileLeft = tileComponents.left; + var tileTop = tileComponents.top; + + var src = tileComponents.items; + var srcPosition = 0; + var dataPosition = (width * tileTop + tileLeft) * componentsCount; + var imgRowSize = width * componentsCount; + var tileRowSize = tileWidth * componentsCount; + + for (var j = 0; j < tileHeight; j++) { + var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize); + data.set(rowBytes, dataPosition); + srcPosition += tileRowSize; + dataPosition += imgRowSize; + } + } + this.buffer = data; + } + this.bufferLength = this.buffer.length; + this.eof = true; + }; + + return JpxStream; +})(); + +/** + * For JBIG2's we use a library to decode these images and + * the stream behaves like all the other DecodeStreams. + */ +var Jbig2Stream = (function Jbig2StreamClosure() { + function Jbig2Stream(stream, maybeLength, dict) { + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + + DecodeStream.call(this, maybeLength); + } + + Jbig2Stream.prototype = Object.create(DecodeStream.prototype); + + Object.defineProperty(Jbig2Stream.prototype, 'bytes', { + get: function Jbig2Stream_bytes() { + // If this.maybeLength is null, we'll get the entire stream. + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + + Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + + var jbig2Image = new Jbig2Image(); + + var chunks = [], xref = this.dict.xref; + var decodeParams = xref.fetchIfRef(this.dict.get('DecodeParms')); + + // According to the PDF specification, DecodeParms can be either + // a dictionary, or an array whose elements are dictionaries. + if (isArray(decodeParams)) { + if (decodeParams.length > 1) { + warn('JBIG2 - \'DecodeParms\' array with multiple elements ' + + 'not supported.'); + } + decodeParams = xref.fetchIfRef(decodeParams[0]); + } + if (decodeParams && decodeParams.has('JBIG2Globals')) { + var globalsStream = decodeParams.get('JBIG2Globals'); + var globals = globalsStream.getBytes(); + chunks.push({data: globals, start: 0, end: globals.length}); + } + chunks.push({data: this.bytes, start: 0, end: this.bytes.length}); + var data = jbig2Image.parseChunks(chunks); + var dataLength = data.length; + + // JBIG2 had black as 1 and white as 0, inverting the colors + for (var i = 0; i < dataLength; i++) { + data[i] ^= 0xFF; + } + + this.buffer = data; + this.bufferLength = dataLength; + this.eof = true; + }; + + return Jbig2Stream; +})(); + +var DecryptStream = (function DecryptStreamClosure() { + function DecryptStream(str, maybeLength, decrypt) { + this.str = str; + this.dict = str.dict; + this.decrypt = decrypt; + this.nextChunk = null; + this.initialized = false; + + DecodeStream.call(this, maybeLength); + } + + var chunkSize = 512; + + DecryptStream.prototype = Object.create(DecodeStream.prototype); + + DecryptStream.prototype.readBlock = function DecryptStream_readBlock() { + var chunk; + if (this.initialized) { + chunk = this.nextChunk; + } else { + chunk = this.str.getBytes(chunkSize); + this.initialized = true; + } + if (!chunk || chunk.length === 0) { + this.eof = true; + return; + } + this.nextChunk = this.str.getBytes(chunkSize); + var hasMoreData = this.nextChunk && this.nextChunk.length > 0; + + var decrypt = this.decrypt; + chunk = decrypt(chunk, !hasMoreData); + + var bufferLength = this.bufferLength; + var i, n = chunk.length; + var buffer = this.ensureBuffer(bufferLength + n); + for (i = 0; i < n; i++) { + buffer[bufferLength++] = chunk[i]; + } + this.bufferLength = bufferLength; + }; + + return DecryptStream; +})(); + +var Ascii85Stream = (function Ascii85StreamClosure() { + function Ascii85Stream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + this.input = new Uint8Array(5); + + // Most streams increase in size when decoded, but Ascii85 streams + // typically shrink by ~20%. + if (maybeLength) { + maybeLength = 0.8 * maybeLength; + } + DecodeStream.call(this, maybeLength); + } + + Ascii85Stream.prototype = Object.create(DecodeStream.prototype); + + Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() { + var TILDA_CHAR = 0x7E; // '~' + var Z_LOWER_CHAR = 0x7A; // 'z' + var EOF = -1; + + var str = this.str; + + var c = str.getByte(); + while (Lexer.isSpace(c)) { + c = str.getByte(); + } + + if (c === EOF || c === TILDA_CHAR) { + this.eof = true; + return; + } + + var bufferLength = this.bufferLength, buffer; + var i; + + // special code for z + if (c === Z_LOWER_CHAR) { + buffer = this.ensureBuffer(bufferLength + 4); + for (i = 0; i < 4; ++i) { + buffer[bufferLength + i] = 0; + } + this.bufferLength += 4; + } else { + var input = this.input; + input[0] = c; + for (i = 1; i < 5; ++i) { + c = str.getByte(); + while (Lexer.isSpace(c)) { + c = str.getByte(); + } + + input[i] = c; + + if (c === EOF || c === TILDA_CHAR) { + break; + } + } + buffer = this.ensureBuffer(bufferLength + i - 1); + this.bufferLength += i - 1; + + // partial ending; + if (i < 5) { + for (; i < 5; ++i) { + input[i] = 0x21 + 84; + } + this.eof = true; + } + var t = 0; + for (i = 0; i < 5; ++i) { + t = t * 85 + (input[i] - 0x21); + } + + for (i = 3; i >= 0; --i) { + buffer[bufferLength + i] = t & 0xFF; + t >>= 8; + } + } + }; + + return Ascii85Stream; +})(); + +var AsciiHexStream = (function AsciiHexStreamClosure() { + function AsciiHexStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + + this.firstDigit = -1; + + // Most streams increase in size when decoded, but AsciiHex streams shrink + // by 50%. + if (maybeLength) { + maybeLength = 0.5 * maybeLength; + } + DecodeStream.call(this, maybeLength); + } + + AsciiHexStream.prototype = Object.create(DecodeStream.prototype); + + AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() { + var UPSTREAM_BLOCK_SIZE = 8000; + var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE); + if (!bytes.length) { + this.eof = true; + return; + } + + var maxDecodeLength = (bytes.length + 1) >> 1; + var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); + var bufferLength = this.bufferLength; + + var firstDigit = this.firstDigit; + for (var i = 0, ii = bytes.length; i < ii; i++) { + var ch = bytes[i], digit; + if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' + digit = ch & 0x0F; + } else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { + // 'A'-'Z', 'a'-'z' + digit = (ch & 0x0F) + 9; + } else if (ch === 0x3E) { // '>' + this.eof = true; + break; + } else { // probably whitespace + continue; // ignoring + } + if (firstDigit < 0) { + firstDigit = digit; + } else { + buffer[bufferLength++] = (firstDigit << 4) | digit; + firstDigit = -1; + } + } + if (firstDigit >= 0 && this.eof) { + // incomplete byte + buffer[bufferLength++] = (firstDigit << 4); + firstDigit = -1; + } + this.firstDigit = firstDigit; + this.bufferLength = bufferLength; + }; + + return AsciiHexStream; +})(); + +var RunLengthStream = (function RunLengthStreamClosure() { + function RunLengthStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + + DecodeStream.call(this, maybeLength); + } + + RunLengthStream.prototype = Object.create(DecodeStream.prototype); + + RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() { + // The repeatHeader has following format. The first byte defines type of run + // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes + // (in addition to the second byte from the header), n = 129 through 255 - + // duplicate the second byte from the header (257 - n) times, n = 128 - end. + var repeatHeader = this.str.getBytes(2); + if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) { + this.eof = true; + return; + } + + var buffer; + var bufferLength = this.bufferLength; + var n = repeatHeader[0]; + if (n < 128) { + // copy n bytes + buffer = this.ensureBuffer(bufferLength + n + 1); + buffer[bufferLength++] = repeatHeader[1]; + if (n > 0) { + var source = this.str.getBytes(n); + buffer.set(source, bufferLength); + bufferLength += n; + } + } else { + n = 257 - n; + var b = repeatHeader[1]; + buffer = this.ensureBuffer(bufferLength + n + 1); + for (var i = 0; i < n; i++) { + buffer[bufferLength++] = b; + } + } + this.bufferLength = bufferLength; + }; + + return RunLengthStream; +})(); + +var CCITTFaxStream = (function CCITTFaxStreamClosure() { + + var ccittEOL = -2; + var twoDimPass = 0; + var twoDimHoriz = 1; + var twoDimVert0 = 2; + var twoDimVertR1 = 3; + var twoDimVertL1 = 4; + var twoDimVertR2 = 5; + var twoDimVertL2 = 6; + var twoDimVertR3 = 7; + var twoDimVertL3 = 8; + + var twoDimTable = [ + [-1, -1], [-1, -1], // 000000x + [7, twoDimVertL3], // 0000010 + [7, twoDimVertR3], // 0000011 + [6, twoDimVertL2], [6, twoDimVertL2], // 000010x + [6, twoDimVertR2], [6, twoDimVertR2], // 000011x + [4, twoDimPass], [4, twoDimPass], // 0001xxx + [4, twoDimPass], [4, twoDimPass], + [4, twoDimPass], [4, twoDimPass], + [4, twoDimPass], [4, twoDimPass], + [3, twoDimHoriz], [3, twoDimHoriz], // 001xxxx + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimVertL1], [3, twoDimVertL1], // 010xxxx + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertR1], [3, twoDimVertR1], // 011xxxx + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [1, twoDimVert0], [1, twoDimVert0], // 1xxxxxx + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0] + ]; + + var whiteTable1 = [ + [-1, -1], // 00000 + [12, ccittEOL], // 00001 + [-1, -1], [-1, -1], // 0001x + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 001xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 010xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 011xx + [11, 1792], [11, 1792], // 1000x + [12, 1984], // 10010 + [12, 2048], // 10011 + [12, 2112], // 10100 + [12, 2176], // 10101 + [12, 2240], // 10110 + [12, 2304], // 10111 + [11, 1856], [11, 1856], // 1100x + [11, 1920], [11, 1920], // 1101x + [12, 2368], // 11100 + [12, 2432], // 11101 + [12, 2496], // 11110 + [12, 2560] // 11111 + ]; + + var whiteTable2 = [ + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000000xx + [8, 29], [8, 29], // 00000010x + [8, 30], [8, 30], // 00000011x + [8, 45], [8, 45], // 00000100x + [8, 46], [8, 46], // 00000101x + [7, 22], [7, 22], [7, 22], [7, 22], // 0000011xx + [7, 23], [7, 23], [7, 23], [7, 23], // 0000100xx + [8, 47], [8, 47], // 00001010x + [8, 48], [8, 48], // 00001011x + [6, 13], [6, 13], [6, 13], [6, 13], // 000011xxx + [6, 13], [6, 13], [6, 13], [6, 13], + [7, 20], [7, 20], [7, 20], [7, 20], // 0001000xx + [8, 33], [8, 33], // 00010010x + [8, 34], [8, 34], // 00010011x + [8, 35], [8, 35], // 00010100x + [8, 36], [8, 36], // 00010101x + [8, 37], [8, 37], // 00010110x + [8, 38], [8, 38], // 00010111x + [7, 19], [7, 19], [7, 19], [7, 19], // 0001100xx + [8, 31], [8, 31], // 00011010x + [8, 32], [8, 32], // 00011011x + [6, 1], [6, 1], [6, 1], [6, 1], // 000111xxx + [6, 1], [6, 1], [6, 1], [6, 1], + [6, 12], [6, 12], [6, 12], [6, 12], // 001000xxx + [6, 12], [6, 12], [6, 12], [6, 12], + [8, 53], [8, 53], // 00100100x + [8, 54], [8, 54], // 00100101x + [7, 26], [7, 26], [7, 26], [7, 26], // 0010011xx + [8, 39], [8, 39], // 00101000x + [8, 40], [8, 40], // 00101001x + [8, 41], [8, 41], // 00101010x + [8, 42], [8, 42], // 00101011x + [8, 43], [8, 43], // 00101100x + [8, 44], [8, 44], // 00101101x + [7, 21], [7, 21], [7, 21], [7, 21], // 0010111xx + [7, 28], [7, 28], [7, 28], [7, 28], // 0011000xx + [8, 61], [8, 61], // 00110010x + [8, 62], [8, 62], // 00110011x + [8, 63], [8, 63], // 00110100x + [8, 0], [8, 0], // 00110101x + [8, 320], [8, 320], // 00110110x + [8, 384], [8, 384], // 00110111x + [5, 10], [5, 10], [5, 10], [5, 10], // 00111xxxx + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 11], [5, 11], [5, 11], [5, 11], // 01000xxxx + [5, 11], [5, 11], [5, 11], [5, 11], + [5, 11], [5, 11], [5, 11], [5, 11], + [5, 11], [5, 11], [5, 11], [5, 11], + [7, 27], [7, 27], [7, 27], [7, 27], // 0100100xx + [8, 59], [8, 59], // 01001010x + [8, 60], [8, 60], // 01001011x + [9, 1472], // 010011000 + [9, 1536], // 010011001 + [9, 1600], // 010011010 + [9, 1728], // 010011011 + [7, 18], [7, 18], [7, 18], [7, 18], // 0100111xx + [7, 24], [7, 24], [7, 24], [7, 24], // 0101000xx + [8, 49], [8, 49], // 01010010x + [8, 50], [8, 50], // 01010011x + [8, 51], [8, 51], // 01010100x + [8, 52], [8, 52], // 01010101x + [7, 25], [7, 25], [7, 25], [7, 25], // 0101011xx + [8, 55], [8, 55], // 01011000x + [8, 56], [8, 56], // 01011001x + [8, 57], [8, 57], // 01011010x + [8, 58], [8, 58], // 01011011x + [6, 192], [6, 192], [6, 192], [6, 192], // 010111xxx + [6, 192], [6, 192], [6, 192], [6, 192], + [6, 1664], [6, 1664], [6, 1664], [6, 1664], // 011000xxx + [6, 1664], [6, 1664], [6, 1664], [6, 1664], + [8, 448], [8, 448], // 01100100x + [8, 512], [8, 512], // 01100101x + [9, 704], // 011001100 + [9, 768], // 011001101 + [8, 640], [8, 640], // 01100111x + [8, 576], [8, 576], // 01101000x + [9, 832], // 011010010 + [9, 896], // 011010011 + [9, 960], // 011010100 + [9, 1024], // 011010101 + [9, 1088], // 011010110 + [9, 1152], // 011010111 + [9, 1216], // 011011000 + [9, 1280], // 011011001 + [9, 1344], // 011011010 + [9, 1408], // 011011011 + [7, 256], [7, 256], [7, 256], [7, 256], // 0110111xx + [4, 2], [4, 2], [4, 2], [4, 2], // 0111xxxxx + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 3], [4, 3], [4, 3], [4, 3], // 1000xxxxx + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [5, 128], [5, 128], [5, 128], [5, 128], // 10010xxxx + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 8], [5, 8], [5, 8], [5, 8], // 10011xxxx + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 9], [5, 9], [5, 9], [5, 9], // 10100xxxx + [5, 9], [5, 9], [5, 9], [5, 9], + [5, 9], [5, 9], [5, 9], [5, 9], + [5, 9], [5, 9], [5, 9], [5, 9], + [6, 16], [6, 16], [6, 16], [6, 16], // 101010xxx + [6, 16], [6, 16], [6, 16], [6, 16], + [6, 17], [6, 17], [6, 17], [6, 17], // 101011xxx + [6, 17], [6, 17], [6, 17], [6, 17], + [4, 4], [4, 4], [4, 4], [4, 4], // 1011xxxxx + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 5], [4, 5], [4, 5], [4, 5], // 1100xxxxx + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [6, 14], [6, 14], [6, 14], [6, 14], // 110100xxx + [6, 14], [6, 14], [6, 14], [6, 14], + [6, 15], [6, 15], [6, 15], [6, 15], // 110101xxx + [6, 15], [6, 15], [6, 15], [6, 15], + [5, 64], [5, 64], [5, 64], [5, 64], // 11011xxxx + [5, 64], [5, 64], [5, 64], [5, 64], + [5, 64], [5, 64], [5, 64], [5, 64], + [5, 64], [5, 64], [5, 64], [5, 64], + [4, 6], [4, 6], [4, 6], [4, 6], // 1110xxxxx + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 7], [4, 7], [4, 7], [4, 7], // 1111xxxxx + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7] + ]; + + var blackTable1 = [ + [-1, -1], [-1, -1], // 000000000000x + [12, ccittEOL], [12, ccittEOL], // 000000000001x + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000001xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000010xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000011xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000100xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000101xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000110xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000111xx + [11, 1792], [11, 1792], [11, 1792], [11, 1792], // 00000001000xx + [12, 1984], [12, 1984], // 000000010010x + [12, 2048], [12, 2048], // 000000010011x + [12, 2112], [12, 2112], // 000000010100x + [12, 2176], [12, 2176], // 000000010101x + [12, 2240], [12, 2240], // 000000010110x + [12, 2304], [12, 2304], // 000000010111x + [11, 1856], [11, 1856], [11, 1856], [11, 1856], // 00000001100xx + [11, 1920], [11, 1920], [11, 1920], [11, 1920], // 00000001101xx + [12, 2368], [12, 2368], // 000000011100x + [12, 2432], [12, 2432], // 000000011101x + [12, 2496], [12, 2496], // 000000011110x + [12, 2560], [12, 2560], // 000000011111x + [10, 18], [10, 18], [10, 18], [10, 18], // 0000001000xxx + [10, 18], [10, 18], [10, 18], [10, 18], + [12, 52], [12, 52], // 000000100100x + [13, 640], // 0000001001010 + [13, 704], // 0000001001011 + [13, 768], // 0000001001100 + [13, 832], // 0000001001101 + [12, 55], [12, 55], // 000000100111x + [12, 56], [12, 56], // 000000101000x + [13, 1280], // 0000001010010 + [13, 1344], // 0000001010011 + [13, 1408], // 0000001010100 + [13, 1472], // 0000001010101 + [12, 59], [12, 59], // 000000101011x + [12, 60], [12, 60], // 000000101100x + [13, 1536], // 0000001011010 + [13, 1600], // 0000001011011 + [11, 24], [11, 24], [11, 24], [11, 24], // 00000010111xx + [11, 25], [11, 25], [11, 25], [11, 25], // 00000011000xx + [13, 1664], // 0000001100100 + [13, 1728], // 0000001100101 + [12, 320], [12, 320], // 000000110011x + [12, 384], [12, 384], // 000000110100x + [12, 448], [12, 448], // 000000110101x + [13, 512], // 0000001101100 + [13, 576], // 0000001101101 + [12, 53], [12, 53], // 000000110111x + [12, 54], [12, 54], // 000000111000x + [13, 896], // 0000001110010 + [13, 960], // 0000001110011 + [13, 1024], // 0000001110100 + [13, 1088], // 0000001110101 + [13, 1152], // 0000001110110 + [13, 1216], // 0000001110111 + [10, 64], [10, 64], [10, 64], [10, 64], // 0000001111xxx + [10, 64], [10, 64], [10, 64], [10, 64] + ]; + + var blackTable2 = [ + [8, 13], [8, 13], [8, 13], [8, 13], // 00000100xxxx + [8, 13], [8, 13], [8, 13], [8, 13], + [8, 13], [8, 13], [8, 13], [8, 13], + [8, 13], [8, 13], [8, 13], [8, 13], + [11, 23], [11, 23], // 00000101000x + [12, 50], // 000001010010 + [12, 51], // 000001010011 + [12, 44], // 000001010100 + [12, 45], // 000001010101 + [12, 46], // 000001010110 + [12, 47], // 000001010111 + [12, 57], // 000001011000 + [12, 58], // 000001011001 + [12, 61], // 000001011010 + [12, 256], // 000001011011 + [10, 16], [10, 16], [10, 16], [10, 16], // 0000010111xx + [10, 17], [10, 17], [10, 17], [10, 17], // 0000011000xx + [12, 48], // 000001100100 + [12, 49], // 000001100101 + [12, 62], // 000001100110 + [12, 63], // 000001100111 + [12, 30], // 000001101000 + [12, 31], // 000001101001 + [12, 32], // 000001101010 + [12, 33], // 000001101011 + [12, 40], // 000001101100 + [12, 41], // 000001101101 + [11, 22], [11, 22], // 00000110111x + [8, 14], [8, 14], [8, 14], [8, 14], // 00000111xxxx + [8, 14], [8, 14], [8, 14], [8, 14], + [8, 14], [8, 14], [8, 14], [8, 14], + [8, 14], [8, 14], [8, 14], [8, 14], + [7, 10], [7, 10], [7, 10], [7, 10], // 0000100xxxxx + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 11], [7, 11], [7, 11], [7, 11], // 0000101xxxxx + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [9, 15], [9, 15], [9, 15], [9, 15], // 000011000xxx + [9, 15], [9, 15], [9, 15], [9, 15], + [12, 128], // 000011001000 + [12, 192], // 000011001001 + [12, 26], // 000011001010 + [12, 27], // 000011001011 + [12, 28], // 000011001100 + [12, 29], // 000011001101 + [11, 19], [11, 19], // 00001100111x + [11, 20], [11, 20], // 00001101000x + [12, 34], // 000011010010 + [12, 35], // 000011010011 + [12, 36], // 000011010100 + [12, 37], // 000011010101 + [12, 38], // 000011010110 + [12, 39], // 000011010111 + [11, 21], [11, 21], // 00001101100x + [12, 42], // 000011011010 + [12, 43], // 000011011011 + [10, 0], [10, 0], [10, 0], [10, 0], // 0000110111xx + [7, 12], [7, 12], [7, 12], [7, 12], // 0000111xxxxx + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12] + ]; + + var blackTable3 = [ + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000xx + [6, 9], // 000100 + [6, 8], // 000101 + [5, 7], [5, 7], // 00011x + [4, 6], [4, 6], [4, 6], [4, 6], // 0010xx + [4, 5], [4, 5], [4, 5], [4, 5], // 0011xx + [3, 1], [3, 1], [3, 1], [3, 1], // 010xxx + [3, 1], [3, 1], [3, 1], [3, 1], + [3, 4], [3, 4], [3, 4], [3, 4], // 011xxx + [3, 4], [3, 4], [3, 4], [3, 4], + [2, 3], [2, 3], [2, 3], [2, 3], // 10xxxx + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 2], [2, 2], [2, 2], [2, 2], // 11xxxx + [2, 2], [2, 2], [2, 2], [2, 2], + [2, 2], [2, 2], [2, 2], [2, 2], + [2, 2], [2, 2], [2, 2], [2, 2] + ]; + + function CCITTFaxStream(str, maybeLength, params) { + this.str = str; + this.dict = str.dict; + + params = params || Dict.empty; + + this.encoding = params.get('K') || 0; + this.eoline = params.get('EndOfLine') || false; + this.byteAlign = params.get('EncodedByteAlign') || false; + this.columns = params.get('Columns') || 1728; + this.rows = params.get('Rows') || 0; + var eoblock = params.get('EndOfBlock'); + if (eoblock === null || eoblock === undefined) { + eoblock = true; + } + this.eoblock = eoblock; + this.black = params.get('BlackIs1') || false; + + this.codingLine = new Uint32Array(this.columns + 1); + this.refLine = new Uint32Array(this.columns + 2); + + this.codingLine[0] = this.columns; + this.codingPos = 0; + + this.row = 0; + this.nextLine2D = this.encoding < 0; + this.inputBits = 0; + this.inputBuf = 0; + this.outputBits = 0; + + var code1; + while ((code1 = this.lookBits(12)) === 0) { + this.eatBits(1); + } + if (code1 === 1) { + this.eatBits(12); + } + if (this.encoding > 0) { + this.nextLine2D = !this.lookBits(1); + this.eatBits(1); + } + + DecodeStream.call(this, maybeLength); + } + + CCITTFaxStream.prototype = Object.create(DecodeStream.prototype); + + CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() { + while (!this.eof) { + var c = this.lookChar(); + this.ensureBuffer(this.bufferLength + 1); + this.buffer[this.bufferLength++] = c; + } + }; + + CCITTFaxStream.prototype.addPixels = + function ccittFaxStreamAddPixels(a1, blackPixels) { + var codingLine = this.codingLine; + var codingPos = this.codingPos; + + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info('row is wrong length'); + this.err = true; + a1 = this.columns; + } + if ((codingPos & 1) ^ blackPixels) { + ++codingPos; + } + + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + }; + + CCITTFaxStream.prototype.addPixelsNeg = + function ccittFaxStreamAddPixelsNeg(a1, blackPixels) { + var codingLine = this.codingLine; + var codingPos = this.codingPos; + + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info('row is wrong length'); + this.err = true; + a1 = this.columns; + } + if ((codingPos & 1) ^ blackPixels) { + ++codingPos; + } + + codingLine[codingPos] = a1; + } else if (a1 < codingLine[codingPos]) { + if (a1 < 0) { + info('invalid code'); + this.err = true; + a1 = 0; + } + while (codingPos > 0 && a1 < codingLine[codingPos - 1]) { + --codingPos; + } + codingLine[codingPos] = a1; + } + + this.codingPos = codingPos; + }; + + CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() { + var refLine = this.refLine; + var codingLine = this.codingLine; + var columns = this.columns; + + var refPos, blackPixels, bits, i; + + if (this.outputBits === 0) { + if (this.eof) { + return null; + } + this.err = false; + + var code1, code2, code3; + if (this.nextLine2D) { + for (i = 0; codingLine[i] < columns; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i++] = columns; + refLine[i] = columns; + codingLine[0] = 0; + this.codingPos = 0; + refPos = 0; + blackPixels = 0; + + while (codingLine[this.codingPos] < columns) { + code1 = this.getTwoDimCode(); + switch (code1) { + case twoDimPass: + this.addPixels(refLine[refPos + 1], blackPixels); + if (refLine[refPos + 1] < columns) { + refPos += 2; + } + break; + case twoDimHoriz: + code1 = code2 = 0; + if (blackPixels) { + do { + code1 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + do { + code2 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + } else { + do { + code1 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + do { + code2 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + } + this.addPixels(codingLine[this.codingPos] + + code1, blackPixels); + if (codingLine[this.codingPos] < columns) { + this.addPixels(codingLine[this.codingPos] + code2, + blackPixels ^ 1); + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + break; + case twoDimVertR3: + this.addPixels(refLine[refPos] + 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR2: + this.addPixels(refLine[refPos] + 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR1: + this.addPixels(refLine[refPos] + 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVert0: + this.addPixels(refLine[refPos], blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL3: + this.addPixelsNeg(refLine[refPos] - 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL2: + this.addPixelsNeg(refLine[refPos] - 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL1: + this.addPixelsNeg(refLine[refPos] - 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case EOF: + this.addPixels(columns, 0); + this.eof = true; + break; + default: + info('bad 2d code'); + this.addPixels(columns, 0); + this.err = true; + } + } + } else { + codingLine[0] = 0; + this.codingPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = 0; + if (blackPixels) { + do { + code1 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + } else { + do { + code1 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + } + this.addPixels(codingLine[this.codingPos] + code1, blackPixels); + blackPixels ^= 1; + } + } + + var gotEOL = false; + + if (this.byteAlign) { + this.inputBits &= ~7; + } + + if (!this.eoblock && this.row === this.rows - 1) { + this.eof = true; + } else { + code1 = this.lookBits(12); + if (this.eoline) { + while (code1 !== EOF && code1 !== 1) { + this.eatBits(1); + code1 = this.lookBits(12); + } + } else { + while (code1 === 0) { + this.eatBits(1); + code1 = this.lookBits(12); + } + } + if (code1 === 1) { + this.eatBits(12); + gotEOL = true; + } else if (code1 === EOF) { + this.eof = true; + } + } + + if (!this.eof && this.encoding > 0) { + this.nextLine2D = !this.lookBits(1); + this.eatBits(1); + } + + if (this.eoblock && gotEOL && this.byteAlign) { + code1 = this.lookBits(12); + if (code1 === 1) { + this.eatBits(12); + if (this.encoding > 0) { + this.lookBits(1); + this.eatBits(1); + } + if (this.encoding >= 0) { + for (i = 0; i < 4; ++i) { + code1 = this.lookBits(12); + if (code1 !== 1) { + info('bad rtc code: ' + code1); + } + this.eatBits(12); + if (this.encoding > 0) { + this.lookBits(1); + this.eatBits(1); + } + } + } + this.eof = true; + } + } else if (this.err && this.eoline) { + while (true) { + code1 = this.lookBits(13); + if (code1 === EOF) { + this.eof = true; + return null; + } + if ((code1 >> 1) === 1) { + break; + } + this.eatBits(1); + } + this.eatBits(12); + if (this.encoding > 0) { + this.eatBits(1); + this.nextLine2D = !(code1 & 1); + } + } + + if (codingLine[0] > 0) { + this.outputBits = codingLine[this.codingPos = 0]; + } else { + this.outputBits = codingLine[this.codingPos = 1]; + } + this.row++; + } + + var c; + if (this.outputBits >= 8) { + c = (this.codingPos & 1) ? 0 : 0xFF; + this.outputBits -= 8; + if (this.outputBits === 0 && codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = (codingLine[this.codingPos] - + codingLine[this.codingPos - 1]); + } + } else { + bits = 8; + c = 0; + do { + if (this.outputBits > bits) { + c <<= bits; + if (!(this.codingPos & 1)) { + c |= 0xFF >> (8 - bits); + } + this.outputBits -= bits; + bits = 0; + } else { + c <<= this.outputBits; + if (!(this.codingPos & 1)) { + c |= 0xFF >> (8 - this.outputBits); + } + bits -= this.outputBits; + this.outputBits = 0; + if (codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = (codingLine[this.codingPos] - + codingLine[this.codingPos - 1]); + } else if (bits > 0) { + c <<= bits; + bits = 0; + } + } + } while (bits); + } + if (this.black) { + c ^= 0xFF; + } + return c; + }; + + // This functions returns the code found from the table. + // The start and end parameters set the boundaries for searching the table. + // The limit parameter is optional. Function returns an array with three + // values. The first array element indicates whether a valid code is being + // returned. The second array element is the actual code. The third array + // element indicates whether EOF was reached. + CCITTFaxStream.prototype.findTableCode = + function ccittFaxStreamFindTableCode(start, end, table, limit) { + + var limitValue = limit || 0; + for (var i = start; i <= end; ++i) { + var code = this.lookBits(i); + if (code === EOF) { + return [true, 1, false]; + } + if (i < end) { + code <<= end - i; + } + if (!limitValue || code >= limitValue) { + var p = table[code - limitValue]; + if (p[0] === i) { + this.eatBits(i); + return [true, p[1], true]; + } + } + } + return [false, 0, false]; + }; + + CCITTFaxStream.prototype.getTwoDimCode = + function ccittFaxStreamGetTwoDimCode() { + + var code = 0; + var p; + if (this.eoblock) { + code = this.lookBits(7); + p = twoDimTable[code]; + if (p && p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(1, 7, twoDimTable); + if (result[0] && result[2]) { + return result[1]; + } + } + info('Bad two dim code'); + return EOF; + }; + + CCITTFaxStream.prototype.getWhiteCode = + function ccittFaxStreamGetWhiteCode() { + + var code = 0; + var p; + if (this.eoblock) { + code = this.lookBits(12); + if (code === EOF) { + return 1; + } + + if ((code >> 5) === 0) { + p = whiteTable1[code]; + } else { + p = whiteTable2[code >> 3]; + } + + if (p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(1, 9, whiteTable2); + if (result[0]) { + return result[1]; + } + + result = this.findTableCode(11, 12, whiteTable1); + if (result[0]) { + return result[1]; + } + } + info('bad white code'); + this.eatBits(1); + return 1; + }; + + CCITTFaxStream.prototype.getBlackCode = + function ccittFaxStreamGetBlackCode() { + + var code, p; + if (this.eoblock) { + code = this.lookBits(13); + if (code === EOF) { + return 1; + } + if ((code >> 7) === 0) { + p = blackTable1[code]; + } else if ((code >> 9) === 0 && (code >> 7) !== 0) { + p = blackTable2[(code >> 1) - 64]; + } else { + p = blackTable3[code >> 7]; + } + + if (p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(2, 6, blackTable3); + if (result[0]) { + return result[1]; + } + + result = this.findTableCode(7, 12, blackTable2, 64); + if (result[0]) { + return result[1]; + } + + result = this.findTableCode(10, 13, blackTable1); + if (result[0]) { + return result[1]; + } + } + info('bad black code'); + this.eatBits(1); + return 1; + }; + + CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) { + var c; + while (this.inputBits < n) { + if ((c = this.str.getByte()) === -1) { + if (this.inputBits === 0) { + return EOF; + } + return ((this.inputBuf << (n - this.inputBits)) & + (0xFFFF >> (16 - n))); + } + this.inputBuf = (this.inputBuf << 8) + c; + this.inputBits += 8; + } + return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n)); + }; + + CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) { + if ((this.inputBits -= n) < 0) { + this.inputBits = 0; + } + }; + + return CCITTFaxStream; +})(); + +var LZWStream = (function LZWStreamClosure() { + function LZWStream(str, maybeLength, earlyChange) { + this.str = str; + this.dict = str.dict; + this.cachedData = 0; + this.bitsCached = 0; + + var maxLzwDictionarySize = 4096; + var lzwState = { + earlyChange: earlyChange, + codeLength: 9, + nextCode: 258, + dictionaryValues: new Uint8Array(maxLzwDictionarySize), + dictionaryLengths: new Uint16Array(maxLzwDictionarySize), + dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), + currentSequence: new Uint8Array(maxLzwDictionarySize), + currentSequenceLength: 0 + }; + for (var i = 0; i < 256; ++i) { + lzwState.dictionaryValues[i] = i; + lzwState.dictionaryLengths[i] = 1; + } + this.lzwState = lzwState; + + DecodeStream.call(this, maybeLength); + } + + LZWStream.prototype = Object.create(DecodeStream.prototype); + + LZWStream.prototype.readBits = function LZWStream_readBits(n) { + var bitsCached = this.bitsCached; + var cachedData = this.cachedData; + while (bitsCached < n) { + var c = this.str.getByte(); + if (c === -1) { + this.eof = true; + return null; + } + cachedData = (cachedData << 8) | c; + bitsCached += 8; + } + this.bitsCached = (bitsCached -= n); + this.cachedData = cachedData; + this.lastCode = null; + return (cachedData >>> bitsCached) & ((1 << n) - 1); + }; + + LZWStream.prototype.readBlock = function LZWStream_readBlock() { + var blockSize = 512; + var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize; + var i, j, q; + + var lzwState = this.lzwState; + if (!lzwState) { + return; // eof was found + } + + var earlyChange = lzwState.earlyChange; + var nextCode = lzwState.nextCode; + var dictionaryValues = lzwState.dictionaryValues; + var dictionaryLengths = lzwState.dictionaryLengths; + var dictionaryPrevCodes = lzwState.dictionaryPrevCodes; + var codeLength = lzwState.codeLength; + var prevCode = lzwState.prevCode; + var currentSequence = lzwState.currentSequence; + var currentSequenceLength = lzwState.currentSequenceLength; + + var decodedLength = 0; + var currentBufferLength = this.bufferLength; + var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + + for (i = 0; i < blockSize; i++) { + var code = this.readBits(codeLength); + var hasPrev = currentSequenceLength > 0; + if (code < 256) { + currentSequence[0] = code; + currentSequenceLength = 1; + } else if (code >= 258) { + if (code < nextCode) { + currentSequenceLength = dictionaryLengths[code]; + for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { + currentSequence[j] = dictionaryValues[q]; + q = dictionaryPrevCodes[q]; + } + } else { + currentSequence[currentSequenceLength++] = currentSequence[0]; + } + } else if (code === 256) { + codeLength = 9; + nextCode = 258; + currentSequenceLength = 0; + continue; + } else { + this.eof = true; + delete this.lzwState; + break; + } + + if (hasPrev) { + dictionaryPrevCodes[nextCode] = prevCode; + dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; + dictionaryValues[nextCode] = currentSequence[0]; + nextCode++; + codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ? + codeLength : Math.min(Math.log(nextCode + earlyChange) / + 0.6931471805599453 + 1, 12) | 0; + } + prevCode = code; + + decodedLength += currentSequenceLength; + if (estimatedDecodedSize < decodedLength) { + do { + estimatedDecodedSize += decodedSizeDelta; + } while (estimatedDecodedSize < decodedLength); + buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + } + for (j = 0; j < currentSequenceLength; j++) { + buffer[currentBufferLength++] = currentSequence[j]; + } + } + lzwState.nextCode = nextCode; + lzwState.codeLength = codeLength; + lzwState.prevCode = prevCode; + lzwState.currentSequenceLength = currentSequenceLength; + + this.bufferLength = currentBufferLength; + }; + + return LZWStream; +})(); + +var NullStream = (function NullStreamClosure() { + function NullStream() { + Stream.call(this, new Uint8Array(0)); + } + + NullStream.prototype = Stream.prototype; + + return NullStream; +})(); + + +var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { + setup: function wphSetup(handler) { + var pdfManager; + + function loadDocument(recoveryMode) { + var loadDocumentCapability = createPromiseCapability(); + + var parseSuccess = function parseSuccess() { + var numPagesPromise = pdfManager.ensureDoc('numPages'); + var fingerprintPromise = pdfManager.ensureDoc('fingerprint'); + var encryptedPromise = pdfManager.ensureXRef('encrypt'); + Promise.all([numPagesPromise, fingerprintPromise, + encryptedPromise]).then(function onDocReady(results) { + var doc = { + numPages: results[0], + fingerprint: results[1], + encrypted: !!results[2], + }; + loadDocumentCapability.resolve(doc); + }, + parseFailure); + }; + + var parseFailure = function parseFailure(e) { + loadDocumentCapability.reject(e); + }; + + pdfManager.ensureDoc('checkHeader', []).then(function() { + pdfManager.ensureDoc('parseStartXRef', []).then(function() { + pdfManager.ensureDoc('parse', [recoveryMode]).then( + parseSuccess, parseFailure); + }, parseFailure); + }, parseFailure); + + return loadDocumentCapability.promise; + } + + function getPdfManager(data) { + var pdfManagerCapability = createPromiseCapability(); + + var source = data.source; + var disableRange = data.disableRange; + if (source.data) { + try { + pdfManager = new LocalPdfManager(source.data, source.password); + pdfManagerCapability.resolve(); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + return pdfManagerCapability.promise; + } else if (source.chunkedViewerLoading) { + try { + pdfManager = new NetworkPdfManager(source, handler); + pdfManagerCapability.resolve(); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + return pdfManagerCapability.promise; + } + + var networkManager = new NetworkManager(source.url, { + httpHeaders: source.httpHeaders, + withCredentials: source.withCredentials + }); + var cachedChunks = []; + var fullRequestXhrId = networkManager.requestFull({ + onHeadersReceived: function onHeadersReceived() { + if (disableRange) { + return; + } + + var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId); + if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') { + return; + } + + var contentEncoding = + fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity'; + if (contentEncoding !== 'identity') { + return; + } + + var length = fullRequestXhr.getResponseHeader('Content-Length'); + length = parseInt(length, 10); + if (!isInt(length)) { + return; + } + source.length = length; + if (length <= 2 * RANGE_CHUNK_SIZE) { + // The file size is smaller than the size of two chunks, so it does + // not make any sense to abort the request and retry with a range + // request. + return; + } + + if (networkManager.isStreamingRequest(fullRequestXhrId)) { + // We can continue fetching when progressive loading is enabled, + // and we don't need the autoFetch feature. + source.disableAutoFetch = true; + } else { + // NOTE: by cancelling the full request, and then issuing range + // requests, there will be an issue for sites where you can only + // request the pdf once. However, if this is the case, then the + // server should not be returning that it can support range + // requests. + networkManager.abortRequest(fullRequestXhrId); + } + + try { + pdfManager = new NetworkPdfManager(source, handler); + pdfManagerCapability.resolve(pdfManager); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + }, + + onProgressiveData: source.disableStream ? null : + function onProgressiveData(chunk) { + if (!pdfManager) { + cachedChunks.push(chunk); + return; + } + pdfManager.sendProgressiveData(chunk); + }, + + onDone: function onDone(args) { + if (pdfManager) { + return; // already processed + } + + var pdfFile; + if (args === null) { + // TODO add some streaming manager, e.g. for unknown length files. + // The data was returned in the onProgressiveData, combining... + var pdfFileLength = 0, pos = 0; + cachedChunks.forEach(function (chunk) { + pdfFileLength += chunk.byteLength; + }); + if (source.length && pdfFileLength !== source.length) { + warn('reported HTTP length is different from actual'); + } + var pdfFileArray = new Uint8Array(pdfFileLength); + cachedChunks.forEach(function (chunk) { + pdfFileArray.set(new Uint8Array(chunk), pos); + pos += chunk.byteLength; + }); + pdfFile = pdfFileArray.buffer; + } else { + pdfFile = args.chunk; + } + + // the data is array, instantiating directly from it + try { + pdfManager = new LocalPdfManager(pdfFile, source.password); + pdfManagerCapability.resolve(); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + }, + + onError: function onError(status) { + var exception; + if (status === 404) { + exception = new MissingPDFException('Missing PDF "' + + source.url + '".'); + handler.send('MissingPDF', exception); + } else { + exception = new UnexpectedResponseException( + 'Unexpected server response (' + status + + ') while retrieving PDF "' + source.url + '".', status); + handler.send('UnexpectedResponse', exception); + } + }, + + onProgress: function onProgress(evt) { + handler.send('DocProgress', { + loaded: evt.loaded, + total: evt.lengthComputable ? evt.total : source.length + }); + } + }); + + return pdfManagerCapability.promise; + } + + handler.on('test', function wphSetupTest(data) { + // check if Uint8Array can be sent to worker + if (!(data instanceof Uint8Array)) { + handler.send('test', false); + return; + } + // making sure postMessage transfers are working + var supportTransfers = data[0] === 255; + handler.postMessageTransfers = supportTransfers; + // check if the response property is supported by xhr + var xhr = new XMLHttpRequest(); + var responseExists = 'response' in xhr; + // check if the property is actually implemented + try { + var dummy = xhr.responseType; + } catch (e) { + responseExists = false; + } + if (!responseExists) { + handler.send('test', false); + return; + } + handler.send('test', { + supportTypedArray: true, + supportTransfers: supportTransfers + }); + }); + + handler.on('GetDocRequest', function wphSetupDoc(data) { + + var onSuccess = function(doc) { + handler.send('GetDoc', { pdfInfo: doc }); + }; + + var onFailure = function(e) { + if (e instanceof PasswordException) { + if (e.code === PasswordResponses.NEED_PASSWORD) { + handler.send('NeedPassword', e); + } else if (e.code === PasswordResponses.INCORRECT_PASSWORD) { + handler.send('IncorrectPassword', e); + } + } else if (e instanceof InvalidPDFException) { + handler.send('InvalidPDF', e); + } else if (e instanceof MissingPDFException) { + handler.send('MissingPDF', e); + } else if (e instanceof UnexpectedResponseException) { + handler.send('UnexpectedResponse', e); + } else { + handler.send('UnknownError', + new UnknownErrorException(e.message, e.toString())); + } + }; + + PDFJS.maxImageSize = data.maxImageSize === undefined ? + -1 : data.maxImageSize; + PDFJS.disableFontFace = data.disableFontFace; + PDFJS.disableCreateObjectURL = data.disableCreateObjectURL; + PDFJS.verbosity = data.verbosity; + PDFJS.cMapUrl = data.cMapUrl === undefined ? + null : data.cMapUrl; + PDFJS.cMapPacked = data.cMapPacked === true; + + getPdfManager(data).then(function () { + handler.send('PDFManagerReady', null); + pdfManager.onLoadedStream().then(function(stream) { + handler.send('DataLoaded', { length: stream.bytes.byteLength }); + }); + }).then(function pdfManagerReady() { + loadDocument(false).then(onSuccess, function loadFailure(ex) { + // Try again with recoveryMode == true + if (!(ex instanceof XRefParseException)) { + if (ex instanceof PasswordException) { + // after password exception prepare to receive a new password + // to repeat loading + pdfManager.passwordChanged().then(pdfManagerReady); + } + + onFailure(ex); + return; + } + + pdfManager.requestLoadedStream(); + pdfManager.onLoadedStream().then(function() { + loadDocument(true).then(onSuccess, onFailure); + }); + }, onFailure); + }, onFailure); + }); + + handler.on('GetPage', function wphSetupGetPage(data) { + return pdfManager.getPage(data.pageIndex).then(function(page) { + var rotatePromise = pdfManager.ensure(page, 'rotate'); + var refPromise = pdfManager.ensure(page, 'ref'); + var viewPromise = pdfManager.ensure(page, 'view'); + + return Promise.all([rotatePromise, refPromise, viewPromise]).then( + function(results) { + return { + rotate: results[0], + ref: results[1], + view: results[2] + }; + }); + }); + }); + + handler.on('GetPageIndex', function wphSetupGetPageIndex(data) { + var ref = new Ref(data.ref.num, data.ref.gen); + var catalog = pdfManager.pdfDocument.catalog; + return catalog.getPageIndex(ref); + }); + + handler.on('GetDestinations', + function wphSetupGetDestinations(data) { + return pdfManager.ensureCatalog('destinations'); + } + ); + + handler.on('GetDestination', + function wphSetupGetDestination(data) { + return pdfManager.ensureCatalog('getDestination', [ data.id ]); + } + ); + + handler.on('GetAttachments', + function wphSetupGetAttachments(data) { + return pdfManager.ensureCatalog('attachments'); + } + ); + + handler.on('GetJavaScript', + function wphSetupGetJavaScript(data) { + return pdfManager.ensureCatalog('javaScript'); + } + ); + + handler.on('GetOutline', + function wphSetupGetOutline(data) { + return pdfManager.ensureCatalog('documentOutline'); + } + ); + + handler.on('GetMetadata', + function wphSetupGetMetadata(data) { + return Promise.all([pdfManager.ensureDoc('documentInfo'), + pdfManager.ensureCatalog('metadata')]); + } + ); + + handler.on('GetData', function wphSetupGetData(data) { + pdfManager.requestLoadedStream(); + return pdfManager.onLoadedStream().then(function(stream) { + return stream.bytes; + }); + }); + + handler.on('GetStats', + function wphSetupGetStats(data) { + return pdfManager.pdfDocument.xref.stats; + } + ); + + handler.on('UpdatePassword', function wphSetupUpdatePassword(data) { + pdfManager.updatePassword(data); + }); + + handler.on('GetAnnotations', function wphSetupGetAnnotations(data) { + return pdfManager.getPage(data.pageIndex).then(function(page) { + return pdfManager.ensure(page, 'getAnnotationsData', []); + }); + }); + + handler.on('RenderPageRequest', function wphSetupRenderPage(data) { + pdfManager.getPage(data.pageIndex).then(function(page) { + + var pageNum = data.pageIndex + 1; + var start = Date.now(); + // Pre compile the pdf page and fetch the fonts/images. + page.getOperatorList(handler, data.intent).then(function(operatorList) { + + info('page=' + pageNum + ' - getOperatorList: time=' + + (Date.now() - start) + 'ms, len=' + operatorList.fnArray.length); + + }, function(e) { + + var minimumStackMessage = + 'worker.js: while trying to getPage() and getOperatorList()'; + + var wrappedException; + + // Turn the error into an obj that can be serialized + if (typeof e === 'string') { + wrappedException = { + message: e, + stack: minimumStackMessage + }; + } else if (typeof e === 'object') { + wrappedException = { + message: e.message || e.toString(), + stack: e.stack || minimumStackMessage + }; + } else { + wrappedException = { + message: 'Unknown exception type: ' + (typeof e), + stack: minimumStackMessage + }; + } + + handler.send('PageError', { + pageNum: pageNum, + error: wrappedException, + intent: data.intent + }); + }); + }); + }, this); + + handler.on('GetTextContent', function wphExtractText(data) { + return pdfManager.getPage(data.pageIndex).then(function(page) { + var pageNum = data.pageIndex + 1; + var start = Date.now(); + return page.extractTextContent().then(function(textContent) { + info('text indexing: page=' + pageNum + ' - time=' + + (Date.now() - start) + 'ms'); + return textContent; + }); + }); + }); + + handler.on('Cleanup', function wphCleanup(data) { + return pdfManager.cleanup(); + }); + + handler.on('Terminate', function wphTerminate(data) { + pdfManager.terminate(); + }); + } +}; + +var consoleTimer = {}; + +var workerConsole = { + log: function log() { + var args = Array.prototype.slice.call(arguments); + globalScope.postMessage({ + action: 'console_log', + data: args + }); + }, + + error: function error() { + var args = Array.prototype.slice.call(arguments); + globalScope.postMessage({ + action: 'console_error', + data: args + }); + throw 'pdf.js execution error'; + }, + + time: function time(name) { + consoleTimer[name] = Date.now(); + }, + + timeEnd: function timeEnd(name) { + var time = consoleTimer[name]; + if (!time) { + error('Unknown timer name ' + name); + } + this.log('Timer:', name, Date.now() - time); + } +}; + + +// Worker thread? +if (typeof window === 'undefined') { + if (!('console' in globalScope)) { + globalScope.console = workerConsole; + } + + // Listen for unsupported features so we can pass them on to the main thread. + PDFJS.UnsupportedManager.listen(function (msg) { + globalScope.postMessage({ + action: '_unsupported_feature', + data: msg + }); + }); + + var handler = new MessageHandler('worker_processor', this); + WorkerMessageHandler.setup(handler); +} + + +/* This class implements the QM Coder decoding as defined in + * JPEG 2000 Part I Final Committee Draft Version 1.0 + * Annex C.3 Arithmetic decoding procedure + * available at http://www.jpeg.org/public/fcd15444-1.pdf + * + * The arithmetic decoder is used in conjunction with context models to decode + * JPEG2000 and JBIG2 streams. + */ +var ArithmeticDecoder = (function ArithmeticDecoderClosure() { + // Table C-2 + var QeTable = [ + {qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1}, + {qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0}, + {qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0}, + {qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0}, + {qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0}, + {qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0}, + {qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1}, + {qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0}, + {qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0}, + {qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0}, + {qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0}, + {qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0}, + {qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0}, + {qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0}, + {qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1}, + {qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0}, + {qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0}, + {qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0}, + {qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0}, + {qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0}, + {qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0}, + {qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0}, + {qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0}, + {qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0}, + {qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0}, + {qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0}, + {qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0}, + {qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0}, + {qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0}, + {qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0}, + {qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0}, + {qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0}, + {qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0}, + {qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0}, + {qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0}, + {qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0}, + {qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0}, + {qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0}, + {qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0}, + {qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0}, + {qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0}, + {qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0}, + {qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0}, + {qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0}, + {qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0}, + {qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0}, + {qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0} + ]; + + // C.3.5 Initialisation of the decoder (INITDEC) + function ArithmeticDecoder(data, start, end) { + this.data = data; + this.bp = start; + this.dataEnd = end; + + this.chigh = data[start]; + this.clow = 0; + + this.byteIn(); + + this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F); + this.clow = (this.clow << 7) & 0xFFFF; + this.ct -= 7; + this.a = 0x8000; + } + + ArithmeticDecoder.prototype = { + // C.3.4 Compressed data input (BYTEIN) + byteIn: function ArithmeticDecoder_byteIn() { + var data = this.data; + var bp = this.bp; + if (data[bp] === 0xFF) { + var b1 = data[bp + 1]; + if (b1 > 0x8F) { + this.clow += 0xFF00; + this.ct = 8; + } else { + bp++; + this.clow += (data[bp] << 9); + this.ct = 7; + this.bp = bp; + } + } else { + bp++; + this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00; + this.ct = 8; + this.bp = bp; + } + if (this.clow > 0xFFFF) { + this.chigh += (this.clow >> 16); + this.clow &= 0xFFFF; + } + }, + // C.3.2 Decoding a decision (DECODE) + readBit: function ArithmeticDecoder_readBit(contexts, pos) { + // contexts are packed into 1 byte: + // highest 7 bits carry cx.index, lowest bit carries cx.mps + var cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1; + var qeTableIcx = QeTable[cx_index]; + var qeIcx = qeTableIcx.qe; + var d; + var a = this.a - qeIcx; + + if (this.chigh < qeIcx) { + // exchangeLps + if (a < qeIcx) { + a = qeIcx; + d = cx_mps; + cx_index = qeTableIcx.nmps; + } else { + a = qeIcx; + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } + } else { + this.chigh -= qeIcx; + if ((a & 0x8000) !== 0) { + this.a = a; + return cx_mps; + } + // exchangeMps + if (a < qeIcx) { + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } else { + d = cx_mps; + cx_index = qeTableIcx.nmps; + } + } + // C.3.3 renormD; + do { + if (this.ct === 0) { + this.byteIn(); + } + + a <<= 1; + this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1); + this.clow = (this.clow << 1) & 0xFFFF; + this.ct--; + } while ((a & 0x8000) === 0); + this.a = a; + + contexts[pos] = cx_index << 1 | cx_mps; + return d; + } + }; + + return ArithmeticDecoder; +})(); + + +var JpegImage = (function jpegImage() { + var dctZigZag = new Uint8Array([ + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 + ]); + + var dctCos1 = 4017; // cos(pi/16) + var dctSin1 = 799; // sin(pi/16) + var dctCos3 = 3406; // cos(3*pi/16) + var dctSin3 = 2276; // sin(3*pi/16) + var dctCos6 = 1567; // cos(6*pi/16) + var dctSin6 = 3784; // sin(6*pi/16) + var dctSqrt2 = 5793; // sqrt(2) + var dctSqrt1d2 = 2896; // sqrt(2) / 2 + + function constructor() { + } + + function buildHuffmanTable(codeLengths, values) { + var k = 0, code = [], i, j, length = 16; + while (length > 0 && !codeLengths[length - 1]) { + length--; + } + code.push({children: [], index: 0}); + var p = code[0], q; + for (i = 0; i < length; i++) { + for (j = 0; j < codeLengths[i]; j++) { + p = code.pop(); + p.children[p.index] = values[k]; + while (p.index > 0) { + p = code.pop(); + } + p.index++; + code.push(p); + while (code.length <= i) { + code.push(q = {children: [], index: 0}); + p.children[p.index] = q.children; + p = q; + } + k++; + } + if (i + 1 < length) { + // p here points to last code + code.push(q = {children: [], index: 0}); + p.children[p.index] = q.children; + p = q; + } + } + return code[0].children; + } + + function getBlockBufferOffset(component, row, col) { + return 64 * ((component.blocksPerLine + 1) * row + col); + } + + function decodeScan(data, offset, frame, components, resetInterval, + spectralStart, spectralEnd, successivePrev, successive) { + var precision = frame.precision; + var samplesPerLine = frame.samplesPerLine; + var scanLines = frame.scanLines; + var mcusPerLine = frame.mcusPerLine; + var progressive = frame.progressive; + var maxH = frame.maxH, maxV = frame.maxV; + + var startOffset = offset, bitsData = 0, bitsCount = 0; + + function readBit() { + if (bitsCount > 0) { + bitsCount--; + return (bitsData >> bitsCount) & 1; + } + bitsData = data[offset++]; + if (bitsData === 0xFF) { + var nextByte = data[offset++]; + if (nextByte) { + throw 'unexpected marker: ' + + ((bitsData << 8) | nextByte).toString(16); + } + // unstuff 0 + } + bitsCount = 7; + return bitsData >>> 7; + } + + function decodeHuffman(tree) { + var node = tree; + while (true) { + node = node[readBit()]; + if (typeof node === 'number') { + return node; + } + if (typeof node !== 'object') { + throw 'invalid huffman sequence'; + } + } + } + + function receive(length) { + var n = 0; + while (length > 0) { + n = (n << 1) | readBit(); + length--; + } + return n; + } + + function receiveAndExtend(length) { + if (length === 1) { + return readBit() === 1 ? 1 : -1; + } + var n = receive(length); + if (n >= 1 << (length - 1)) { + return n; + } + return n + (-1 << length) + 1; + } + + function decodeBaseline(component, offset) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : receiveAndExtend(t); + component.blockData[offset] = (component.pred += diff); + var k = 1; + while (k < 64) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + break; + } + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + component.blockData[offset + z] = receiveAndExtend(s); + k++; + } + } + + function decodeDCFirst(component, offset) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive); + component.blockData[offset] = (component.pred += diff); + } + + function decodeDCSuccessive(component, offset) { + component.blockData[offset] |= readBit() << successive; + } + + var eobrun = 0; + function decodeACFirst(component, offset) { + if (eobrun > 0) { + eobrun--; + return; + } + var k = spectralStart, e = spectralEnd; + while (k <= e) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r) - 1; + break; + } + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + component.blockData[offset + z] = + receiveAndExtend(s) * (1 << successive); + k++; + } + } + + var successiveACState = 0, successiveACNextValue; + function decodeACSuccessive(component, offset) { + var k = spectralStart; + var e = spectralEnd; + var r = 0; + var s; + var rs; + while (k <= e) { + var z = dctZigZag[k]; + switch (successiveACState) { + case 0: // initial state + rs = decodeHuffman(component.huffmanTableAC); + s = rs & 15; + r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r); + successiveACState = 4; + } else { + r = 16; + successiveACState = 1; + } + } else { + if (s !== 1) { + throw 'invalid ACn encoding'; + } + successiveACNextValue = receiveAndExtend(s); + successiveACState = r ? 2 : 3; + } + continue; + case 1: // skipping r zero items + case 2: + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); + } else { + r--; + if (r === 0) { + successiveACState = successiveACState === 2 ? 3 : 0; + } + } + break; + case 3: // set value for a zero item + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); + } else { + component.blockData[offset + z] = + successiveACNextValue << successive; + successiveACState = 0; + } + break; + case 4: // eob + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); + } + break; + } + k++; + } + if (successiveACState === 4) { + eobrun--; + if (eobrun === 0) { + successiveACState = 0; + } + } + } + + function decodeMcu(component, decode, mcu, row, col) { + var mcuRow = (mcu / mcusPerLine) | 0; + var mcuCol = mcu % mcusPerLine; + var blockRow = mcuRow * component.v + row; + var blockCol = mcuCol * component.h + col; + var offset = getBlockBufferOffset(component, blockRow, blockCol); + decode(component, offset); + } + + function decodeBlock(component, decode, mcu) { + var blockRow = (mcu / component.blocksPerLine) | 0; + var blockCol = mcu % component.blocksPerLine; + var offset = getBlockBufferOffset(component, blockRow, blockCol); + decode(component, offset); + } + + var componentsLength = components.length; + var component, i, j, k, n; + var decodeFn; + if (progressive) { + if (spectralStart === 0) { + decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; + } else { + decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; + } + } else { + decodeFn = decodeBaseline; + } + + var mcu = 0, marker; + var mcuExpected; + if (componentsLength === 1) { + mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn; + } else { + mcuExpected = mcusPerLine * frame.mcusPerColumn; + } + if (!resetInterval) { + resetInterval = mcuExpected; + } + + var h, v; + while (mcu < mcuExpected) { + // reset interval stuff + for (i = 0; i < componentsLength; i++) { + components[i].pred = 0; + } + eobrun = 0; + + if (componentsLength === 1) { + component = components[0]; + for (n = 0; n < resetInterval; n++) { + decodeBlock(component, decodeFn, mcu); + mcu++; + } + } else { + for (n = 0; n < resetInterval; n++) { + for (i = 0; i < componentsLength; i++) { + component = components[i]; + h = component.h; + v = component.v; + for (j = 0; j < v; j++) { + for (k = 0; k < h; k++) { + decodeMcu(component, decodeFn, mcu, j, k); + } + } + } + mcu++; + } + } + + // find marker + bitsCount = 0; + marker = (data[offset] << 8) | data[offset + 1]; + if (marker <= 0xFF00) { + throw 'marker was not found'; + } + + if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx + offset += 2; + } else { + break; + } + } + + return offset - startOffset; + } + + // A port of poppler's IDCT method which in turn is taken from: + // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, + // 'Practical Fast 1-D DCT Algorithms with 11 Multiplications', + // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, + // 988-991. + function quantizeAndInverse(component, blockBufferOffset, p) { + var qt = component.quantizationTable, blockData = component.blockData; + var v0, v1, v2, v3, v4, v5, v6, v7; + var p0, p1, p2, p3, p4, p5, p6, p7; + var t; + + // inverse DCT on rows + for (var row = 0; row < 64; row += 8) { + // gather block data + p0 = blockData[blockBufferOffset + row]; + p1 = blockData[blockBufferOffset + row + 1]; + p2 = blockData[blockBufferOffset + row + 2]; + p3 = blockData[blockBufferOffset + row + 3]; + p4 = blockData[blockBufferOffset + row + 4]; + p5 = blockData[blockBufferOffset + row + 5]; + p6 = blockData[blockBufferOffset + row + 6]; + p7 = blockData[blockBufferOffset + row + 7]; + + // dequant p0 + p0 *= qt[row]; + + // check for all-zero AC coefficients + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = (dctSqrt2 * p0 + 512) >> 10; + p[row] = t; + p[row + 1] = t; + p[row + 2] = t; + p[row + 3] = t; + p[row + 4] = t; + p[row + 5] = t; + p[row + 6] = t; + p[row + 7] = t; + continue; + } + // dequant p1 ... p7 + p1 *= qt[row + 1]; + p2 *= qt[row + 2]; + p3 *= qt[row + 3]; + p4 *= qt[row + 4]; + p5 *= qt[row + 5]; + p6 *= qt[row + 6]; + p7 *= qt[row + 7]; + + // stage 4 + v0 = (dctSqrt2 * p0 + 128) >> 8; + v1 = (dctSqrt2 * p4 + 128) >> 8; + v2 = p2; + v3 = p6; + v4 = (dctSqrt1d2 * (p1 - p7) + 128) >> 8; + v7 = (dctSqrt1d2 * (p1 + p7) + 128) >> 8; + v5 = p3 << 4; + v6 = p5 << 4; + + // stage 3 + v0 = (v0 + v1 + 1) >> 1; + v1 = v0 - v1; + t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; + v3 = t; + v4 = (v4 + v6 + 1) >> 1; + v6 = v4 - v6; + v7 = (v7 + v5 + 1) >> 1; + v5 = v7 - v5; + + // stage 2 + v0 = (v0 + v3 + 1) >> 1; + v3 = v0 - v3; + v1 = (v1 + v2 + 1) >> 1; + v2 = v1 - v2; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p[row] = v0 + v7; + p[row + 7] = v0 - v7; + p[row + 1] = v1 + v6; + p[row + 6] = v1 - v6; + p[row + 2] = v2 + v5; + p[row + 5] = v2 - v5; + p[row + 3] = v3 + v4; + p[row + 4] = v3 - v4; + } + + // inverse DCT on columns + for (var col = 0; col < 8; ++col) { + p0 = p[col]; + p1 = p[col + 8]; + p2 = p[col + 16]; + p3 = p[col + 24]; + p4 = p[col + 32]; + p5 = p[col + 40]; + p6 = p[col + 48]; + p7 = p[col + 56]; + + // check for all-zero AC coefficients + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = (dctSqrt2 * p0 + 8192) >> 14; + // convert to 8 bit + t = (t < -2040) ? 0 : (t >= 2024) ? 255 : (t + 2056) >> 4; + blockData[blockBufferOffset + col] = t; + blockData[blockBufferOffset + col + 8] = t; + blockData[blockBufferOffset + col + 16] = t; + blockData[blockBufferOffset + col + 24] = t; + blockData[blockBufferOffset + col + 32] = t; + blockData[blockBufferOffset + col + 40] = t; + blockData[blockBufferOffset + col + 48] = t; + blockData[blockBufferOffset + col + 56] = t; + continue; + } + + // stage 4 + v0 = (dctSqrt2 * p0 + 2048) >> 12; + v1 = (dctSqrt2 * p4 + 2048) >> 12; + v2 = p2; + v3 = p6; + v4 = (dctSqrt1d2 * (p1 - p7) + 2048) >> 12; + v7 = (dctSqrt1d2 * (p1 + p7) + 2048) >> 12; + v5 = p3; + v6 = p5; + + // stage 3 + // Shift v0 by 128.5 << 5 here, so we don't need to shift p0...p7 when + // converting to UInt8 range later. + v0 = ((v0 + v1 + 1) >> 1) + 4112; + v1 = v0 - v1; + t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; + v3 = t; + v4 = (v4 + v6 + 1) >> 1; + v6 = v4 - v6; + v7 = (v7 + v5 + 1) >> 1; + v5 = v7 - v5; + + // stage 2 + v0 = (v0 + v3 + 1) >> 1; + v3 = v0 - v3; + v1 = (v1 + v2 + 1) >> 1; + v2 = v1 - v2; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p0 = v0 + v7; + p7 = v0 - v7; + p1 = v1 + v6; + p6 = v1 - v6; + p2 = v2 + v5; + p5 = v2 - v5; + p3 = v3 + v4; + p4 = v3 - v4; + + // convert to 8-bit integers + p0 = (p0 < 16) ? 0 : (p0 >= 4080) ? 255 : p0 >> 4; + p1 = (p1 < 16) ? 0 : (p1 >= 4080) ? 255 : p1 >> 4; + p2 = (p2 < 16) ? 0 : (p2 >= 4080) ? 255 : p2 >> 4; + p3 = (p3 < 16) ? 0 : (p3 >= 4080) ? 255 : p3 >> 4; + p4 = (p4 < 16) ? 0 : (p4 >= 4080) ? 255 : p4 >> 4; + p5 = (p5 < 16) ? 0 : (p5 >= 4080) ? 255 : p5 >> 4; + p6 = (p6 < 16) ? 0 : (p6 >= 4080) ? 255 : p6 >> 4; + p7 = (p7 < 16) ? 0 : (p7 >= 4080) ? 255 : p7 >> 4; + + // store block data + blockData[blockBufferOffset + col] = p0; + blockData[blockBufferOffset + col + 8] = p1; + blockData[blockBufferOffset + col + 16] = p2; + blockData[blockBufferOffset + col + 24] = p3; + blockData[blockBufferOffset + col + 32] = p4; + blockData[blockBufferOffset + col + 40] = p5; + blockData[blockBufferOffset + col + 48] = p6; + blockData[blockBufferOffset + col + 56] = p7; + } + } + + function buildComponentData(frame, component) { + var blocksPerLine = component.blocksPerLine; + var blocksPerColumn = component.blocksPerColumn; + var computationBuffer = new Int16Array(64); + + for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { + var offset = getBlockBufferOffset(component, blockRow, blockCol); + quantizeAndInverse(component, offset, computationBuffer); + } + } + return component.blockData; + } + + function clamp0to255(a) { + return a <= 0 ? 0 : a >= 255 ? 255 : a; + } + + constructor.prototype = { + parse: function parse(data) { + + function readUint16() { + var value = (data[offset] << 8) | data[offset + 1]; + offset += 2; + return value; + } + + function readDataBlock() { + var length = readUint16(); + var array = data.subarray(offset, offset + length - 2); + offset += array.length; + return array; + } + + function prepareComponents(frame) { + var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH); + var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV); + for (var i = 0; i < frame.components.length; i++) { + component = frame.components[i]; + var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * + component.h / frame.maxH); + var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * + component.v / frame.maxV); + var blocksPerLineForMcu = mcusPerLine * component.h; + var blocksPerColumnForMcu = mcusPerColumn * component.v; + + var blocksBufferSize = 64 * blocksPerColumnForMcu * + (blocksPerLineForMcu + 1); + component.blockData = new Int16Array(blocksBufferSize); + component.blocksPerLine = blocksPerLine; + component.blocksPerColumn = blocksPerColumn; + } + frame.mcusPerLine = mcusPerLine; + frame.mcusPerColumn = mcusPerColumn; + } + + var offset = 0, length = data.length; + var jfif = null; + var adobe = null; + var pixels = null; + var frame, resetInterval; + var quantizationTables = []; + var huffmanTablesAC = [], huffmanTablesDC = []; + var fileMarker = readUint16(); + if (fileMarker !== 0xFFD8) { // SOI (Start of Image) + throw 'SOI not found'; + } + + fileMarker = readUint16(); + while (fileMarker !== 0xFFD9) { // EOI (End of image) + var i, j, l; + switch(fileMarker) { + case 0xFFE0: // APP0 (Application Specific) + case 0xFFE1: // APP1 + case 0xFFE2: // APP2 + case 0xFFE3: // APP3 + case 0xFFE4: // APP4 + case 0xFFE5: // APP5 + case 0xFFE6: // APP6 + case 0xFFE7: // APP7 + case 0xFFE8: // APP8 + case 0xFFE9: // APP9 + case 0xFFEA: // APP10 + case 0xFFEB: // APP11 + case 0xFFEC: // APP12 + case 0xFFED: // APP13 + case 0xFFEE: // APP14 + case 0xFFEF: // APP15 + case 0xFFFE: // COM (Comment) + var appData = readDataBlock(); + + if (fileMarker === 0xFFE0) { + if (appData[0] === 0x4A && appData[1] === 0x46 && + appData[2] === 0x49 && appData[3] === 0x46 && + appData[4] === 0) { // 'JFIF\x00' + jfif = { + version: { major: appData[5], minor: appData[6] }, + densityUnits: appData[7], + xDensity: (appData[8] << 8) | appData[9], + yDensity: (appData[10] << 8) | appData[11], + thumbWidth: appData[12], + thumbHeight: appData[13], + thumbData: appData.subarray(14, 14 + + 3 * appData[12] * appData[13]) + }; + } + } + // TODO APP1 - Exif + if (fileMarker === 0xFFEE) { + if (appData[0] === 0x41 && appData[1] === 0x64 && + appData[2] === 0x6F && appData[3] === 0x62 && + appData[4] === 0x65) { // 'Adobe' + adobe = { + version: (appData[5] << 8) | appData[6], + flags0: (appData[7] << 8) | appData[8], + flags1: (appData[9] << 8) | appData[10], + transformCode: appData[11] + }; + } + } + break; + + case 0xFFDB: // DQT (Define Quantization Tables) + var quantizationTablesLength = readUint16(); + var quantizationTablesEnd = quantizationTablesLength + offset - 2; + var z; + while (offset < quantizationTablesEnd) { + var quantizationTableSpec = data[offset++]; + var tableData = new Uint16Array(64); + if ((quantizationTableSpec >> 4) === 0) { // 8 bit values + for (j = 0; j < 64; j++) { + z = dctZigZag[j]; + tableData[z] = data[offset++]; + } + } else if ((quantizationTableSpec >> 4) === 1) { //16 bit + for (j = 0; j < 64; j++) { + z = dctZigZag[j]; + tableData[z] = readUint16(); + } + } else { + throw 'DQT: invalid table spec'; + } + quantizationTables[quantizationTableSpec & 15] = tableData; + } + break; + + case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT) + case 0xFFC1: // SOF1 (Start of Frame, Extended DCT) + case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT) + if (frame) { + throw 'Only single frame JPEGs supported'; + } + readUint16(); // skip data length + frame = {}; + frame.extended = (fileMarker === 0xFFC1); + frame.progressive = (fileMarker === 0xFFC2); + frame.precision = data[offset++]; + frame.scanLines = readUint16(); + frame.samplesPerLine = readUint16(); + frame.components = []; + frame.componentIds = {}; + var componentsCount = data[offset++], componentId; + var maxH = 0, maxV = 0; + for (i = 0; i < componentsCount; i++) { + componentId = data[offset]; + var h = data[offset + 1] >> 4; + var v = data[offset + 1] & 15; + if (maxH < h) { + maxH = h; + } + if (maxV < v) { + maxV = v; + } + var qId = data[offset + 2]; + l = frame.components.push({ + h: h, + v: v, + quantizationTable: quantizationTables[qId] + }); + frame.componentIds[componentId] = l - 1; + offset += 3; + } + frame.maxH = maxH; + frame.maxV = maxV; + prepareComponents(frame); + break; + + case 0xFFC4: // DHT (Define Huffman Tables) + var huffmanLength = readUint16(); + for (i = 2; i < huffmanLength;) { + var huffmanTableSpec = data[offset++]; + var codeLengths = new Uint8Array(16); + var codeLengthSum = 0; + for (j = 0; j < 16; j++, offset++) { + codeLengthSum += (codeLengths[j] = data[offset]); + } + var huffmanValues = new Uint8Array(codeLengthSum); + for (j = 0; j < codeLengthSum; j++, offset++) { + huffmanValues[j] = data[offset]; + } + i += 17 + codeLengthSum; + + ((huffmanTableSpec >> 4) === 0 ? + huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = + buildHuffmanTable(codeLengths, huffmanValues); + } + break; + + case 0xFFDD: // DRI (Define Restart Interval) + readUint16(); // skip data length + resetInterval = readUint16(); + break; + + case 0xFFDA: // SOS (Start of Scan) + var scanLength = readUint16(); + var selectorsCount = data[offset++]; + var components = [], component; + for (i = 0; i < selectorsCount; i++) { + var componentIndex = frame.componentIds[data[offset++]]; + component = frame.components[componentIndex]; + var tableSpec = data[offset++]; + component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; + component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; + components.push(component); + } + var spectralStart = data[offset++]; + var spectralEnd = data[offset++]; + var successiveApproximation = data[offset++]; + var processed = decodeScan(data, offset, + frame, components, resetInterval, + spectralStart, spectralEnd, + successiveApproximation >> 4, successiveApproximation & 15); + offset += processed; + break; + + case 0xFFFF: // Fill bytes + if (data[offset] !== 0xFF) { // Avoid skipping a valid marker. + offset--; + } + break; + + default: + if (data[offset - 3] === 0xFF && + data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) { + // could be incorrect encoding -- last 0xFF byte of the previous + // block was eaten by the encoder + offset -= 3; + break; + } + throw 'unknown JPEG marker ' + fileMarker.toString(16); + } + fileMarker = readUint16(); + } + + this.width = frame.samplesPerLine; + this.height = frame.scanLines; + this.jfif = jfif; + this.adobe = adobe; + this.components = []; + for (i = 0; i < frame.components.length; i++) { + component = frame.components[i]; + this.components.push({ + output: buildComponentData(frame, component), + scaleX: component.h / frame.maxH, + scaleY: component.v / frame.maxV, + blocksPerLine: component.blocksPerLine, + blocksPerColumn: component.blocksPerColumn + }); + } + this.numComponents = this.components.length; + }, + + _getLinearizedBlockData: function getLinearizedBlockData(width, height) { + var scaleX = this.width / width, scaleY = this.height / height; + + var component, componentScaleX, componentScaleY, blocksPerScanline; + var x, y, i, j, k; + var index; + var offset = 0; + var output; + var numComponents = this.components.length; + var dataLength = width * height * numComponents; + var data = new Uint8Array(dataLength); + var xScaleBlockOffset = new Uint32Array(width); + var mask3LSB = 0xfffffff8; // used to clear the 3 LSBs + + for (i = 0; i < numComponents; i++) { + component = this.components[i]; + componentScaleX = component.scaleX * scaleX; + componentScaleY = component.scaleY * scaleY; + offset = i; + output = component.output; + blocksPerScanline = (component.blocksPerLine + 1) << 3; + // precalculate the xScaleBlockOffset + for (x = 0; x < width; x++) { + j = 0 | (x * componentScaleX); + xScaleBlockOffset[x] = ((j & mask3LSB) << 3) | (j & 7); + } + // linearize the blocks of the component + for (y = 0; y < height; y++) { + j = 0 | (y * componentScaleY); + index = blocksPerScanline * (j & mask3LSB) | ((j & 7) << 3); + for (x = 0; x < width; x++) { + data[offset] = output[index + xScaleBlockOffset[x]]; + offset += numComponents; + } + } + } + + // decodeTransform contains pairs of multiplier (-256..256) and additive + var transform = this.decodeTransform; + if (transform) { + for (i = 0; i < dataLength;) { + for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) { + data[i] = ((data[i] * transform[k]) >> 8) + transform[k + 1]; + } + } + } + return data; + }, + + _isColorConversionNeeded: function isColorConversionNeeded() { + if (this.adobe && this.adobe.transformCode) { + // The adobe transform marker overrides any previous setting + return true; + } else if (this.numComponents === 3) { + return true; + } else { + return false; + } + }, + + _convertYccToRgb: function convertYccToRgb(data) { + var Y, Cb, Cr; + for (var i = 0, length = data.length; i < length; i += 3) { + Y = data[i ]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i ] = clamp0to255(Y - 179.456 + 1.402 * Cr); + data[i + 1] = clamp0to255(Y + 135.459 - 0.344 * Cb - 0.714 * Cr); + data[i + 2] = clamp0to255(Y - 226.816 + 1.772 * Cb); + } + return data; + }, + + _convertYcckToRgb: function convertYcckToRgb(data) { + var Y, Cb, Cr, k; + var offset = 0; + for (var i = 0, length = data.length; i < length; i += 4) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + k = data[i + 3]; + + var r = -122.67195406894 + + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - + 5.4080610064599e-5 * Y + 0.00048449797120281 * k - + 0.154362151871126) + + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - + 0.00477271405408747 * k + 1.53380253221734) + + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + + 0.48357088451265) + + k * (-0.000336197177618394 * k + 0.484791561490776); + + var g = 107.268039397724 + + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + + 0.000659397001245577 * Y + 0.000426105652938837 * k - + 0.176491792462875) + + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + + 0.000770482631801132 * k - 0.151051492775562) + + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + + 0.25802910206845) + + k * (-0.000318913117588328 * k - 0.213742400323665); + + var b = -20.810012546947 + + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + + 0.0020741088115012 * Y - 0.00288260236853442 * k + + 0.814272968359295) + + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + + 0.000560833691242812 * k - 0.195152027534049) + + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + + 0.116935020465145) + + k * (-0.000343531996510555 * k + 0.24165260232407); + + data[offset++] = clamp0to255(r); + data[offset++] = clamp0to255(g); + data[offset++] = clamp0to255(b); + } + return data; + }, + + _convertYcckToCmyk: function convertYcckToCmyk(data) { + var Y, Cb, Cr; + for (var i = 0, length = data.length; i < length; i += 4) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i ] = clamp0to255(434.456 - Y - 1.402 * Cr); + data[i + 1] = clamp0to255(119.541 - Y + 0.344 * Cb + 0.714 * Cr); + data[i + 2] = clamp0to255(481.816 - Y - 1.772 * Cb); + // K in data[i + 3] is unchanged + } + return data; + }, + + _convertCmykToRgb: function convertCmykToRgb(data) { + var c, m, y, k; + var offset = 0; + var min = -255 * 255 * 255; + var scale = 1 / 255 / 255; + for (var i = 0, length = data.length; i < length; i += 4) { + c = data[i]; + m = data[i + 1]; + y = data[i + 2]; + k = data[i + 3]; + + var r = + c * (-4.387332384609988 * c + 54.48615194189176 * m + + 18.82290502165302 * y + 212.25662451639585 * k - + 72734.4411664936) + + m * (1.7149763477362134 * m - 5.6096736904047315 * y - + 17.873870861415444 * k - 1401.7366389350734) + + y * (-2.5217340131683033 * y - 21.248923337353073 * k + + 4465.541406466231) - + k * (21.86122147463605 * k + 48317.86113160301); + var g = + c * (8.841041422036149 * c + 60.118027045597366 * m + + 6.871425592049007 * y + 31.159100130055922 * k - + 20220.756542821975) + + m * (-15.310361306967817 * m + 17.575251261109482 * y + + 131.35250912493976 * k - 48691.05921601825) + + y * (4.444339102852739 * y + 9.8632861493405 * k - + 6341.191035517494) - + k * (20.737325471181034 * k + 47890.15695978492); + var b = + c * (0.8842522430003296 * c + 8.078677503112928 * m + + 30.89978309703729 * y - 0.23883238689178934 * k - + 3616.812083916688) + + m * (10.49593273432072 * m + 63.02378494754052 * y + + 50.606957656360734 * k - 28620.90484698408) + + y * (0.03296041114873217 * y + 115.60384449646641 * k - + 49363.43385999684) - + k * (22.33816807309886 * k + 45932.16563550634); + + data[offset++] = r >= 0 ? 255 : r <= min ? 0 : 255 + r * scale | 0; + data[offset++] = g >= 0 ? 255 : g <= min ? 0 : 255 + g * scale | 0; + data[offset++] = b >= 0 ? 255 : b <= min ? 0 : 255 + b * scale | 0; + } + return data; + }, + + getData: function getData(width, height, forceRGBoutput) { + if (this.numComponents > 4) { + throw 'Unsupported color mode'; + } + // type of data: Uint8Array(width * height * numComponents) + var data = this._getLinearizedBlockData(width, height); + + if (this.numComponents === 3) { + return this._convertYccToRgb(data); + } else if (this.numComponents === 4) { + if (this._isColorConversionNeeded()) { + if (forceRGBoutput) { + return this._convertYcckToRgb(data); + } else { + return this._convertYcckToCmyk(data); + } + } else if (forceRGBoutput) { + return this._convertCmykToRgb(data); + } + } + return data; + } + }; + + return constructor; +})(); + + +var JpxImage = (function JpxImageClosure() { + // Table E.1 + var SubbandsGainLog2 = { + 'LL': 0, + 'LH': 1, + 'HL': 1, + 'HH': 2 + }; + function JpxImage() { + this.failOnCorruptedImage = false; + } + JpxImage.prototype = { + parse: function JpxImage_parse(data) { + + var head = readUint16(data, 0); + // No box header, immediate start of codestream (SOC) + if (head === 0xFF4F) { + this.parseCodestream(data, 0, data.length); + return; + } + + var position = 0, length = data.length; + while (position < length) { + var headerSize = 8; + var lbox = readUint32(data, position); + var tbox = readUint32(data, position + 4); + position += headerSize; + if (lbox === 1) { + // XLBox: read UInt64 according to spec. + // JavaScript's int precision of 53 bit should be sufficient here. + lbox = readUint32(data, position) * 4294967296 + + readUint32(data, position + 4); + position += 8; + headerSize += 8; + } + if (lbox === 0) { + lbox = length - position + headerSize; + } + if (lbox < headerSize) { + throw new Error('JPX Error: Invalid box field size'); + } + var dataLength = lbox - headerSize; + var jumpDataLength = true; + switch (tbox) { + case 0x6A703268: // 'jp2h' + jumpDataLength = false; // parsing child boxes + break; + case 0x636F6C72: // 'colr' + // Colorspaces are not used, the CS from the PDF is used. + var method = data[position]; + var precedence = data[position + 1]; + var approximation = data[position + 2]; + if (method === 1) { + // enumerated colorspace + var colorspace = readUint32(data, position + 3); + switch (colorspace) { + case 16: // this indicates a sRGB colorspace + case 17: // this indicates a grayscale colorspace + case 18: // this indicates a YUV colorspace + break; + default: + warn('Unknown colorspace ' + colorspace); + break; + } + } else if (method === 2) { + info('ICC profile not supported'); + } + break; + case 0x6A703263: // 'jp2c' + this.parseCodestream(data, position, position + dataLength); + break; + case 0x6A502020: // 'jP\024\024' + if (0x0d0a870a !== readUint32(data, position)) { + warn('Invalid JP2 signature'); + } + break; + // The following header types are valid but currently not used: + case 0x6A501A1A: // 'jP\032\032' + case 0x66747970: // 'ftyp' + case 0x72726571: // 'rreq' + case 0x72657320: // 'res ' + case 0x69686472: // 'ihdr' + break; + default: + var headerType = String.fromCharCode((tbox >> 24) & 0xFF, + (tbox >> 16) & 0xFF, + (tbox >> 8) & 0xFF, + tbox & 0xFF); + warn('Unsupported header type ' + tbox + ' (' + headerType + ')'); + break; + } + if (jumpDataLength) { + position += dataLength; + } + } + }, + parseImageProperties: function JpxImage_parseImageProperties(stream) { + var newByte = stream.getByte(); + while (newByte >= 0) { + var oldByte = newByte; + newByte = stream.getByte(); + var code = (oldByte << 8) | newByte; + // Image and tile size (SIZ) + if (code === 0xFF51) { + stream.skip(4); + var Xsiz = stream.getInt32() >>> 0; // Byte 4 + var Ysiz = stream.getInt32() >>> 0; // Byte 8 + var XOsiz = stream.getInt32() >>> 0; // Byte 12 + var YOsiz = stream.getInt32() >>> 0; // Byte 16 + stream.skip(16); + var Csiz = stream.getUint16(); // Byte 36 + this.width = Xsiz - XOsiz; + this.height = Ysiz - YOsiz; + this.componentsCount = Csiz; + // Results are always returned as Uint8Arrays + this.bitsPerComponent = 8; + return; + } + } + throw new Error('JPX Error: No size marker found in JPX stream'); + }, + parseCodestream: function JpxImage_parseCodestream(data, start, end) { + var context = {}; + try { + var doNotRecover = false; + var position = start; + while (position + 1 < end) { + var code = readUint16(data, position); + position += 2; + + var length = 0, j, sqcd, spqcds, spqcdSize, scalarExpounded, tile; + switch (code) { + case 0xFF4F: // Start of codestream (SOC) + context.mainHeader = true; + break; + case 0xFFD9: // End of codestream (EOC) + break; + case 0xFF51: // Image and tile size (SIZ) + length = readUint16(data, position); + var siz = {}; + siz.Xsiz = readUint32(data, position + 4); + siz.Ysiz = readUint32(data, position + 8); + siz.XOsiz = readUint32(data, position + 12); + siz.YOsiz = readUint32(data, position + 16); + siz.XTsiz = readUint32(data, position + 20); + siz.YTsiz = readUint32(data, position + 24); + siz.XTOsiz = readUint32(data, position + 28); + siz.YTOsiz = readUint32(data, position + 32); + var componentsCount = readUint16(data, position + 36); + siz.Csiz = componentsCount; + var components = []; + j = position + 38; + for (var i = 0; i < componentsCount; i++) { + var component = { + precision: (data[j] & 0x7F) + 1, + isSigned: !!(data[j] & 0x80), + XRsiz: data[j + 1], + YRsiz: data[j + 1] + }; + calculateComponentDimensions(component, siz); + components.push(component); + } + context.SIZ = siz; + context.components = components; + calculateTileGrids(context, components); + context.QCC = []; + context.COC = []; + break; + case 0xFF5C: // Quantization default (QCD) + length = readUint16(data, position); + var qcd = {}; + j = position + 2; + sqcd = data[j++]; + switch (sqcd & 0x1F) { + case 0: + spqcdSize = 8; + scalarExpounded = true; + break; + case 1: + spqcdSize = 16; + scalarExpounded = false; + break; + case 2: + spqcdSize = 16; + scalarExpounded = true; + break; + default: + throw new Error('JPX Error: Invalid SQcd value ' + sqcd); + } + qcd.noQuantization = (spqcdSize === 8); + qcd.scalarExpounded = scalarExpounded; + qcd.guardBits = sqcd >> 5; + spqcds = []; + while (j < length + position) { + var spqcd = {}; + if (spqcdSize === 8) { + spqcd.epsilon = data[j++] >> 3; + spqcd.mu = 0; + } else { + spqcd.epsilon = data[j] >> 3; + spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1]; + j += 2; + } + spqcds.push(spqcd); + } + qcd.SPqcds = spqcds; + if (context.mainHeader) { + context.QCD = qcd; + } else { + context.currentTile.QCD = qcd; + context.currentTile.QCC = []; + } + break; + case 0xFF5D: // Quantization component (QCC) + length = readUint16(data, position); + var qcc = {}; + j = position + 2; + var cqcc; + if (context.SIZ.Csiz < 257) { + cqcc = data[j++]; + } else { + cqcc = readUint16(data, j); + j += 2; + } + sqcd = data[j++]; + switch (sqcd & 0x1F) { + case 0: + spqcdSize = 8; + scalarExpounded = true; + break; + case 1: + spqcdSize = 16; + scalarExpounded = false; + break; + case 2: + spqcdSize = 16; + scalarExpounded = true; + break; + default: + throw new Error('JPX Error: Invalid SQcd value ' + sqcd); + } + qcc.noQuantization = (spqcdSize === 8); + qcc.scalarExpounded = scalarExpounded; + qcc.guardBits = sqcd >> 5; + spqcds = []; + while (j < (length + position)) { + spqcd = {}; + if (spqcdSize === 8) { + spqcd.epsilon = data[j++] >> 3; + spqcd.mu = 0; + } else { + spqcd.epsilon = data[j] >> 3; + spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1]; + j += 2; + } + spqcds.push(spqcd); + } + qcc.SPqcds = spqcds; + if (context.mainHeader) { + context.QCC[cqcc] = qcc; + } else { + context.currentTile.QCC[cqcc] = qcc; + } + break; + case 0xFF52: // Coding style default (COD) + length = readUint16(data, position); + var cod = {}; + j = position + 2; + var scod = data[j++]; + cod.entropyCoderWithCustomPrecincts = !!(scod & 1); + cod.sopMarkerUsed = !!(scod & 2); + cod.ephMarkerUsed = !!(scod & 4); + cod.progressionOrder = data[j++]; + cod.layersCount = readUint16(data, j); + j += 2; + cod.multipleComponentTransform = data[j++]; + + cod.decompositionLevelsCount = data[j++]; + cod.xcb = (data[j++] & 0xF) + 2; + cod.ycb = (data[j++] & 0xF) + 2; + var blockStyle = data[j++]; + cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1); + cod.resetContextProbabilities = !!(blockStyle & 2); + cod.terminationOnEachCodingPass = !!(blockStyle & 4); + cod.verticalyStripe = !!(blockStyle & 8); + cod.predictableTermination = !!(blockStyle & 16); + cod.segmentationSymbolUsed = !!(blockStyle & 32); + cod.reversibleTransformation = data[j++]; + if (cod.entropyCoderWithCustomPrecincts) { + var precinctsSizes = []; + while (j < length + position) { + var precinctsSize = data[j++]; + precinctsSizes.push({ + PPx: precinctsSize & 0xF, + PPy: precinctsSize >> 4 + }); + } + cod.precinctsSizes = precinctsSizes; + } + var unsupported = []; + if (cod.selectiveArithmeticCodingBypass) { + unsupported.push('selectiveArithmeticCodingBypass'); + } + if (cod.resetContextProbabilities) { + unsupported.push('resetContextProbabilities'); + } + if (cod.terminationOnEachCodingPass) { + unsupported.push('terminationOnEachCodingPass'); + } + if (cod.verticalyStripe) { + unsupported.push('verticalyStripe'); + } + if (cod.predictableTermination) { + unsupported.push('predictableTermination'); + } + if (unsupported.length > 0) { + doNotRecover = true; + throw new Error('JPX Error: Unsupported COD options (' + + unsupported.join(', ') + ')'); + } + if (context.mainHeader) { + context.COD = cod; + } else { + context.currentTile.COD = cod; + context.currentTile.COC = []; + } + break; + case 0xFF90: // Start of tile-part (SOT) + length = readUint16(data, position); + tile = {}; + tile.index = readUint16(data, position + 2); + tile.length = readUint32(data, position + 4); + tile.dataEnd = tile.length + position - 2; + tile.partIndex = data[position + 8]; + tile.partsCount = data[position + 9]; + + context.mainHeader = false; + if (tile.partIndex === 0) { + // reset component specific settings + tile.COD = context.COD; + tile.COC = context.COC.slice(0); // clone of the global COC + tile.QCD = context.QCD; + tile.QCC = context.QCC.slice(0); // clone of the global COC + } + context.currentTile = tile; + break; + case 0xFF93: // Start of data (SOD) + tile = context.currentTile; + if (tile.partIndex === 0) { + initializeTile(context, tile.index); + buildPackets(context); + } + + // moving to the end of the data + length = tile.dataEnd - position; + parseTilePackets(context, data, position, length); + break; + case 0xFF55: // Tile-part lengths, main header (TLM) + case 0xFF57: // Packet length, main header (PLM) + case 0xFF58: // Packet length, tile-part header (PLT) + case 0xFF64: // Comment (COM) + length = readUint16(data, position); + // skipping content + break; + case 0xFF53: // Coding style component (COC) + throw new Error('JPX Error: Codestream code 0xFF53 (COC) is ' + + 'not implemented'); + default: + throw new Error('JPX Error: Unknown codestream code: ' + + code.toString(16)); + } + position += length; + } + } catch (e) { + if (doNotRecover || this.failOnCorruptedImage) { + throw e; + } else { + warn('Trying to recover from ' + e.message); + } + } + this.tiles = transformComponents(context); + this.width = context.SIZ.Xsiz - context.SIZ.XOsiz; + this.height = context.SIZ.Ysiz - context.SIZ.YOsiz; + this.componentsCount = context.SIZ.Csiz; + } + }; + function calculateComponentDimensions(component, siz) { + // Section B.2 Component mapping + component.x0 = Math.ceil(siz.XOsiz / component.XRsiz); + component.x1 = Math.ceil(siz.Xsiz / component.XRsiz); + component.y0 = Math.ceil(siz.YOsiz / component.YRsiz); + component.y1 = Math.ceil(siz.Ysiz / component.YRsiz); + component.width = component.x1 - component.x0; + component.height = component.y1 - component.y0; + } + function calculateTileGrids(context, components) { + var siz = context.SIZ; + // Section B.3 Division into tile and tile-components + var tile, tiles = []; + var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz); + var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz); + for (var q = 0; q < numYtiles; q++) { + for (var p = 0; p < numXtiles; p++) { + tile = {}; + tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz); + tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz); + tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz); + tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz); + tile.width = tile.tx1 - tile.tx0; + tile.height = tile.ty1 - tile.ty0; + tile.components = []; + tiles.push(tile); + } + } + context.tiles = tiles; + + var componentsCount = siz.Csiz; + for (var i = 0, ii = componentsCount; i < ii; i++) { + var component = components[i]; + for (var j = 0, jj = tiles.length; j < jj; j++) { + var tileComponent = {}; + tile = tiles[j]; + tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz); + tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz); + tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz); + tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz); + tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0; + tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0; + tile.components[i] = tileComponent; + } + } + } + function getBlocksDimensions(context, component, r) { + var codOrCoc = component.codingStyleParameters; + var result = {}; + if (!codOrCoc.entropyCoderWithCustomPrecincts) { + result.PPx = 15; + result.PPy = 15; + } else { + result.PPx = codOrCoc.precinctsSizes[r].PPx; + result.PPy = codOrCoc.precinctsSizes[r].PPy; + } + // calculate codeblock size as described in section B.7 + result.xcb_ = (r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : + Math.min(codOrCoc.xcb, result.PPx)); + result.ycb_ = (r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : + Math.min(codOrCoc.ycb, result.PPy)); + return result; + } + function buildPrecincts(context, resolution, dimensions) { + // Section B.6 Division resolution to precincts + var precinctWidth = 1 << dimensions.PPx; + var precinctHeight = 1 << dimensions.PPy; + // Jasper introduces codeblock groups for mapping each subband codeblocks + // to precincts. Precinct partition divides a resolution according to width + // and height parameters. The subband that belongs to the resolution level + // has a different size than the level, unless it is the zero resolution. + + // From Jasper documentation: jpeg2000.pdf, section K: Tier-2 coding: + // The precinct partitioning for a particular subband is derived from a + // partitioning of its parent LL band (i.e., the LL band at the next higher + // resolution level)... The LL band associated with each resolution level is + // divided into precincts... Each of the resulting precinct regions is then + // mapped into its child subbands (if any) at the next lower resolution + // level. This is accomplished by using the coordinate transformation + // (u, v) = (ceil(x/2), ceil(y/2)) where (x, y) and (u, v) are the + // coordinates of a point in the LL band and child subband, respectively. + var isZeroRes = resolution.resLevel === 0; + var precinctWidthInSubband = 1 << (dimensions.PPx + (isZeroRes ? 0 : -1)); + var precinctHeightInSubband = 1 << (dimensions.PPy + (isZeroRes ? 0 : -1)); + var numprecinctswide = (resolution.trx1 > resolution.trx0 ? + Math.ceil(resolution.trx1 / precinctWidth) - + Math.floor(resolution.trx0 / precinctWidth) : 0); + var numprecinctshigh = (resolution.try1 > resolution.try0 ? + Math.ceil(resolution.try1 / precinctHeight) - + Math.floor(resolution.try0 / precinctHeight) : 0); + var numprecincts = numprecinctswide * numprecinctshigh; + + resolution.precinctParameters = { + precinctWidth: precinctWidth, + precinctHeight: precinctHeight, + numprecinctswide: numprecinctswide, + numprecinctshigh: numprecinctshigh, + numprecincts: numprecincts, + precinctWidthInSubband: precinctWidthInSubband, + precinctHeightInSubband: precinctHeightInSubband + }; + } + function buildCodeblocks(context, subband, dimensions) { + // Section B.7 Division sub-band into code-blocks + var xcb_ = dimensions.xcb_; + var ycb_ = dimensions.ycb_; + var codeblockWidth = 1 << xcb_; + var codeblockHeight = 1 << ycb_; + var cbx0 = subband.tbx0 >> xcb_; + var cby0 = subband.tby0 >> ycb_; + var cbx1 = (subband.tbx1 + codeblockWidth - 1) >> xcb_; + var cby1 = (subband.tby1 + codeblockHeight - 1) >> ycb_; + var precinctParameters = subband.resolution.precinctParameters; + var codeblocks = []; + var precincts = []; + var i, j, codeblock, precinctNumber; + for (j = cby0; j < cby1; j++) { + for (i = cbx0; i < cbx1; i++) { + codeblock = { + cbx: i, + cby: j, + tbx0: codeblockWidth * i, + tby0: codeblockHeight * j, + tbx1: codeblockWidth * (i + 1), + tby1: codeblockHeight * (j + 1) + }; + + codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0); + codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0); + codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1); + codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1); + + // Calculate precinct number for this codeblock, codeblock position + // should be relative to its subband, use actual dimension and position + // See comment about codeblock group width and height + var pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / + precinctParameters.precinctWidthInSubband); + var pj = Math.floor((codeblock.tby0_ - subband.tby0) / + precinctParameters.precinctHeightInSubband); + precinctNumber = pi + (pj * precinctParameters.numprecinctswide); + + codeblock.precinctNumber = precinctNumber; + codeblock.subbandType = subband.type; + codeblock.Lblock = 3; + + if (codeblock.tbx1_ <= codeblock.tbx0_ || + codeblock.tby1_ <= codeblock.tby0_) { + continue; + } + codeblocks.push(codeblock); + // building precinct for the sub-band + var precinct = precincts[precinctNumber]; + if (precinct !== undefined) { + if (i < precinct.cbxMin) { + precinct.cbxMin = i; + } else if (i > precinct.cbxMax) { + precinct.cbxMax = i; + } + if (j < precinct.cbyMin) { + precinct.cbxMin = j; + } else if (j > precinct.cbyMax) { + precinct.cbyMax = j; + } + } else { + precincts[precinctNumber] = precinct = { + cbxMin: i, + cbyMin: j, + cbxMax: i, + cbyMax: j + }; + } + codeblock.precinct = precinct; + } + } + subband.codeblockParameters = { + codeblockWidth: xcb_, + codeblockHeight: ycb_, + numcodeblockwide: cbx1 - cbx0 + 1, + numcodeblockhigh: cby1 - cby0 + 1 + }; + subband.codeblocks = codeblocks; + subband.precincts = precincts; + } + function createPacket(resolution, precinctNumber, layerNumber) { + var precinctCodeblocks = []; + // Section B.10.8 Order of info in packet + var subbands = resolution.subbands; + // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence + for (var i = 0, ii = subbands.length; i < ii; i++) { + var subband = subbands[i]; + var codeblocks = subband.codeblocks; + for (var j = 0, jj = codeblocks.length; j < jj; j++) { + var codeblock = codeblocks[j]; + if (codeblock.precinctNumber !== precinctNumber) { + continue; + } + precinctCodeblocks.push(codeblock); + } + } + return { + layerNumber: layerNumber, + codeblocks: precinctCodeblocks + }; + } + function LayerResolutionComponentPositionIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var maxDecompositionLevelsCount = 0; + for (var q = 0; q < componentsCount; q++) { + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, + tile.components[q].codingStyleParameters.decompositionLevelsCount); + } + + var l = 0, r = 0, i = 0, k = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.1 Layer-resolution-component-position + for (; l < layersCount; l++) { + for (; r <= maxDecompositionLevelsCount; r++) { + for (; i < componentsCount; i++) { + var component = tile.components[i]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + for (; k < numprecincts;) { + var packet = createPacket(resolution, k, l); + k++; + return packet; + } + k = 0; + } + i = 0; + } + r = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function ResolutionLayerComponentPositionIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var maxDecompositionLevelsCount = 0; + for (var q = 0; q < componentsCount; q++) { + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, + tile.components[q].codingStyleParameters.decompositionLevelsCount); + } + + var r = 0, l = 0, i = 0, k = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.2 Resolution-layer-component-position + for (; r <= maxDecompositionLevelsCount; r++) { + for (; l < layersCount; l++) { + for (; i < componentsCount; i++) { + var component = tile.components[i]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + for (; k < numprecincts;) { + var packet = createPacket(resolution, k, l); + k++; + return packet; + } + k = 0; + } + i = 0; + } + l = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function ResolutionPositionComponentLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var l, r, c, p; + var maxDecompositionLevelsCount = 0; + for (c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, + component.codingStyleParameters.decompositionLevelsCount); + } + var maxNumPrecinctsInLevel = new Int32Array( + maxDecompositionLevelsCount + 1); + for (r = 0; r <= maxDecompositionLevelsCount; ++r) { + var maxNumPrecincts = 0; + for (c = 0; c < componentsCount; ++c) { + var resolutions = tile.components[c].resolutions; + if (r < resolutions.length) { + maxNumPrecincts = Math.max(maxNumPrecincts, + resolutions[r].precinctParameters.numprecincts); + } + } + maxNumPrecinctsInLevel[r] = maxNumPrecincts; + } + l = 0; + r = 0; + c = 0; + p = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.3 Resolution-position-component-layer + for (; r <= maxDecompositionLevelsCount; r++) { + for (; p < maxNumPrecinctsInLevel[r]; p++) { + for (; c < componentsCount; c++) { + var component = tile.components[c]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + if (p >= numprecincts) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, p, l); + l++; + return packet; + } + l = 0; + } + c = 0; + } + p = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function PositionComponentResolutionLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var precinctsSizes = getPrecinctSizesInImageScale(tile); + var precinctsIterationSizes = precinctsSizes; + var l = 0, r = 0, c = 0, px = 0, py = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.4 Position-component-resolution-layer + for (; py < precinctsIterationSizes.maxNumHigh; py++) { + for (; px < precinctsIterationSizes.maxNumWide; px++) { + for (; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + for (; r <= decompositionLevelsCount; r++) { + var resolution = component.resolutions[r]; + var sizeInImageScale = + precinctsSizes.components[c].resolutions[r]; + var k = getPrecinctIndexIfExist( + px, + py, + sizeInImageScale, + precinctsIterationSizes, + resolution); + if (k === null) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, k, l); + l++; + return packet; + } + l = 0; + } + r = 0; + } + c = 0; + } + px = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function ComponentPositionResolutionLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var precinctsSizes = getPrecinctSizesInImageScale(tile); + var l = 0, r = 0, c = 0, px = 0, py = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.5 Component-position-resolution-layer + for (; c < componentsCount; ++c) { + var component = tile.components[c]; + var precinctsIterationSizes = precinctsSizes.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + for (; py < precinctsIterationSizes.maxNumHigh; py++) { + for (; px < precinctsIterationSizes.maxNumWide; px++) { + for (; r <= decompositionLevelsCount; r++) { + var resolution = component.resolutions[r]; + var sizeInImageScale = precinctsIterationSizes.resolutions[r]; + var k = getPrecinctIndexIfExist( + px, + py, + sizeInImageScale, + precinctsIterationSizes, + resolution); + if (k === null) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, k, l); + l++; + return packet; + } + l = 0; + } + r = 0; + } + px = 0; + } + py = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function getPrecinctIndexIfExist( + pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) { + var posX = pxIndex * precinctIterationSizes.minWidth; + var posY = pyIndex * precinctIterationSizes.minHeight; + if (posX % sizeInImageScale.width !== 0 || + posY % sizeInImageScale.height !== 0) { + return null; + } + var startPrecinctRowIndex = + (posY / sizeInImageScale.width) * + resolution.precinctParameters.numprecinctswide; + return (posX / sizeInImageScale.height) + startPrecinctRowIndex; + } + function getPrecinctSizesInImageScale(tile) { + var componentsCount = tile.components.length; + var minWidth = Number.MAX_VALUE; + var minHeight = Number.MAX_VALUE; + var maxNumWide = 0; + var maxNumHigh = 0; + var sizePerComponent = new Array(componentsCount); + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + var sizePerResolution = new Array(decompositionLevelsCount + 1); + var minWidthCurrentComponent = Number.MAX_VALUE; + var minHeightCurrentComponent = Number.MAX_VALUE; + var maxNumWideCurrentComponent = 0; + var maxNumHighCurrentComponent = 0; + var scale = 1; + for (var r = decompositionLevelsCount; r >= 0; --r) { + var resolution = component.resolutions[r]; + var widthCurrentResolution = + scale * resolution.precinctParameters.precinctWidth; + var heightCurrentResolution = + scale * resolution.precinctParameters.precinctHeight; + minWidthCurrentComponent = Math.min( + minWidthCurrentComponent, + widthCurrentResolution); + minHeightCurrentComponent = Math.min( + minHeightCurrentComponent, + heightCurrentResolution); + maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, + resolution.precinctParameters.numprecinctswide); + maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, + resolution.precinctParameters.numprecinctshigh); + sizePerResolution[r] = { + width: widthCurrentResolution, + height: heightCurrentResolution + }; + scale <<= 1; + } + minWidth = Math.min(minWidth, minWidthCurrentComponent); + minHeight = Math.min(minHeight, minHeightCurrentComponent); + maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent); + maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent); + sizePerComponent[c] = { + resolutions: sizePerResolution, + minWidth: minWidthCurrentComponent, + minHeight: minHeightCurrentComponent, + maxNumWide: maxNumWideCurrentComponent, + maxNumHigh: maxNumHighCurrentComponent + }; + } + return { + components: sizePerComponent, + minWidth: minWidth, + minHeight: minHeight, + maxNumWide: maxNumWide, + maxNumHigh: maxNumHigh + }; + } + function buildPackets(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var componentsCount = siz.Csiz; + // Creating resolutions and sub-bands for each component + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + // Section B.5 Resolution levels and sub-bands + var resolutions = []; + var subbands = []; + for (var r = 0; r <= decompositionLevelsCount; r++) { + var blocksDimensions = getBlocksDimensions(context, component, r); + var resolution = {}; + var scale = 1 << (decompositionLevelsCount - r); + resolution.trx0 = Math.ceil(component.tcx0 / scale); + resolution.try0 = Math.ceil(component.tcy0 / scale); + resolution.trx1 = Math.ceil(component.tcx1 / scale); + resolution.try1 = Math.ceil(component.tcy1 / scale); + resolution.resLevel = r; + buildPrecincts(context, resolution, blocksDimensions); + resolutions.push(resolution); + + var subband; + if (r === 0) { + // one sub-band (LL) with last decomposition + subband = {}; + subband.type = 'LL'; + subband.tbx0 = Math.ceil(component.tcx0 / scale); + subband.tby0 = Math.ceil(component.tcy0 / scale); + subband.tbx1 = Math.ceil(component.tcx1 / scale); + subband.tby1 = Math.ceil(component.tcy1 / scale); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolution.subbands = [subband]; + } else { + var bscale = 1 << (decompositionLevelsCount - r + 1); + var resolutionSubbands = []; + // three sub-bands (HL, LH and HH) with rest of decompositions + subband = {}; + subband.type = 'HL'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); + subband.tby0 = Math.ceil(component.tcy0 / bscale); + subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); + subband.tby1 = Math.ceil(component.tcy1 / bscale); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + subband = {}; + subband.type = 'LH'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale); + subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); + subband.tbx1 = Math.ceil(component.tcx1 / bscale); + subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + subband = {}; + subband.type = 'HH'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); + subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); + subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); + subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + resolution.subbands = resolutionSubbands; + } + } + component.resolutions = resolutions; + component.subbands = subbands; + } + // Generate the packets sequence + var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder; + switch (progressionOrder) { + case 0: + tile.packetsIterator = + new LayerResolutionComponentPositionIterator(context); + break; + case 1: + tile.packetsIterator = + new ResolutionLayerComponentPositionIterator(context); + break; + case 2: + tile.packetsIterator = + new ResolutionPositionComponentLayerIterator(context); + break; + case 3: + tile.packetsIterator = + new PositionComponentResolutionLayerIterator(context); + break; + case 4: + tile.packetsIterator = + new ComponentPositionResolutionLayerIterator(context); + break; + default: + throw new Error('JPX Error: Unsupported progression order ' + + progressionOrder); + } + } + function parseTilePackets(context, data, offset, dataLength) { + var position = 0; + var buffer, bufferSize = 0, skipNextBit = false; + function readBits(count) { + while (bufferSize < count) { + var b = data[offset + position]; + position++; + if (skipNextBit) { + buffer = (buffer << 7) | b; + bufferSize += 7; + skipNextBit = false; + } else { + buffer = (buffer << 8) | b; + bufferSize += 8; + } + if (b === 0xFF) { + skipNextBit = true; + } + } + bufferSize -= count; + return (buffer >>> bufferSize) & ((1 << count) - 1); + } + function skipMarkerIfEqual(value) { + if (data[offset + position - 1] === 0xFF && + data[offset + position] === value) { + skipBytes(1); + return true; + } else if (data[offset + position] === 0xFF && + data[offset + position + 1] === value) { + skipBytes(2); + return true; + } + return false; + } + function skipBytes(count) { + position += count; + } + function alignToByte() { + bufferSize = 0; + if (skipNextBit) { + position++; + skipNextBit = false; + } + } + function readCodingpasses() { + if (readBits(1) === 0) { + return 1; + } + if (readBits(1) === 0) { + return 2; + } + var value = readBits(2); + if (value < 3) { + return value + 3; + } + value = readBits(5); + if (value < 31) { + return value + 6; + } + value = readBits(7); + return value + 37; + } + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var sopMarkerUsed = context.COD.sopMarkerUsed; + var ephMarkerUsed = context.COD.ephMarkerUsed; + var packetsIterator = tile.packetsIterator; + while (position < dataLength) { + alignToByte(); + if (sopMarkerUsed && skipMarkerIfEqual(0x91)) { + // Skip also marker segment length and packet sequence ID + skipBytes(4); + } + var packet = packetsIterator.nextPacket(); + if (!readBits(1)) { + continue; + } + var layerNumber = packet.layerNumber; + var queue = [], codeblock; + for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) { + codeblock = packet.codeblocks[i]; + var precinct = codeblock.precinct; + var codeblockColumn = codeblock.cbx - precinct.cbxMin; + var codeblockRow = codeblock.cby - precinct.cbyMin; + var codeblockIncluded = false; + var firstTimeInclusion = false; + var valueReady; + if (codeblock['included'] !== undefined) { + codeblockIncluded = !!readBits(1); + } else { + // reading inclusion tree + precinct = codeblock.precinct; + var inclusionTree, zeroBitPlanesTree; + if (precinct['inclusionTree'] !== undefined) { + inclusionTree = precinct.inclusionTree; + } else { + // building inclusion and zero bit-planes trees + var width = precinct.cbxMax - precinct.cbxMin + 1; + var height = precinct.cbyMax - precinct.cbyMin + 1; + inclusionTree = new InclusionTree(width, height, layerNumber); + zeroBitPlanesTree = new TagTree(width, height); + precinct.inclusionTree = inclusionTree; + precinct.zeroBitPlanesTree = zeroBitPlanesTree; + } + + if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) { + while (true) { + if (readBits(1)) { + valueReady = !inclusionTree.nextLevel(); + if (valueReady) { + codeblock.included = true; + codeblockIncluded = firstTimeInclusion = true; + break; + } + } else { + inclusionTree.incrementValue(layerNumber); + break; + } + } + } + } + if (!codeblockIncluded) { + continue; + } + if (firstTimeInclusion) { + zeroBitPlanesTree = precinct.zeroBitPlanesTree; + zeroBitPlanesTree.reset(codeblockColumn, codeblockRow); + while (true) { + if (readBits(1)) { + valueReady = !zeroBitPlanesTree.nextLevel(); + if (valueReady) { + break; + } + } else { + zeroBitPlanesTree.incrementValue(); + } + } + codeblock.zeroBitPlanes = zeroBitPlanesTree.value; + } + var codingpasses = readCodingpasses(); + while (readBits(1)) { + codeblock.Lblock++; + } + var codingpassesLog2 = log2(codingpasses); + // rounding down log2 + var bits = ((codingpasses < (1 << codingpassesLog2)) ? + codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock; + var codedDataLength = readBits(bits); + queue.push({ + codeblock: codeblock, + codingpasses: codingpasses, + dataLength: codedDataLength + }); + } + alignToByte(); + if (ephMarkerUsed) { + skipMarkerIfEqual(0x92); + } + while (queue.length > 0) { + var packetItem = queue.shift(); + codeblock = packetItem.codeblock; + if (codeblock['data'] === undefined) { + codeblock.data = []; + } + codeblock.data.push({ + data: data, + start: offset + position, + end: offset + position + packetItem.dataLength, + codingpasses: packetItem.codingpasses + }); + position += packetItem.dataLength; + } + } + return position; + } + function copyCoefficients(coefficients, levelWidth, levelHeight, subband, + delta, mb, reversible, segmentationSymbolUsed) { + var x0 = subband.tbx0; + var y0 = subband.tby0; + var width = subband.tbx1 - subband.tbx0; + var codeblocks = subband.codeblocks; + var right = subband.type.charAt(0) === 'H' ? 1 : 0; + var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0; + + for (var i = 0, ii = codeblocks.length; i < ii; ++i) { + var codeblock = codeblocks[i]; + var blockWidth = codeblock.tbx1_ - codeblock.tbx0_; + var blockHeight = codeblock.tby1_ - codeblock.tby0_; + if (blockWidth === 0 || blockHeight === 0) { + continue; + } + if (codeblock['data'] === undefined) { + continue; + } + + var bitModel, currentCodingpassType; + bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, + codeblock.zeroBitPlanes, mb); + currentCodingpassType = 2; // first bit plane starts from cleanup + + // collect data + var data = codeblock.data, totalLength = 0, codingpasses = 0; + var j, jj, dataItem; + for (j = 0, jj = data.length; j < jj; j++) { + dataItem = data[j]; + totalLength += dataItem.end - dataItem.start; + codingpasses += dataItem.codingpasses; + } + var encodedData = new Uint8Array(totalLength); + var position = 0; + for (j = 0, jj = data.length; j < jj; j++) { + dataItem = data[j]; + var chunk = dataItem.data.subarray(dataItem.start, dataItem.end); + encodedData.set(chunk, position); + position += chunk.length; + } + // decoding the item + var decoder = new ArithmeticDecoder(encodedData, 0, totalLength); + bitModel.setDecoder(decoder); + + for (j = 0; j < codingpasses; j++) { + switch (currentCodingpassType) { + case 0: + bitModel.runSignificancePropogationPass(); + break; + case 1: + bitModel.runMagnitudeRefinementPass(); + break; + case 2: + bitModel.runCleanupPass(); + if (segmentationSymbolUsed) { + bitModel.checkSegmentationSymbol(); + } + break; + } + currentCodingpassType = (currentCodingpassType + 1) % 3; + } + + var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width; + var sign = bitModel.coefficentsSign; + var magnitude = bitModel.coefficentsMagnitude; + var bitsDecoded = bitModel.bitsDecoded; + var magnitudeCorrection = reversible ? 0 : 0.5; + var k, n, nb; + position = 0; + // Do the interleaving of Section F.3.3 here, so we do not need + // to copy later. LL level is not interleaved, just copied. + var interleave = (subband.type !== 'LL'); + for (j = 0; j < blockHeight; j++) { + var row = (offset / width) | 0; // row in the non-interleaved subband + var levelOffset = 2 * row * (levelWidth - width) + right + bottom; + for (k = 0; k < blockWidth; k++) { + n = magnitude[position]; + if (n !== 0) { + n = (n + magnitudeCorrection) * delta; + if (sign[position] !== 0) { + n = -n; + } + nb = bitsDecoded[position]; + var pos = interleave ? (levelOffset + (offset << 1)) : offset; + if (reversible && (nb >= mb)) { + coefficients[pos] = n; + } else { + coefficients[pos] = n * (1 << (mb - nb)); + } + } + offset++; + position++; + } + offset += width - blockWidth; + } + } + } + function transformTile(context, tile, c) { + var component = tile.components[c]; + var codingStyleParameters = component.codingStyleParameters; + var quantizationParameters = component.quantizationParameters; + var decompositionLevelsCount = + codingStyleParameters.decompositionLevelsCount; + var spqcds = quantizationParameters.SPqcds; + var scalarExpounded = quantizationParameters.scalarExpounded; + var guardBits = quantizationParameters.guardBits; + var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed; + var precision = context.components[c].precision; + + var reversible = codingStyleParameters.reversibleTransformation; + var transform = (reversible ? new ReversibleTransform() : + new IrreversibleTransform()); + + var subbandCoefficients = []; + var b = 0; + for (var i = 0; i <= decompositionLevelsCount; i++) { + var resolution = component.resolutions[i]; + + var width = resolution.trx1 - resolution.trx0; + var height = resolution.try1 - resolution.try0; + // Allocate space for the whole sublevel. + var coefficients = new Float32Array(width * height); + + for (var j = 0, jj = resolution.subbands.length; j < jj; j++) { + var mu, epsilon; + if (!scalarExpounded) { + // formula E-5 + mu = spqcds[0].mu; + epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0); + } else { + mu = spqcds[b].mu; + epsilon = spqcds[b].epsilon; + b++; + } + + var subband = resolution.subbands[j]; + var gainLog2 = SubbandsGainLog2[subband.type]; + + // calulate quantization coefficient (Section E.1.1.1) + var delta = (reversible ? 1 : + Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048)); + var mb = (guardBits + epsilon - 1); + + // In the first resolution level, copyCoefficients will fill the + // whole array with coefficients. In the succeding passes, + // copyCoefficients will consecutively fill in the values that belong + // to the interleaved positions of the HL, LH, and HH coefficients. + // The LL coefficients will then be interleaved in Transform.iterate(). + copyCoefficients(coefficients, width, height, subband, delta, mb, + reversible, segmentationSymbolUsed); + } + subbandCoefficients.push({ + width: width, + height: height, + items: coefficients + }); + } + + var result = transform.calculate(subbandCoefficients, + component.tcx0, component.tcy0); + return { + left: component.tcx0, + top: component.tcy0, + width: result.width, + height: result.height, + items: result.items + }; + } + function transformComponents(context) { + var siz = context.SIZ; + var components = context.components; + var componentsCount = siz.Csiz; + var resultImages = []; + for (var i = 0, ii = context.tiles.length; i < ii; i++) { + var tile = context.tiles[i]; + var transformedTiles = []; + var c; + for (c = 0; c < componentsCount; c++) { + transformedTiles[c] = transformTile(context, tile, c); + } + var tile0 = transformedTiles[0]; + var out = new Uint8Array(tile0.items.length * componentsCount); + var result = { + left: tile0.left, + top: tile0.top, + width: tile0.width, + height: tile0.height, + items: out + }; + + // Section G.2.2 Inverse multi component transform + var shift, offset, max, min, maxK; + var pos = 0, j, jj, y0, y1, y2, r, g, b, k, val; + if (tile.codingStyleDefaultParameters.multipleComponentTransform) { + var fourComponents = componentsCount === 4; + var y0items = transformedTiles[0].items; + var y1items = transformedTiles[1].items; + var y2items = transformedTiles[2].items; + var y3items = fourComponents ? transformedTiles[3].items : null; + + // HACK: The multiple component transform formulas below assume that + // all components have the same precision. With this in mind, we + // compute shift and offset only once. + shift = components[0].precision - 8; + offset = (128 << shift) + 0.5; + max = 255 * (1 << shift); + maxK = max * 0.5; + min = -maxK; + + var component0 = tile.components[0]; + var alpha01 = componentsCount - 3; + jj = y0items.length; + if (!component0.codingStyleParameters.reversibleTransformation) { + // inverse irreversible multiple component transform + for (j = 0; j < jj; j++, pos += alpha01) { + y0 = y0items[j] + offset; + y1 = y1items[j]; + y2 = y2items[j]; + r = y0 + 1.402 * y2; + g = y0 - 0.34413 * y1 - 0.71414 * y2; + b = y0 + 1.772 * y1; + out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift; + out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift; + out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift; + } + } else { + // inverse reversible multiple component transform + for (j = 0; j < jj; j++, pos += alpha01) { + y0 = y0items[j] + offset; + y1 = y1items[j]; + y2 = y2items[j]; + g = y0 - ((y2 + y1) >> 2); + r = g + y2; + b = g + y1; + out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift; + out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift; + out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift; + } + } + if (fourComponents) { + for (j = 0, pos = 3; j < jj; j++, pos += 4) { + k = y3items[j]; + out[pos] = k <= min ? 0 : k >= maxK ? 255 : (k + offset) >> shift; + } + } + } else { // no multi-component transform + for (c = 0; c < componentsCount; c++) { + var items = transformedTiles[c].items; + shift = components[c].precision - 8; + offset = (128 << shift) + 0.5; + max = (127.5 * (1 << shift)); + min = -max; + for (pos = c, j = 0, jj = items.length; j < jj; j++) { + val = items[j]; + out[pos] = val <= min ? 0 : + val >= max ? 255 : (val + offset) >> shift; + pos += componentsCount; + } + } + } + resultImages.push(result); + } + return resultImages; + } + function initializeTile(context, tileIndex) { + var siz = context.SIZ; + var componentsCount = siz.Csiz; + var tile = context.tiles[tileIndex]; + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var qcdOrQcc = (context.currentTile.QCC[c] !== undefined ? + context.currentTile.QCC[c] : context.currentTile.QCD); + component.quantizationParameters = qcdOrQcc; + var codOrCoc = (context.currentTile.COC[c] !== undefined ? + context.currentTile.COC[c] : context.currentTile.COD); + component.codingStyleParameters = codOrCoc; + } + tile.codingStyleDefaultParameters = context.currentTile.COD; + } + + // Section B.10.2 Tag trees + var TagTree = (function TagTreeClosure() { + function TagTree(width, height) { + var levelsLength = log2(Math.max(width, height)) + 1; + this.levels = []; + for (var i = 0; i < levelsLength; i++) { + var level = { + width: width, + height: height, + items: [] + }; + this.levels.push(level); + width = Math.ceil(width / 2); + height = Math.ceil(height / 2); + } + } + TagTree.prototype = { + reset: function TagTree_reset(i, j) { + var currentLevel = 0, value = 0, level; + while (currentLevel < this.levels.length) { + level = this.levels[currentLevel]; + var index = i + j * level.width; + if (level.items[index] !== undefined) { + value = level.items[index]; + break; + } + level.index = index; + i >>= 1; + j >>= 1; + currentLevel++; + } + currentLevel--; + level = this.levels[currentLevel]; + level.items[level.index] = value; + this.currentLevel = currentLevel; + delete this.value; + }, + incrementValue: function TagTree_incrementValue() { + var level = this.levels[this.currentLevel]; + level.items[level.index]++; + }, + nextLevel: function TagTree_nextLevel() { + var currentLevel = this.currentLevel; + var level = this.levels[currentLevel]; + var value = level.items[level.index]; + currentLevel--; + if (currentLevel < 0) { + this.value = value; + return false; + } + + this.currentLevel = currentLevel; + level = this.levels[currentLevel]; + level.items[level.index] = value; + return true; + } + }; + return TagTree; + })(); + + var InclusionTree = (function InclusionTreeClosure() { + function InclusionTree(width, height, defaultValue) { + var levelsLength = log2(Math.max(width, height)) + 1; + this.levels = []; + for (var i = 0; i < levelsLength; i++) { + var items = new Uint8Array(width * height); + for (var j = 0, jj = items.length; j < jj; j++) { + items[j] = defaultValue; + } + + var level = { + width: width, + height: height, + items: items + }; + this.levels.push(level); + + width = Math.ceil(width / 2); + height = Math.ceil(height / 2); + } + } + InclusionTree.prototype = { + reset: function InclusionTree_reset(i, j, stopValue) { + var currentLevel = 0; + while (currentLevel < this.levels.length) { + var level = this.levels[currentLevel]; + var index = i + j * level.width; + level.index = index; + var value = level.items[index]; + + if (value === 0xFF) { + break; + } + + if (value > stopValue) { + this.currentLevel = currentLevel; + // already know about this one, propagating the value to top levels + this.propagateValues(); + return false; + } + + i >>= 1; + j >>= 1; + currentLevel++; + } + this.currentLevel = currentLevel - 1; + return true; + }, + incrementValue: function InclusionTree_incrementValue(stopValue) { + var level = this.levels[this.currentLevel]; + level.items[level.index] = stopValue + 1; + this.propagateValues(); + }, + propagateValues: function InclusionTree_propagateValues() { + var levelIndex = this.currentLevel; + var level = this.levels[levelIndex]; + var currentValue = level.items[level.index]; + while (--levelIndex >= 0) { + level = this.levels[levelIndex]; + level.items[level.index] = currentValue; + } + }, + nextLevel: function InclusionTree_nextLevel() { + var currentLevel = this.currentLevel; + var level = this.levels[currentLevel]; + var value = level.items[level.index]; + level.items[level.index] = 0xFF; + currentLevel--; + if (currentLevel < 0) { + return false; + } + + this.currentLevel = currentLevel; + level = this.levels[currentLevel]; + level.items[level.index] = value; + return true; + } + }; + return InclusionTree; + })(); + + // Section D. Coefficient bit modeling + var BitModel = (function BitModelClosure() { + var UNIFORM_CONTEXT = 17; + var RUNLENGTH_CONTEXT = 18; + // Table D-1 + // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4), + // vv - sum of Vi (0..2), and hh - sum of Hi (0..2) + var LLAndLHContextsLabel = new Uint8Array([ + 0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4, + 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, + 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8 + ]); + var HLContextLabel = new Uint8Array([ + 0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8, + 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, + 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8 + ]); + var HHContextLabel = new Uint8Array([ + 0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5, + 5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8, + 8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8 + ]); + + function BitModel(width, height, subband, zeroBitPlanes, mb) { + this.width = width; + this.height = height; + + this.contextLabelTable = (subband === 'HH' ? HHContextLabel : + (subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel)); + + var coefficientCount = width * height; + + // coefficients outside the encoding region treated as insignificant + // add border state cells for significanceState + this.neighborsSignificance = new Uint8Array(coefficientCount); + this.coefficentsSign = new Uint8Array(coefficientCount); + this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) : + mb > 6 ? new Uint16Array(coefficientCount) : + new Uint8Array(coefficientCount); + this.processingFlags = new Uint8Array(coefficientCount); + + var bitsDecoded = new Uint8Array(coefficientCount); + if (zeroBitPlanes !== 0) { + for (var i = 0; i < coefficientCount; i++) { + bitsDecoded[i] = zeroBitPlanes; + } + } + this.bitsDecoded = bitsDecoded; + + this.reset(); + } + + BitModel.prototype = { + setDecoder: function BitModel_setDecoder(decoder) { + this.decoder = decoder; + }, + reset: function BitModel_reset() { + // We have 17 contexts that are accessed via context labels, + // plus the uniform and runlength context. + this.contexts = new Int8Array(19); + + // Contexts are packed into 1 byte: + // highest 7 bits carry the index, lowest bit carries mps + this.contexts[0] = (4 << 1) | 0; + this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0; + this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0; + }, + setNeighborsSignificance: + function BitModel_setNeighborsSignificance(row, column, index) { + var neighborsSignificance = this.neighborsSignificance; + var width = this.width, height = this.height; + var left = (column > 0); + var right = (column + 1 < width); + var i; + + if (row > 0) { + i = index - width; + if (left) { + neighborsSignificance[i - 1] += 0x10; + } + if (right) { + neighborsSignificance[i + 1] += 0x10; + } + neighborsSignificance[i] += 0x04; + } + + if (row + 1 < height) { + i = index + width; + if (left) { + neighborsSignificance[i - 1] += 0x10; + } + if (right) { + neighborsSignificance[i + 1] += 0x10; + } + neighborsSignificance[i] += 0x04; + } + + if (left) { + neighborsSignificance[index - 1] += 0x01; + } + if (right) { + neighborsSignificance[index + 1] += 0x01; + } + neighborsSignificance[index] |= 0x80; + }, + runSignificancePropogationPass: + function BitModel_runSignificancePropogationPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var neighborsSignificance = this.neighborsSignificance; + var processingFlags = this.processingFlags; + var contexts = this.contexts; + var labels = this.contextLabelTable; + var bitsDecoded = this.bitsDecoded; + var processedInverseMask = ~1; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + + for (var i0 = 0; i0 < height; i0 += 4) { + for (var j = 0; j < width; j++) { + var index = i0 * width + j; + for (var i1 = 0; i1 < 4; i1++, index += width) { + var i = i0 + i1; + if (i >= height) { + break; + } + // clear processed flag first + processingFlags[index] &= processedInverseMask; + + if (coefficentsMagnitude[index] || + !neighborsSignificance[index]) { + continue; + } + + var contextLabel = labels[neighborsSignificance[index]]; + var decision = decoder.readBit(contexts, contextLabel); + if (decision) { + var sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + } + bitsDecoded[index]++; + processingFlags[index] |= processedMask; + } + } + } + }, + decodeSignBit: function BitModel_decodeSignBit(row, column, index) { + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var contribution, sign0, sign1, significance1; + var contextLabel, decoded; + + // calculate horizontal contribution + significance1 = (column > 0 && coefficentsMagnitude[index - 1] !== 0); + if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) { + sign1 = coefficentsSign[index + 1]; + if (significance1) { + sign0 = coefficentsSign[index - 1]; + contribution = 1 - sign1 - sign0; + } else { + contribution = 1 - sign1 - sign1; + } + } else if (significance1) { + sign0 = coefficentsSign[index - 1]; + contribution = 1 - sign0 - sign0; + } else { + contribution = 0; + } + var horizontalContribution = 3 * contribution; + + // calculate vertical contribution and combine with the horizontal + significance1 = (row > 0 && coefficentsMagnitude[index - width] !== 0); + if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) { + sign1 = coefficentsSign[index + width]; + if (significance1) { + sign0 = coefficentsSign[index - width]; + contribution = 1 - sign1 - sign0 + horizontalContribution; + } else { + contribution = 1 - sign1 - sign1 + horizontalContribution; + } + } else if (significance1) { + sign0 = coefficentsSign[index - width]; + contribution = 1 - sign0 - sign0 + horizontalContribution; + } else { + contribution = horizontalContribution; + } + + if (contribution >= 0) { + contextLabel = 9 + contribution; + decoded = this.decoder.readBit(this.contexts, contextLabel); + } else { + contextLabel = 9 - contribution; + decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1; + } + return decoded; + }, + runMagnitudeRefinementPass: + function BitModel_runMagnitudeRefinementPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var neighborsSignificance = this.neighborsSignificance; + var contexts = this.contexts; + var bitsDecoded = this.bitsDecoded; + var processingFlags = this.processingFlags; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + var length = width * height; + var width4 = width * 4; + + for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) { + indexNext = Math.min(length, index0 + width4); + for (var j = 0; j < width; j++) { + for (var index = index0 + j; index < indexNext; index += width) { + + // significant but not those that have just become + if (!coefficentsMagnitude[index] || + (processingFlags[index] & processedMask) !== 0) { + continue; + } + + var contextLabel = 16; + if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) { + processingFlags[index] ^= firstMagnitudeBitMask; + // first refinement + var significance = neighborsSignificance[index] & 127; + contextLabel = significance === 0 ? 15 : 14; + } + + var bit = decoder.readBit(contexts, contextLabel); + coefficentsMagnitude[index] = + (coefficentsMagnitude[index] << 1) | bit; + bitsDecoded[index]++; + processingFlags[index] |= processedMask; + } + } + } + }, + runCleanupPass: function BitModel_runCleanupPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var neighborsSignificance = this.neighborsSignificance; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var contexts = this.contexts; + var labels = this.contextLabelTable; + var bitsDecoded = this.bitsDecoded; + var processingFlags = this.processingFlags; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + var oneRowDown = width; + var twoRowsDown = width * 2; + var threeRowsDown = width * 3; + var iNext; + for (var i0 = 0; i0 < height; i0 = iNext) { + iNext = Math.min(i0 + 4, height); + var indexBase = i0 * width; + var checkAllEmpty = i0 + 3 < height; + for (var j = 0; j < width; j++) { + var index0 = indexBase + j; + // using the property: labels[neighborsSignificance[index]] === 0 + // when neighborsSignificance[index] === 0 + var allEmpty = (checkAllEmpty && + processingFlags[index0] === 0 && + processingFlags[index0 + oneRowDown] === 0 && + processingFlags[index0 + twoRowsDown] === 0 && + processingFlags[index0 + threeRowsDown] === 0 && + neighborsSignificance[index0] === 0 && + neighborsSignificance[index0 + oneRowDown] === 0 && + neighborsSignificance[index0 + twoRowsDown] === 0 && + neighborsSignificance[index0 + threeRowsDown] === 0); + var i1 = 0, index = index0; + var i = i0, sign; + if (allEmpty) { + var hasSignificantCoefficent = + decoder.readBit(contexts, RUNLENGTH_CONTEXT); + if (!hasSignificantCoefficent) { + bitsDecoded[index0]++; + bitsDecoded[index0 + oneRowDown]++; + bitsDecoded[index0 + twoRowsDown]++; + bitsDecoded[index0 + threeRowsDown]++; + continue; // next column + } + i1 = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) | + decoder.readBit(contexts, UNIFORM_CONTEXT); + if (i1 !== 0) { + i = i0 + i1; + index += i1 * width; + } + + sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + + index = index0; + for (var i2 = i0; i2 <= i; i2++, index += width) { + bitsDecoded[index]++; + } + + i1++; + } + for (i = i0 + i1; i < iNext; i++, index += width) { + if (coefficentsMagnitude[index] || + (processingFlags[index] & processedMask) !== 0) { + continue; + } + + var contextLabel = labels[neighborsSignificance[index]]; + var decision = decoder.readBit(contexts, contextLabel); + if (decision === 1) { + sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + } + bitsDecoded[index]++; + } + } + } + }, + checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() { + var decoder = this.decoder; + var contexts = this.contexts; + var symbol = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 3) | + (decoder.readBit(contexts, UNIFORM_CONTEXT) << 2) | + (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) | + decoder.readBit(contexts, UNIFORM_CONTEXT); + if (symbol !== 0xA) { + throw new Error('JPX Error: Invalid segmentation symbol'); + } + } + }; + + return BitModel; + })(); + + // Section F, Discrete wavelet transformation + var Transform = (function TransformClosure() { + function Transform() {} + + Transform.prototype.calculate = + function transformCalculate(subbands, u0, v0) { + var ll = subbands[0]; + for (var i = 1, ii = subbands.length; i < ii; i++) { + ll = this.iterate(ll, subbands[i], u0, v0); + } + return ll; + }; + Transform.prototype.extend = function extend(buffer, offset, size) { + // Section F.3.7 extending... using max extension of 4 + var i1 = offset - 1, j1 = offset + 1; + var i2 = offset + size - 2, j2 = offset + size; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1] = buffer[j1]; + buffer[j2] = buffer[i2]; + }; + Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh, + u0, v0) { + var llWidth = ll.width, llHeight = ll.height, llItems = ll.items; + var width = hl_lh_hh.width; + var height = hl_lh_hh.height; + var items = hl_lh_hh.items; + var i, j, k, l, u, v; + + // Interleave LL according to Section F.3.3 + for (k = 0, i = 0; i < llHeight; i++) { + l = i * 2 * width; + for (j = 0; j < llWidth; j++, k++, l += 2) { + items[l] = llItems[k]; + } + } + // The LL band is not needed anymore. + llItems = ll.items = null; + + var bufferPadding = 4; + var rowBuffer = new Float32Array(width + 2 * bufferPadding); + + // Section F.3.4 HOR_SR + if (width === 1) { + // if width = 1, when u0 even keep items as is, when odd divide by 2 + if ((u0 & 1) !== 0) { + for (v = 0, k = 0; v < height; v++, k += width) { + items[k] *= 0.5; + } + } + } else { + for (v = 0, k = 0; v < height; v++, k += width) { + rowBuffer.set(items.subarray(k, k + width), bufferPadding); + + this.extend(rowBuffer, bufferPadding, width); + this.filter(rowBuffer, bufferPadding, width); + + items.set( + rowBuffer.subarray(bufferPadding, bufferPadding + width), + k); + } + } + + // Accesses to the items array can take long, because it may not fit into + // CPU cache and has to be fetched from main memory. Since subsequent + // accesses to the items array are not local when reading columns, we + // have a cache miss every time. To reduce cache misses, get up to + // 'numBuffers' items at a time and store them into the individual + // buffers. The colBuffers should be small enough to fit into CPU cache. + var numBuffers = 16; + var colBuffers = []; + for (i = 0; i < numBuffers; i++) { + colBuffers.push(new Float32Array(height + 2 * bufferPadding)); + } + var b, currentBuffer = 0; + ll = bufferPadding + height; + + // Section F.3.5 VER_SR + if (height === 1) { + // if height = 1, when v0 even keep items as is, when odd divide by 2 + if ((v0 & 1) !== 0) { + for (u = 0; u < width; u++) { + items[u] *= 0.5; + } + } + } else { + for (u = 0; u < width; u++) { + // if we ran out of buffers, copy several image columns at once + if (currentBuffer === 0) { + numBuffers = Math.min(width - u, numBuffers); + for (k = u, l = bufferPadding; l < ll; k += width, l++) { + for (b = 0; b < numBuffers; b++) { + colBuffers[b][l] = items[k + b]; + } + } + currentBuffer = numBuffers; + } + + currentBuffer--; + var buffer = colBuffers[currentBuffer]; + this.extend(buffer, bufferPadding, height); + this.filter(buffer, bufferPadding, height); + + // If this is last buffer in this group of buffers, flush all buffers. + if (currentBuffer === 0) { + k = u - numBuffers + 1; + for (l = bufferPadding; l < ll; k += width, l++) { + for (b = 0; b < numBuffers; b++) { + items[k + b] = colBuffers[b][l]; + } + } + } + } + } + + return { + width: width, + height: height, + items: items + }; + }; + return Transform; + })(); + + // Section 3.8.2 Irreversible 9-7 filter + var IrreversibleTransform = (function IrreversibleTransformClosure() { + function IrreversibleTransform() { + Transform.call(this); + } + + IrreversibleTransform.prototype = Object.create(Transform.prototype); + IrreversibleTransform.prototype.filter = + function irreversibleTransformFilter(x, offset, length) { + var len = length >> 1; + offset = offset | 0; + var j, n, current, next; + + var alpha = -1.586134342059924; + var beta = -0.052980118572961; + var gamma = 0.882911075530934; + var delta = 0.443506852043971; + var K = 1.230174104914001; + var K_ = 1 / K; + + // step 1 is combined with step 3 + + // step 2 + j = offset - 3; + for (n = len + 4; n--; j += 2) { + x[j] *= K_; + } + + // step 1 & 3 + j = offset - 2; + current = delta * x[j -1]; + for (n = len + 3; n--; j += 2) { + next = delta * x[j + 1]; + x[j] = K * x[j] - current - next; + if (n--) { + j += 2; + current = delta * x[j + 1]; + x[j] = K * x[j] - current - next; + } else { + break; + } + } + + // step 4 + j = offset - 1; + current = gamma * x[j - 1]; + for (n = len + 2; n--; j += 2) { + next = gamma * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = gamma * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + + // step 5 + j = offset; + current = beta * x[j - 1]; + for (n = len + 1; n--; j += 2) { + next = beta * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = beta * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + + // step 6 + if (len !== 0) { + j = offset + 1; + current = alpha * x[j - 1]; + for (n = len; n--; j += 2) { + next = alpha * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = alpha * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + } + }; + + return IrreversibleTransform; + })(); + + // Section 3.8.1 Reversible 5-3 filter + var ReversibleTransform = (function ReversibleTransformClosure() { + function ReversibleTransform() { + Transform.call(this); + } + + ReversibleTransform.prototype = Object.create(Transform.prototype); + ReversibleTransform.prototype.filter = + function reversibleTransformFilter(x, offset, length) { + var len = length >> 1; + offset = offset | 0; + var j, n; + + for (j = offset, n = len + 1; n--; j += 2) { + x[j] -= (x[j - 1] + x[j + 1] + 2) >> 2; + } + + for (j = offset + 1, n = len; n--; j += 2) { + x[j] += (x[j - 1] + x[j + 1]) >> 1; + } + }; + + return ReversibleTransform; + })(); + + return JpxImage; +})(); + + +var Jbig2Image = (function Jbig2ImageClosure() { + // Utility data structures + function ContextCache() {} + + ContextCache.prototype = { + getContexts: function(id) { + if (id in this) { + return this[id]; + } + return (this[id] = new Int8Array(1 << 16)); + } + }; + + function DecodingContext(data, start, end) { + this.data = data; + this.start = start; + this.end = end; + } + + DecodingContext.prototype = { + get decoder() { + var decoder = new ArithmeticDecoder(this.data, this.start, this.end); + return shadow(this, 'decoder', decoder); + }, + get contextCache() { + var cache = new ContextCache(); + return shadow(this, 'contextCache', cache); + } + }; + + // Annex A. Arithmetic Integer Decoding Procedure + // A.2 Procedure for decoding values + function decodeInteger(contextCache, procedure, decoder) { + var contexts = contextCache.getContexts(procedure); + var prev = 1; + + function readBits(length) { + var v = 0; + for (var i = 0; i < length; i++) { + var bit = decoder.readBit(contexts, prev); + prev = (prev < 256 ? (prev << 1) | bit : + (((prev << 1) | bit) & 511) | 256); + v = (v << 1) | bit; + } + return v >>> 0; + } + + var sign = readBits(1); + var value = readBits(1) ? + (readBits(1) ? + (readBits(1) ? + (readBits(1) ? + (readBits(1) ? + (readBits(32) + 4436) : + readBits(12) + 340) : + readBits(8) + 84) : + readBits(6) + 20) : + readBits(4) + 4) : + readBits(2); + return (sign === 0 ? value : (value > 0 ? -value : null)); + } + + // A.3 The IAID decoding procedure + function decodeIAID(contextCache, decoder, codeLength) { + var contexts = contextCache.getContexts('IAID'); + + var prev = 1; + for (var i = 0; i < codeLength; i++) { + var bit = decoder.readBit(contexts, prev); + prev = (prev << 1) | bit; + } + if (codeLength < 31) { + return prev & ((1 << codeLength) - 1); + } + return prev & 0x7FFFFFFF; + } + + // 7.3 Segment types + var SegmentTypes = [ + 'SymbolDictionary', null, null, null, 'IntermediateTextRegion', null, + 'ImmediateTextRegion', 'ImmediateLosslessTextRegion', null, null, null, + null, null, null, null, null, 'patternDictionary', null, null, null, + 'IntermediateHalftoneRegion', null, 'ImmediateHalftoneRegion', + 'ImmediateLosslessHalftoneRegion', null, null, null, null, null, null, null, + null, null, null, null, null, 'IntermediateGenericRegion', null, + 'ImmediateGenericRegion', 'ImmediateLosslessGenericRegion', + 'IntermediateGenericRefinementRegion', null, + 'ImmediateGenericRefinementRegion', + 'ImmediateLosslessGenericRefinementRegion', null, null, null, null, + 'PageInformation', 'EndOfPage', 'EndOfStripe', 'EndOfFile', 'Profiles', + 'Tables', null, null, null, null, null, null, null, null, + 'Extension' + ]; + + var CodingTemplates = [ + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1}, + {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: 2, y: -1}, + {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}], + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: 2, y: -2}, + {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, + {x: 2, y: -1}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}], + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1}, + {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -2, y: 0}, + {x: -1, y: 0}], + [{x: -3, y: -1}, {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, + {x: 1, y: -1}, {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}] + ]; + + var RefinementTemplates = [ + { + coding: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}], + reference: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, + {x: 1, y: 0}, {x: -1, y: 1}, {x: 0, y: 1}, {x: 1, y: 1}] + }, + { + coding: [{x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}], + reference: [{x: 0, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, {x: 1, y: 0}, + {x: 0, y: 1}, {x: 1, y: 1}] + } + ]; + + // See 6.2.5.7 Decoding the bitmap. + var ReusedContexts = [ + 0x9B25, // 10011 0110010 0101 + 0x0795, // 0011 110010 101 + 0x00E5, // 001 11001 01 + 0x0195 // 011001 0101 + ]; + + var RefinementReusedContexts = [ + 0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference) + 0x0008 // '0000' + '001000' + ]; + + function decodeBitmapTemplate0(width, height, decodingContext) { + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GB'); + var contextLabel, i, j, pixel, row, row1, row2, bitmap = []; + + // ...ooooo.... + // ..ooooooo... Context template for current pixel (X) + // .ooooX...... (concatenate values of 'o'-pixels to get contextLabel) + var OLD_PIXEL_MASK = 0x7BF7; // 01111 0111111 0111 + + for (i = 0; i < height; i++) { + row = bitmap[i] = new Uint8Array(width); + row1 = (i < 1) ? row : bitmap[i - 1]; + row2 = (i < 2) ? row : bitmap[i - 2]; + + // At the beginning of each row: + // Fill contextLabel with pixels that are above/right of (X) + contextLabel = (row2[0] << 13) | (row2[1] << 12) | (row2[2] << 11) | + (row1[0] << 7) | (row1[1] << 6) | (row1[2] << 5) | + (row1[3] << 4); + + for (j = 0; j < width; j++) { + row[j] = pixel = decoder.readBit(contexts, contextLabel); + + // At each pixel: Clear contextLabel pixels that are shifted + // out of the context, then add new ones. + contextLabel = ((contextLabel & OLD_PIXEL_MASK) << 1) | + (j + 3 < width ? row2[j + 3] << 11 : 0) | + (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel; + } + } + + return bitmap; + } + + // 6.2 Generic Region Decoding Procedure + function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, + decodingContext) { + if (mmr) { + error('JBIG2 error: MMR encoding is not supported'); + } + + // Use optimized version for the most common case + if (templateIndex === 0 && !skip && !prediction && at.length === 4 && + at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && + at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) { + return decodeBitmapTemplate0(width, height, decodingContext); + } + + var useskip = !!skip; + var template = CodingTemplates[templateIndex].concat(at); + + // Sorting is non-standard, and it is not required. But sorting increases + // the number of template bits that can be reused from the previous + // contextLabel in the main loop. + template.sort(function (a, b) { + return (a.y - b.y) || (a.x - b.x); + }); + + var templateLength = template.length; + var templateX = new Int8Array(templateLength); + var templateY = new Int8Array(templateLength); + var changingTemplateEntries = []; + var reuseMask = 0, minX = 0, maxX = 0, minY = 0; + var c, k; + + for (k = 0; k < templateLength; k++) { + templateX[k] = template[k].x; + templateY[k] = template[k].y; + minX = Math.min(minX, template[k].x); + maxX = Math.max(maxX, template[k].x); + minY = Math.min(minY, template[k].y); + // Check if the template pixel appears in two consecutive context labels, + // so it can be reused. Otherwise, we add it to the list of changing + // template entries. + if (k < templateLength - 1 && + template[k].y === template[k + 1].y && + template[k].x === template[k + 1].x - 1) { + reuseMask |= 1 << (templateLength - 1 - k); + } else { + changingTemplateEntries.push(k); + } + } + var changingEntriesLength = changingTemplateEntries.length; + + var changingTemplateX = new Int8Array(changingEntriesLength); + var changingTemplateY = new Int8Array(changingEntriesLength); + var changingTemplateBit = new Uint16Array(changingEntriesLength); + for (c = 0; c < changingEntriesLength; c++) { + k = changingTemplateEntries[c]; + changingTemplateX[c] = template[k].x; + changingTemplateY[c] = template[k].y; + changingTemplateBit[c] = 1 << (templateLength - 1 - k); + } + + // Get the safe bounding box edges from the width, height, minX, maxX, minY + var sbb_left = -minX; + var sbb_top = -minY; + var sbb_right = width - maxX; + + var pseudoPixelContext = ReusedContexts[templateIndex]; + var row = new Uint8Array(width); + var bitmap = []; + + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GB'); + + var ltp = 0, j, i0, j0, contextLabel = 0, bit, shift; + for (var i = 0; i < height; i++) { + if (prediction) { + var sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + bitmap.push(row); // duplicate previous row + continue; + } + } + row = new Uint8Array(row); + bitmap.push(row); + for (j = 0; j < width; j++) { + if (useskip && skip[i][j]) { + row[j] = 0; + continue; + } + // Are we in the middle of a scanline, so we can reuse contextLabel + // bits? + if (j >= sbb_left && j < sbb_right && i >= sbb_top) { + // If yes, we can just shift the bits that are reusable and only + // fetch the remaining ones. + contextLabel = (contextLabel << 1) & reuseMask; + for (k = 0; k < changingEntriesLength; k++) { + i0 = i + changingTemplateY[k]; + j0 = j + changingTemplateX[k]; + bit = bitmap[i0][j0]; + if (bit) { + bit = changingTemplateBit[k]; + contextLabel |= bit; + } + } + } else { + // compute the contextLabel from scratch + contextLabel = 0; + shift = templateLength - 1; + for (k = 0; k < templateLength; k++, shift--) { + j0 = j + templateX[k]; + if (j0 >= 0 && j0 < width) { + i0 = i + templateY[k]; + if (i0 >= 0) { + bit = bitmap[i0][j0]; + if (bit) { + contextLabel |= bit << shift; + } + } + } + } + } + var pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; + } + + // 6.3.2 Generic Refinement Region Decoding Procedure + function decodeRefinement(width, height, templateIndex, referenceBitmap, + offsetX, offsetY, prediction, at, + decodingContext) { + var codingTemplate = RefinementTemplates[templateIndex].coding; + if (templateIndex === 0) { + codingTemplate = codingTemplate.concat([at[0]]); + } + var codingTemplateLength = codingTemplate.length; + var codingTemplateX = new Int32Array(codingTemplateLength); + var codingTemplateY = new Int32Array(codingTemplateLength); + var k; + for (k = 0; k < codingTemplateLength; k++) { + codingTemplateX[k] = codingTemplate[k].x; + codingTemplateY[k] = codingTemplate[k].y; + } + + var referenceTemplate = RefinementTemplates[templateIndex].reference; + if (templateIndex === 0) { + referenceTemplate = referenceTemplate.concat([at[1]]); + } + var referenceTemplateLength = referenceTemplate.length; + var referenceTemplateX = new Int32Array(referenceTemplateLength); + var referenceTemplateY = new Int32Array(referenceTemplateLength); + for (k = 0; k < referenceTemplateLength; k++) { + referenceTemplateX[k] = referenceTemplate[k].x; + referenceTemplateY[k] = referenceTemplate[k].y; + } + var referenceWidth = referenceBitmap[0].length; + var referenceHeight = referenceBitmap.length; + + var pseudoPixelContext = RefinementReusedContexts[templateIndex]; + var bitmap = []; + + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GR'); + + var ltp = 0; + for (var i = 0; i < height; i++) { + if (prediction) { + var sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + error('JBIG2 error: prediction is not supported'); + } + } + var row = new Uint8Array(width); + bitmap.push(row); + for (var j = 0; j < width; j++) { + var i0, j0; + var contextLabel = 0; + for (k = 0; k < codingTemplateLength; k++) { + i0 = i + codingTemplateY[k]; + j0 = j + codingTemplateX[k]; + if (i0 < 0 || j0 < 0 || j0 >= width) { + contextLabel <<= 1; // out of bound pixel + } else { + contextLabel = (contextLabel << 1) | bitmap[i0][j0]; + } + } + for (k = 0; k < referenceTemplateLength; k++) { + i0 = i + referenceTemplateY[k] + offsetY; + j0 = j + referenceTemplateX[k] + offsetX; + if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || + j0 >= referenceWidth) { + contextLabel <<= 1; // out of bound pixel + } else { + contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0]; + } + } + var pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + + return bitmap; + } + + // 6.5.5 Decoding the symbol dictionary + function decodeSymbolDictionary(huffman, refinement, symbols, + numberOfNewSymbols, numberOfExportedSymbols, + huffmanTables, templateIndex, at, + refinementTemplateIndex, refinementAt, + decodingContext) { + if (huffman) { + error('JBIG2 error: huffman is not supported'); + } + + var newSymbols = []; + var currentHeight = 0; + var symbolCodeLength = log2(symbols.length + numberOfNewSymbols); + + var decoder = decodingContext.decoder; + var contextCache = decodingContext.contextCache; + + while (newSymbols.length < numberOfNewSymbols) { + var deltaHeight = decodeInteger(contextCache, 'IADH', decoder); // 6.5.6 + currentHeight += deltaHeight; + var currentWidth = 0; + var totalWidth = 0; + while (true) { + var deltaWidth = decodeInteger(contextCache, 'IADW', decoder); // 6.5.7 + if (deltaWidth === null) { + break; // OOB + } + currentWidth += deltaWidth; + totalWidth += currentWidth; + var bitmap; + if (refinement) { + // 6.5.8.2 Refinement/aggregate-coded symbol bitmap + var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder); + if (numberOfInstances > 1) { + bitmap = decodeTextRegion(huffman, refinement, + currentWidth, currentHeight, 0, + numberOfInstances, 1, //strip size + symbols.concat(newSymbols), + symbolCodeLength, + 0, //transposed + 0, //ds offset + 1, //top left 7.4.3.1.1 + 0, //OR operator + huffmanTables, + refinementTemplateIndex, refinementAt, + decodingContext); + } else { + var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); + var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3 + var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4 + var symbol = (symbolId < symbols.length ? symbols[symbolId] : + newSymbols[symbolId - symbols.length]); + bitmap = decodeRefinement(currentWidth, currentHeight, + refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, + decodingContext); + } + } else { + // 6.5.8.1 Direct-coded symbol bitmap + bitmap = decodeBitmap(false, currentWidth, currentHeight, + templateIndex, false, null, at, decodingContext); + } + newSymbols.push(bitmap); + } + } + // 6.5.10 Exported symbols + var exportedSymbols = []; + var flags = [], currentFlag = false; + var totalSymbolsLength = symbols.length + numberOfNewSymbols; + while (flags.length < totalSymbolsLength) { + var runLength = decodeInteger(contextCache, 'IAEX', decoder); + while (runLength--) { + flags.push(currentFlag); + } + currentFlag = !currentFlag; + } + for (var i = 0, ii = symbols.length; i < ii; i++) { + if (flags[i]) { + exportedSymbols.push(symbols[i]); + } + } + for (var j = 0; j < numberOfNewSymbols; i++, j++) { + if (flags[i]) { + exportedSymbols.push(newSymbols[j]); + } + } + return exportedSymbols; + } + + function decodeTextRegion(huffman, refinement, width, height, + defaultPixelValue, numberOfSymbolInstances, + stripSize, inputSymbols, symbolCodeLength, + transposed, dsOffset, referenceCorner, + combinationOperator, huffmanTables, + refinementTemplateIndex, refinementAt, + decodingContext) { + if (huffman) { + error('JBIG2 error: huffman is not supported'); + } + + // Prepare bitmap + var bitmap = []; + var i, row; + for (i = 0; i < height; i++) { + row = new Uint8Array(width); + if (defaultPixelValue) { + for (var j = 0; j < width; j++) { + row[j] = defaultPixelValue; + } + } + bitmap.push(row); + } + + var decoder = decodingContext.decoder; + var contextCache = decodingContext.contextCache; + var stripT = -decodeInteger(contextCache, 'IADT', decoder); // 6.4.6 + var firstS = 0; + i = 0; + while (i < numberOfSymbolInstances) { + var deltaT = decodeInteger(contextCache, 'IADT', decoder); // 6.4.6 + stripT += deltaT; + + var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder); // 6.4.7 + firstS += deltaFirstS; + var currentS = firstS; + do { + var currentT = (stripSize === 1 ? 0 : + decodeInteger(contextCache, 'IAIT', decoder)); // 6.4.9 + var t = stripSize * stripT + currentT; + var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); + var applyRefinement = (refinement && + decodeInteger(contextCache, 'IARI', decoder)); + var symbolBitmap = inputSymbols[symbolId]; + var symbolWidth = symbolBitmap[0].length; + var symbolHeight = symbolBitmap.length; + if (applyRefinement) { + var rdw = decodeInteger(contextCache, 'IARDW', decoder); // 6.4.11.1 + var rdh = decodeInteger(contextCache, 'IARDH', decoder); // 6.4.11.2 + var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3 + var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4 + symbolWidth += rdw; + symbolHeight += rdh; + symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, + refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, + (rdh >> 1) + rdy, false, refinementAt, + decodingContext); + } + var offsetT = t - ((referenceCorner & 1) ? 0 : symbolHeight); + var offsetS = currentS - ((referenceCorner & 2) ? symbolWidth : 0); + var s2, t2, symbolRow; + if (transposed) { + // Place Symbol Bitmap from T1,S1 + for (s2 = 0; s2 < symbolHeight; s2++) { + row = bitmap[offsetS + s2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[s2]; + // To ignore Parts of Symbol bitmap which goes + // outside bitmap region + var maxWidth = Math.min(width - offsetT, symbolWidth); + switch (combinationOperator) { + case 0: // OR + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] |= symbolRow[t2]; + } + break; + case 2: // XOR + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] ^= symbolRow[t2]; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + } + currentS += symbolHeight - 1; + } else { + for (t2 = 0; t2 < symbolHeight; t2++) { + row = bitmap[offsetT + t2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[t2]; + switch (combinationOperator) { + case 0: // OR + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] |= symbolRow[s2]; + } + break; + case 2: // XOR + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] ^= symbolRow[s2]; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + } + currentS += symbolWidth - 1; + } + i++; + var deltaS = decodeInteger(contextCache, 'IADS', decoder); // 6.4.8 + if (deltaS === null) { + break; // OOB + } + currentS += deltaS + dsOffset; + } while (true); + } + return bitmap; + } + + function readSegmentHeader(data, start) { + var segmentHeader = {}; + segmentHeader.number = readUint32(data, start); + var flags = data[start + 4]; + var segmentType = flags & 0x3F; + if (!SegmentTypes[segmentType]) { + error('JBIG2 error: invalid segment type: ' + segmentType); + } + segmentHeader.type = segmentType; + segmentHeader.typeName = SegmentTypes[segmentType]; + segmentHeader.deferredNonRetain = !!(flags & 0x80); + + var pageAssociationFieldSize = !!(flags & 0x40); + var referredFlags = data[start + 5]; + var referredToCount = (referredFlags >> 5) & 7; + var retainBits = [referredFlags & 31]; + var position = start + 6; + if (referredFlags === 7) { + referredToCount = readUint32(data, position - 1) & 0x1FFFFFFF; + position += 3; + var bytes = (referredToCount + 7) >> 3; + retainBits[0] = data[position++]; + while (--bytes > 0) { + retainBits.push(data[position++]); + } + } else if (referredFlags === 5 || referredFlags === 6) { + error('JBIG2 error: invalid referred-to flags'); + } + + segmentHeader.retainBits = retainBits; + var referredToSegmentNumberSize = (segmentHeader.number <= 256 ? 1 : + (segmentHeader.number <= 65536 ? 2 : 4)); + var referredTo = []; + var i, ii; + for (i = 0; i < referredToCount; i++) { + var number = (referredToSegmentNumberSize === 1 ? data[position] : + (referredToSegmentNumberSize === 2 ? readUint16(data, position) : + readUint32(data, position))); + referredTo.push(number); + position += referredToSegmentNumberSize; + } + segmentHeader.referredTo = referredTo; + if (!pageAssociationFieldSize) { + segmentHeader.pageAssociation = data[position++]; + } else { + segmentHeader.pageAssociation = readUint32(data, position); + position += 4; + } + segmentHeader.length = readUint32(data, position); + position += 4; + + if (segmentHeader.length === 0xFFFFFFFF) { + // 7.2.7 Segment data length, unknown segment length + if (segmentType === 38) { // ImmediateGenericRegion + var genericRegionInfo = readRegionSegmentInformation(data, position); + var genericRegionSegmentFlags = data[position + + RegionSegmentInformationFieldLength]; + var genericRegionMmr = !!(genericRegionSegmentFlags & 1); + // searching for the segment end + var searchPatternLength = 6; + var searchPattern = new Uint8Array(searchPatternLength); + if (!genericRegionMmr) { + searchPattern[0] = 0xFF; + searchPattern[1] = 0xAC; + } + searchPattern[2] = (genericRegionInfo.height >>> 24) & 0xFF; + searchPattern[3] = (genericRegionInfo.height >> 16) & 0xFF; + searchPattern[4] = (genericRegionInfo.height >> 8) & 0xFF; + searchPattern[5] = genericRegionInfo.height & 0xFF; + for (i = position, ii = data.length; i < ii; i++) { + var j = 0; + while (j < searchPatternLength && searchPattern[j] === data[i + j]) { + j++; + } + if (j === searchPatternLength) { + segmentHeader.length = i + searchPatternLength; + break; + } + } + if (segmentHeader.length === 0xFFFFFFFF) { + error('JBIG2 error: segment end was not found'); + } + } else { + error('JBIG2 error: invalid unknown segment length'); + } + } + segmentHeader.headerEnd = position; + return segmentHeader; + } + + function readSegments(header, data, start, end) { + var segments = []; + var position = start; + while (position < end) { + var segmentHeader = readSegmentHeader(data, position); + position = segmentHeader.headerEnd; + var segment = { + header: segmentHeader, + data: data + }; + if (!header.randomAccess) { + segment.start = position; + position += segmentHeader.length; + segment.end = position; + } + segments.push(segment); + if (segmentHeader.type === 51) { + break; // end of file is found + } + } + if (header.randomAccess) { + for (var i = 0, ii = segments.length; i < ii; i++) { + segments[i].start = position; + position += segments[i].header.length; + segments[i].end = position; + } + } + return segments; + } + + // 7.4.1 Region segment information field + function readRegionSegmentInformation(data, start) { + return { + width: readUint32(data, start), + height: readUint32(data, start + 4), + x: readUint32(data, start + 8), + y: readUint32(data, start + 12), + combinationOperator: data[start + 16] & 7 + }; + } + var RegionSegmentInformationFieldLength = 17; + + function processSegment(segment, visitor) { + var header = segment.header; + + var data = segment.data, position = segment.start, end = segment.end; + var args, at, i, atLength; + switch (header.type) { + case 0: // SymbolDictionary + // 7.4.2 Symbol dictionary segment syntax + var dictionary = {}; + var dictionaryFlags = readUint16(data, position); // 7.4.2.1.1 + dictionary.huffman = !!(dictionaryFlags & 1); + dictionary.refinement = !!(dictionaryFlags & 2); + dictionary.huffmanDHSelector = (dictionaryFlags >> 2) & 3; + dictionary.huffmanDWSelector = (dictionaryFlags >> 4) & 3; + dictionary.bitmapSizeSelector = (dictionaryFlags >> 6) & 1; + dictionary.aggregationInstancesSelector = (dictionaryFlags >> 7) & 1; + dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256); + dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512); + dictionary.template = (dictionaryFlags >> 10) & 3; + dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1; + position += 2; + if (!dictionary.huffman) { + atLength = dictionary.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.at = at; + } + if (dictionary.refinement && !dictionary.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.refinementAt = at; + } + dictionary.numberOfExportedSymbols = readUint32(data, position); + position += 4; + dictionary.numberOfNewSymbols = readUint32(data, position); + position += 4; + args = [dictionary, header.number, header.referredTo, + data, position, end]; + break; + case 6: // ImmediateTextRegion + case 7: // ImmediateLosslessTextRegion + var textRegion = {}; + textRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + var textRegionSegmentFlags = readUint16(data, position); + position += 2; + textRegion.huffman = !!(textRegionSegmentFlags & 1); + textRegion.refinement = !!(textRegionSegmentFlags & 2); + textRegion.stripSize = 1 << ((textRegionSegmentFlags >> 2) & 3); + textRegion.referenceCorner = (textRegionSegmentFlags >> 4) & 3; + textRegion.transposed = !!(textRegionSegmentFlags & 64); + textRegion.combinationOperator = (textRegionSegmentFlags >> 7) & 3; + textRegion.defaultPixelValue = (textRegionSegmentFlags >> 9) & 1; + textRegion.dsOffset = (textRegionSegmentFlags << 17) >> 27; + textRegion.refinementTemplate = (textRegionSegmentFlags >> 15) & 1; + if (textRegion.huffman) { + var textRegionHuffmanFlags = readUint16(data, position); + position += 2; + textRegion.huffmanFS = (textRegionHuffmanFlags) & 3; + textRegion.huffmanDS = (textRegionHuffmanFlags >> 2) & 3; + textRegion.huffmanDT = (textRegionHuffmanFlags >> 4) & 3; + textRegion.huffmanRefinementDW = (textRegionHuffmanFlags >> 6) & 3; + textRegion.huffmanRefinementDH = (textRegionHuffmanFlags >> 8) & 3; + textRegion.huffmanRefinementDX = (textRegionHuffmanFlags >> 10) & 3; + textRegion.huffmanRefinementDY = (textRegionHuffmanFlags >> 12) & 3; + textRegion.huffmanRefinementSizeSelector = + !!(textRegionHuffmanFlags & 14); + } + if (textRegion.refinement && !textRegion.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + textRegion.refinementAt = at; + } + textRegion.numberOfSymbolInstances = readUint32(data, position); + position += 4; + // TODO 7.4.3.1.7 Symbol ID Huffman table decoding + if (textRegion.huffman) { + error('JBIG2 error: huffman is not supported'); + } + args = [textRegion, header.referredTo, data, position, end]; + break; + case 38: // ImmediateGenericRegion + case 39: // ImmediateLosslessGenericRegion + var genericRegion = {}; + genericRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + var genericRegionSegmentFlags = data[position++]; + genericRegion.mmr = !!(genericRegionSegmentFlags & 1); + genericRegion.template = (genericRegionSegmentFlags >> 1) & 3; + genericRegion.prediction = !!(genericRegionSegmentFlags & 8); + if (!genericRegion.mmr) { + atLength = genericRegion.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + genericRegion.at = at; + } + args = [genericRegion, data, position, end]; + break; + case 48: // PageInformation + var pageInfo = { + width: readUint32(data, position), + height: readUint32(data, position + 4), + resolutionX: readUint32(data, position + 8), + resolutionY: readUint32(data, position + 12) + }; + if (pageInfo.height === 0xFFFFFFFF) { + delete pageInfo.height; + } + var pageSegmentFlags = data[position + 16]; + var pageStripingInformatiom = readUint16(data, position + 17); + pageInfo.lossless = !!(pageSegmentFlags & 1); + pageInfo.refinement = !!(pageSegmentFlags & 2); + pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1; + pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3; + pageInfo.requiresBuffer = !!(pageSegmentFlags & 32); + pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64); + args = [pageInfo]; + break; + case 49: // EndOfPage + break; + case 50: // EndOfStripe + break; + case 51: // EndOfFile + break; + case 62: // 7.4.15 defines 2 extension types which + // are comments and can be ignored. + break; + default: + error('JBIG2 error: segment type ' + header.typeName + '(' + + header.type + ') is not implemented'); + } + var callbackName = 'on' + header.typeName; + if (callbackName in visitor) { + visitor[callbackName].apply(visitor, args); + } + } + + function processSegments(segments, visitor) { + for (var i = 0, ii = segments.length; i < ii; i++) { + processSegment(segments[i], visitor); + } + } + + function parseJbig2(data, start, end) { + var position = start; + if (data[position] !== 0x97 || data[position + 1] !== 0x4A || + data[position + 2] !== 0x42 || data[position + 3] !== 0x32 || + data[position + 4] !== 0x0D || data[position + 5] !== 0x0A || + data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) { + error('JBIG2 error: invalid header'); + } + var header = {}; + position += 8; + var flags = data[position++]; + header.randomAccess = !(flags & 1); + if (!(flags & 2)) { + header.numberOfPages = readUint32(data, position); + position += 4; + } + var segments = readSegments(header, data, position, end); + error('Not implemented'); + // processSegments(segments, new SimpleSegmentVisitor()); + } + + function parseJbig2Chunks(chunks) { + var visitor = new SimpleSegmentVisitor(); + for (var i = 0, ii = chunks.length; i < ii; i++) { + var chunk = chunks[i]; + var segments = readSegments({}, chunk.data, chunk.start, chunk.end); + processSegments(segments, visitor); + } + return visitor.buffer; + } + + function SimpleSegmentVisitor() {} + + SimpleSegmentVisitor.prototype = { + onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) { + this.currentPageInfo = info; + var rowSize = (info.width + 7) >> 3; + var buffer = new Uint8Array(rowSize * info.height); + // The contents of ArrayBuffers are initialized to 0. + // Fill the buffer with 0xFF only if info.defaultPixelValue is set + if (info.defaultPixelValue) { + for (var i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] = 0xFF; + } + } + this.buffer = buffer; + }, + drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) { + var pageInfo = this.currentPageInfo; + var width = regionInfo.width, height = regionInfo.height; + var rowSize = (pageInfo.width + 7) >> 3; + var combinationOperator = pageInfo.combinationOperatorOverride ? + regionInfo.combinationOperator : pageInfo.combinationOperator; + var buffer = this.buffer; + var mask0 = 128 >> (regionInfo.x & 7); + var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3); + var i, j, mask, offset; + switch (combinationOperator) { + case 0: // OR + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer[offset] |= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + case 2: // XOR + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer[offset] ^= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + }, + onImmediateGenericRegion: + function SimpleSegmentVisitor_onImmediateGenericRegion(region, data, + start, end) { + var regionInfo = region.info; + var decodingContext = new DecodingContext(data, start, end); + var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, + region.template, region.prediction, null, + region.at, decodingContext); + this.drawBitmap(regionInfo, bitmap); + }, + onImmediateLosslessGenericRegion: + function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() { + this.onImmediateGenericRegion.apply(this, arguments); + }, + onSymbolDictionary: + function SimpleSegmentVisitor_onSymbolDictionary(dictionary, + currentSegment, + referredSegments, + data, start, end) { + var huffmanTables; + if (dictionary.huffman) { + error('JBIG2 error: huffman is not supported'); + } + + // Combines exported symbols from all referred segments + var symbols = this.symbols; + if (!symbols) { + this.symbols = symbols = {}; + } + + var inputSymbols = []; + for (var i = 0, ii = referredSegments.length; i < ii; i++) { + inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); + } + + var decodingContext = new DecodingContext(data, start, end); + symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, + dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, + dictionary.numberOfExportedSymbols, huffmanTables, + dictionary.template, dictionary.at, + dictionary.refinementTemplate, dictionary.refinementAt, + decodingContext); + }, + onImmediateTextRegion: + function SimpleSegmentVisitor_onImmediateTextRegion(region, + referredSegments, + data, start, end) { + var regionInfo = region.info; + var huffmanTables; + + // Combines exported symbols from all referred segments + var symbols = this.symbols; + var inputSymbols = []; + for (var i = 0, ii = referredSegments.length; i < ii; i++) { + inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); + } + var symbolCodeLength = log2(inputSymbols.length); + + var decodingContext = new DecodingContext(data, start, end); + var bitmap = decodeTextRegion(region.huffman, region.refinement, + regionInfo.width, regionInfo.height, region.defaultPixelValue, + region.numberOfSymbolInstances, region.stripSize, inputSymbols, + symbolCodeLength, region.transposed, region.dsOffset, + region.referenceCorner, region.combinationOperator, huffmanTables, + region.refinementTemplate, region.refinementAt, decodingContext); + this.drawBitmap(regionInfo, bitmap); + }, + onImmediateLosslessTextRegion: + function SimpleSegmentVisitor_onImmediateLosslessTextRegion() { + this.onImmediateTextRegion.apply(this, arguments); + } + }; + + function Jbig2Image() {} + + Jbig2Image.prototype = { + parseChunks: function Jbig2Image_parseChunks(chunks) { + return parseJbig2Chunks(chunks); + } + }; + + return Jbig2Image; +})(); + + +var bidi = PDFJS.bidi = (function bidiClosure() { + // Character types for symbols from 0000 to 00FF. + var baseTypes = [ + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS', + 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON', + 'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN', + 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON', + 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', + 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN', + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON', + 'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON', + 'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L' + ]; + + // Character types for symbols from 0600 to 06FF + var arabicTypes = [ + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', + 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', + 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', + 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM', + 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL' + ]; + + function isOdd(i) { + return (i & 1) !== 0; + } + + function isEven(i) { + return (i & 1) === 0; + } + + function findUnequal(arr, start, value) { + for (var j = start, jj = arr.length; j < jj; ++j) { + if (arr[j] !== value) { + return j; + } + } + return j; + } + + function setValues(arr, start, end, value) { + for (var j = start; j < end; ++j) { + arr[j] = value; + } + } + + function reverseValues(arr, start, end) { + for (var i = start, j = end - 1; i < j; ++i, --j) { + var temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + } + + function createBidiText(str, isLTR, vertical) { + return { + str: str, + dir: (vertical ? 'ttb' : (isLTR ? 'ltr' : 'rtl')) + }; + } + + // These are used in bidi(), which is called frequently. We re-use them on + // each call to avoid unnecessary allocations. + var chars = []; + var types = []; + + function bidi(str, startLevel, vertical) { + var isLTR = true; + var strLength = str.length; + if (strLength === 0 || vertical) { + return createBidiText(str, isLTR, vertical); + } + + // Get types and fill arrays + chars.length = strLength; + types.length = strLength; + var numBidi = 0; + + var i, ii; + for (i = 0; i < strLength; ++i) { + chars[i] = str.charAt(i); + + var charCode = str.charCodeAt(i); + var charType = 'L'; + if (charCode <= 0x00ff) { + charType = baseTypes[charCode]; + } else if (0x0590 <= charCode && charCode <= 0x05f4) { + charType = 'R'; + } else if (0x0600 <= charCode && charCode <= 0x06ff) { + charType = arabicTypes[charCode & 0xff]; + } else if (0x0700 <= charCode && charCode <= 0x08AC) { + charType = 'AL'; + } + if (charType === 'R' || charType === 'AL' || charType === 'AN') { + numBidi++; + } + types[i] = charType; + } + + // Detect the bidi method + // - If there are no rtl characters then no bidi needed + // - If less than 30% chars are rtl then string is primarily ltr + // - If more than 30% chars are rtl then string is primarily rtl + if (numBidi === 0) { + isLTR = true; + return createBidiText(str, isLTR); + } + + if (startLevel === -1) { + if ((strLength / numBidi) < 0.3) { + isLTR = true; + startLevel = 0; + } else { + isLTR = false; + startLevel = 1; + } + } + + var levels = []; + for (i = 0; i < strLength; ++i) { + levels[i] = startLevel; + } + + /* + X1-X10: skip most of this, since we are NOT doing the embeddings. + */ + var e = (isOdd(startLevel) ? 'R' : 'L'); + var sor = e; + var eor = sor; + + /* + W1. Examine each non-spacing mark (NSM) in the level run, and change the + type of the NSM to the type of the previous character. If the NSM is at the + start of the level run, it will get the type of sor. + */ + var lastType = sor; + for (i = 0; i < strLength; ++i) { + if (types[i] === 'NSM') { + types[i] = lastType; + } else { + lastType = types[i]; + } + } + + /* + W2. Search backwards from each instance of a European number until the + first strong type (R, L, AL, or sor) is found. If an AL is found, change + the type of the European number to Arabic number. + */ + lastType = sor; + var t; + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'EN') { + types[i] = (lastType === 'AL') ? 'AN' : 'EN'; + } else if (t === 'R' || t === 'L' || t === 'AL') { + lastType = t; + } + } + + /* + W3. Change all ALs to R. + */ + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'AL') { + types[i] = 'R'; + } + } + + /* + W4. A single European separator between two European numbers changes to a + European number. A single common separator between two numbers of the same + type changes to that type: + */ + for (i = 1; i < strLength - 1; ++i) { + if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') { + types[i] = 'EN'; + } + if (types[i] === 'CS' && + (types[i - 1] === 'EN' || types[i - 1] === 'AN') && + types[i + 1] === types[i - 1]) { + types[i] = types[i - 1]; + } + } + + /* + W5. A sequence of European terminators adjacent to European numbers changes + to all European numbers: + */ + for (i = 0; i < strLength; ++i) { + if (types[i] === 'EN') { + // do before + var j; + for (j = i - 1; j >= 0; --j) { + if (types[j] !== 'ET') { + break; + } + types[j] = 'EN'; + } + // do after + for (j = i + 1; j < strLength; --j) { + if (types[j] !== 'ET') { + break; + } + types[j] = 'EN'; + } + } + } + + /* + W6. Otherwise, separators and terminators change to Other Neutral: + */ + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') { + types[i] = 'ON'; + } + } + + /* + W7. Search backwards from each instance of a European number until the + first strong type (R, L, or sor) is found. If an L is found, then change + the type of the European number to L. + */ + lastType = sor; + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'EN') { + types[i] = ((lastType === 'L') ? 'L' : 'EN'); + } else if (t === 'R' || t === 'L') { + lastType = t; + } + } + + /* + N1. A sequence of neutrals takes the direction of the surrounding strong + text if the text on both sides has the same direction. European and Arabic + numbers are treated as though they were R. Start-of-level-run (sor) and + end-of-level-run (eor) are used at level run boundaries. + */ + for (i = 0; i < strLength; ++i) { + if (types[i] === 'ON') { + var end = findUnequal(types, i + 1, 'ON'); + var before = sor; + if (i > 0) { + before = types[i - 1]; + } + + var after = eor; + if (end + 1 < strLength) { + after = types[end + 1]; + } + if (before !== 'L') { + before = 'R'; + } + if (after !== 'L') { + after = 'R'; + } + if (before === after) { + setValues(types, i, end, before); + } + i = end - 1; // reset to end (-1 so next iteration is ok) + } + } + + /* + N2. Any remaining neutrals take the embedding direction. + */ + for (i = 0; i < strLength; ++i) { + if (types[i] === 'ON') { + types[i] = e; + } + } + + /* + I1. For all characters with an even (left-to-right) embedding direction, + those of type R go up one level and those of type AN or EN go up two + levels. + I2. For all characters with an odd (right-to-left) embedding direction, + those of type L, EN or AN go up one level. + */ + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (isEven(levels[i])) { + if (t === 'R') { + levels[i] += 1; + } else if (t === 'AN' || t === 'EN') { + levels[i] += 2; + } + } else { // isOdd + if (t === 'L' || t === 'AN' || t === 'EN') { + levels[i] += 1; + } + } + } + + /* + L1. On each line, reset the embedding level of the following characters to + the paragraph embedding level: + + segment separators, + paragraph separators, + any sequence of whitespace characters preceding a segment separator or + paragraph separator, and any sequence of white space characters at the end + of the line. + */ + + // don't bother as text is only single line + + /* + L2. From the highest level found in the text to the lowest odd level on + each line, reverse any contiguous sequence of characters that are at that + level or higher. + */ + + // find highest level & lowest odd level + var highestLevel = -1; + var lowestOddLevel = 99; + var level; + for (i = 0, ii = levels.length; i < ii; ++i) { + level = levels[i]; + if (highestLevel < level) { + highestLevel = level; + } + if (lowestOddLevel > level && isOdd(level)) { + lowestOddLevel = level; + } + } + + // now reverse between those limits + for (level = highestLevel; level >= lowestOddLevel; --level) { + // find segments to reverse + var start = -1; + for (i = 0, ii = levels.length; i < ii; ++i) { + if (levels[i] < level) { + if (start >= 0) { + reverseValues(chars, start, i); + start = -1; + } + } else if (start < 0) { + start = i; + } + } + if (start >= 0) { + reverseValues(chars, start, levels.length); + } + } + + /* + L3. Combining marks applied to a right-to-left base character will at this + point precede their base character. If the rendering engine expects them to + follow the base characters in the final display process, then the ordering + of the marks and the base character must be reversed. + */ + + // don't bother for now + + /* + L4. A character that possesses the mirrored property as specified by + Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved + directionality of that character is R. + */ + + // don't mirror as characters are already mirrored in the pdf + + // Finally, return string + var result = ''; + for (i = 0, ii = chars.length; i < ii; ++i) { + var ch = chars[i]; + if (ch !== '<' && ch !== '>') { + result += ch; + } + } + return createBidiText(result, isLTR); + } + + return bidi; +})(); + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +/* Copyright 2014 Opera Software ASA + * + * 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. + * + * + * Based on https://code.google.com/p/smhasher/wiki/MurmurHash3. + * Hashes roughly 100 KB per millisecond on i7 3.4 GHz. + */ +/* globals Uint32ArrayView */ + +'use strict'; + +var MurmurHash3_64 = (function MurmurHash3_64Closure (seed) { + // Workaround for missing math precison in JS. + var MASK_HIGH = 0xffff0000; + var MASK_LOW = 0xffff; + + function MurmurHash3_64 (seed) { + var SEED = 0xc3d2e1f0; + this.h1 = seed ? seed & 0xffffffff : SEED; + this.h2 = seed ? seed & 0xffffffff : SEED; + } + + var alwaysUseUint32ArrayView = false; + // old webkits have issues with non-aligned arrays + try { + new Uint32Array(new Uint8Array(5).buffer, 0, 1); + } catch (e) { + alwaysUseUint32ArrayView = true; + } + + MurmurHash3_64.prototype = { + update: function MurmurHash3_64_update(input) { + var useUint32ArrayView = alwaysUseUint32ArrayView; + var i; + if (typeof input === 'string') { + var data = new Uint8Array(input.length * 2); + var length = 0; + for (i = 0; i < input.length; i++) { + var code = input.charCodeAt(i); + if (code <= 0xff) { + data[length++] = code; + } + else { + data[length++] = code >>> 8; + data[length++] = code & 0xff; + } + } + } else if (input instanceof Uint8Array) { + data = input; + length = data.length; + } else if (typeof input === 'object' && ('length' in input)) { + // processing regular arrays as well, e.g. for IE9 + data = input; + length = data.length; + useUint32ArrayView = true; + } else { + throw new Error('Wrong data format in MurmurHash3_64_update. ' + + 'Input must be a string or array.'); + } + + var blockCounts = length >> 2; + var tailLength = length - blockCounts * 4; + // we don't care about endianness here + var dataUint32 = useUint32ArrayView ? + new Uint32ArrayView(data, blockCounts) : + new Uint32Array(data.buffer, 0, blockCounts); + var k1 = 0; + var k2 = 0; + var h1 = this.h1; + var h2 = this.h2; + var C1 = 0xcc9e2d51; + var C2 = 0x1b873593; + var C1_LOW = C1 & MASK_LOW; + var C2_LOW = C2 & MASK_LOW; + + for (i = 0; i < blockCounts; i++) { + if (i & 1) { + k1 = dataUint32[i]; + k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW); + k1 = k1 << 15 | k1 >>> 17; + k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW); + h1 ^= k1; + h1 = h1 << 13 | h1 >>> 19; + h1 = h1 * 5 + 0xe6546b64; + } else { + k2 = dataUint32[i]; + k2 = (k2 * C1 & MASK_HIGH) | (k2 * C1_LOW & MASK_LOW); + k2 = k2 << 15 | k2 >>> 17; + k2 = (k2 * C2 & MASK_HIGH) | (k2 * C2_LOW & MASK_LOW); + h2 ^= k2; + h2 = h2 << 13 | h2 >>> 19; + h2 = h2 * 5 + 0xe6546b64; + } + } + + k1 = 0; + + switch (tailLength) { + case 3: + k1 ^= data[blockCounts * 4 + 2] << 16; + /* falls through */ + case 2: + k1 ^= data[blockCounts * 4 + 1] << 8; + /* falls through */ + case 1: + k1 ^= data[blockCounts * 4]; + /* falls through */ + k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW); + k1 = k1 << 15 | k1 >>> 17; + k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW); + if (blockCounts & 1) { + h1 ^= k1; + } else { + h2 ^= k1; + } + } + + this.h1 = h1; + this.h2 = h2; + return this; + }, + + hexdigest: function MurmurHash3_64_hexdigest () { + var h1 = this.h1; + var h2 = this.h2; + + h1 ^= h2 >>> 1; + h1 = (h1 * 0xed558ccd & MASK_HIGH) | (h1 * 0x8ccd & MASK_LOW); + h2 = (h2 * 0xff51afd7 & MASK_HIGH) | + (((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16); + h1 ^= h2 >>> 1; + h1 = (h1 * 0x1a85ec53 & MASK_HIGH) | (h1 * 0xec53 & MASK_LOW); + h2 = (h2 * 0xc4ceb9fe & MASK_HIGH) | + (((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16); + h1 ^= h2 >>> 1; + + for (var i = 0, arr = [h1, h2], str = ''; i < arr.length; i++) { + var hex = (arr[i] >>> 0).toString(16); + while (hex.length < 8) { + hex = '0' + hex; + } + str += hex; + } + + return str; + } + }; + + return MurmurHash3_64; +})(); + + +}).call((typeof window === 'undefined') ? this : window); + +if (!PDFJS.workerSrc && typeof document !== 'undefined') { + // workerSrc is not set -- using last script url to define default location + PDFJS.workerSrc = (function () { + 'use strict'; + var scriptTagContainer = document.body || + document.getElementsByTagName('head')[0]; + var pdfjsSrc = scriptTagContainer.lastChild.src; + return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js'); + })(); +} + + diff --git a/src/main/resources/static/generic/web/cmaps/78-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/78-EUC-H.bcmap new file mode 100644 index 0000000..2655fc7 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/78-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/78-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/78-EUC-V.bcmap new file mode 100644 index 0000000..f1ed853 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/78-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/78-H.bcmap b/src/main/resources/static/generic/web/cmaps/78-H.bcmap new file mode 100644 index 0000000..39e89d3 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/78-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/78-RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/78-RKSJ-H.bcmap new file mode 100644 index 0000000..e4167cb Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/78-RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/78-RKSJ-V.bcmap b/src/main/resources/static/generic/web/cmaps/78-RKSJ-V.bcmap new file mode 100644 index 0000000..50b1646 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/78-RKSJ-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/78-V.bcmap b/src/main/resources/static/generic/web/cmaps/78-V.bcmap new file mode 100644 index 0000000..d7af99b Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/78-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/78ms-RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/78ms-RKSJ-H.bcmap new file mode 100644 index 0000000..37077d0 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/78ms-RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/78ms-RKSJ-V.bcmap b/src/main/resources/static/generic/web/cmaps/78ms-RKSJ-V.bcmap new file mode 100644 index 0000000..acf2323 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/78ms-RKSJ-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/83pv-RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/83pv-RKSJ-H.bcmap new file mode 100644 index 0000000..2359bc5 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/83pv-RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/90ms-RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/90ms-RKSJ-H.bcmap new file mode 100644 index 0000000..af82938 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/90ms-RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/90ms-RKSJ-V.bcmap b/src/main/resources/static/generic/web/cmaps/90ms-RKSJ-V.bcmap new file mode 100644 index 0000000..780549d Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/90ms-RKSJ-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/90msp-RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/90msp-RKSJ-H.bcmap new file mode 100644 index 0000000..bfd3119 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/90msp-RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/90msp-RKSJ-V.bcmap b/src/main/resources/static/generic/web/cmaps/90msp-RKSJ-V.bcmap new file mode 100644 index 0000000..25ef14a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/90msp-RKSJ-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/90pv-RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/90pv-RKSJ-H.bcmap new file mode 100644 index 0000000..02f713b Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/90pv-RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/90pv-RKSJ-V.bcmap b/src/main/resources/static/generic/web/cmaps/90pv-RKSJ-V.bcmap new file mode 100644 index 0000000..d08e0cc Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/90pv-RKSJ-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Add-H.bcmap b/src/main/resources/static/generic/web/cmaps/Add-H.bcmap new file mode 100644 index 0000000..59442ac Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Add-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Add-RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/Add-RKSJ-H.bcmap new file mode 100644 index 0000000..a3065e4 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Add-RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Add-RKSJ-V.bcmap b/src/main/resources/static/generic/web/cmaps/Add-RKSJ-V.bcmap new file mode 100644 index 0000000..040014c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Add-RKSJ-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Add-V.bcmap b/src/main/resources/static/generic/web/cmaps/Add-V.bcmap new file mode 100644 index 0000000..2f816d3 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Add-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-0.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-0.bcmap new file mode 100644 index 0000000..88ec04a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-0.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-1.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-1.bcmap new file mode 100644 index 0000000..03a5014 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-1.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-2.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-2.bcmap new file mode 100644 index 0000000..2aa9514 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-2.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-3.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-3.bcmap new file mode 100644 index 0000000..86d8b8c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-3.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-4.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-4.bcmap new file mode 100644 index 0000000..f50fc6c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-4.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-5.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-5.bcmap new file mode 100644 index 0000000..6caf4a8 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-5.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-6.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-6.bcmap new file mode 100644 index 0000000..b77fb07 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-6.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-UCS2.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-UCS2.bcmap new file mode 100644 index 0000000..69d79a2 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-CNS1-UCS2.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-GB1-0.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-0.bcmap new file mode 100644 index 0000000..3610108 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-0.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-GB1-1.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-1.bcmap new file mode 100644 index 0000000..707bb10 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-1.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-GB1-2.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-2.bcmap new file mode 100644 index 0000000..f7648cc Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-2.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-GB1-3.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-3.bcmap new file mode 100644 index 0000000..8521458 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-3.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-GB1-4.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-4.bcmap new file mode 100644 index 0000000..e40c63a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-4.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-GB1-5.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-5.bcmap new file mode 100644 index 0000000..d7623b5 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-5.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-GB1-UCS2.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-UCS2.bcmap new file mode 100644 index 0000000..7586525 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-GB1-UCS2.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-0.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-0.bcmap new file mode 100644 index 0000000..f0e94ec Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-0.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-1.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-1.bcmap new file mode 100644 index 0000000..dad42c5 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-1.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-2.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-2.bcmap new file mode 100644 index 0000000..090819a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-2.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-3.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-3.bcmap new file mode 100644 index 0000000..087dfc1 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-3.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-4.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-4.bcmap new file mode 100644 index 0000000..46aa9bf Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-4.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-5.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-5.bcmap new file mode 100644 index 0000000..5b4b65c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-5.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-6.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-6.bcmap new file mode 100644 index 0000000..e77d699 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-6.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-UCS2.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-UCS2.bcmap new file mode 100644 index 0000000..128a141 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Japan1-UCS2.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-0.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-0.bcmap new file mode 100644 index 0000000..cef1a99 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-0.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-1.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-1.bcmap new file mode 100644 index 0000000..11ffa36 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-1.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-2.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-2.bcmap new file mode 100644 index 0000000..3172308 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-2.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-UCS2.bcmap b/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-UCS2.bcmap new file mode 100644 index 0000000..f3371c0 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Adobe-Korea1-UCS2.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/B5-H.bcmap new file mode 100644 index 0000000..beb4d22 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/B5-V.bcmap new file mode 100644 index 0000000..2d4f87d Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/B5pc-H.bcmap b/src/main/resources/static/generic/web/cmaps/B5pc-H.bcmap new file mode 100644 index 0000000..ce00131 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/B5pc-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/B5pc-V.bcmap b/src/main/resources/static/generic/web/cmaps/B5pc-V.bcmap new file mode 100644 index 0000000..73b99ff Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/B5pc-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/CNS-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/CNS-EUC-H.bcmap new file mode 100644 index 0000000..61d1d0c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/CNS-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/CNS-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/CNS-EUC-V.bcmap new file mode 100644 index 0000000..1a393a5 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/CNS-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/CNS1-H.bcmap b/src/main/resources/static/generic/web/cmaps/CNS1-H.bcmap new file mode 100644 index 0000000..f738e21 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/CNS1-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/CNS1-V.bcmap b/src/main/resources/static/generic/web/cmaps/CNS1-V.bcmap new file mode 100644 index 0000000..9c3169f Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/CNS1-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/CNS2-H.bcmap b/src/main/resources/static/generic/web/cmaps/CNS2-H.bcmap new file mode 100644 index 0000000..c89b352 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/CNS2-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/CNS2-V.bcmap b/src/main/resources/static/generic/web/cmaps/CNS2-V.bcmap new file mode 100644 index 0000000..7588cec --- /dev/null +++ b/src/main/resources/static/generic/web/cmaps/CNS2-V.bcmap @@ -0,0 +1,3 @@ +RCopyright 1990-2009 Adobe Systems Incorporated. +All rights reserved. +See ./LICENSECNS2-H \ No newline at end of file diff --git a/src/main/resources/static/generic/web/cmaps/ETHK-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/ETHK-B5-H.bcmap new file mode 100644 index 0000000..cb29415 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/ETHK-B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/ETHK-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/ETHK-B5-V.bcmap new file mode 100644 index 0000000..f09aec6 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/ETHK-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/ETen-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/ETen-B5-H.bcmap new file mode 100644 index 0000000..c2d7746 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/ETen-B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/ETen-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/ETen-B5-V.bcmap new file mode 100644 index 0000000..89bff15 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/ETen-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/ETenms-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/ETenms-B5-H.bcmap new file mode 100644 index 0000000..a7d69db --- /dev/null +++ b/src/main/resources/static/generic/web/cmaps/ETenms-B5-H.bcmap @@ -0,0 +1,3 @@ +RCopyright 1990-2009 Adobe Systems Incorporated. +All rights reserved. +See ./LICENSE ETen-B5-H` ^ \ No newline at end of file diff --git a/src/main/resources/static/generic/web/cmaps/ETenms-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/ETenms-B5-V.bcmap new file mode 100644 index 0000000..adc5d61 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/ETenms-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/EUC-H.bcmap new file mode 100644 index 0000000..e92ea5b Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/EUC-V.bcmap new file mode 100644 index 0000000..7a7c183 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Ext-H.bcmap b/src/main/resources/static/generic/web/cmaps/Ext-H.bcmap new file mode 100644 index 0000000..3b5cde4 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Ext-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Ext-RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/Ext-RKSJ-H.bcmap new file mode 100644 index 0000000..ea4d2d9 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Ext-RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Ext-RKSJ-V.bcmap b/src/main/resources/static/generic/web/cmaps/Ext-RKSJ-V.bcmap new file mode 100644 index 0000000..3457c27 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Ext-RKSJ-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Ext-V.bcmap b/src/main/resources/static/generic/web/cmaps/Ext-V.bcmap new file mode 100644 index 0000000..4999ca4 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Ext-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GB-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/GB-EUC-H.bcmap new file mode 100644 index 0000000..e39908b Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GB-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GB-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/GB-EUC-V.bcmap new file mode 100644 index 0000000..d5be544 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GB-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GB-H.bcmap b/src/main/resources/static/generic/web/cmaps/GB-H.bcmap new file mode 100644 index 0000000..39189c5 --- /dev/null +++ b/src/main/resources/static/generic/web/cmaps/GB-H.bcmap @@ -0,0 +1,4 @@ +RCopyright 1990-2009 Adobe Systems Incorporated. +All rights reserved. +See ./LICENSE!!]aX!!]`21> p z$]"Rd-U7* 4%+ Z {/%<9Kb1]." `],"] +"]h"]F"]$"]"]`"]>"]"]z"]X"]6"]"]r"]P"]."] "]j"]H"]&"]"]b"]@"]"]|"]Z"]8"]"]t"]R"]0"]"]l"]J"]("]"]d"]B"] "X~']W"]5"]"]q"]O"]-"] "]i"]G"]%"]"]a"]?"]"]{"]Y"]7"]"]s"]Q"]/"] "]k"]I"]'"]"]c"]A"]"]}"]["]9 \ No newline at end of file diff --git a/src/main/resources/static/generic/web/cmaps/GB-V.bcmap b/src/main/resources/static/generic/web/cmaps/GB-V.bcmap new file mode 100644 index 0000000..3108345 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GB-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBK-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/GBK-EUC-H.bcmap new file mode 100644 index 0000000..05fff7e Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBK-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBK-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/GBK-EUC-V.bcmap new file mode 100644 index 0000000..0cdf6be Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBK-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBK2K-H.bcmap b/src/main/resources/static/generic/web/cmaps/GBK2K-H.bcmap new file mode 100644 index 0000000..46f6ba5 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBK2K-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBK2K-V.bcmap b/src/main/resources/static/generic/web/cmaps/GBK2K-V.bcmap new file mode 100644 index 0000000..d9a9479 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBK2K-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBKp-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/GBKp-EUC-H.bcmap new file mode 100644 index 0000000..5cb0af6 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBKp-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBKp-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/GBKp-EUC-V.bcmap new file mode 100644 index 0000000..bca93b8 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBKp-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBT-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/GBT-EUC-H.bcmap new file mode 100644 index 0000000..4b4e2d3 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBT-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBT-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/GBT-EUC-V.bcmap new file mode 100644 index 0000000..38f7066 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBT-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBT-H.bcmap b/src/main/resources/static/generic/web/cmaps/GBT-H.bcmap new file mode 100644 index 0000000..8437ac3 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBT-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBT-V.bcmap b/src/main/resources/static/generic/web/cmaps/GBT-V.bcmap new file mode 100644 index 0000000..697ab4a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBT-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBTpc-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/GBTpc-EUC-H.bcmap new file mode 100644 index 0000000..f6e50e8 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBTpc-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBTpc-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/GBTpc-EUC-V.bcmap new file mode 100644 index 0000000..6c0d71a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBTpc-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBpc-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/GBpc-EUC-H.bcmap new file mode 100644 index 0000000..c9edf67 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBpc-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/GBpc-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/GBpc-EUC-V.bcmap new file mode 100644 index 0000000..31450c9 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/GBpc-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/H.bcmap b/src/main/resources/static/generic/web/cmaps/H.bcmap new file mode 100644 index 0000000..7b24ea4 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKdla-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/HKdla-B5-H.bcmap new file mode 100644 index 0000000..7d30c05 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKdla-B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKdla-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/HKdla-B5-V.bcmap new file mode 100644 index 0000000..7894694 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKdla-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKdlb-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/HKdlb-B5-H.bcmap new file mode 100644 index 0000000..d829a23 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKdlb-B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKdlb-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/HKdlb-B5-V.bcmap new file mode 100644 index 0000000..2b572b5 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKdlb-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKgccs-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/HKgccs-B5-H.bcmap new file mode 100644 index 0000000..971a4f2 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKgccs-B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKgccs-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/HKgccs-B5-V.bcmap new file mode 100644 index 0000000..d353ca2 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKgccs-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKm314-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/HKm314-B5-H.bcmap new file mode 100644 index 0000000..576dc01 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKm314-B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKm314-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/HKm314-B5-V.bcmap new file mode 100644 index 0000000..0e96d0e Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKm314-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKm471-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/HKm471-B5-H.bcmap new file mode 100644 index 0000000..11d170c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKm471-B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKm471-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/HKm471-B5-V.bcmap new file mode 100644 index 0000000..54959bf Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKm471-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKscs-B5-H.bcmap b/src/main/resources/static/generic/web/cmaps/HKscs-B5-H.bcmap new file mode 100644 index 0000000..6ef7857 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKscs-B5-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/HKscs-B5-V.bcmap b/src/main/resources/static/generic/web/cmaps/HKscs-B5-V.bcmap new file mode 100644 index 0000000..1fb2fa2 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/HKscs-B5-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Hankaku.bcmap b/src/main/resources/static/generic/web/cmaps/Hankaku.bcmap new file mode 100644 index 0000000..4b8ec7f Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Hankaku.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Hiragana.bcmap b/src/main/resources/static/generic/web/cmaps/Hiragana.bcmap new file mode 100644 index 0000000..17e983e Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Hiragana.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSC-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/KSC-EUC-H.bcmap new file mode 100644 index 0000000..a45c65f Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSC-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSC-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/KSC-EUC-V.bcmap new file mode 100644 index 0000000..0e7b21f Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSC-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSC-H.bcmap b/src/main/resources/static/generic/web/cmaps/KSC-H.bcmap new file mode 100644 index 0000000..b9b22b6 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSC-Johab-H.bcmap b/src/main/resources/static/generic/web/cmaps/KSC-Johab-H.bcmap new file mode 100644 index 0000000..2531ffc Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSC-Johab-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSC-Johab-V.bcmap b/src/main/resources/static/generic/web/cmaps/KSC-Johab-V.bcmap new file mode 100644 index 0000000..367ceb2 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSC-Johab-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSC-V.bcmap b/src/main/resources/static/generic/web/cmaps/KSC-V.bcmap new file mode 100644 index 0000000..6ae2f0b Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSCms-UHC-H.bcmap b/src/main/resources/static/generic/web/cmaps/KSCms-UHC-H.bcmap new file mode 100644 index 0000000..a8d4240 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSCms-UHC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSCms-UHC-HW-H.bcmap b/src/main/resources/static/generic/web/cmaps/KSCms-UHC-HW-H.bcmap new file mode 100644 index 0000000..8b4ae18 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSCms-UHC-HW-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSCms-UHC-HW-V.bcmap b/src/main/resources/static/generic/web/cmaps/KSCms-UHC-HW-V.bcmap new file mode 100644 index 0000000..b655dbc Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSCms-UHC-HW-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSCms-UHC-V.bcmap b/src/main/resources/static/generic/web/cmaps/KSCms-UHC-V.bcmap new file mode 100644 index 0000000..21f97f6 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSCms-UHC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSCpc-EUC-H.bcmap b/src/main/resources/static/generic/web/cmaps/KSCpc-EUC-H.bcmap new file mode 100644 index 0000000..e06f361 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSCpc-EUC-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/KSCpc-EUC-V.bcmap b/src/main/resources/static/generic/web/cmaps/KSCpc-EUC-V.bcmap new file mode 100644 index 0000000..f3c9113 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/KSCpc-EUC-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Katakana.bcmap b/src/main/resources/static/generic/web/cmaps/Katakana.bcmap new file mode 100644 index 0000000..524303c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Katakana.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/LICENSE b/src/main/resources/static/generic/web/cmaps/LICENSE new file mode 100644 index 0000000..b1ad168 --- /dev/null +++ b/src/main/resources/static/generic/web/cmaps/LICENSE @@ -0,0 +1,36 @@ +%%Copyright: ----------------------------------------------------------- +%%Copyright: Copyright 1990-2009 Adobe Systems Incorporated. +%%Copyright: All rights reserved. +%%Copyright: +%%Copyright: Redistribution and use in source and binary forms, with or +%%Copyright: without modification, are permitted provided that the +%%Copyright: following conditions are met: +%%Copyright: +%%Copyright: Redistributions of source code must retain the above +%%Copyright: copyright notice, this list of conditions and the following +%%Copyright: disclaimer. +%%Copyright: +%%Copyright: Redistributions in binary form must reproduce the above +%%Copyright: copyright notice, this list of conditions and the following +%%Copyright: disclaimer in the documentation and/or other materials +%%Copyright: provided with the distribution. +%%Copyright: +%%Copyright: Neither the name of Adobe Systems Incorporated nor the names +%%Copyright: of its contributors may be used to endorse or promote +%%Copyright: products derived from this software without specific prior +%%Copyright: written permission. +%%Copyright: +%%Copyright: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +%%Copyright: CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +%%Copyright: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +%%Copyright: MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +%%Copyright: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +%%Copyright: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +%%Copyright: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +%%Copyright: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +%%Copyright: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +%%Copyright: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +%%Copyright: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +%%Copyright: OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +%%Copyright: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +%%Copyright: ----------------------------------------------------------- diff --git a/src/main/resources/static/generic/web/cmaps/NWP-H.bcmap b/src/main/resources/static/generic/web/cmaps/NWP-H.bcmap new file mode 100644 index 0000000..afc5e4b Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/NWP-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/NWP-V.bcmap b/src/main/resources/static/generic/web/cmaps/NWP-V.bcmap new file mode 100644 index 0000000..bb5785e Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/NWP-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/RKSJ-H.bcmap b/src/main/resources/static/generic/web/cmaps/RKSJ-H.bcmap new file mode 100644 index 0000000..fb8d298 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/RKSJ-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/RKSJ-V.bcmap b/src/main/resources/static/generic/web/cmaps/RKSJ-V.bcmap new file mode 100644 index 0000000..a2555a6 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/RKSJ-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/Roman.bcmap b/src/main/resources/static/generic/web/cmaps/Roman.bcmap new file mode 100644 index 0000000..f896dcf Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/Roman.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniCNS-UCS2-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniCNS-UCS2-H.bcmap new file mode 100644 index 0000000..d5db27c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniCNS-UCS2-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniCNS-UCS2-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniCNS-UCS2-V.bcmap new file mode 100644 index 0000000..1dc9b7a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniCNS-UCS2-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniCNS-UTF16-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF16-H.bcmap new file mode 100644 index 0000000..961afef Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF16-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniCNS-UTF16-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF16-V.bcmap new file mode 100644 index 0000000..df0cffe Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF16-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniCNS-UTF32-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF32-H.bcmap new file mode 100644 index 0000000..1ab18a1 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF32-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniCNS-UTF32-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF32-V.bcmap new file mode 100644 index 0000000..ad14662 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF32-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniCNS-UTF8-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF8-H.bcmap new file mode 100644 index 0000000..83c6bd7 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF8-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniCNS-UTF8-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF8-V.bcmap new file mode 100644 index 0000000..22a27e4 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniCNS-UTF8-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniGB-UCS2-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniGB-UCS2-H.bcmap new file mode 100644 index 0000000..5bd6228 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniGB-UCS2-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniGB-UCS2-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniGB-UCS2-V.bcmap new file mode 100644 index 0000000..53c534b Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniGB-UCS2-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniGB-UTF16-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniGB-UTF16-H.bcmap new file mode 100644 index 0000000..b95045b Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniGB-UTF16-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniGB-UTF16-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniGB-UTF16-V.bcmap new file mode 100644 index 0000000..51f023e Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniGB-UTF16-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniGB-UTF32-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniGB-UTF32-H.bcmap new file mode 100644 index 0000000..f0dbd14 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniGB-UTF32-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniGB-UTF32-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniGB-UTF32-V.bcmap new file mode 100644 index 0000000..ce9c30a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniGB-UTF32-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniGB-UTF8-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniGB-UTF8-H.bcmap new file mode 100644 index 0000000..982ca46 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniGB-UTF8-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniGB-UTF8-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniGB-UTF8-V.bcmap new file mode 100644 index 0000000..f78020d Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniGB-UTF8-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-H.bcmap new file mode 100644 index 0000000..7daf56a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-HW-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-HW-H.bcmap new file mode 100644 index 0000000..ac9975c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-HW-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-HW-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-HW-V.bcmap new file mode 100644 index 0000000..3da0a1c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-HW-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-V.bcmap new file mode 100644 index 0000000..c50b9dd Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UCS2-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UTF16-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF16-H.bcmap new file mode 100644 index 0000000..6761344 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF16-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UTF16-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF16-V.bcmap new file mode 100644 index 0000000..70bf90c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF16-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UTF32-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF32-H.bcmap new file mode 100644 index 0000000..7a83d53 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF32-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UTF32-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF32-V.bcmap new file mode 100644 index 0000000..7a87135 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF32-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UTF8-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF8-H.bcmap new file mode 100644 index 0000000..9f0334c Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF8-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS-UTF8-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF8-V.bcmap new file mode 100644 index 0000000..808a94f Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS-UTF8-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF16-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF16-H.bcmap new file mode 100644 index 0000000..d768bf8 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF16-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF16-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF16-V.bcmap new file mode 100644 index 0000000..3d5bf6f Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF16-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF32-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF32-H.bcmap new file mode 100644 index 0000000..09eee10 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF32-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF32-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF32-V.bcmap new file mode 100644 index 0000000..6c54600 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF32-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF8-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF8-H.bcmap new file mode 100644 index 0000000..1b1a64f Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF8-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF8-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF8-V.bcmap new file mode 100644 index 0000000..994aa9e Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJIS2004-UTF8-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJISPro-UCS2-HW-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJISPro-UCS2-HW-V.bcmap new file mode 100644 index 0000000..643f921 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJISPro-UCS2-HW-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJISPro-UCS2-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJISPro-UCS2-V.bcmap new file mode 100644 index 0000000..c148f67 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJISPro-UCS2-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJISPro-UTF8-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJISPro-UTF8-V.bcmap new file mode 100644 index 0000000..1849d80 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJISPro-UTF8-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJISX0213-UTF32-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJISX0213-UTF32-H.bcmap new file mode 100644 index 0000000..a83a677 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJISX0213-UTF32-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJISX0213-UTF32-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJISX0213-UTF32-V.bcmap new file mode 100644 index 0000000..f527248 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJISX0213-UTF32-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJISX02132004-UTF32-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniJISX02132004-UTF32-H.bcmap new file mode 100644 index 0000000..e1a988d Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJISX02132004-UTF32-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniJISX02132004-UTF32-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniJISX02132004-UTF32-V.bcmap new file mode 100644 index 0000000..47e054a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniJISX02132004-UTF32-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniKS-UCS2-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniKS-UCS2-H.bcmap new file mode 100644 index 0000000..b5b9485 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniKS-UCS2-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniKS-UCS2-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniKS-UCS2-V.bcmap new file mode 100644 index 0000000..026adca Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniKS-UCS2-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniKS-UTF16-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniKS-UTF16-H.bcmap new file mode 100644 index 0000000..fd4e66e Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniKS-UTF16-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniKS-UTF16-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniKS-UTF16-V.bcmap new file mode 100644 index 0000000..075efb7 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniKS-UTF16-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniKS-UTF32-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniKS-UTF32-H.bcmap new file mode 100644 index 0000000..769d214 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniKS-UTF32-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniKS-UTF32-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniKS-UTF32-V.bcmap new file mode 100644 index 0000000..bdab208 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniKS-UTF32-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniKS-UTF8-H.bcmap b/src/main/resources/static/generic/web/cmaps/UniKS-UTF8-H.bcmap new file mode 100644 index 0000000..6ff8674 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniKS-UTF8-H.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/UniKS-UTF8-V.bcmap b/src/main/resources/static/generic/web/cmaps/UniKS-UTF8-V.bcmap new file mode 100644 index 0000000..8dfa76a Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/UniKS-UTF8-V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/V.bcmap b/src/main/resources/static/generic/web/cmaps/V.bcmap new file mode 100644 index 0000000..fdec990 Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/V.bcmap differ diff --git a/src/main/resources/static/generic/web/cmaps/WP-Symbol.bcmap b/src/main/resources/static/generic/web/cmaps/WP-Symbol.bcmap new file mode 100644 index 0000000..46729bb Binary files /dev/null and b/src/main/resources/static/generic/web/cmaps/WP-Symbol.bcmap differ diff --git a/src/main/resources/static/generic/web/compatibility.js b/src/main/resources/static/generic/web/compatibility.js new file mode 100644 index 0000000..06f54bf --- /dev/null +++ b/src/main/resources/static/generic/web/compatibility.js @@ -0,0 +1,577 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * 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. + */ +/* globals VBArray, PDFJS */ + +'use strict'; + +// Initializing PDFJS global object here, it case if we need to change/disable +// some PDF.js features, e.g. range requests +if (typeof PDFJS === 'undefined') { + (typeof window !== 'undefined' ? window : this).PDFJS = {}; +} + +// Checking if the typed arrays are supported +// Support: iOS<6.0 (subarray), IE<10, Android<4.0 +(function checkTypedArrayCompatibility() { + if (typeof Uint8Array !== 'undefined') { + // Support: iOS<6.0 + if (typeof Uint8Array.prototype.subarray === 'undefined') { + Uint8Array.prototype.subarray = function subarray(start, end) { + return new Uint8Array(this.slice(start, end)); + }; + Float32Array.prototype.subarray = function subarray(start, end) { + return new Float32Array(this.slice(start, end)); + }; + } + + // Support: Android<4.1 + if (typeof Float64Array === 'undefined') { + window.Float64Array = Float32Array; + } + return; + } + + function subarray(start, end) { + return new TypedArray(this.slice(start, end)); + } + + function setArrayOffset(array, offset) { + if (arguments.length < 2) { + offset = 0; + } + for (var i = 0, n = array.length; i < n; ++i, ++offset) { + this[offset] = array[i] & 0xFF; + } + } + + function TypedArray(arg1) { + var result, i, n; + if (typeof arg1 === 'number') { + result = []; + for (i = 0; i < arg1; ++i) { + result[i] = 0; + } + } else if ('slice' in arg1) { + result = arg1.slice(0); + } else { + result = []; + for (i = 0, n = arg1.length; i < n; ++i) { + result[i] = arg1[i]; + } + } + + result.subarray = subarray; + result.buffer = result; + result.byteLength = result.length; + result.set = setArrayOffset; + + if (typeof arg1 === 'object' && arg1.buffer) { + result.buffer = arg1.buffer; + } + return result; + } + + window.Uint8Array = TypedArray; + window.Int8Array = TypedArray; + + // we don't need support for set, byteLength for 32-bit array + // so we can use the TypedArray as well + window.Uint32Array = TypedArray; + window.Int32Array = TypedArray; + window.Uint16Array = TypedArray; + window.Float32Array = TypedArray; + window.Float64Array = TypedArray; +})(); + +// URL = URL || webkitURL +// Support: Safari<7, Android 4.2+ +(function normalizeURLObject() { + if (!window.URL) { + window.URL = window.webkitURL; + } +})(); + +// Object.defineProperty()? +// Support: Android<4.0, Safari<5.1 +(function checkObjectDefinePropertyCompatibility() { + if (typeof Object.defineProperty !== 'undefined') { + var definePropertyPossible = true; + try { + // some browsers (e.g. safari) cannot use defineProperty() on DOM objects + // and thus the native version is not sufficient + Object.defineProperty(new Image(), 'id', { value: 'test' }); + // ... another test for android gb browser for non-DOM objects + var Test = function Test() {}; + Test.prototype = { get id() { } }; + Object.defineProperty(new Test(), 'id', + { value: '', configurable: true, enumerable: true, writable: false }); + } catch (e) { + definePropertyPossible = false; + } + if (definePropertyPossible) { + return; + } + } + + Object.defineProperty = function objectDefineProperty(obj, name, def) { + delete obj[name]; + if ('get' in def) { + obj.__defineGetter__(name, def['get']); + } + if ('set' in def) { + obj.__defineSetter__(name, def['set']); + } + if ('value' in def) { + obj.__defineSetter__(name, function objectDefinePropertySetter(value) { + this.__defineGetter__(name, function objectDefinePropertyGetter() { + return value; + }); + return value; + }); + obj[name] = def.value; + } + }; +})(); + + +// No XMLHttpRequest#response? +// Support: IE<11, Android <4.0 +(function checkXMLHttpRequestResponseCompatibility() { + var xhrPrototype = XMLHttpRequest.prototype; + var xhr = new XMLHttpRequest(); + if (!('overrideMimeType' in xhr)) { + // IE10 might have response, but not overrideMimeType + // Support: IE10 + Object.defineProperty(xhrPrototype, 'overrideMimeType', { + value: function xmlHttpRequestOverrideMimeType(mimeType) {} + }); + } + if ('responseType' in xhr) { + return; + } + + // The worker will be using XHR, so we can save time and disable worker. + PDFJS.disableWorker = true; + + Object.defineProperty(xhrPrototype, 'responseType', { + get: function xmlHttpRequestGetResponseType() { + return this._responseType || 'text'; + }, + set: function xmlHttpRequestSetResponseType(value) { + if (value === 'text' || value === 'arraybuffer') { + this._responseType = value; + if (value === 'arraybuffer' && + typeof this.overrideMimeType === 'function') { + this.overrideMimeType('text/plain; charset=x-user-defined'); + } + } + } + }); + + // Support: IE9 + if (typeof VBArray !== 'undefined') { + Object.defineProperty(xhrPrototype, 'response', { + get: function xmlHttpRequestResponseGet() { + if (this.responseType === 'arraybuffer') { + return new Uint8Array(new VBArray(this.responseBody).toArray()); + } else { + return this.responseText; + } + } + }); + return; + } + + Object.defineProperty(xhrPrototype, 'response', { + get: function xmlHttpRequestResponseGet() { + if (this.responseType !== 'arraybuffer') { + return this.responseText; + } + var text = this.responseText; + var i, n = text.length; + var result = new Uint8Array(n); + for (i = 0; i < n; ++i) { + result[i] = text.charCodeAt(i) & 0xFF; + } + return result.buffer; + } + }); +})(); + +// window.btoa (base64 encode function) ? +// Support: IE<10 +(function checkWindowBtoaCompatibility() { + if ('btoa' in window) { + return; + } + + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + window.btoa = function windowBtoa(chars) { + var buffer = ''; + var i, n; + for (i = 0, n = chars.length; i < n; i += 3) { + var b1 = chars.charCodeAt(i) & 0xFF; + var b2 = chars.charCodeAt(i + 1) & 0xFF; + var b3 = chars.charCodeAt(i + 2) & 0xFF; + var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < n ? (b3 & 0x3F) : 64; + buffer += (digits.charAt(d1) + digits.charAt(d2) + + digits.charAt(d3) + digits.charAt(d4)); + } + return buffer; + }; +})(); + +// window.atob (base64 encode function)? +// Support: IE<10 +(function checkWindowAtobCompatibility() { + if ('atob' in window) { + return; + } + + // https://github.com/davidchambers/Base64.js + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + window.atob = function (input) { + input = input.replace(/=+$/, ''); + if (input.length % 4 === 1) { + throw new Error('bad atob input'); + } + for ( + // initialize result and counters + var bc = 0, bs, buffer, idx = 0, output = ''; + // get next character + buffer = input.charAt(idx++); + // character found in table? + // initialize bit storage and add its ascii value + ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, + // and if not first of each 4 characters, + // convert the first 8 bits to one ascii character + bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0 + ) { + // try to find character in table (0-63, not found => -1) + buffer = digits.indexOf(buffer); + } + return output; + }; +})(); + +// Function.prototype.bind? +// Support: Android<4.0, iOS<6.0 +(function checkFunctionPrototypeBindCompatibility() { + if (typeof Function.prototype.bind !== 'undefined') { + return; + } + + Function.prototype.bind = function functionPrototypeBind(obj) { + var fn = this, headArgs = Array.prototype.slice.call(arguments, 1); + var bound = function functionPrototypeBindBound() { + var args = headArgs.concat(Array.prototype.slice.call(arguments)); + return fn.apply(obj, args); + }; + return bound; + }; +})(); + +// HTMLElement dataset property +// Support: IE<11, Safari<5.1, Android<4.0 +(function checkDatasetProperty() { + var div = document.createElement('div'); + if ('dataset' in div) { + return; // dataset property exists + } + + Object.defineProperty(HTMLElement.prototype, 'dataset', { + get: function() { + if (this._dataset) { + return this._dataset; + } + + var dataset = {}; + for (var j = 0, jj = this.attributes.length; j < jj; j++) { + var attribute = this.attributes[j]; + if (attribute.name.substring(0, 5) !== 'data-') { + continue; + } + var key = attribute.name.substring(5).replace(/\-([a-z])/g, + function(all, ch) { + return ch.toUpperCase(); + }); + dataset[key] = attribute.value; + } + + Object.defineProperty(this, '_dataset', { + value: dataset, + writable: false, + enumerable: false + }); + return dataset; + }, + enumerable: true + }); +})(); + +// HTMLElement classList property +// Support: IE<10, Android<4.0, iOS<5.0 +(function checkClassListProperty() { + var div = document.createElement('div'); + if ('classList' in div) { + return; // classList property exists + } + + function changeList(element, itemName, add, remove) { + var s = element.className || ''; + var list = s.split(/\s+/g); + if (list[0] === '') { + list.shift(); + } + var index = list.indexOf(itemName); + if (index < 0 && add) { + list.push(itemName); + } + if (index >= 0 && remove) { + list.splice(index, 1); + } + element.className = list.join(' '); + return (index >= 0); + } + + var classListPrototype = { + add: function(name) { + changeList(this.element, name, true, false); + }, + contains: function(name) { + return changeList(this.element, name, false, false); + }, + remove: function(name) { + changeList(this.element, name, false, true); + }, + toggle: function(name) { + changeList(this.element, name, true, true); + } + }; + + Object.defineProperty(HTMLElement.prototype, 'classList', { + get: function() { + if (this._classList) { + return this._classList; + } + + var classList = Object.create(classListPrototype, { + element: { + value: this, + writable: false, + enumerable: true + } + }); + Object.defineProperty(this, '_classList', { + value: classList, + writable: false, + enumerable: false + }); + return classList; + }, + enumerable: true + }); +})(); + +// Check console compatibility +// In older IE versions the console object is not available +// unless console is open. +// Support: IE<10 +(function checkConsoleCompatibility() { + if (!('console' in window)) { + window.console = { + log: function() {}, + error: function() {}, + warn: function() {} + }; + } else if (!('bind' in console.log)) { + // native functions in IE9 might not have bind + console.log = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.log); + console.error = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.error); + console.warn = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.warn); + } +})(); + +// Check onclick compatibility in Opera +// Support: Opera<15 +(function checkOnClickCompatibility() { + // workaround for reported Opera bug DSK-354448: + // onclick fires on disabled buttons with opaque content + function ignoreIfTargetDisabled(event) { + if (isDisabled(event.target)) { + event.stopPropagation(); + } + } + function isDisabled(node) { + return node.disabled || (node.parentNode && isDisabled(node.parentNode)); + } + if (navigator.userAgent.indexOf('Opera') !== -1) { + // use browser detection since we cannot feature-check this bug + document.addEventListener('click', ignoreIfTargetDisabled, true); + } +})(); + +// Checks if possible to use URL.createObjectURL() +// Support: IE +(function checkOnBlobSupport() { + // sometimes IE loosing the data created with createObjectURL(), see #3977 + if (navigator.userAgent.indexOf('Trident') >= 0) { + PDFJS.disableCreateObjectURL = true; + } +})(); + +// Checks if navigator.language is supported +(function checkNavigatorLanguage() { + if ('language' in navigator) { + return; + } + PDFJS.locale = navigator.userLanguage || 'en-US'; +})(); + +(function checkRangeRequests() { + // Safari has issues with cached range requests see: + // https://github.com/mozilla/pdf.js/issues/3260 + // Last tested with version 6.0.4. + // Support: Safari 6.0+ + var isSafari = Object.prototype.toString.call( + window.HTMLElement).indexOf('Constructor') > 0; + + // Older versions of Android (pre 3.0) has issues with range requests, see: + // https://github.com/mozilla/pdf.js/issues/3381. + // Make sure that we only match webkit-based Android browsers, + // since Firefox/Fennec works as expected. + // Support: Android<3.0 + var regex = /Android\s[0-2][^\d]/; + var isOldAndroid = regex.test(navigator.userAgent); + + // Range requests are broken in Chrome 39 and 40, https://crbug.com/442318 + var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent); + + if (isSafari || isOldAndroid || isChromeWithRangeBug) { + PDFJS.disableRange = true; + PDFJS.disableStream = true; + } +})(); + +// Check if the browser supports manipulation of the history. +// Support: IE<10, Android<4.2 +(function checkHistoryManipulation() { + // Android 2.x has so buggy pushState support that it was removed in + // Android 3.0 and restored as late as in Android 4.2. + // Support: Android 2.x + if (!history.pushState || navigator.userAgent.indexOf('Android 2.') >= 0) { + PDFJS.disableHistory = true; + } +})(); + +// Support: IE<11, Chrome<21, Android<4.4, Safari<6 +(function checkSetPresenceInImageData() { + // IE < 11 will use window.CanvasPixelArray which lacks set function. + if (window.CanvasPixelArray) { + if (typeof window.CanvasPixelArray.prototype.set !== 'function') { + window.CanvasPixelArray.prototype.set = function(arr) { + for (var i = 0, ii = this.length; i < ii; i++) { + this[i] = arr[i]; + } + }; + } + } else { + // Old Chrome and Android use an inaccessible CanvasPixelArray prototype. + // Because we cannot feature detect it, we rely on user agent parsing. + var polyfill = false, versionMatch; + if (navigator.userAgent.indexOf('Chrom') >= 0) { + versionMatch = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./); + // Chrome < 21 lacks the set function. + polyfill = versionMatch && parseInt(versionMatch[2]) < 21; + } else if (navigator.userAgent.indexOf('Android') >= 0) { + // Android < 4.4 lacks the set function. + // Android >= 4.4 will contain Chrome in the user agent, + // thus pass the Chrome check above and not reach this block. + polyfill = /Android\s[0-4][^\d]/g.test(navigator.userAgent); + } else if (navigator.userAgent.indexOf('Safari') >= 0) { + versionMatch = navigator.userAgent. + match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//); + // Safari < 6 lacks the set function. + polyfill = versionMatch && parseInt(versionMatch[1]) < 6; + } + + if (polyfill) { + var contextPrototype = window.CanvasRenderingContext2D.prototype; + contextPrototype._createImageData = contextPrototype.createImageData; + contextPrototype.createImageData = function(w, h) { + var imageData = this._createImageData(w, h); + imageData.data.set = function(arr) { + for (var i = 0, ii = this.length; i < ii; i++) { + this[i] = arr[i]; + } + }; + return imageData; + }; + } + } +})(); + +// Support: IE<10, Android<4.0, iOS +(function checkRequestAnimationFrame() { + function fakeRequestAnimationFrame(callback) { + window.setTimeout(callback, 20); + } + + var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent); + if (isIOS) { + // requestAnimationFrame on iOS is broken, replacing with fake one. + window.requestAnimationFrame = fakeRequestAnimationFrame; + return; + } + if ('requestAnimationFrame' in window) { + return; + } + window.requestAnimationFrame = + window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + fakeRequestAnimationFrame; +})(); + +(function checkCanvasSizeLimitation() { + var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent); + var isAndroid = /Android/g.test(navigator.userAgent); + if (isIOS || isAndroid) { + // 5MP + PDFJS.maxCanvasPixels = 5242880; + } +})(); + +// Disable fullscreen support for certain problematic configurations. +// Support: IE11+ (when embedded). +(function checkFullscreenSupport() { + var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 && + window.parent !== window); + if (isEmbeddedIE) { + PDFJS.disableFullscreen = true; + } +})(); diff --git a/src/main/resources/static/generic/web/compressed.tracemonkey-pldi-09.pdf b/src/main/resources/static/generic/web/compressed.tracemonkey-pldi-09.pdf new file mode 100644 index 0000000..6557018 --- /dev/null +++ b/src/main/resources/static/generic/web/compressed.tracemonkey-pldi-09.pdf @@ -0,0 +1,1000 @@ + Trace-based Just-in-Time Type Specialization for Dynamic + Languages + + Andreas Gal∗+, Brendan Eich∗, Mike Shaver∗, David Anderson∗, David Mandelin∗, + Mohammad R. Haghighat$, Blake Kaplan∗, Graydon Hoare∗, Boris Zbarsky∗, Jason Orendorff∗, +Jesse Ruderman∗, Edwin Smith#, Rick Reitmaier#, Michael Bebenita+, Mason Chang+#, Michael Franz+ + + Mozilla Corporation∗ + {gal,brendan,shaver,danderson,dmandelin,mrbkap,graydon,bz,jorendorff,jruderman}@mozilla.com + + Adobe Corporation# + {edwsmith,rreitmai}@adobe.com + + Intel Corporation$ + {mohammad.r.haghighat}@intel.com + + University of California, Irvine+ + {mbebenit,changm,franz}@uci.edu + +Abstract and is used for the application logic of browser-based productivity + applications such as Google Mail, Google Docs and Zimbra Col- +Dynamic languages such as JavaScript are more difficult to com- laboration Suite. In this domain, in order to provide a fluid user +pile than statically typed ones. Since no concrete type information experience and enable a new generation of applications, virtual ma- +is available, traditional compilers need to emit generic code that can chines must provide a low startup time and high performance. +handle all possible type combinations at runtime. We present an al- +ternative compilation technique for dynamically-typed languages Compilers for statically typed languages rely on type informa- +that identifies frequently executed loop traces at run-time and then tion to generate efficient machine code. In a dynamically typed pro- +generates machine code on the fly that is specialized for the ac- gramming language such as JavaScript, the types of expressions +tual dynamic types occurring on each path through the loop. Our may vary at runtime. This means that the compiler can no longer +method provides cheap inter-procedural type specialization, and an easily transform operations into machine instructions that operate +elegant and efficient way of incrementally compiling lazily discov- on one specific type. Without exact type information, the compiler +ered alternative paths through nested loops. We have implemented must emit slower generalized machine code that can deal with all +a dynamic compiler for JavaScript based on our technique and we potential type combinations. While compile-time static type infer- +have measured speedups of 10x and more for certain benchmark ence might be able to gather type information to generate opti- +programs. mized machine code, traditional static analysis is very expensive + and hence not well suited for the highly interactive environment of +Categories and Subject Descriptors D.3.4 [Programming Lan- a web browser. +guages]: Processors — Incremental compilers, code generation. + We present a trace-based compilation technique for dynamic +General Terms Design, Experimentation, Measurement, Perfor- languages that reconciles speed of compilation with excellent per- +mance. formance of the generated machine code. Our system uses a mixed- + mode execution approach: the system starts running JavaScript in a +Keywords JavaScript, just-in-time compilation, trace trees. fast-starting bytecode interpreter. As the program runs, the system + identifies hot (frequently executed) bytecode sequences, records +1. Introduction them, and compiles them to fast native code. We call such a se- + quence of instructions a trace. +Dynamic languages such as JavaScript, Python, and Ruby, are pop- +ular since they are expressive, accessible to non-experts, and make Unlike method-based dynamic compilers, our dynamic com- +deployment as easy as distributing a source file. They are used for piler operates at the granularity of individual loops. This design +small scripts as well as for complex applications. JavaScript, for choice is based on the expectation that programs spend most of +example, is the de facto standard for client-side web programming their time in hot loops. Even in dynamically typed languages, we + expect hot loops to be mostly type-stable, meaning that the types of +Permission to make digital or hard copies of all or part of this work for personal or values are invariant. (12) For example, we would expect loop coun- +classroom use is granted without fee provided that copies are not made or distributed ters that start as integers to remain integers for all iterations. When +for profit or commercial advantage and that copies bear this notice and the full citation both of these expectations hold, a trace-based compiler can cover +on the first page. To copy otherwise, to republish, to post on servers or to redistribute the program execution with a small number of type-specialized, ef- +to lists, requires prior specific permission and/or a fee. ficiently compiled traces. +PLDI’09, June 15–20, 2009, Dublin, Ireland. +Copyright c 2009 ACM 978-1-60558-392-1/09/06. . . $5.00 Each compiled trace covers one path through the program with + one mapping of values to types. When the VM executes a compiled + trace, it cannot guarantee that the same path will be followed + or that the same types will occur in subsequent loop iterations. + Hence, recording and compiling a trace speculates that the path and 1 for (var i = 2; i < 100; ++i) { +typing will be exactly as they were during recording for subsequent +iterations of the loop. 2 if (!primes[i]) + + Every compiled trace contains all the guards (checks) required 3 continue; +to validate the speculation. If one of the guards fails (if control +flow is different, or a value of a different type is generated), the 4 for (var k = i + i; i < 100; k += i) +trace exits. If an exit becomes hot, the VM can record a branch +trace starting at the exit to cover the new path. In this way, the VM 5 primes[k] = false; +records a trace tree covering all the hot paths through the loop. + 6} + Nested loops can be difficult to optimize for tracing VMs. In +a na¨ıve implementation, inner loops would become hot first, and Figure 1. Sample program: sieve of Eratosthenes. primes is +the VM would start tracing there. When the inner loop exits, the initialized to an array of 100 false values on entry to this code +VM would detect that a different branch was taken. The VM would snippet. +try to record a branch trace, and find that the trace reaches not the +inner loop header, but the outer loop header. At this point, the VM Interpret cold/blacklisted Symbol Key +could continue tracing until it reaches the inner loop header again, Bytecodes loop/exit Overhead +thus tracing the outer loop inside a trace tree for the inner loop. Interpreting +But this requires tracing a copy of the outer loop for every side exit loop +and type combination in the inner loop. In essence, this is a form edge Native +of unintended tail duplication, which can easily overflow the code +cache. Alternatively, the VM could simply stop tracing, and give up abort Monitor compiled trace +on ever tracing outer loops. recording ready + hot + We solve the nested loop problem by recording nested trace Record loop/exit Enter +trees. Our system traces the inner loop exactly as the na¨ıve version. LIR Trace Compiled Trace +The system stops extending the inner tree when it reaches an outer +loop, but then it starts a new trace at the outer loop header. When finish at loop edge with +the outer loop reaches the inner loop header, the system tries to call loop header same types +the trace tree for the inner loop. If the call succeeds, the VM records +the call to the inner tree as part of the outer trace and finishes Compile Execute +the outer trace as normal. In this way, our system can trace any LIR Trace Compiled Trace +number of loops nested to any depth without causing excessive tail +duplication. side exit, side exit to + no existing trace existing trace + These techniques allow a VM to dynamically translate a pro- +gram to nested, type-specialized trace trees. Because traces can Leave +cross function call boundaries, our techniques also achieve the ef- Compiled Trace +fects of inlining. Because traces have no internal control-flow joins, +they can be optimized in linear time by a simple compiler (10). Figure 2. State machine describing the major activities of Trace- +Thus, our tracing VM efficiently performs the same kind of op- Monkey and the conditions that cause transitions to a new activ- +timizations that would require interprocedural analysis in a static ity. In the dark box, TM executes JS as compiled traces. In the +optimization setting. This makes tracing an attractive and effective light gray boxes, TM executes JS in the standard interpreter. White +tool to type specialize even complex function call-rich code. boxes are overhead. Thus, to maximize performance, we need to + maximize time spent in the darkest box and minimize time spent in + We implemented these techniques for an existing JavaScript in- the white boxes. The best case is a loop where the types at the loop +terpreter, SpiderMonkey. We call the resulting tracing VM Trace- edge are the same as the types on entry–then TM can stay in native +Monkey. TraceMonkey supports all the JavaScript features of Spi- code until the loop is done. +derMonkey, with a 2x-20x speedup for traceable programs. + a set of industry benchmarks. The paper ends with conclusions in + This paper makes the following contributions: Section 9 and an outlook on future work is presented in Section 10. + + • We explain an algorithm for dynamically forming trace trees to 2. Overview: Example Tracing Run + cover a program, representing nested loops as nested trace trees. + This section provides an overview of our system by describing + • We explain how to speculatively generate efficient type-specialized how TraceMonkey executes an example program. The example + code for traces from dynamic language programs. program, shown in Figure 1, computes the first 100 prime numbers + with nested loops. The narrative should be read along with Figure 2, + • We validate our tracing techniques in an implementation based which describes the activities TraceMonkey performs and when it + on the SpiderMonkey JavaScript interpreter, achieving 2x-20x transitions between the loops. + speedups on many programs. + TraceMonkey always begins executing a program in the byte- + The remainder of this paper is organized as follows. Section 3 is code interpreter. Every loop back edge is a potential trace point. +a general overview of trace tree based compilation we use to cap- When the interpreter crosses a loop edge, TraceMonkey invokes +ture and compile frequently executed code regions. In Section 4 the trace monitor, which may decide to record or execute a native +we describe our approach of covering nested loops using a num- trace. At the start of execution, there are no compiled traces yet, so +ber of individual trace trees. In Section 5 we describe our trace- the trace monitor counts the number of times each loop back edge is +compilation based speculative type specialization approach we use executed until a loop becomes hot, currently after 2 crossings. Note +to generate efficient machine code from recorded bytecode traces. that the way our loops are compiled, the loop edge is crossed before +Our implementation of a dynamic type-specializing compiler for entering the loop, so the second crossing occurs immediately after +JavaScript is described in Section 6. Related work is discussed in the first iteration. +Section 8. In Section 7 we evaluate our dynamic compiler based on + Here is the sequence of events broken down by outer loop + iteration: + v0 := ld state[748] // load primes from the trace activation record + +st sp[0], v0 // store primes to interpreter stack + +v1 := ld state[764] // load k from the trace activation record + +v2 := i2f(v1) // convert k from int to double + +st sp[8], v1 // store k to interpreter stack + +st sp[16], 0 // store false to interpreter stack + +v3 := ld v0[4] // load class word for primes + +v4 := and v3, -4 // mask out object class tag for primes + +v5 := eq v4, Array // test whether primes is an array + +xf v5 // side exit if v5 is false + +v6 := js_Array_set(v0, v2, false) // call function to set array element + +v7 := eq v6, 0 // test return value from call + +xt v7 // side exit if js_Array_set returns false. + +Figure 3. LIR snippet for sample program. This is the LIR recorded for line 5 of the sample program in Figure 1. The LIR encodes +the semantics in SSA form using temporary variables. The LIR also encodes all the stores that the interpreter would do to its data stack. +Sometimes these stores can be optimized away as the stack locations are live only on exits to the interpreter. Finally, the LIR records guards +and side exits to verify the assumptions made in this recording: that primes is an array and that the call to set its element succeeds. + +mov edx, ebx(748) // load primes from the trace activation record +mov edi(0), edx // (*) store primes to interpreter stack +mov esi, ebx(764) // load k from the trace activation record +mov edi(8), esi // (*) store k to interpreter stack +mov edi(16), 0 // (*) store false to interpreter stack +mov eax, edx(4) // (*) load object class word for primes +and eax, -4 // (*) mask out object class tag for primes +cmp eax, Array // (*) test whether primes is an array +jne side_exit_1 // (*) side exit if primes is not an array +sub esp, 8 // bump stack for call alignment convention +push false // push last argument for call +push esi // push first argument for call +call js_Array_set // call function to set array element +add esp, 8 // clean up extra stack space +mov ecx, ebx // (*) created by register allocator +test eax, eax // (*) test return value of js_Array_set +je side_exit_2 // (*) side exit if call failed +... +side_exit_1: // restore ecx +mov ecx, ebp(-4) // restore esp +mov esp, ebp // jump to ret statement +jmp epilog + +Figure 4. x86 snippet for sample program. This is the x86 code compiled from the LIR snippet in Figure 3. Most LIR instructions compile +to a single x86 instruction. Instructions marked with (*) would be omitted by an idealized compiler that knew that none of the side exits +would ever be taken. The 17 instructions generated by the compiler compare favorably with the 100+ instructions that the interpreter would +execute for the same code snippet, including 4 indirect jumps. + + i=2. This is the first iteration of the outer loop. The loop on interpreter PC and the types of values match those observed when +lines 4-5 becomes hot on its second iteration, so TraceMonkey en- trace recording was started. The first trace in our example, T45, +ters recording mode on line 4. In recording mode, TraceMonkey covers lines 4 and 5. This trace can be entered if the PC is at line 4, +records the code along the trace in a low-level compiler intermedi- i and k are integers, and primes is an object. After compiling T45, +ate representation we call LIR. The LIR trace encodes all the oper- TraceMonkey returns to the interpreter and loops back to line 1. +ations performed and the types of all operands. The LIR trace also +encodes guards, which are checks that verify that the control flow i=3. Now the loop header at line 1 has become hot, so Trace- +and types are identical to those observed during trace recording. Monkey starts recording. When recording reaches line 4, Trace- +Thus, on later executions, if and only if all guards are passed, the Monkey observes that it has reached an inner loop header that al- +trace has the required program semantics. ready has a compiled trace, so TraceMonkey attempts to nest the + inner loop inside the current trace. The first step is to call the inner + TraceMonkey stops recording when execution returns to the trace as a subroutine. This executes the loop on line 4 to completion +loop header or exits the loop. In this case, execution returns to the and then returns to the recorder. TraceMonkey verifies that the call +loop header on line 4. was successful and then records the call to the inner trace as part of + the current trace. Recording continues until execution reaches line + After recording is finished, TraceMonkey compiles the trace to 1, and at which point TraceMonkey finishes and compiles a trace +native code using the recorded type information for optimization. for the outer loop, T16. +The result is a native code fragment that can be entered if the + i=4. On this iteration, TraceMonkey calls T16. Because i=4, the A trace records all its intermediate values in a small activation +if statement on line 2 is taken. This branch was not taken in the record area. To make variable accesses fast on trace, the trace also +original trace, so this causes T16 to fail a guard and take a side exit. imports local and global variables by unboxing them and copying +The exit is not yet hot, so TraceMonkey returns to the interpreter, them to its activation record. Thus, the trace can read and write +which executes the continue statement. these variables with simple loads and stores from a native activation + recording, independently of the boxing mechanism used by the + i=5. TraceMonkey calls T16, which in turn calls the nested trace interpreter. When the trace exits, the VM boxes the values from +T45. T16 loops back to its own header, starting the next iteration this native storage location and copies them back to the interpreter +without ever returning to the monitor. structures. + + i=6. On this iteration, the side exit on line 2 is taken again. This For every control-flow branch in the source program, the +time, the side exit becomes hot, so a trace T23,1 is recorded that recorder generates conditional exit LIR instructions. These instruc- +covers line 3 and returns to the loop header. Thus, the end of T23,1 tions exit from the trace if required control flow is different from +jumps directly to the start of T16. The side exit is patched so that what it was at trace recording, ensuring that the trace instructions +on future iterations, it jumps directly to T23,1. are run only if they are supposed to. We call these instructions + guard instructions. + At this point, TraceMonkey has compiled enough traces to cover +the entire nested loop structure, so the rest of the program runs Most of our traces represent loops and end with the special loop +entirely as native code. LIR instruction. This is just an unconditional branch to the top of + the trace. Such traces return only via guards. +3. Trace Trees + Now, we describe the key optimizations that are performed as +In this section, we describe traces, trace trees, and how they are part of recording LIR. All of these optimizations reduce complex +formed at run time. Although our techniques apply to any dynamic dynamic language constructs to simple typed constructs by spe- +language interpreter, we will describe them assuming a bytecode cializing for the current trace. Each optimization requires guard in- +interpreter to keep the exposition simple. structions to verify their assumptions about the state and exit the + trace if necessary. +3.1 Traces + Type specialization. +A trace is simply a program path, which may cross function call All LIR primitives apply to operands of specific types. Thus, +boundaries. TraceMonkey focuses on loop traces, that originate at LIR traces are necessarily type-specialized, and a compiler can +a loop edge and represent a single iteration through the associated easily produce a translation that requires no type dispatches. A +loop. typical bytecode interpreter carries tag bits along with each value, + and to perform any operation, must check the tag bits, dynamically + Similar to an extended basic block, a trace is only entered at dispatch, mask out the tag bits to recover the untagged value, +the top, but may have many exits. In contrast to an extended basic perform the operation, and then reapply tags. LIR omits everything +block, a trace can contain join nodes. Since a trace always only except the operation itself. +follows one single path through the original program, however, join A potential problem is that some operations can produce values +nodes are not recognizable as such in a trace and have a single of unpredictable types. For example, reading a property from an +predecessor node like regular nodes. object could yield a value of any type, not necessarily the type + observed during recording. The recorder emits guard instructions + A typed trace is a trace annotated with a type for every variable that conditionally exit if the operation yields a value of a different +(including temporaries) on the trace. A typed trace also has an entry type from that seen during recording. These guard instructions +type map giving the required types for variables used on the trace guarantee that as long as execution is on trace, the types of values +before they are defined. For example, a trace could have a type map match those of the typed trace. When the VM observes a side exit +(x: int, b: boolean), meaning that the trace may be entered along such a type guard, a new typed trace is recorded originating +only if the value of the variable x is of type int and the value of b at the side exit location, capturing the new type of the operation in +is of type boolean. The entry type map is much like the signature question. +of a function. Representation specialization: objects. In JavaScript, name + lookup semantics are complex and potentially expensive because + In this paper, we only discuss typed loop traces, and we will they include features like object inheritance and eval. To evaluate +refer to them simply as “traces”. The key property of typed loop an object property read expression like o.x, the interpreter must +traces is that they can be compiled to efficient machine code using search the property map of o and all of its prototypes and parents. +the same techniques used for typed languages. Property maps can be implemented with different data structures + (e.g., per-object hash tables or shared hash tables), so the search + In TraceMonkey, traces are recorded in trace-flavored SSA LIR process also must dispatch on the representation of each object +(low-level intermediate representation). In trace-flavored SSA (or found during search. TraceMonkey can simply observe the result of +TSSA), phi nodes appear only at the entry point, which is reached the search process and record the simplest possible LIR to access +both on entry and via loop edges. The important LIR primitives the property value. For example, the search might finds the value of +are constant values, memory loads and stores (by address and o.x in the prototype of o, which uses a shared hash-table represen- +offset), integer operators, floating-point operators, function calls, tation that places x in slot 2 of a property vector. Then the recorded +and conditional exits. Type conversions, such as integer to double, can generate LIR that reads o.x with just two or three loads: one to +are represented by function calls. This makes the LIR used by get the prototype, possibly one to get the property value vector, and +TraceMonkey independent of the concrete type system and type one more to get slot 2 from the vector. This is a vast simplification +conversion rules of the source language. The LIR operations are and speedup compared to the original interpreter code. Inheritance +generic enough that the backend compiler is language independent. relationships and object representations can change during execu- +Figure 3 shows an example LIR trace. tion, so the simplified code requires guard instructions that ensure + the object representation is the same. In TraceMonkey, objects’ rep- + Bytecode interpreters typically represent values in a various +complex data structures (e.g., hash tables) in a boxed format (i.e., +with attached type tag bits). Since a trace is intended to represent +efficient code that eliminates all that complexity, our traces oper- +ate on unboxed values in simple variables and arrays as much as +possible. + resentations are assigned an integer key called the object shape. Starting a tree. Tree trees always start at loop headers, because +Thus, the guard is a simple equality check on the object shape. they are a natural place to look for hot paths. In TraceMonkey, loop + headers are easy to detect–the bytecode compiler ensures that a + Representation specialization: numbers. JavaScript has no bytecode is a loop header iff it is the target of a backward branch. +integer type, only a Number type that is the set of 64-bit IEEE- TraceMonkey starts a tree when a given loop header has been exe- +754 floating-pointer numbers (“doubles”). But many JavaScript cuted a certain number of times (2 in the current implementation). +operators, in particular array accesses and bitwise operators, really Starting a tree just means starting recording a trace for the current +operate on integers, so they first convert the number to an integer, point and type map and marking the trace as the root of a tree. Each +and then convert any integer result back to a double.1 Clearly, a tree is associated with a loop header and type map, so there may be +JavaScript VM that wants to be fast must find a way to operate on several trees for a given loop header. +integers directly and avoid these conversions. + Closing the loop. Trace recording can end in several ways. + In TraceMonkey, we support two representations for numbers: Ideally, the trace reaches the loop header where it started with +integers and doubles. The interpreter uses integer representations the same type map as on entry. This is called a type-stable loop +as much as it can, switching for results that can only be represented iteration. In this case, the end of the trace can jump right to the +as doubles. When a trace is started, some values may be imported beginning, as all the value representations are exactly as needed to +and represented as integers. Some operations on integers require enter the trace. The jump can even skip the usual code that would +guards. For example, adding two integers can produce a value too copy out the state at the end of the trace and copy it back in to the +large for the integer representation. trace activation record to enter a trace. + In certain cases the trace might reach the loop header with a + Function inlining. LIR traces can cross function boundaries different type map. This scenario is sometime observed for the first +in either direction, achieving function inlining. Move instructions iteration of a loop. Some variables inside the loop might initially be +need to be recorded for function entry and exit to copy arguments undefined, before they are set to a concrete type during the first loop +in and return values out. These move statements are then optimized iteration. When recording such an iteration, the recorder cannot +away by the compiler using copy propagation. In order to be able link the trace back to its own loop header since it is type-unstable. +to return to the interpreter, the trace must also generate LIR to Instead, the iteration is terminated with a side exit that will always +record that a call frame has been entered and exited. The frame fail and return to the interpreter. At the same time a new trace is +entry and exit LIR saves just enough information to allow the recorded with the new type map. Every time an additional type- +intepreter call stack to be restored later and is much simpler than unstable trace is added to a region, its exit type map is compared to +the interpreter’s standard call code. If the function being entered the entry map of all existing traces in case they complement each +is not constant (which in JavaScript includes any call by function other. With this approach we are able to cover type-unstable loop +name), the recorder must also emit LIR to guard that the function iterations as long they eventually form a stable equilibrium. +is the same. Finally, the trace might exit the loop before reaching the loop + header, for example because execution reaches a break or return + Guards and side exits. Each optimization described above statement. In this case, the VM simply ends the trace with an exit +requires one or more guards to verify the assumptions made in to the trace monitor. +doing the optimization. A guard is just a group of LIR instructions As mentioned previously, we may speculatively chose to rep- +that performs a test and conditional exit. The exit branches to a resent certain Number-typed values as integers on trace. We do so +side exit, a small off-trace piece of LIR that returns a pointer to when we observe that Number-typed variables contain an integer +a structure that describes the reason for the exit along with the value at trace entry. If during trace recording the variable is unex- +interpreter PC at the exit point and any other data needed to restore pectedly assigned a non-integer value, we have to widen the type +the interpreter’s state structures. of the variable to a double. As a result, the recorded trace becomes + inherently type-unstable since it starts with an integer value but + Aborts. Some constructs are difficult to record in LIR traces. ends with a double value. This represents a mis-speculation, since +For example, eval or calls to external functions can change the at trace entry we specialized the Number-typed value to an integer, +program state in unpredictable ways, making it difficult for the assuming that at the loop edge we would again find an integer value +tracer to know the current type map in order to continue tracing. in the variable, allowing us to close the loop. To avoid future spec- +A tracing implementation can also have any number of other limi- ulative failures involving this variable, and to obtain a type-stable +tations, e.g.,a small-memory device may limit the length of traces. trace we note the fact that the variable in question as been observed +When any situation occurs that prevents the implementation from to sometimes hold non-integer values in an advisory data structure +continuing trace recording, the implementation aborts trace record- which we call the “oracle”. +ing and returns to the trace monitor. When compiling loops, we consult the oracle before specializ- + ing values to integers. Speculation towards integers is performed +3.2 Trace Trees only if no adverse information is known to the oracle about that + particular variable. Whenever we accidentally compile a loop that +Especially simple loops, namely those where control flow, value is type-unstable due to mis-speculation of a Number-typed vari- +types, value representations, and inlined functions are all invariant, able, we immediately trigger the recording of a new trace, which +can be represented by a single trace. But most loops have at least based on the now updated oracle information will start with a dou- +some variation, and so the program will take side exits from the ble value and thus become type stable. +main trace. When a side exit becomes hot, TraceMonkey starts a Extending a tree. Side exits lead to different paths through +new branch trace from that point and patches the side exit to jump the loop, or paths with different types or representations. Thus, to +directly to that trace. In this way, a single trace expands on demand completely cover the loop, the VM must record traces starting at all +to a single-entry, multiple-exit trace tree. side exits. These traces are recorded much like root traces: there is + a counter for each side exit, and when the counter reaches a hotness + This section explains how trace trees are formed during execu- threshold, recording starts. Recording stops exactly as for the root +tion. The goal is to form trace trees during execution that cover all trace, using the loop header of the root trace as the target to reach. +the hot paths of the program. + +1 Arrays are actually worse than this: if the index value is a number, it must +be converted from a double to a string for the property access operator, and +then to an integer internally to the array implementation. + Our implementation does not extend at all side exits. It extends T +only if the side exit is for a control-flow branch, and only if the side +exit does not leave the loop. In particular we do not want to extend Tree
Anchor +a trace tree along a path that leads to an outer loop, because we Trunk
Trace +want to cover such paths in an outer tree through tree nesting. Trace
Anchor + Branch
Trace +3.3 Blacklisting + Guard +Sometimes, a program follows a path that cannot be compiled Side
Exit +into a trace, usually because of limitations in the implementation. +TraceMonkey does not currently support recording throwing and Figure 5. A tree with two traces, a trunk trace and one branch +catching of arbitrary exceptions. This design trade off was chosen, trace. The trunk trace contains a guard to which a branch trace was +because exceptions are usually rare in JavaScript. However, if a attached. The branch trace contain a guard that may fail and trigger +program opts to use exceptions intensively, we would suddenly a side exit. Both the trunk and the branch trace loop back to the tree +incur a punishing runtime overhead if we repeatedly try to record anchor, which is the beginning of the trace tree. +a trace for this path and repeatedly fail to do so, since we abort +tracing every time we observe an exception being thrown. Trace
1 Trace
2 Trace
1 Trace
2 + Number Boolean Number Boolean + As a result, if a hot loop contains traces that always fail, the VM +could potentially run much more slowly than the base interpreter: Number Number Boolean Number +the VM repeatedly spends time trying to record traces, but is never +able to run any. To avoid this problem, whenever the VM is about Closed Linked Linked Linked +to start tracing, it must try to predict whether it will finish the trace. + (a) (b) + Our prediction algorithm is based on blacklisting traces that +have been tried and failed. When the VM fails to finish a trace start- Trace
1 Trace
2 Trace
3 +ing at a given point, the VM records that a failure has occurred. The +VM also sets a counter so that it will not try to record a trace starting Number Boolean String +at that point until it is passed a few more times (32 in our imple- +mentation). This backoff counter gives temporary conditions that Number String String +prevent tracing a chance to end. For example, a loop may behave Closed +differently during startup than during its steady-state execution. Af- String Linked Linked +ter a given number of failures (2 in our implementation), the VM Linked +marks the fragment as blacklisted, which means the VM will never (c) +again start recording at that point. + Figure 6. We handle type-unstable loops by allowing traces to + After implementing this basic strategy, we observed that for compile that cannot loop back to themselves due to a type mis- +small loops that get blacklisted, the system can spend a noticeable match. As such traces accumulate, we attempt to connect their loop +amount of time just finding the loop fragment and determining that edges to form groups of trace trees that can execute without having +it has been blacklisted. We now avoid that problem by patching the to side-exit to the interpreter to cover odd type cases. This is par- +bytecode. We define an extra no-op bytecode that indicates a loop ticularly important for nested trace trees where an outer tree tries to +header. The VM calls into the trace monitor every time the inter- call an inner tree (or in this case a forest of inner trees), since inner +preter executes a loop header no-op. To blacklist a fragment, we loops frequently have initially undefined values which change type +simply replace the loop header no-op with a regular no-op. Thus, to a concrete value after the first iteration. +the interpreter will never again even call into the trace monitor. + through the inner loop, {i2, i3, i5, α}. The α symbol is used to + There is a related problem we have not yet solved, which occurs indicate that the trace loops back the tree anchor. +when a loop meets all of these conditions: + When execution leaves the inner loop, the basic design has two + • The VM can form at least one root trace for the loop. choices. First, the system can stop tracing and give up on compiling + the outer loop, clearly an undesirable solution. The other choice is + • There is at least one hot side exit for which the VM cannot to continue tracing, compiling traces for the outer loop inside the + complete a trace. inner loop’s trace tree. + + • The loop body is short. For example, the program might exit at i5 and record a branch + trace that incorporates the outer loop: {i5, i7, i1, i6, i7, i1, α}. + In this case, the VM will repeatedly pass the loop header, search Later, the program might take the other branch at i2 and then +for a trace, find it, execute it, and fall back to the interpreter. exit, recording another branch trace incorporating the outer loop: +With a short loop body, the overhead of finding and calling the {i2, i4, i5, i7, i1, i6, i7, i1, α}. Thus, the outer loop is recorded and +trace is high, and causes performance to be even slower than the compiled twice, and both copies must be retained in the trace cache. +basic interpreter. So far, in this situation we have improved the +implementation so that the VM can complete the branch trace. +But it is hard to guarantee that this situation will never happen. +As future work, this situation could be avoided by detecting and +blacklisting loops for which the average trace call executes few +bytecodes before returning to the interpreter. + +4. Nested Trace Tree Formation + +Figure 7 shows basic trace tree compilation (11) applied to a nested +loop where the inner loop contains two paths. Usually, the inner +loop (with header at i2) becomes hot first, and a trace tree is rooted +at that point. For example, the first recorded trace may be a cycle + i1 Outer
Tree i1 t1 + i2 t1 + Nested
Tree + Tree
Call + Nested
Tree i2 t2 + t2 + i3 + Exit
Guard +i6 i3 i4 + + Exit
Guard + + i4 t4 + + i5 + + i5 + + i7 + + i6 + + (a) (b) + +Figure 7. Control flow graph of a nested loop with an if statement Figure 8. Control flow graph of a loop with two nested loops (left) +inside the inner most loop (a). An inner tree captures the inner and its nested trace tree configuration (right). The outer tree calls +loop, and is nested inside an outer tree which “calls” the inner tree. the two inner nested trace trees and places guards at their side exit +The inner tree returns to the outer tree once it exits along its loop locations. +condition guard (b). + loop is entered with m different type maps (on geometric average), +In general, if loops are nested to depth k, and each loop has n paths then we compile O(mk) copies of the innermost loop. As long as +(on geometric average), this na¨ıve strategy yields O(nk) traces, m is close to 1, the resulting trace trees will be tractable. +which can easily fill the trace cache. + An important detail is that the call to the inner trace tree must act + In order to execute programs with nested loops efficiently, a like a function call site: it must return to the same point every time. +tracing system needs a technique for covering the nested loops with The goal of nesting is to make inner and outer loops independent; +native code without exponential trace duplication. thus when the inner tree is called, it must exit to the same point + in the outer tree every time with the same type map. Because we +4.1 Nesting Algorithm cannot actually guarantee this property, we must guard on it after + the call, and side exit if the property does not hold. A common +The key insight is that if each loop is represented by its own trace reason for the inner tree not to return to the same point would +tree, the code for each loop can be contained only in its own tree, be if the inner tree took a new side exit for which it had never +and outer loop paths will not be duplicated. Another key fact is that compiled a trace. At this point, the interpreter PC is in the inner +we are not tracing arbitrary bytecodes that might have irreduceable tree, so we cannot continue recording or executing the outer tree. +control flow graphs, but rather bytecodes produced by a compiler If this happens during recording, we abort the outer trace, to give +for a language with structured control flow. Thus, given two loop the inner tree a chance to finish growing. A future execution of the +edges, the system can easily determine whether they are nested outer tree would then be able to properly finish and record a call to +and which is the inner loop. Using this knowledge, the system can the inner tree. If an inner tree side exit happens during execution of +compile inner and outer loops separately, and make the outer loop’s a compiled trace for the outer tree, we simply exit the outer trace +traces call the inner loop’s trace tree. and start recording a new branch in the inner tree. + + The algorithm for building nested trace trees is as follows. We 4.2 Blacklisting with Nesting +start tracing at loop headers exactly as in the basic tracing system. +When we exit a loop (detected by comparing the interpreter PC The blacklisting algorithm needs modification to work well with +with the range given by the loop edge), we stop the trace. The nesting. The problem is that outer loop traces often abort during +key step of the algorithm occurs when we are recording a trace startup (because the inner tree is not available or takes a side exit), +for loop LR (R for loop being recorded) and we reach the header which would lead to their being quickly blacklisted by the basic +of a different loop LO (O for other loop). Note that LO must be an algorithm. +inner loop of LR because we stop the trace when we exit a loop. + The key observation is that when an outer trace aborts because + • If LO has a type-matching compiled trace tree, we call LO as the inner tree is not ready, this is probably a temporary condition. + a nested trace tree. If the call succeeds, then we record the call Thus, we should not count such aborts toward blacklisting as long + in the trace for LR. On future executions, the trace for LR will as we are able to build up more traces for the inner tree. + call the inner trace directly. + In our implementation, when an outer tree aborts on the inner + • If LO does not have a type-matching compiled trace tree yet, tree, we increment the outer tree’s blacklist counter as usual and + we have to obtain it before we are able to proceed. In order back off on compiling it. When the inner tree finishes a trace, we + to do this, we simply abort recording the first trace. The trace decrement the blacklist counter on the outer loop, “forgiving” the + monitor will see the inner loop header, and will immediately outer loop for aborting previously. We also undo the backoff so that + start recording the inner loop. 2 the outer tree can start immediately trying to compile the next time + we reach it. + If all the loops in a nest are type-stable, then loop nesting creates +no duplication. Otherwise, if loops are nested to a depth k, and each 5. Trace Tree Optimization + +2 Instead of aborting the outer recording, we could principally merely sus- This section explains how a recorded trace is translated to an +pend the recording, but that would require the implementation to be able optimized machine code trace. The trace compilation subsystem, +to record several traces simultaneously, complicating the implementation, NANOJIT, is separate from the VM and can be used for other +while saving only a few iterations in the interpreter. applications. + 5.1 Optimizations Tag JS Type Description + +Because traces are in SSA form and have no join points or φ- xx1 number 31-bit integer representation +nodes, certain optimizations are easy to implement. In order to +get good startup performance, the optimizations must run quickly, 000 object pointer to JSObject handle +so we chose a small set of optimizations. We implemented the +optimizations as pipelined filters so that they can be turned on and 010 number pointer to double handle +off independently, and yet all run in just two loop passes over the +trace: one forward and one backward. 100 string pointer to JSString handle + + Every time the trace recorder emits a LIR instruction, the in- 110 boolean enumeration for null, undefined, true, false +struction is immediately passed to the first filter in the forward +pipeline. Thus, forward filter optimizations are performed as the null, or +trace is recorded. Each filter may pass each instruction to the next +filter unchanged, write a different instruction to the next filter, or undefined +write no instruction at all. For example, the constant folding filter +can replace a multiply instruction like v13 := mul3, 1000 with a Figure 9. Tagged values in the SpiderMonkey JS interpreter. +constant instruction v13 = 3000. Testing tags, unboxing (extracting the untagged value) and boxing + (creating tagged values) are significant costs. Avoiding these costs + We currently apply four forward filters: is a key benefit of tracing. + + • On ISAs without floating-point instructions, a soft-float filter heuristic selects v with minimum vm. The motivation is that this + converts floating-point LIR instructions to sequences of integer frees up a register for as long as possible given a single spill. + instructions. + If we need to spill a value vs at this point, we generate the + • CSE (constant subexpression elimination), restore code just after the code for the current instruction. The + corresponding spill code is generated just after the last point where + • expression simplification, including constant folding and a few vs was used. The register that was assigned to vs is marked free for + algebraic identities (e.g., a − a = 0), and the preceding code, because that register can now be used freely + without affecting the following code + • source language semantic-specific expression simplification, + primarily algebraic identities that allow DOUBLE to be replaced 6. Implementation + with INT. For example, LIR that converts an INT to a DOUBLE + and then back again would be removed by this filter. To demonstrate the effectiveness of our approach, we have im- + plemented a trace-based dynamic compiler for the SpiderMonkey + When trace recording is completed, nanojit runs the backward JavaScript Virtual Machine (4). SpiderMonkey is the JavaScript +optimization filters. These are used for optimizations that require VM embedded in Mozilla’s Firefox open-source web browser (2), +backward program analysis. When running the backward filters, which is used by more than 200 million users world-wide. The core +nanojit reads one LIR instruction at a time, and the reads are passed of SpiderMonkey is a bytecode interpreter implemented in C++. +through the pipeline. + In SpiderMonkey, all JavaScript values are represented by the + We currently apply three backward filters: type jsval. A jsval is machine word in which up to the 3 of the + least significant bits are a type tag, and the remaining bits are data. + • Dead data-stack store elimination. The LIR trace encodes many See Figure 6 for details. All pointers contained in jsvals point to + stores to locations in the interpreter stack. But these values are GC-controlled blocks aligned on 8-byte boundaries. + never read back before exiting the trace (by the interpreter or + another trace). Thus, stores to the stack that are overwritten JavaScript object values are mappings of string-valued property + before the next exit are dead. Stores to locations that are off names to arbitrary values. They are represented in one of two ways + the top of the interpreter stack at future exits are also dead. in SpiderMonkey. Most objects are represented by a shared struc- + tural description, called the object shape, that maps property names + • Dead call-stack store elimination. This is the same optimization to array indexes using a hash table. The object stores a pointer to + as above, except applied to the interpreter’s call stack used for the shape and the array of its own property values. Objects with + function call inlining. large, unique sets of property names store their properties directly + in a hash table. + • Dead code elimination. This eliminates any operation that + stores to a value that is never used. The garbage collector is an exact, non-generational, stop-the- + world mark-and-sweep collector. + After a LIR instruction is successfully read (“pulled”) from +the backward filter pipeline, nanojit’s code generator emits native In the rest of this section we discuss key areas of the TraceMon- +machine instruction(s) for it. key implementation. + +5.2 Register Allocation 6.1 Calling Compiled Traces + +We use a simple greedy register allocator that makes a single Compiled traces are stored in a trace cache, indexed by intepreter +backward pass over the trace (it is integrated with the code gen- PC and type map. Traces are compiled so that they may be +erator). By the time the allocator has reached an instruction like called as functions using standard native calling conventions (e.g., +v3 = add v1, v2, it has already assigned a register to v3. If v1 and FASTCALL on x86). +v2 have not yet been assigned registers, the allocator assigns a free +register to each. If there are no free registers, a value is selected for The interpreter must hit a loop edge and enter the monitor in +spilling. We use a class heuristic that selects the “oldest” register- order to call a native trace for the first time. The monitor computes +carried value (6). the current type map, checks the trace cache for a trace for the + current PC and type map, and if it finds one, executes the trace. + The heuristic considers the set R of values v in registers imme- +diately after the current instruction for spilling. Let vm be the last To execute a trace, the monitor must build a trace activation +instruction before the current where each v is referred to. Then the record containing imported local and global variables, temporary + stack space, and space for arguments to native calls. The local and + global values are then copied from the interpreter state to the trace + activation record. Then, the trace is called like a normal C function + pointer. + When a trace call returns, the monitor restores the interpreter Recording is activated by a pointer swap that sets the inter- +state. First, the monitor checks the reason for the trace exit and preter’s dispatch table to call a single “interrupt” routine for ev- +applies blacklisting if needed. Then, it pops or synthesizes inter- ery bytecode. The interrupt routine first calls a bytecode-specific +preter JavaScript call stack frames as needed. Finally, it copies the recording routine. Then, it turns off recording if necessary (e.g., +imported variables back from the trace activation record to the in- the trace ended). Finally, it jumps to the standard interpreter byte- +terpreter state. code implementation. Some bytecodes have effects on the type map + that cannot be predicted before executing the bytecode (e.g., call- + At least in the current implementation, these steps have a non- ing String.charCodeAt, which returns an integer or NaN if the +negligible runtime cost, so minimizing the number of interpreter- index argument is out of range). For these, we arrange for the inter- +to-trace and trace-to-interpreter transitions is essential for perfor- preter to call into the recorder again after executing the bytecode. +mance. (see also Section 3.3). Our experiments (see Figure 12) Since such hooks are relatively rare, we embed them directly into +show that for programs we can trace well such transitions hap- the interpreter, with an additional runtime check to see whether a +pen infrequently and hence do not contribute significantly to total recorder is currently active. +runtime. In a few programs, where the system is prevented from +recording branch traces for hot side exits by aborts, this cost can While separating the interpreter from the recorder reduces indi- +rise to up to 10% of total execution time. vidual code complexity, it also requires careful implementation and + extensive testing to achieve semantic equivalence. +6.2 Trace Stitching + In some cases achieving this equivalence is difficult since Spi- +Transitions from a trace to a branch trace at a side exit avoid the derMonkey follows a fat-bytecode design, which was found to be +costs of calling traces from the monitor, in a feature called trace beneficial to pure interpreter performance. +stitching. At a side exit, the exiting trace only needs to write live +register-carried values back to its trace activation record. In our im- In fat-bytecode designs, individual bytecodes can implement +plementation, identical type maps yield identical activation record complex processing (e.g., the getprop bytecode, which imple- +layouts, so the trace activation record can be reused immediately ments full JavaScript property value access, including special cases +by the branch trace. for cached and dense array access). + + In programs with branchy trace trees with small traces, trace Fat bytecodes have two advantages: fewer bytecodes means +stitching has a noticeable cost. Although writing to memory and lower dispatch cost, and bigger bytecode implementations give the +then soon reading back would be expected to have a high L1 compiler more opportunities to optimize the interpreter. +cache hit rate, for small traces the increased instruction count has +a noticeable cost. Also, if the writes and reads are very close Fat bytecodes are a problem for TraceMonkey because they +in the dynamic instruction stream, we have found that current require the recorder to reimplement the same special case logic +x86 processors often incur penalties of 6 cycles or more (e.g., if in the same way. Also, the advantages are reduced because (a) +the instructions use different base registers with equal values, the dispatch costs are eliminated entirely in compiled traces, (b) the +processor may not be able to detect that the addresses are the same traces contain only one special case, not the interpreter’s large +right away). chunk of code, and (c) TraceMonkey spends less time running the + base interpreter. + The alternate solution is to recompile an entire trace tree, thus +achieving inter-trace register allocation (10). The disadvantage is One way we have mitigated these problems is by implementing +that tree recompilation takes time quadratic in the number of traces. certain complex bytecodes in the recorder as sequences of simple +We believe that the cost of recompiling a trace tree every time bytecodes. Expressing the original semantics this way is not too dif- +a branch is added would be prohibitive. That problem might be ficult, and recording simple bytecodes is much easier. This enables +mitigated by recompiling only at certain points, or only for very us to retain the advantages of fat bytecodes while avoiding some of +hot, stable trees. their problems for trace recording. This is particularly effective for + fat bytecodes that recurse back into the interpreter, for example to + In the future, multicore hardware is expected to be common, convert an object into a primitive value by invoking a well-known +making background tree recompilation attractive. In a closely re- method on the object, since it lets us inline this function call. +lated project (13) background recompilation yielded speedups of +up to 1.25x on benchmarks with many branch traces. We plan to It is important to note that we split fat opcodes into thinner op- +apply this technique to TraceMonkey as future work. codes only during recording. When running purely interpretatively + (i.e. code that has been blacklisted), the interpreter directly and ef- +6.3 Trace Recording ficiently executes the fat opcodes. + +The job of the trace recorder is to emit LIR with identical semantics 6.4 Preemption +to the currently running interpreter bytecode trace. A good imple- +mentation should have low impact on non-tracing interpreter per- SpiderMonkey, like many VMs, needs to preempt the user program +formance and a convenient way for implementers to maintain se- periodically. The main reasons are to prevent infinitely looping +mantic equivalence. scripts from locking up the host system and to schedule GC. + + In our implementation, the only direct modification to the inter- In the interpreter, this had been implemented by setting a “pre- +preter is a call to the trace monitor at loop edges. In our benchmark empt now” flag that was checked on every backward jump. This +results (see Figure 12) the total time spent in the monitor (for all strategy carried over into TraceMonkey: the VM inserts a guard on +activities) is usually less than 5%, so we consider the interpreter the preemption flag at every loop edge. We measured less than a +impact requirement met. Incrementing the loop hit counter is ex- 1% increase in runtime on most benchmarks for this extra guard. +pensive because it requires us to look up the loop in the trace cache, In practice, the cost is detectable only for programs with very short +but we have tuned our loops to become hot and trace very quickly loops. +(on the second iteration). The hit counter implementation could be +improved, which might give us a small increase in overall perfor- We tested and rejected a solution that avoided the guards by +mance, as well as more flexibility with tuning hotness thresholds. compiling the loop edge as an unconditional jump, and patching +Once a loop is blacklisted we never call into the trace monitor for the jump target to an exit routine when preemption is required. +that loop (see Section 3.3). This solution can make the normal case slightly faster, but then + preemption becomes very slow. The implementation was also very + complex, especially trying to restart execution after the preemption. + 6.5 Calling External Functions ?>9@AJ.D2.@A:0>#3$4,56# + ?>9@AJ.0A:9@AJ.>9@AJ.B<#3$4(56# +dard signature for JS-callable functions, the key argument of which +is an array of boxed values. External functions called through the ?>9@AJ.1;.?:2/>9;.:<9I;./89-@/#3'4,56# +order to speed up code that interacts with the host system inside hot -<>2.B897<>.5:<91#3$4!56# +loops. -<>2.B897<>.>8H2#3$4$56# + /9=:>8.?;<$#3(4,56# + Calling external functions from TraceMonkey is potentially dif- /9=:>8.7-(#3%4&56# +ficult because traces do not update the interpreter state until exit- /9=:>8.<2?#3$4)56# +ing. In particular, external functions may need the call stack or the +global variables, but they may be out of date. /8A>98FG8E.92/09?@D2#3$4!56# + 1@>8:?.A?@2D2.1@>?#3%4*56# + For the out-of-date call stack problem, we refactored some of +the interpreter API implementation functions to re-materialize the 1@>8:?.1@>E@?2.8:?.1@>?.@A.1=>2#3+4*56# + + We developed a C++ static analysis and annotated some inter- 1@>8:?.&1@>.1@>?.@A.1=>2#3%(4(56# +preter functions in order to verify that the call stack is refreshed 922?#3!4,56# +stack transitively. FORCESSTACK is a trusted annotation, applied +to only 5 functions, that means the function refreshes the call stack. &-.9<=>929:92># L?J+B:F>*:?7-<#0(1923# $!"# %!"# &!"# '!"# (!!"# erate native code with nearly the same structure but better perfor- + =<6>?J+-?7:,A+,5*/#0(1$23# N:FF#O6:,/# mance. + + =<6>?J+<:J,F5-*#0(1(23# Call threading, also known as context threading (8), compiles + =<6>?J+@:=<:#0(1C23# methods by generating a native call instruction to an interpreter + method for each interpreter bytecode. A call-return pair has been + =<6>?J+.:=/&%#0$1C23# shown to be a potentially much more efficient dispatch mechanism + 6/J/27+*?:#0%1$23# than the indirect jumps used in standard bytecode interpreters. + + 4:<8+=7/,<6:F+?564#0D1(23# Inline threading (15) copies chunks of interpreter native code + 4:<8+7:6I:F+=-4=#0C1923# which implement the required bytecodes into a native code cache, + 4:<8+,56*>,#0%1923# thus acting as a simple per-method JIT compiler that eliminates the + *:B/#0(1!23# tion based on call threading with selective inline threading. Com- + .><57=+?=>/B/+.><=#0$1D23# bined with efficient interpreter engineering, these threading tech- + niques have given SFX excellent performance on the standard Sun- + .><57=+.>=/+:?*#0$C1$23# Spider benchmarks. + .><57=+.><=+>?+.;<57=+).><+.><=+>?+.;/B/#0)1!23# operations. + :,,/==+?.5*;#0%1$23# + 9. Conclusions + :,,/==+@:??A-,8#0$1$23# + :,,/==+.>?:6;+<6//=#0!1923# This paper described how to run dynamic languages efficiently by + recording hot traces and generating type-specialized native code. + )*+6:;<6:,/#0(1$23# Our technique focuses on aggressively inlined loops, and for each + )*+45678#0$1923# loop, it generates a tree of native code traces representing the + )*+,-./#0$1$23# paths and value types through the loop observed at run time. We + explained how to identify loop nesting relationships and generate + !"# nested traces in order to avoid excessive code duplication due + to the many paths through a loop nest. We described our type +K?<56# M/,56*# N547>F/# M-?#O6:,/# specialization algorithm. We also described our trace compiler, + which translates a trace from an intermediate representation to +Figure 12. Fraction of time spent on major VM activities. The optimized native code in two linear passes. +speedup vs. interpreter is shown in parentheses next to each test. +Most programs where the VM spends the majority of its time run- Our experimental results show that in practice loops typically +ning native code have a good speedup. Recording and compilation are entered with only a few different combinations of value types +costs can be substantial; speeding up those parts of the implemen- of variables. Thus, a small number of traces per loop is sufficient +tation would improve SunSpider performance. to run a program efficiently. Our experiments also show that on + programs amenable to tracing, we achieve speedups of 2x to 20x. +inner loops become hot first), leading to much greater tail duplica- +tion. 10. Future Work + + YETI, from Zaleski et al. (19) applied Dynamo-style tracing Work is underway in a number of areas to further improve the +to Java in order to achieve inlining, indirect jump elimination, performance of our trace-based JavaScript compiler. We currently +and other optimizations. Their primary focus was on designing an do not trace across recursive function calls, but plan to add the +interpreter that could easily be gradually re-engineered as a tracing support for this capability in the near term. We are also exploring +VM. adoption of the existing work on tree recompilation in the context + of the presented dynamic compiler in order to minimize JIT pause + Suganuma et al. (18) described region-based compilation (RBC), times and obtain the best of both worlds, fast tree stitching as well +a relative of tracing. A region is an subprogram worth optimizing as the improved code quality due to tree recompilation. +that can include subsets of any number of methods. Thus, the com- +piler has more flexibility and can potentially generate better code, We also plan on adding support for tracing across regular ex- +but the profiling and compilation systems are correspondingly more pression substitutions using lambda functions, function applica- +complex. tions and expression evaluation using eval. All these language + constructs are currently executed via interpretation, which limits + Type specialization for dynamic languages. Dynamic lan- our performance for applications that use those features. +guage implementors have long recognized the importance of type +specialization for performance. Most previous work has focused on Acknowledgments +methods instead of traces. + Parts of this effort have been sponsored by the National Science + Chambers et. al (9) pioneered the idea of compiling multiple Foundation under grants CNS-0615443 and CNS-0627747, as well +versions of a procedure specialized for the input types in the lan- as by the California MICRO Program and industrial sponsor Sun +guage Self. In one implementation, they generated a specialized Microsystems under Project No. 07-127. +method online each time a method was called with new input types. +In another, they used an offline whole-program static analysis to The U.S. Government is authorized to reproduce and distribute +infer input types and constant receiver types at call sites. Interest- reprints for Governmental purposes notwithstanding any copyright +ingly, the two techniques produced nearly the same performance. annotation thereon. Any opinions, findings, and conclusions or rec- + ommendations expressed here are those of the author and should + Salib (17) designed a type inference algorithm for Python based +on the Cartesian Product Algorithm and used the results to special- +ize on types and translate the program to C++. + + McCloskey (14) has work in progress based on a language- +independent type inference that is used to generate efficient C +implementations of JavaScript and Python programs. + + Native code generation by interpreters. The traditional inter- +preter design is a virtual machine that directly executes ASTs or +machine-code-like bytecodes. Researchers have shown how to gen- + not be interpreted as necessarily representing the official views, [10] A. Gal. Efficient Bytecode Verification and Compilation in a Virtual +policies or endorsements, either expressed or implied, of the Na- Machine Dissertation. PhD thesis, University Of California, Irvine, +tional Science foundation (NSF), any other agency of the U.S. Gov- 2006. +ernment, or any of the companies mentioned above. + [11] A. Gal, C. W. Probst, and M. Franz. HotpathVM: An effective JIT +References compiler for resource-constrained devices. In Proceedings of the + International Conference on Virtual Execution Environments, pages +[1] LuaJIT roadmap 2008 - http://lua-users.org/lists/lua-l/2008- 144–153. ACM Press, 2006. + 02/msg00051.html. + [12] C. Garrett, J. Dean, D. Grove, and C. Chambers. Measurement and +[2] Mozilla — Firefox web browser and Thunderbird email client - Application of Dynamic Receiver Class Distributions. 1994. + http://www.mozilla.com. + [13] J. Ha, M. R. Haghighat, S. Cong, and K. S. McKinley. A concurrent +[3] SPECJVM98 - http://www.spec.org/jvm98/. trace-based just-in-time compiler for javascript. Dept.of Computer + Sciences, The University of Texas at Austin, TR-09-06, 2009. +[4] SpiderMonkey (JavaScript-C) Engine - + [14] B. McCloskey. Personal communication. +http://www.mozilla.org/js/spidermonkey/. + [15] I. Piumarta and F. Riccardi. Optimizing direct threaded code by selec- +[5] Surfin’ Safari - Blog Archive - Announcing SquirrelFish Extreme - tive inlining. In Proceedings of the ACM SIGPLAN 1998 conference + http://webkit.org/blog/214/introducing-squirrelfish-extreme/. on Programming language design and implementation, pages 291– + 300. ACM New York, NY, USA, 1998. +[6] A. Aho, R. Sethi, J. Ullman, and M. Lam. Compilers: Principles, + techniques, and tools, 2006. [16] A. Rigo. Representation-Based Just-In-time Specialization and the + Psyco Prototype for Python. In PEPM, 2004. +[7] V. Bala, E. Duesterwald, and S. Banerjia. Dynamo: A transparent + dynamic optimization system. In Proceedings of the ACM SIGPLAN [17] M. Salib. Starkiller: A Static Type Inferencer and Compiler for + Conference on Programming Language Design and Implementation, Python. In Master’s Thesis, 2004. + pages 1–12. ACM Press, 2000. + [18] T. Suganuma, T. Yasue, and T. Nakatani. A Region-Based Compila- +[8] M. Berndl, B. Vitale, M. Zaleski, and A. Brown. Context Threading: tion Technique for Dynamic Compilers. ACM Transactions on Pro- + a Flexible and Efficient Dispatch Technique for Virtual Machine In- gramming Languages and Systems (TOPLAS), 28(1):134–174, 2006. + terpreters. In Code Generation and Optimization, 2005. CGO 2005. + International Symposium on, pages 15–26, 2005. [19] M. Zaleski, A. D. Brown, and K. Stoodley. YETI: A graduallY + Extensible Trace Interpreter. In Proceedings of the International +[9] C. Chambers and D. Ungar. Customization: Optimizing Compiler Conference on Virtual Execution Environments, pages 83–93. ACM + Technology for SELF, a Dynamically-Typed O bject-Oriented Pro- Press, 2007. + gramming Language. In Proceedings of the ACM SIGPLAN 1989 + Conference on Programming Language Design and Implementation, + pages 146–160. ACM New York, NY, USA, 1989. + diff --git a/src/main/resources/static/generic/web/debugger.js b/src/main/resources/static/generic/web/debugger.js new file mode 100644 index 0000000..046fd34 --- /dev/null +++ b/src/main/resources/static/generic/web/debugger.js @@ -0,0 +1,620 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * 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. + */ +/* globals PDFJS */ + +'use strict'; + +var FontInspector = (function FontInspectorClosure() { + var fonts; + var active = false; + var fontAttribute = 'data-font-name'; + function removeSelection() { + var divs = document.querySelectorAll('div[' + fontAttribute + ']'); + for (var i = 0, ii = divs.length; i < ii; ++i) { + var div = divs[i]; + div.className = ''; + } + } + function resetSelection() { + var divs = document.querySelectorAll('div[' + fontAttribute + ']'); + for (var i = 0, ii = divs.length; i < ii; ++i) { + var div = divs[i]; + div.className = 'debuggerHideText'; + } + } + function selectFont(fontName, show) { + var divs = document.querySelectorAll('div[' + fontAttribute + '=' + + fontName + ']'); + for (var i = 0, ii = divs.length; i < ii; ++i) { + var div = divs[i]; + div.className = show ? 'debuggerShowText' : 'debuggerHideText'; + } + } + function textLayerClick(e) { + if (!e.target.dataset.fontName || + e.target.tagName.toUpperCase() !== 'DIV') { + return; + } + var fontName = e.target.dataset.fontName; + var selects = document.getElementsByTagName('input'); + for (var i = 0; i < selects.length; ++i) { + var select = selects[i]; + if (select.dataset.fontName !== fontName) { + continue; + } + select.checked = !select.checked; + selectFont(fontName, select.checked); + select.scrollIntoView(); + } + } + return { + // Properties/functions needed by PDFBug. + id: 'FontInspector', + name: 'Font Inspector', + panel: null, + manager: null, + init: function init() { + var panel = this.panel; + panel.setAttribute('style', 'padding: 5px;'); + var tmp = document.createElement('button'); + tmp.addEventListener('click', resetSelection); + tmp.textContent = 'Refresh'; + panel.appendChild(tmp); + + fonts = document.createElement('div'); + panel.appendChild(fonts); + }, + cleanup: function cleanup() { + fonts.textContent = ''; + }, + enabled: false, + get active() { + return active; + }, + set active(value) { + active = value; + if (active) { + document.body.addEventListener('click', textLayerClick, true); + resetSelection(); + } else { + document.body.removeEventListener('click', textLayerClick, true); + removeSelection(); + } + }, + // FontInspector specific functions. + fontAdded: function fontAdded(fontObj, url) { + function properties(obj, list) { + var moreInfo = document.createElement('table'); + for (var i = 0; i < list.length; i++) { + var tr = document.createElement('tr'); + var td1 = document.createElement('td'); + td1.textContent = list[i]; + tr.appendChild(td1); + var td2 = document.createElement('td'); + td2.textContent = obj[list[i]].toString(); + tr.appendChild(td2); + moreInfo.appendChild(tr); + } + return moreInfo; + } + var moreInfo = properties(fontObj, ['name', 'type']); + var fontName = fontObj.loadedName; + var font = document.createElement('div'); + var name = document.createElement('span'); + name.textContent = fontName; + var download = document.createElement('a'); + if (url) { + url = /url\(['"]?([^\)"']+)/.exec(url); + download.href = url[1]; + } else if (fontObj.data) { + url = URL.createObjectURL(new Blob([fontObj.data], { + type: fontObj.mimeType + })); + download.href = url; + } + download.textContent = 'Download'; + var logIt = document.createElement('a'); + logIt.href = ''; + logIt.textContent = 'Log'; + logIt.addEventListener('click', function(event) { + event.preventDefault(); + console.log(fontObj); + }); + var select = document.createElement('input'); + select.setAttribute('type', 'checkbox'); + select.dataset.fontName = fontName; + select.addEventListener('click', (function(select, fontName) { + return (function() { + selectFont(fontName, select.checked); + }); + })(select, fontName)); + font.appendChild(select); + font.appendChild(name); + font.appendChild(document.createTextNode(' ')); + font.appendChild(download); + font.appendChild(document.createTextNode(' ')); + font.appendChild(logIt); + font.appendChild(moreInfo); + fonts.appendChild(font); + // Somewhat of a hack, should probably add a hook for when the text layer + // is done rendering. + setTimeout(function() { + if (this.active) { + resetSelection(); + } + }.bind(this), 2000); + } + }; +})(); + +// Manages all the page steppers. +var StepperManager = (function StepperManagerClosure() { + var steppers = []; + var stepperDiv = null; + var stepperControls = null; + var stepperChooser = null; + var breakPoints = {}; + return { + // Properties/functions needed by PDFBug. + id: 'Stepper', + name: 'Stepper', + panel: null, + manager: null, + init: function init() { + var self = this; + this.panel.setAttribute('style', 'padding: 5px;'); + stepperControls = document.createElement('div'); + stepperChooser = document.createElement('select'); + stepperChooser.addEventListener('change', function(event) { + self.selectStepper(this.value); + }); + stepperControls.appendChild(stepperChooser); + stepperDiv = document.createElement('div'); + this.panel.appendChild(stepperControls); + this.panel.appendChild(stepperDiv); + if (sessionStorage.getItem('pdfjsBreakPoints')) { + breakPoints = JSON.parse(sessionStorage.getItem('pdfjsBreakPoints')); + } + }, + cleanup: function cleanup() { + stepperChooser.textContent = ''; + stepperDiv.textContent = ''; + steppers = []; + }, + enabled: false, + active: false, + // Stepper specific functions. + create: function create(pageIndex) { + var debug = document.createElement('div'); + debug.id = 'stepper' + pageIndex; + debug.setAttribute('hidden', true); + debug.className = 'stepper'; + stepperDiv.appendChild(debug); + var b = document.createElement('option'); + b.textContent = 'Page ' + (pageIndex + 1); + b.value = pageIndex; + stepperChooser.appendChild(b); + var initBreakPoints = breakPoints[pageIndex] || []; + var stepper = new Stepper(debug, pageIndex, initBreakPoints); + steppers.push(stepper); + if (steppers.length === 1) { + this.selectStepper(pageIndex, false); + } + return stepper; + }, + selectStepper: function selectStepper(pageIndex, selectPanel) { + var i; + pageIndex = pageIndex | 0; + if (selectPanel) { + this.manager.selectPanel(this); + } + for (i = 0; i < steppers.length; ++i) { + var stepper = steppers[i]; + if (stepper.pageIndex === pageIndex) { + stepper.panel.removeAttribute('hidden'); + } else { + stepper.panel.setAttribute('hidden', true); + } + } + var options = stepperChooser.options; + for (i = 0; i < options.length; ++i) { + var option = options[i]; + option.selected = (option.value | 0) === pageIndex; + } + }, + saveBreakPoints: function saveBreakPoints(pageIndex, bps) { + breakPoints[pageIndex] = bps; + sessionStorage.setItem('pdfjsBreakPoints', JSON.stringify(breakPoints)); + } + }; +})(); + +// The stepper for each page's IRQueue. +var Stepper = (function StepperClosure() { + // Shorter way to create element and optionally set textContent. + function c(tag, textContent) { + var d = document.createElement(tag); + if (textContent) { + d.textContent = textContent; + } + return d; + } + + var opMap = null; + + function simplifyArgs(args) { + if (typeof args === 'string') { + var MAX_STRING_LENGTH = 75; + return args.length <= MAX_STRING_LENGTH ? args : + args.substr(0, MAX_STRING_LENGTH) + '...'; + } + if (typeof args !== 'object' || args === null) { + return args; + } + if ('length' in args) { // array + var simpleArgs = [], i, ii; + var MAX_ITEMS = 10; + for (i = 0, ii = Math.min(MAX_ITEMS, args.length); i < ii; i++) { + simpleArgs.push(simplifyArgs(args[i])); + } + if (i < args.length) { + simpleArgs.push('...'); + } + return simpleArgs; + } + var simpleObj = {}; + for (var key in args) { + simpleObj[key] = simplifyArgs(args[key]); + } + return simpleObj; + } + + function Stepper(panel, pageIndex, initialBreakPoints) { + this.panel = panel; + this.breakPoint = 0; + this.nextBreakPoint = null; + this.pageIndex = pageIndex; + this.breakPoints = initialBreakPoints; + this.currentIdx = -1; + this.operatorListIdx = 0; + } + Stepper.prototype = { + init: function init() { + var panel = this.panel; + var content = c('div', 'c=continue, s=step'); + var table = c('table'); + content.appendChild(table); + table.cellSpacing = 0; + var headerRow = c('tr'); + table.appendChild(headerRow); + headerRow.appendChild(c('th', 'Break')); + headerRow.appendChild(c('th', 'Idx')); + headerRow.appendChild(c('th', 'fn')); + headerRow.appendChild(c('th', 'args')); + panel.appendChild(content); + this.table = table; + if (!opMap) { + opMap = Object.create(null); + for (var key in PDFJS.OPS) { + opMap[PDFJS.OPS[key]] = key; + } + } + }, + updateOperatorList: function updateOperatorList(operatorList) { + var self = this; + + function cboxOnClick() { + var x = +this.dataset.idx; + if (this.checked) { + self.breakPoints.push(x); + } else { + self.breakPoints.splice(self.breakPoints.indexOf(x), 1); + } + StepperManager.saveBreakPoints(self.pageIndex, self.breakPoints); + } + + var MAX_OPERATORS_COUNT = 15000; + if (this.operatorListIdx > MAX_OPERATORS_COUNT) { + return; + } + + var chunk = document.createDocumentFragment(); + var operatorsToDisplay = Math.min(MAX_OPERATORS_COUNT, + operatorList.fnArray.length); + for (var i = this.operatorListIdx; i < operatorsToDisplay; i++) { + var line = c('tr'); + line.className = 'line'; + line.dataset.idx = i; + chunk.appendChild(line); + var checked = this.breakPoints.indexOf(i) !== -1; + var args = operatorList.argsArray[i] || []; + + var breakCell = c('td'); + var cbox = c('input'); + cbox.type = 'checkbox'; + cbox.className = 'points'; + cbox.checked = checked; + cbox.dataset.idx = i; + cbox.onclick = cboxOnClick; + + breakCell.appendChild(cbox); + line.appendChild(breakCell); + line.appendChild(c('td', i.toString())); + var fn = opMap[operatorList.fnArray[i]]; + var decArgs = args; + if (fn === 'showText') { + var glyphs = args[0]; + var newArgs = []; + var str = []; + for (var j = 0; j < glyphs.length; j++) { + var glyph = glyphs[j]; + if (typeof glyph === 'object' && glyph !== null) { + str.push(glyph.fontChar); + } else { + if (str.length > 0) { + newArgs.push(str.join('')); + str = []; + } + newArgs.push(glyph); // null or number + } + } + if (str.length > 0) { + newArgs.push(str.join('')); + } + decArgs = [newArgs]; + } + line.appendChild(c('td', fn)); + line.appendChild(c('td', JSON.stringify(simplifyArgs(decArgs)))); + } + if (operatorsToDisplay < operatorList.fnArray.length) { + line = c('tr'); + var lastCell = c('td', '...'); + lastCell.colspan = 4; + chunk.appendChild(lastCell); + } + this.operatorListIdx = operatorList.fnArray.length; + this.table.appendChild(chunk); + }, + getNextBreakPoint: function getNextBreakPoint() { + this.breakPoints.sort(function(a, b) { return a - b; }); + for (var i = 0; i < this.breakPoints.length; i++) { + if (this.breakPoints[i] > this.currentIdx) { + return this.breakPoints[i]; + } + } + return null; + }, + breakIt: function breakIt(idx, callback) { + StepperManager.selectStepper(this.pageIndex, true); + var self = this; + var dom = document; + self.currentIdx = idx; + var listener = function(e) { + switch (e.keyCode) { + case 83: // step + dom.removeEventListener('keydown', listener, false); + self.nextBreakPoint = self.currentIdx + 1; + self.goTo(-1); + callback(); + break; + case 67: // continue + dom.removeEventListener('keydown', listener, false); + var breakPoint = self.getNextBreakPoint(); + self.nextBreakPoint = breakPoint; + self.goTo(-1); + callback(); + break; + } + }; + dom.addEventListener('keydown', listener, false); + self.goTo(idx); + }, + goTo: function goTo(idx) { + var allRows = this.panel.getElementsByClassName('line'); + for (var x = 0, xx = allRows.length; x < xx; ++x) { + var row = allRows[x]; + if ((row.dataset.idx | 0) === idx) { + row.style.backgroundColor = 'rgb(251,250,207)'; + row.scrollIntoView(); + } else { + row.style.backgroundColor = null; + } + } + } + }; + return Stepper; +})(); + +var Stats = (function Stats() { + var stats = []; + function clear(node) { + while (node.hasChildNodes()) { + node.removeChild(node.lastChild); + } + } + function getStatIndex(pageNumber) { + for (var i = 0, ii = stats.length; i < ii; ++i) { + if (stats[i].pageNumber === pageNumber) { + return i; + } + } + return false; + } + return { + // Properties/functions needed by PDFBug. + id: 'Stats', + name: 'Stats', + panel: null, + manager: null, + init: function init() { + this.panel.setAttribute('style', 'padding: 5px;'); + PDFJS.enableStats = true; + }, + enabled: false, + active: false, + // Stats specific functions. + add: function(pageNumber, stat) { + if (!stat) { + return; + } + var statsIndex = getStatIndex(pageNumber); + if (statsIndex !== false) { + var b = stats[statsIndex]; + this.panel.removeChild(b.div); + stats.splice(statsIndex, 1); + } + var wrapper = document.createElement('div'); + wrapper.className = 'stats'; + var title = document.createElement('div'); + title.className = 'title'; + title.textContent = 'Page: ' + pageNumber; + var statsDiv = document.createElement('div'); + statsDiv.textContent = stat.toString(); + wrapper.appendChild(title); + wrapper.appendChild(statsDiv); + stats.push({ pageNumber: pageNumber, div: wrapper }); + stats.sort(function(a, b) { return a.pageNumber - b.pageNumber; }); + clear(this.panel); + for (var i = 0, ii = stats.length; i < ii; ++i) { + this.panel.appendChild(stats[i].div); + } + }, + cleanup: function () { + stats = []; + clear(this.panel); + } + }; +})(); + +// Manages all the debugging tools. +var PDFBug = (function PDFBugClosure() { + var panelWidth = 300; + var buttons = []; + var activePanel = null; + + return { + tools: [ + FontInspector, + StepperManager, + Stats + ], + enable: function(ids) { + var all = false, tools = this.tools; + if (ids.length === 1 && ids[0] === 'all') { + all = true; + } + for (var i = 0; i < tools.length; ++i) { + var tool = tools[i]; + if (all || ids.indexOf(tool.id) !== -1) { + tool.enabled = true; + } + } + if (!all) { + // Sort the tools by the order they are enabled. + tools.sort(function(a, b) { + var indexA = ids.indexOf(a.id); + indexA = indexA < 0 ? tools.length : indexA; + var indexB = ids.indexOf(b.id); + indexB = indexB < 0 ? tools.length : indexB; + return indexA - indexB; + }); + } + }, + init: function init() { + /* + * Basic Layout: + * PDFBug + * Controls + * Panels + * Panel + * Panel + * ... + */ + var ui = document.createElement('div'); + ui.id = 'PDFBug'; + + var controls = document.createElement('div'); + controls.setAttribute('class', 'controls'); + ui.appendChild(controls); + + var panels = document.createElement('div'); + panels.setAttribute('class', 'panels'); + ui.appendChild(panels); + + var container = document.getElementById('viewerContainer'); + container.appendChild(ui); + container.style.right = panelWidth + 'px'; + + // Initialize all the debugging tools. + var tools = this.tools; + var self = this; + for (var i = 0; i < tools.length; ++i) { + var tool = tools[i]; + var panel = document.createElement('div'); + var panelButton = document.createElement('button'); + panelButton.textContent = tool.name; + panelButton.addEventListener('click', (function(selected) { + return function(event) { + event.preventDefault(); + self.selectPanel(selected); + }; + })(i)); + controls.appendChild(panelButton); + panels.appendChild(panel); + tool.panel = panel; + tool.manager = this; + if (tool.enabled) { + tool.init(); + } else { + panel.textContent = tool.name + ' is disabled. To enable add ' + + ' "' + tool.id + '" to the pdfBug parameter ' + + 'and refresh (seperate multiple by commas).'; + } + buttons.push(panelButton); + } + this.selectPanel(0); + }, + cleanup: function cleanup() { + for (var i = 0, ii = this.tools.length; i < ii; i++) { + if (this.tools[i].enabled) { + this.tools[i].cleanup(); + } + } + }, + selectPanel: function selectPanel(index) { + if (typeof index !== 'number') { + index = this.tools.indexOf(index); + } + if (index === activePanel) { + return; + } + activePanel = index; + var tools = this.tools; + for (var j = 0; j < tools.length; ++j) { + if (j === index) { + buttons[j].setAttribute('class', 'active'); + tools[j].active = true; + tools[j].panel.removeAttribute('hidden'); + } else { + buttons[j].setAttribute('class', ''); + tools[j].active = false; + tools[j].panel.setAttribute('hidden', 'true'); + } + } + } + }; +})(); diff --git a/src/main/resources/static/generic/web/images/annotation-check.svg b/src/main/resources/static/generic/web/images/annotation-check.svg new file mode 100644 index 0000000..71cd16d --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-check.svg @@ -0,0 +1,11 @@ + + + + diff --git a/src/main/resources/static/generic/web/images/annotation-comment.svg b/src/main/resources/static/generic/web/images/annotation-comment.svg new file mode 100644 index 0000000..86f1f17 --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-comment.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/src/main/resources/static/generic/web/images/annotation-help.svg b/src/main/resources/static/generic/web/images/annotation-help.svg new file mode 100644 index 0000000..00938fe --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-help.svg @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/src/main/resources/static/generic/web/images/annotation-insert.svg b/src/main/resources/static/generic/web/images/annotation-insert.svg new file mode 100644 index 0000000..519ef68 --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-insert.svg @@ -0,0 +1,10 @@ + + + + diff --git a/src/main/resources/static/generic/web/images/annotation-key.svg b/src/main/resources/static/generic/web/images/annotation-key.svg new file mode 100644 index 0000000..8d09d53 --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-key.svg @@ -0,0 +1,11 @@ + + + + diff --git a/src/main/resources/static/generic/web/images/annotation-newparagraph.svg b/src/main/resources/static/generic/web/images/annotation-newparagraph.svg new file mode 100644 index 0000000..38d2497 --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-newparagraph.svg @@ -0,0 +1,11 @@ + + + + diff --git a/src/main/resources/static/generic/web/images/annotation-noicon.svg b/src/main/resources/static/generic/web/images/annotation-noicon.svg new file mode 100644 index 0000000..c07d108 --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-noicon.svg @@ -0,0 +1,7 @@ + + + diff --git a/src/main/resources/static/generic/web/images/annotation-note.svg b/src/main/resources/static/generic/web/images/annotation-note.svg new file mode 100644 index 0000000..7017365 --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-note.svg @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/src/main/resources/static/generic/web/images/annotation-paragraph.svg b/src/main/resources/static/generic/web/images/annotation-paragraph.svg new file mode 100644 index 0000000..6ae5212 --- /dev/null +++ b/src/main/resources/static/generic/web/images/annotation-paragraph.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/src/main/resources/static/generic/web/images/findbarButton-next-rtl.png b/src/main/resources/static/generic/web/images/findbarButton-next-rtl.png new file mode 100644 index 0000000..bef0274 Binary files /dev/null and b/src/main/resources/static/generic/web/images/findbarButton-next-rtl.png differ diff --git a/src/main/resources/static/generic/web/images/findbarButton-next-rtl@2x.png b/src/main/resources/static/generic/web/images/findbarButton-next-rtl@2x.png new file mode 100644 index 0000000..1da6dc9 Binary files /dev/null and b/src/main/resources/static/generic/web/images/findbarButton-next-rtl@2x.png differ diff --git a/src/main/resources/static/generic/web/images/findbarButton-next.png b/src/main/resources/static/generic/web/images/findbarButton-next.png new file mode 100644 index 0000000..de1d0fc Binary files /dev/null and b/src/main/resources/static/generic/web/images/findbarButton-next.png differ diff --git a/src/main/resources/static/generic/web/images/findbarButton-next@2x.png b/src/main/resources/static/generic/web/images/findbarButton-next@2x.png new file mode 100644 index 0000000..0250307 Binary files /dev/null and b/src/main/resources/static/generic/web/images/findbarButton-next@2x.png differ diff --git a/src/main/resources/static/generic/web/images/findbarButton-previous-rtl.png b/src/main/resources/static/generic/web/images/findbarButton-previous-rtl.png new file mode 100644 index 0000000..de1d0fc Binary files /dev/null and b/src/main/resources/static/generic/web/images/findbarButton-previous-rtl.png differ diff --git a/src/main/resources/static/generic/web/images/findbarButton-previous-rtl@2x.png b/src/main/resources/static/generic/web/images/findbarButton-previous-rtl@2x.png new file mode 100644 index 0000000..0250307 Binary files /dev/null and b/src/main/resources/static/generic/web/images/findbarButton-previous-rtl@2x.png differ diff --git a/src/main/resources/static/generic/web/images/findbarButton-previous.png b/src/main/resources/static/generic/web/images/findbarButton-previous.png new file mode 100644 index 0000000..bef0274 Binary files /dev/null and b/src/main/resources/static/generic/web/images/findbarButton-previous.png differ diff --git a/src/main/resources/static/generic/web/images/findbarButton-previous@2x.png b/src/main/resources/static/generic/web/images/findbarButton-previous@2x.png new file mode 100644 index 0000000..1da6dc9 Binary files /dev/null and b/src/main/resources/static/generic/web/images/findbarButton-previous@2x.png differ diff --git a/src/main/resources/static/generic/web/images/grab.cur b/src/main/resources/static/generic/web/images/grab.cur new file mode 100644 index 0000000..db7ad5a Binary files /dev/null and b/src/main/resources/static/generic/web/images/grab.cur differ diff --git a/src/main/resources/static/generic/web/images/grabbing.cur b/src/main/resources/static/generic/web/images/grabbing.cur new file mode 100644 index 0000000..e0dfd04 Binary files /dev/null and b/src/main/resources/static/generic/web/images/grabbing.cur differ diff --git a/src/main/resources/static/generic/web/images/loading-icon.gif b/src/main/resources/static/generic/web/images/loading-icon.gif new file mode 100644 index 0000000..1c72ebb Binary files /dev/null and b/src/main/resources/static/generic/web/images/loading-icon.gif differ diff --git a/src/main/resources/static/generic/web/images/loading-small.png b/src/main/resources/static/generic/web/images/loading-small.png new file mode 100644 index 0000000..8831a80 Binary files /dev/null and b/src/main/resources/static/generic/web/images/loading-small.png differ diff --git a/src/main/resources/static/generic/web/images/loading-small@2x.png b/src/main/resources/static/generic/web/images/loading-small@2x.png new file mode 100644 index 0000000..b25b445 Binary files /dev/null and b/src/main/resources/static/generic/web/images/loading-small@2x.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-documentProperties.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-documentProperties.png new file mode 100644 index 0000000..40925e2 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-documentProperties.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-documentProperties@2x.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-documentProperties@2x.png new file mode 100644 index 0000000..adb240e Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-documentProperties@2x.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-firstPage.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-firstPage.png new file mode 100644 index 0000000..e68846a Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-firstPage.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-firstPage@2x.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-firstPage@2x.png new file mode 100644 index 0000000..3ad8af5 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-firstPage@2x.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-handTool.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-handTool.png new file mode 100644 index 0000000..cb85a84 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-handTool.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-handTool@2x.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-handTool@2x.png new file mode 100644 index 0000000..5c13f77 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-handTool@2x.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-lastPage.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-lastPage.png new file mode 100644 index 0000000..be763e0 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-lastPage.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-lastPage@2x.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-lastPage@2x.png new file mode 100644 index 0000000..8570984 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-lastPage@2x.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCcw.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCcw.png new file mode 100644 index 0000000..675d6da Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCcw.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCcw@2x.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCcw@2x.png new file mode 100644 index 0000000..b9e7431 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCcw@2x.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCw.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCw.png new file mode 100644 index 0000000..e1c7598 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCw.png differ diff --git a/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCw@2x.png b/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCw@2x.png new file mode 100644 index 0000000..cb257b4 Binary files /dev/null and b/src/main/resources/static/generic/web/images/secondaryToolbarButton-rotateCw@2x.png differ diff --git a/src/main/resources/static/generic/web/images/shadow.png b/src/main/resources/static/generic/web/images/shadow.png new file mode 100644 index 0000000..31d3bdb Binary files /dev/null and b/src/main/resources/static/generic/web/images/shadow.png differ diff --git a/src/main/resources/static/generic/web/images/texture.png b/src/main/resources/static/generic/web/images/texture.png new file mode 100644 index 0000000..eb5ccb5 Binary files /dev/null and b/src/main/resources/static/generic/web/images/texture.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-bookmark.png b/src/main/resources/static/generic/web/images/toolbarButton-bookmark.png new file mode 100644 index 0000000..a187be6 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-bookmark.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-bookmark@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-bookmark@2x.png new file mode 100644 index 0000000..4efbaa6 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-bookmark@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-download.png b/src/main/resources/static/generic/web/images/toolbarButton-download.png new file mode 100644 index 0000000..eaab35f Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-download.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-download@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-download@2x.png new file mode 100644 index 0000000..896face Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-download@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-menuArrows.png b/src/main/resources/static/generic/web/images/toolbarButton-menuArrows.png new file mode 100644 index 0000000..306eb43 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-menuArrows.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-menuArrows@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-menuArrows@2x.png new file mode 100644 index 0000000..f7570bc Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-menuArrows@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-openFile.png b/src/main/resources/static/generic/web/images/toolbarButton-openFile.png new file mode 100644 index 0000000..b5cf1bd Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-openFile.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-openFile@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-openFile@2x.png new file mode 100644 index 0000000..91ab765 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-openFile@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-pageDown-rtl.png b/src/main/resources/static/generic/web/images/toolbarButton-pageDown-rtl.png new file mode 100644 index 0000000..1957f79 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-pageDown-rtl.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-pageDown-rtl@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-pageDown-rtl@2x.png new file mode 100644 index 0000000..16ebcb8 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-pageDown-rtl@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-pageDown.png b/src/main/resources/static/generic/web/images/toolbarButton-pageDown.png new file mode 100644 index 0000000..8219ecf Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-pageDown.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-pageDown@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-pageDown@2x.png new file mode 100644 index 0000000..758c01d Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-pageDown@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-pageUp-rtl.png b/src/main/resources/static/generic/web/images/toolbarButton-pageUp-rtl.png new file mode 100644 index 0000000..98e7ce4 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-pageUp-rtl.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-pageUp-rtl@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-pageUp-rtl@2x.png new file mode 100644 index 0000000..a01b023 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-pageUp-rtl@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-pageUp.png b/src/main/resources/static/generic/web/images/toolbarButton-pageUp.png new file mode 100644 index 0000000..fb9daa3 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-pageUp.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-pageUp@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-pageUp@2x.png new file mode 100644 index 0000000..a5cfd75 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-pageUp@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-presentationMode.png b/src/main/resources/static/generic/web/images/toolbarButton-presentationMode.png new file mode 100644 index 0000000..3ac2124 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-presentationMode.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-presentationMode@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-presentationMode@2x.png new file mode 100644 index 0000000..cada9e7 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-presentationMode@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-print.png b/src/main/resources/static/generic/web/images/toolbarButton-print.png new file mode 100644 index 0000000..51275e5 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-print.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-print@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-print@2x.png new file mode 100644 index 0000000..53d18da Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-print@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-search.png b/src/main/resources/static/generic/web/images/toolbarButton-search.png new file mode 100644 index 0000000..f9b7557 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-search.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-search@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-search@2x.png new file mode 100644 index 0000000..456b133 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-search@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle-rtl.png b/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle-rtl.png new file mode 100644 index 0000000..8437095 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle-rtl.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle-rtl@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle-rtl@2x.png new file mode 100644 index 0000000..9d9bfa4 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle-rtl@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle.png b/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle.png new file mode 100644 index 0000000..1f90f83 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle@2x.png new file mode 100644 index 0000000..b066fe5 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-secondaryToolbarToggle@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle-rtl.png b/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle-rtl.png new file mode 100644 index 0000000..6f85ec0 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle-rtl.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle-rtl@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle-rtl@2x.png new file mode 100644 index 0000000..291e006 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle-rtl@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle.png b/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle.png new file mode 100644 index 0000000..025dc90 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle@2x.png new file mode 100644 index 0000000..7f834df Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-sidebarToggle@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-viewAttachments.png b/src/main/resources/static/generic/web/images/toolbarButton-viewAttachments.png new file mode 100644 index 0000000..fcd0b26 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-viewAttachments.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-viewAttachments@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-viewAttachments@2x.png new file mode 100644 index 0000000..b979e52 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-viewAttachments@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-viewOutline-rtl.png b/src/main/resources/static/generic/web/images/toolbarButton-viewOutline-rtl.png new file mode 100644 index 0000000..aaa9430 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-viewOutline-rtl.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-viewOutline-rtl@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-viewOutline-rtl@2x.png new file mode 100644 index 0000000..3410f70 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-viewOutline-rtl@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-viewOutline.png b/src/main/resources/static/generic/web/images/toolbarButton-viewOutline.png new file mode 100644 index 0000000..976365a Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-viewOutline.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-viewOutline@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-viewOutline@2x.png new file mode 100644 index 0000000..b6a197f Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-viewOutline@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-viewThumbnail.png b/src/main/resources/static/generic/web/images/toolbarButton-viewThumbnail.png new file mode 100644 index 0000000..584ba55 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-viewThumbnail.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-viewThumbnail@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-viewThumbnail@2x.png new file mode 100644 index 0000000..fb7db93 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-viewThumbnail@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-zoomIn.png b/src/main/resources/static/generic/web/images/toolbarButton-zoomIn.png new file mode 100644 index 0000000..513d081 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-zoomIn.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-zoomIn@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-zoomIn@2x.png new file mode 100644 index 0000000..d5d49d5 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-zoomIn@2x.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-zoomOut.png b/src/main/resources/static/generic/web/images/toolbarButton-zoomOut.png new file mode 100644 index 0000000..156c26b Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-zoomOut.png differ diff --git a/src/main/resources/static/generic/web/images/toolbarButton-zoomOut@2x.png b/src/main/resources/static/generic/web/images/toolbarButton-zoomOut@2x.png new file mode 100644 index 0000000..959e191 Binary files /dev/null and b/src/main/resources/static/generic/web/images/toolbarButton-zoomOut@2x.png differ diff --git a/src/main/resources/static/generic/web/l10n.js b/src/main/resources/static/generic/web/l10n.js new file mode 100644 index 0000000..487a7c0 --- /dev/null +++ b/src/main/resources/static/generic/web/l10n.js @@ -0,0 +1,1033 @@ +/** + * Copyright (c) 2011-2013 Fabien Cazenave, Mozilla. + * + * 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. + */ +/* + Additional modifications for PDF.js project: + - Disables language initialization on page loading; + - Removes consoleWarn and consoleLog and use console.log/warn directly. + - Removes window._ assignment. + - Remove compatibility code for OldIE. +*/ + +/*jshint browser: true, devel: true, es5: true, globalstrict: true */ +'use strict'; + +document.webL10n = (function(window, document, undefined) { + var gL10nData = {}; + var gTextData = ''; + var gTextProp = 'textContent'; + var gLanguage = ''; + var gMacros = {}; + var gReadyState = 'loading'; + + + /** + * Synchronously loading l10n resources significantly minimizes flickering + * from displaying the app with non-localized strings and then updating the + * strings. Although this will block all script execution on this page, we + * expect that the l10n resources are available locally on flash-storage. + * + * As synchronous XHR is generally considered as a bad idea, we're still + * loading l10n resources asynchronously -- but we keep this in a setting, + * just in case... and applications using this library should hide their + * content until the `localized' event happens. + */ + + var gAsyncResourceLoading = true; // read-only + + + /** + * DOM helpers for the so-called "HTML API". + * + * These functions are written for modern browsers. For old versions of IE, + * they're overridden in the 'startup' section at the end of this file. + */ + + function getL10nResourceLinks() { + return document.querySelectorAll('link[type="application/l10n"]'); + } + + function getL10nDictionary() { + var script = document.querySelector('script[type="application/l10n"]'); + // TODO: support multiple and external JSON dictionaries + return script ? JSON.parse(script.innerHTML) : null; + } + + function getTranslatableChildren(element) { + return element ? element.querySelectorAll('*[data-l10n-id]') : []; + } + + function getL10nAttributes(element) { + if (!element) + return {}; + + var l10nId = element.getAttribute('data-l10n-id'); + var l10nArgs = element.getAttribute('data-l10n-args'); + var args = {}; + if (l10nArgs) { + try { + args = JSON.parse(l10nArgs); + } catch (e) { + console.warn('could not parse arguments for #' + l10nId); + } + } + return { id: l10nId, args: args }; + } + + function fireL10nReadyEvent(lang) { + var evtObject = document.createEvent('Event'); + evtObject.initEvent('localized', true, false); + evtObject.language = lang; + document.dispatchEvent(evtObject); + } + + function xhrLoadText(url, onSuccess, onFailure) { + onSuccess = onSuccess || function _onSuccess(data) {}; + onFailure = onFailure || function _onFailure() { + console.warn(url + ' not found.'); + }; + + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, gAsyncResourceLoading); + if (xhr.overrideMimeType) { + xhr.overrideMimeType('text/plain; charset=utf-8'); + } + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + if (xhr.status == 200 || xhr.status === 0) { + onSuccess(xhr.responseText); + } else { + onFailure(); + } + } + }; + xhr.onerror = onFailure; + xhr.ontimeout = onFailure; + + // in Firefox OS with the app:// protocol, trying to XHR a non-existing + // URL will raise an exception here -- hence this ugly try...catch. + try { + xhr.send(null); + } catch (e) { + onFailure(); + } + } + + + /** + * l10n resource parser: + * - reads (async XHR) the l10n resource matching `lang'; + * - imports linked resources (synchronously) when specified; + * - parses the text data (fills `gL10nData' and `gTextData'); + * - triggers success/failure callbacks when done. + * + * @param {string} href + * URL of the l10n resource to parse. + * + * @param {string} lang + * locale (language) to parse. Must be a lowercase string. + * + * @param {Function} successCallback + * triggered when the l10n resource has been successully parsed. + * + * @param {Function} failureCallback + * triggered when the an error has occured. + * + * @return {void} + * uses the following global variables: gL10nData, gTextData, gTextProp. + */ + + function parseResource(href, lang, successCallback, failureCallback) { + var baseURL = href.replace(/[^\/]*$/, '') || './'; + + // handle escaped characters (backslashes) in a string + function evalString(text) { + if (text.lastIndexOf('\\') < 0) + return text; + return text.replace(/\\\\/g, '\\') + .replace(/\\n/g, '\n') + .replace(/\\r/g, '\r') + .replace(/\\t/g, '\t') + .replace(/\\b/g, '\b') + .replace(/\\f/g, '\f') + .replace(/\\{/g, '{') + .replace(/\\}/g, '}') + .replace(/\\"/g, '"') + .replace(/\\'/g, "'"); + } + + // parse *.properties text data into an l10n dictionary + // If gAsyncResourceLoading is false, then the callback will be called + // synchronously. Otherwise it is called asynchronously. + function parseProperties(text, parsedPropertiesCallback) { + var dictionary = {}; + + // token expressions + var reBlank = /^\s*|\s*$/; + var reComment = /^\s*#|^\s*$/; + var reSection = /^\s*\[(.*)\]\s*$/; + var reImport = /^\s*@import\s+url\((.*)\)\s*$/i; + var reSplit = /^([^=\s]*)\s*=\s*(.+)$/; // TODO: escape EOLs with '\' + + // parse the *.properties file into an associative array + function parseRawLines(rawText, extendedSyntax, parsedRawLinesCallback) { + var entries = rawText.replace(reBlank, '').split(/[\r\n]+/); + var currentLang = '*'; + var genericLang = lang.split('-', 1)[0]; + var skipLang = false; + var match = ''; + + function nextEntry() { + // Use infinite loop instead of recursion to avoid reaching the + // maximum recursion limit for content with many lines. + while (true) { + if (!entries.length) { + parsedRawLinesCallback(); + return; + } + var line = entries.shift(); + + // comment or blank line? + if (reComment.test(line)) + continue; + + // the extended syntax supports [lang] sections and @import rules + if (extendedSyntax) { + match = reSection.exec(line); + if (match) { // section start? + // RFC 4646, section 4.4, "All comparisons MUST be performed + // in a case-insensitive manner." + + currentLang = match[1].toLowerCase(); + skipLang = (currentLang !== '*') && + (currentLang !== lang) && (currentLang !== genericLang); + continue; + } else if (skipLang) { + continue; + } + match = reImport.exec(line); + if (match) { // @import rule? + loadImport(baseURL + match[1], nextEntry); + return; + } + } + + // key-value pair + var tmp = line.match(reSplit); + if (tmp && tmp.length == 3) { + dictionary[tmp[1]] = evalString(tmp[2]); + } + } + } + nextEntry(); + } + + // import another *.properties file + function loadImport(url, callback) { + xhrLoadText(url, function(content) { + parseRawLines(content, false, callback); // don't allow recursive imports + }, null); + } + + // fill the dictionary + parseRawLines(text, true, function() { + parsedPropertiesCallback(dictionary); + }); + } + + // load and parse l10n data (warning: global variables are used here) + xhrLoadText(href, function(response) { + gTextData += response; // mostly for debug + + // parse *.properties text data into an l10n dictionary + parseProperties(response, function(data) { + + // find attribute descriptions, if any + for (var key in data) { + var id, prop, index = key.lastIndexOf('.'); + if (index > 0) { // an attribute has been specified + id = key.substring(0, index); + prop = key.substr(index + 1); + } else { // no attribute: assuming text content by default + id = key; + prop = gTextProp; + } + if (!gL10nData[id]) { + gL10nData[id] = {}; + } + gL10nData[id][prop] = data[key]; + } + + // trigger callback + if (successCallback) { + successCallback(); + } + }); + }, failureCallback); + } + + // load and parse all resources for the specified locale + function loadLocale(lang, callback) { + // RFC 4646, section 2.1 states that language tags have to be treated as + // case-insensitive. Convert to lowercase for case-insensitive comparisons. + if (lang) { + lang = lang.toLowerCase(); + } + + callback = callback || function _callback() {}; + + clear(); + gLanguage = lang; + + // check all nodes + // and load the resource files + var langLinks = getL10nResourceLinks(); + var langCount = langLinks.length; + if (langCount === 0) { + // we might have a pre-compiled dictionary instead + var dict = getL10nDictionary(); + if (dict && dict.locales && dict.default_locale) { + console.log('using the embedded JSON directory, early way out'); + gL10nData = dict.locales[lang]; + if (!gL10nData) { + var defaultLocale = dict.default_locale.toLowerCase(); + for (var anyCaseLang in dict.locales) { + anyCaseLang = anyCaseLang.toLowerCase(); + if (anyCaseLang === lang) { + gL10nData = dict.locales[lang]; + break; + } else if (anyCaseLang === defaultLocale) { + gL10nData = dict.locales[defaultLocale]; + } + } + } + callback(); + } else { + console.log('no resource to load, early way out'); + } + // early way out + fireL10nReadyEvent(lang); + gReadyState = 'complete'; + return; + } + + // start the callback when all resources are loaded + var onResourceLoaded = null; + var gResourceCount = 0; + onResourceLoaded = function() { + gResourceCount++; + if (gResourceCount >= langCount) { + callback(); + fireL10nReadyEvent(lang); + gReadyState = 'complete'; + } + }; + + // load all resource files + function L10nResourceLink(link) { + var href = link.href; + // Note: If |gAsyncResourceLoading| is false, then the following callbacks + // are synchronously called. + this.load = function(lang, callback) { + parseResource(href, lang, callback, function() { + console.warn(href + ' not found.'); + // lang not found, used default resource instead + console.warn('"' + lang + '" resource not found'); + gLanguage = ''; + // Resource not loaded, but we still need to call the callback. + callback(); + }); + }; + } + + for (var i = 0; i < langCount; i++) { + var resource = new L10nResourceLink(langLinks[i]); + resource.load(lang, onResourceLoaded); + } + } + + // clear all l10n data + function clear() { + gL10nData = {}; + gTextData = ''; + gLanguage = ''; + // TODO: clear all non predefined macros. + // There's no such macro /yet/ but we're planning to have some... + } + + + /** + * Get rules for plural forms (shared with JetPack), see: + * http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html + * https://github.com/mozilla/addon-sdk/blob/master/python-lib/plural-rules-generator.p + * + * @param {string} lang + * locale (language) used. + * + * @return {Function} + * returns a function that gives the plural form name for a given integer: + * var fun = getPluralRules('en'); + * fun(1) -> 'one' + * fun(0) -> 'other' + * fun(1000) -> 'other'. + */ + + function getPluralRules(lang) { + var locales2rules = { + 'af': 3, + 'ak': 4, + 'am': 4, + 'ar': 1, + 'asa': 3, + 'az': 0, + 'be': 11, + 'bem': 3, + 'bez': 3, + 'bg': 3, + 'bh': 4, + 'bm': 0, + 'bn': 3, + 'bo': 0, + 'br': 20, + 'brx': 3, + 'bs': 11, + 'ca': 3, + 'cgg': 3, + 'chr': 3, + 'cs': 12, + 'cy': 17, + 'da': 3, + 'de': 3, + 'dv': 3, + 'dz': 0, + 'ee': 3, + 'el': 3, + 'en': 3, + 'eo': 3, + 'es': 3, + 'et': 3, + 'eu': 3, + 'fa': 0, + 'ff': 5, + 'fi': 3, + 'fil': 4, + 'fo': 3, + 'fr': 5, + 'fur': 3, + 'fy': 3, + 'ga': 8, + 'gd': 24, + 'gl': 3, + 'gsw': 3, + 'gu': 3, + 'guw': 4, + 'gv': 23, + 'ha': 3, + 'haw': 3, + 'he': 2, + 'hi': 4, + 'hr': 11, + 'hu': 0, + 'id': 0, + 'ig': 0, + 'ii': 0, + 'is': 3, + 'it': 3, + 'iu': 7, + 'ja': 0, + 'jmc': 3, + 'jv': 0, + 'ka': 0, + 'kab': 5, + 'kaj': 3, + 'kcg': 3, + 'kde': 0, + 'kea': 0, + 'kk': 3, + 'kl': 3, + 'km': 0, + 'kn': 0, + 'ko': 0, + 'ksb': 3, + 'ksh': 21, + 'ku': 3, + 'kw': 7, + 'lag': 18, + 'lb': 3, + 'lg': 3, + 'ln': 4, + 'lo': 0, + 'lt': 10, + 'lv': 6, + 'mas': 3, + 'mg': 4, + 'mk': 16, + 'ml': 3, + 'mn': 3, + 'mo': 9, + 'mr': 3, + 'ms': 0, + 'mt': 15, + 'my': 0, + 'nah': 3, + 'naq': 7, + 'nb': 3, + 'nd': 3, + 'ne': 3, + 'nl': 3, + 'nn': 3, + 'no': 3, + 'nr': 3, + 'nso': 4, + 'ny': 3, + 'nyn': 3, + 'om': 3, + 'or': 3, + 'pa': 3, + 'pap': 3, + 'pl': 13, + 'ps': 3, + 'pt': 3, + 'rm': 3, + 'ro': 9, + 'rof': 3, + 'ru': 11, + 'rwk': 3, + 'sah': 0, + 'saq': 3, + 'se': 7, + 'seh': 3, + 'ses': 0, + 'sg': 0, + 'sh': 11, + 'shi': 19, + 'sk': 12, + 'sl': 14, + 'sma': 7, + 'smi': 7, + 'smj': 7, + 'smn': 7, + 'sms': 7, + 'sn': 3, + 'so': 3, + 'sq': 3, + 'sr': 11, + 'ss': 3, + 'ssy': 3, + 'st': 3, + 'sv': 3, + 'sw': 3, + 'syr': 3, + 'ta': 3, + 'te': 3, + 'teo': 3, + 'th': 0, + 'ti': 4, + 'tig': 3, + 'tk': 3, + 'tl': 4, + 'tn': 3, + 'to': 0, + 'tr': 0, + 'ts': 3, + 'tzm': 22, + 'uk': 11, + 'ur': 3, + 've': 3, + 'vi': 0, + 'vun': 3, + 'wa': 4, + 'wae': 3, + 'wo': 0, + 'xh': 3, + 'xog': 3, + 'yo': 0, + 'zh': 0, + 'zu': 3 + }; + + // utility functions for plural rules methods + function isIn(n, list) { + return list.indexOf(n) !== -1; + } + function isBetween(n, start, end) { + return start <= n && n <= end; + } + + // list of all plural rules methods: + // map an integer to the plural form name to use + var pluralRules = { + '0': function(n) { + return 'other'; + }, + '1': function(n) { + if ((isBetween((n % 100), 3, 10))) + return 'few'; + if (n === 0) + return 'zero'; + if ((isBetween((n % 100), 11, 99))) + return 'many'; + if (n == 2) + return 'two'; + if (n == 1) + return 'one'; + return 'other'; + }, + '2': function(n) { + if (n !== 0 && (n % 10) === 0) + return 'many'; + if (n == 2) + return 'two'; + if (n == 1) + return 'one'; + return 'other'; + }, + '3': function(n) { + if (n == 1) + return 'one'; + return 'other'; + }, + '4': function(n) { + if ((isBetween(n, 0, 1))) + return 'one'; + return 'other'; + }, + '5': function(n) { + if ((isBetween(n, 0, 2)) && n != 2) + return 'one'; + return 'other'; + }, + '6': function(n) { + if (n === 0) + return 'zero'; + if ((n % 10) == 1 && (n % 100) != 11) + return 'one'; + return 'other'; + }, + '7': function(n) { + if (n == 2) + return 'two'; + if (n == 1) + return 'one'; + return 'other'; + }, + '8': function(n) { + if ((isBetween(n, 3, 6))) + return 'few'; + if ((isBetween(n, 7, 10))) + return 'many'; + if (n == 2) + return 'two'; + if (n == 1) + return 'one'; + return 'other'; + }, + '9': function(n) { + if (n === 0 || n != 1 && (isBetween((n % 100), 1, 19))) + return 'few'; + if (n == 1) + return 'one'; + return 'other'; + }, + '10': function(n) { + if ((isBetween((n % 10), 2, 9)) && !(isBetween((n % 100), 11, 19))) + return 'few'; + if ((n % 10) == 1 && !(isBetween((n % 100), 11, 19))) + return 'one'; + return 'other'; + }, + '11': function(n) { + if ((isBetween((n % 10), 2, 4)) && !(isBetween((n % 100), 12, 14))) + return 'few'; + if ((n % 10) === 0 || + (isBetween((n % 10), 5, 9)) || + (isBetween((n % 100), 11, 14))) + return 'many'; + if ((n % 10) == 1 && (n % 100) != 11) + return 'one'; + return 'other'; + }, + '12': function(n) { + if ((isBetween(n, 2, 4))) + return 'few'; + if (n == 1) + return 'one'; + return 'other'; + }, + '13': function(n) { + if ((isBetween((n % 10), 2, 4)) && !(isBetween((n % 100), 12, 14))) + return 'few'; + if (n != 1 && (isBetween((n % 10), 0, 1)) || + (isBetween((n % 10), 5, 9)) || + (isBetween((n % 100), 12, 14))) + return 'many'; + if (n == 1) + return 'one'; + return 'other'; + }, + '14': function(n) { + if ((isBetween((n % 100), 3, 4))) + return 'few'; + if ((n % 100) == 2) + return 'two'; + if ((n % 100) == 1) + return 'one'; + return 'other'; + }, + '15': function(n) { + if (n === 0 || (isBetween((n % 100), 2, 10))) + return 'few'; + if ((isBetween((n % 100), 11, 19))) + return 'many'; + if (n == 1) + return 'one'; + return 'other'; + }, + '16': function(n) { + if ((n % 10) == 1 && n != 11) + return 'one'; + return 'other'; + }, + '17': function(n) { + if (n == 3) + return 'few'; + if (n === 0) + return 'zero'; + if (n == 6) + return 'many'; + if (n == 2) + return 'two'; + if (n == 1) + return 'one'; + return 'other'; + }, + '18': function(n) { + if (n === 0) + return 'zero'; + if ((isBetween(n, 0, 2)) && n !== 0 && n != 2) + return 'one'; + return 'other'; + }, + '19': function(n) { + if ((isBetween(n, 2, 10))) + return 'few'; + if ((isBetween(n, 0, 1))) + return 'one'; + return 'other'; + }, + '20': function(n) { + if ((isBetween((n % 10), 3, 4) || ((n % 10) == 9)) && !( + isBetween((n % 100), 10, 19) || + isBetween((n % 100), 70, 79) || + isBetween((n % 100), 90, 99) + )) + return 'few'; + if ((n % 1000000) === 0 && n !== 0) + return 'many'; + if ((n % 10) == 2 && !isIn((n % 100), [12, 72, 92])) + return 'two'; + if ((n % 10) == 1 && !isIn((n % 100), [11, 71, 91])) + return 'one'; + return 'other'; + }, + '21': function(n) { + if (n === 0) + return 'zero'; + if (n == 1) + return 'one'; + return 'other'; + }, + '22': function(n) { + if ((isBetween(n, 0, 1)) || (isBetween(n, 11, 99))) + return 'one'; + return 'other'; + }, + '23': function(n) { + if ((isBetween((n % 10), 1, 2)) || (n % 20) === 0) + return 'one'; + return 'other'; + }, + '24': function(n) { + if ((isBetween(n, 3, 10) || isBetween(n, 13, 19))) + return 'few'; + if (isIn(n, [2, 12])) + return 'two'; + if (isIn(n, [1, 11])) + return 'one'; + return 'other'; + } + }; + + // return a function that gives the plural form name for a given integer + var index = locales2rules[lang.replace(/-.*$/, '')]; + if (!(index in pluralRules)) { + console.warn('plural form unknown for [' + lang + ']'); + return function() { return 'other'; }; + } + return pluralRules[index]; + } + + // pre-defined 'plural' macro + gMacros.plural = function(str, param, key, prop) { + var n = parseFloat(param); + if (isNaN(n)) + return str; + + // TODO: support other properties (l20n still doesn't...) + if (prop != gTextProp) + return str; + + // initialize _pluralRules + if (!gMacros._pluralRules) { + gMacros._pluralRules = getPluralRules(gLanguage); + } + var index = '[' + gMacros._pluralRules(n) + ']'; + + // try to find a [zero|one|two] key if it's defined + if (n === 0 && (key + '[zero]') in gL10nData) { + str = gL10nData[key + '[zero]'][prop]; + } else if (n == 1 && (key + '[one]') in gL10nData) { + str = gL10nData[key + '[one]'][prop]; + } else if (n == 2 && (key + '[two]') in gL10nData) { + str = gL10nData[key + '[two]'][prop]; + } else if ((key + index) in gL10nData) { + str = gL10nData[key + index][prop]; + } else if ((key + '[other]') in gL10nData) { + str = gL10nData[key + '[other]'][prop]; + } + + return str; + }; + + + /** + * l10n dictionary functions + */ + + // fetch an l10n object, warn if not found, apply `args' if possible + function getL10nData(key, args, fallback) { + var data = gL10nData[key]; + if (!data) { + console.warn('#' + key + ' is undefined.'); + if (!fallback) { + return null; + } + data = fallback; + } + + /** This is where l10n expressions should be processed. + * The plan is to support C-style expressions from the l20n project; + * until then, only two kinds of simple expressions are supported: + * {[ index ]} and {{ arguments }}. + */ + var rv = {}; + for (var prop in data) { + var str = data[prop]; + str = substIndexes(str, args, key, prop); + str = substArguments(str, args, key); + rv[prop] = str; + } + return rv; + } + + // replace {[macros]} with their values + function substIndexes(str, args, key, prop) { + var reIndex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)\s*\]\}/; + var reMatch = reIndex.exec(str); + if (!reMatch || !reMatch.length) + return str; + + // an index/macro has been found + // Note: at the moment, only one parameter is supported + var macroName = reMatch[1]; + var paramName = reMatch[2]; + var param; + if (args && paramName in args) { + param = args[paramName]; + } else if (paramName in gL10nData) { + param = gL10nData[paramName]; + } + + // there's no macro parser yet: it has to be defined in gMacros + if (macroName in gMacros) { + var macro = gMacros[macroName]; + str = macro(str, param, key, prop); + } + return str; + } + + // replace {{arguments}} with their values + function substArguments(str, args, key) { + var reArgs = /\{\{\s*(.+?)\s*\}\}/g; + return str.replace(reArgs, function(matched_text, arg) { + if (args && arg in args) { + return args[arg]; + } + if (arg in gL10nData) { + return gL10nData[arg]; + } + console.log('argument {{' + arg + '}} for #' + key + ' is undefined.'); + return matched_text; + }); + } + + // translate an HTML element + function translateElement(element) { + var l10n = getL10nAttributes(element); + if (!l10n.id) + return; + + // get the related l10n object + var data = getL10nData(l10n.id, l10n.args); + if (!data) { + console.warn('#' + l10n.id + ' is undefined.'); + return; + } + + // translate element (TODO: security checks?) + if (data[gTextProp]) { // XXX + if (getChildElementCount(element) === 0) { + element[gTextProp] = data[gTextProp]; + } else { + // this element has element children: replace the content of the first + // (non-empty) child textNode and clear other child textNodes + var children = element.childNodes; + var found = false; + for (var i = 0, l = children.length; i < l; i++) { + if (children[i].nodeType === 3 && /\S/.test(children[i].nodeValue)) { + if (found) { + children[i].nodeValue = ''; + } else { + children[i].nodeValue = data[gTextProp]; + found = true; + } + } + } + // if no (non-empty) textNode is found, insert a textNode before the + // first element child. + if (!found) { + var textNode = document.createTextNode(data[gTextProp]); + element.insertBefore(textNode, element.firstChild); + } + } + delete data[gTextProp]; + } + + for (var k in data) { + element[k] = data[k]; + } + } + + // webkit browsers don't currently support 'children' on SVG elements... + function getChildElementCount(element) { + if (element.children) { + return element.children.length; + } + if (typeof element.childElementCount !== 'undefined') { + return element.childElementCount; + } + var count = 0; + for (var i = 0; i < element.childNodes.length; i++) { + count += element.nodeType === 1 ? 1 : 0; + } + return count; + } + + // translate an HTML subtree + function translateFragment(element) { + element = element || document.documentElement; + + // check all translatable children (= w/ a `data-l10n-id' attribute) + var children = getTranslatableChildren(element); + var elementCount = children.length; + for (var i = 0; i < elementCount; i++) { + translateElement(children[i]); + } + + // translate element itself if necessary + translateElement(element); + } + + return { + // get a localized string + get: function(key, args, fallbackString) { + var index = key.lastIndexOf('.'); + var prop = gTextProp; + if (index > 0) { // An attribute has been specified + prop = key.substr(index + 1); + key = key.substring(0, index); + } + var fallback; + if (fallbackString) { + fallback = {}; + fallback[prop] = fallbackString; + } + var data = getL10nData(key, args, fallback); + if (data && prop in data) { + return data[prop]; + } + return '{{' + key + '}}'; + }, + + // debug + getData: function() { return gL10nData; }, + getText: function() { return gTextData; }, + + // get|set the document language + getLanguage: function() { return gLanguage; }, + setLanguage: function(lang, callback) { + loadLocale(lang, function() { + if (callback) + callback(); + translateFragment(); + }); + }, + + // get the direction (ltr|rtl) of the current language + getDirection: function() { + // http://www.w3.org/International/questions/qa-scripts + // Arabic, Hebrew, Farsi, Pashto, Urdu + var rtlList = ['ar', 'he', 'fa', 'ps', 'ur']; + var shortCode = gLanguage.split('-', 1)[0]; + return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr'; + }, + + // translate an element or document fragment + translate: translateFragment, + + // this can be used to prevent race conditions + getReadyState: function() { return gReadyState; }, + ready: function(callback) { + if (!callback) { + + } else if (gReadyState == 'complete' || gReadyState == 'interactive') { + window.setTimeout(function() { + callback(); + }); + } else if (document.addEventListener) { + document.addEventListener('localized', function once() { + document.removeEventListener('localized', once); + callback(); + }); + } + } + }; +}) (window, document); diff --git a/src/main/resources/static/generic/web/locale/locale.properties b/src/main/resources/static/generic/web/locale/locale.properties new file mode 100644 index 0000000..e306904 --- /dev/null +++ b/src/main/resources/static/generic/web/locale/locale.properties @@ -0,0 +1,312 @@ +[ach]= +@import=url(ach/viewer.properties) + +[af]= +@import=url(af/viewer.properties) + +[ak]= +@import=url(ak/viewer.properties) + +[an]= +@import=url(an/viewer.properties) + +[ar]= +@import=url(ar/viewer.properties) + +[as]= +@import=url(as/viewer.properties) + +[ast]= +@import=url(ast/viewer.properties) + +[az]= +@import=url(az/viewer.properties) + +[be]= +@import=url(be/viewer.properties) + +[bg]= +@import=url(bg/viewer.properties) + +[bn-BD]= +@import=url(bn-BD/viewer.properties) + +[bn-IN]= +@import=url(bn-IN/viewer.properties) + +[br]= +@import=url(br/viewer.properties) + +[bs]= +@import=url(bs/viewer.properties) + +[ca]= +@import=url(ca/viewer.properties) + +[cs]= +@import=url(cs/viewer.properties) + +[csb]= +@import=url(csb/viewer.properties) + +[cy]= +@import=url(cy/viewer.properties) + +[da]= +@import=url(da/viewer.properties) + +[de]= +@import=url(de/viewer.properties) + +[el]= +@import=url(el/viewer.properties) + +[en-GB]= +@import=url(en-GB/viewer.properties) + +[en-US]= +@import=url(en-US/viewer.properties) + +[en-ZA]= +@import=url(en-ZA/viewer.properties) + +[eo]= +@import=url(eo/viewer.properties) + +[es-AR]= +@import=url(es-AR/viewer.properties) + +[es-CL]= +@import=url(es-CL/viewer.properties) + +[es-ES]= +@import=url(es-ES/viewer.properties) + +[es-MX]= +@import=url(es-MX/viewer.properties) + +[et]= +@import=url(et/viewer.properties) + +[eu]= +@import=url(eu/viewer.properties) + +[fa]= +@import=url(fa/viewer.properties) + +[ff]= +@import=url(ff/viewer.properties) + +[fi]= +@import=url(fi/viewer.properties) + +[fr]= +@import=url(fr/viewer.properties) + +[fy-NL]= +@import=url(fy-NL/viewer.properties) + +[ga-IE]= +@import=url(ga-IE/viewer.properties) + +[gd]= +@import=url(gd/viewer.properties) + +[gl]= +@import=url(gl/viewer.properties) + +[gu-IN]= +@import=url(gu-IN/viewer.properties) + +[he]= +@import=url(he/viewer.properties) + +[hi-IN]= +@import=url(hi-IN/viewer.properties) + +[hr]= +@import=url(hr/viewer.properties) + +[hu]= +@import=url(hu/viewer.properties) + +[hy-AM]= +@import=url(hy-AM/viewer.properties) + +[id]= +@import=url(id/viewer.properties) + +[is]= +@import=url(is/viewer.properties) + +[it]= +@import=url(it/viewer.properties) + +[ja]= +@import=url(ja/viewer.properties) + +[ka]= +@import=url(ka/viewer.properties) + +[kk]= +@import=url(kk/viewer.properties) + +[km]= +@import=url(km/viewer.properties) + +[kn]= +@import=url(kn/viewer.properties) + +[ko]= +@import=url(ko/viewer.properties) + +[ku]= +@import=url(ku/viewer.properties) + +[lg]= +@import=url(lg/viewer.properties) + +[lij]= +@import=url(lij/viewer.properties) + +[lt]= +@import=url(lt/viewer.properties) + +[lv]= +@import=url(lv/viewer.properties) + +[mai]= +@import=url(mai/viewer.properties) + +[mk]= +@import=url(mk/viewer.properties) + +[ml]= +@import=url(ml/viewer.properties) + +[mn]= +@import=url(mn/viewer.properties) + +[mr]= +@import=url(mr/viewer.properties) + +[ms]= +@import=url(ms/viewer.properties) + +[my]= +@import=url(my/viewer.properties) + +[nb-NO]= +@import=url(nb-NO/viewer.properties) + +[nl]= +@import=url(nl/viewer.properties) + +[nn-NO]= +@import=url(nn-NO/viewer.properties) + +[nso]= +@import=url(nso/viewer.properties) + +[oc]= +@import=url(oc/viewer.properties) + +[or]= +@import=url(or/viewer.properties) + +[pa-IN]= +@import=url(pa-IN/viewer.properties) + +[pl]= +@import=url(pl/viewer.properties) + +[pt-BR]= +@import=url(pt-BR/viewer.properties) + +[pt-PT]= +@import=url(pt-PT/viewer.properties) + +[rm]= +@import=url(rm/viewer.properties) + +[ro]= +@import=url(ro/viewer.properties) + +[ru]= +@import=url(ru/viewer.properties) + +[rw]= +@import=url(rw/viewer.properties) + +[sah]= +@import=url(sah/viewer.properties) + +[si]= +@import=url(si/viewer.properties) + +[sk]= +@import=url(sk/viewer.properties) + +[sl]= +@import=url(sl/viewer.properties) + +[son]= +@import=url(son/viewer.properties) + +[sq]= +@import=url(sq/viewer.properties) + +[sr]= +@import=url(sr/viewer.properties) + +[sv-SE]= +@import=url(sv-SE/viewer.properties) + +[sw]= +@import=url(sw/viewer.properties) + +[ta]= +@import=url(ta/viewer.properties) + +[ta-LK]= +@import=url(ta-LK/viewer.properties) + +[te]= +@import=url(te/viewer.properties) + +[th]= +@import=url(th/viewer.properties) + +[tl]= +@import=url(tl/viewer.properties) + +[tn]= +@import=url(tn/viewer.properties) + +[tr]= +@import=url(tr/viewer.properties) + +[uk]= +@import=url(uk/viewer.properties) + +[ur]= +@import=url(ur/viewer.properties) + +[vi]= +@import=url(vi/viewer.properties) + +[wo]= +@import=url(wo/viewer.properties) + +[xh]= +@import=url(xh/viewer.properties) + +[zh-CN]= +@import=url(zh-CN/viewer.properties) + +[zh-TW]= +@import=url(zh-TW/viewer.properties) + +[zu]= +@import=url(zu/viewer.properties) + diff --git a/src/main/resources/static/generic/web/locale/zh-CN/viewer.properties b/src/main/resources/static/generic/web/locale/zh-CN/viewer.properties new file mode 100644 index 0000000..6ec25f7 --- /dev/null +++ b/src/main/resources/static/generic/web/locale/zh-CN/viewer.properties @@ -0,0 +1,167 @@ +# Copyright 2012 Mozilla Foundation +# +# 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. + +# Main toolbar buttons (tooltips and alt text for images) +previous.title=上一页 +previous_label=上一页 +next.title=下一页 +next_label=下一页 + +# LOCALIZATION NOTE (page_label, page_of): +# These strings are concatenated to form the "Page: X of Y" string. +# Do not translate "{{pageCount}}", it will be substituted with a number +# representing the total number of pages. +page_label=页面: +page_of=/ {{pageCount}} + +zoom_out.title=缩小 +zoom_out_label=缩小 +zoom_in.title=放大 +zoom_in_label=放大 +zoom.title=缩放 +presentation_mode.title=切换到演示模式 +presentation_mode_label=演示模式 +open_file.title=打开文件 +open_file_label=打开 +print.title=打印 +print_label=打印 +download.title=下载 +download_label=下载 +bookmark.title=当前视图(复制或在新窗口中打开) +bookmark_label=当前视图 + +# Secondary toolbar and context menu +tools.title=工具 +tools_label=工具 +first_page.title=转到第一页 +first_page.label=转到第一页 +first_page_label=转到第一页 +last_page.title=转到最后一页 +last_page.label=转到最后一页 +last_page_label=转到最后一页 +page_rotate_cw.title=顺时针旋转 +page_rotate_cw.label=顺时针旋转 +page_rotate_cw_label=顺时针旋转 +page_rotate_ccw.title=逆时针旋转 +page_rotate_ccw.label=逆时针旋转 +page_rotate_ccw_label=逆时针旋转 + +hand_tool_enable.title=启用手形工具 +hand_tool_enable_label=启用手形工具 +hand_tool_disable.title=禁用手形工具 +hand_tool_disable_label=禁用手形工具 + +# Document properties dialog box +document_properties.title=文档属性… +document_properties_label=文档属性… +document_properties_file_name=文件名: +document_properties_file_size=文件大小: +document_properties_kb={{size_kb}} KB ({{size_b}} 字节) +document_properties_mb={{size_mb}} MB ({{size_b}} 字节) +document_properties_title=标题: +document_properties_author=作者: +document_properties_subject=主题: +document_properties_keywords=关键词: +document_properties_creation_date=创建日期: +document_properties_modification_date=修改日期: +document_properties_date_string={{date}}, {{time}} +document_properties_creator=创建者: +document_properties_producer=PDF 制作者: +document_properties_version=PDF 版本: +document_properties_page_count=页数: +document_properties_close=关闭 + +# Tooltips and alt text for side panel toolbar buttons +# (the _label strings are alt text for the buttons, the .title strings are +# tooltips) +toggle_sidebar.title=切换侧栏 +toggle_sidebar_label=切换侧栏 +outline.title=显示文档大纲 +outline_label=文档大纲 +attachments.title=显示附件 +attachments_label=附件 +thumbs.title=显示缩略图 +thumbs_label=缩略图 +findbar.title=在文档中查找 +findbar_label=查找 + +# Thumbnails panel item (tooltip and alt text for images) +# LOCALIZATION NOTE (thumb_page_title): "{{page}}" will be replaced by the page +# number. +thumb_page_title=页码 {{page}} +# LOCALIZATION NOTE (thumb_page_canvas): "{{page}}" will be replaced by the page +# number. +thumb_page_canvas=页面 {{page}} 的缩略图 + +# Find panel button title and messages +find_label=查找: +find_previous.title=查找词语上一次出现的位置 +find_previous_label=上一页 +find_next.title=查找词语后一次出现的位置 +find_next_label=下一页 +find_highlight=全部高亮显示 +find_match_case_label=区分大小写 +find_reached_top=到达文档开头,从末尾继续 +find_reached_bottom=到达文档末尾,从开头继续 +find_not_found=词语未找到 + +# Error panel labels +error_more_info=更多信息 +error_less_info=更少信息 +error_close=关闭 +# LOCALIZATION NOTE (error_version_info): "{{version}}" and "{{build}}" will be +# replaced by the PDF.JS version and build ID. +error_version_info=PDF.js v{{version}} (build: {{build}}) +# LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an +# english string describing the error. +error_message=信息:{{message}} +# LOCALIZATION NOTE (error_stack): "{{stack}}" will be replaced with a stack +# trace. +error_stack=堆栈:{{stack}} +# LOCALIZATION NOTE (error_file): "{{file}}" will be replaced with a filename +error_file=文件:{{file}} +# LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number +error_line=行号:{{line}} +rendering_error=渲染页面时发生错误。 + +# Predefined zoom values +page_scale_width=适合页宽 +page_scale_fit=适合页面 +page_scale_auto=自动缩放 +page_scale_actual=实际大小 +# LOCALIZATION NOTE (page_scale_percent): "{{scale}}" will be replaced by a +# numerical scale value. +page_scale_percent={{scale}}% + +# Loading indicator messages +loading_error_indicator=错误 +loading_error=载入PDF时发生错误。 +invalid_file_error=无效或损坏的PDF文件。 +missing_file_error=缺少PDF文件。 +unexpected_response_error=意外的服务器响应。 + +# LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip. +# "{{type}}" will be replaced with an annotation type from a list defined in +# the PDF spec (32000-1:2008 Table 169 – Annotation types). +# Some common types are e.g.: "Check", "Text", "Comment", "Note" +text_annotation_type.alt=[{{type}} 注解] +password_label=输入密码以打开此 PDF 文件。 +password_invalid=密码无效。请重试。 +password_ok=确定 +password_cancel=取消 + +printing_not_supported=警告:打印功能不完全支持此浏览器。 +printing_not_ready=警告:该 PDF 未完全加载以供打印。 +web_fonts_disabled=Web 字体已被禁用:无法使用嵌入的PDF字体。 +document_colors_disabled=不允许 PDF 文档使用自己的颜色:浏览器中“允许页面选择自己的颜色”的选项已停用。 diff --git a/src/main/resources/static/generic/web/viewer.css b/src/main/resources/static/generic/web/viewer.css new file mode 100644 index 0000000..a82150c --- /dev/null +++ b/src/main/resources/static/generic/web/viewer.css @@ -0,0 +1,1999 @@ +/* Copyright 2014 Mozilla Foundation + * + * 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. + */ + +.textLayer { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: hidden; + opacity: 0.2; +} + +.textLayer > div { + color: transparent; + position: absolute; + white-space: pre; + cursor: text; + -webkit-transform-origin: 0% 0%; + -moz-transform-origin: 0% 0%; + -o-transform-origin: 0% 0%; + -ms-transform-origin: 0% 0%; + transform-origin: 0% 0%; +} + +.textLayer .highlight { + margin: -1px; + padding: 1px; + + background-color: rgb(180, 0, 170); + border-radius: 4px; +} + +.textLayer .highlight.begin { + border-radius: 4px 0px 0px 4px; +} + +.textLayer .highlight.end { + border-radius: 0px 4px 4px 0px; +} + +.textLayer .highlight.middle { + border-radius: 0px; +} + +.textLayer .highlight.selected { + background-color: rgb(0, 100, 0); +} + +.textLayer ::selection { background: rgb(0,0,255); } +.textLayer ::-moz-selection { background: rgb(0,0,255); } + +.pdfViewer .canvasWrapper { + overflow: hidden; +} + +.pdfViewer .page { + direction: ltr; + width: 816px; + height: 1056px; + margin: 1px auto -8px auto; + position: relative; + overflow: visible; + border: 9px solid transparent; + background-clip: content-box; + border-image: url(images/shadow.png) 9 9 repeat; + background-color: white; +} + +.pdfViewer.removePageBorders .page { + margin: 0px auto 10px auto; + border: none; +} + +.pdfViewer .page canvas { + margin: 0; + display: block; +} + +.pdfViewer .page .loadingIcon { + position: absolute; + display: block; + left: 0; + top: 0; + right: 0; + bottom: 0; + background: url('images/loading-icon.gif') center no-repeat; +} + +.pdfViewer .page .annotLink > a:hover { + opacity: 0.2; + background: #ff0; + box-shadow: 0px 2px 10px #ff0; +} + +.pdfPresentationMode:-webkit-full-screen .pdfViewer .page { + margin-bottom: 100%; + border: 0; +} + +.pdfPresentationMode:-moz-full-screen .pdfViewer .page { + margin-bottom: 100%; + border: 0; +} + +.pdfPresentationMode:-ms-fullscreen .pdfViewer .page { + margin-bottom: 100% !important; + border: 0; +} + +.pdfPresentationMode:fullscreen .pdfViewer .page { + margin-bottom: 100%; + border: 0; +} + +.pdfViewer .page .annotText > img { + position: absolute; + cursor: pointer; +} + +.pdfViewer .page .annotTextContentWrapper { + position: absolute; + width: 20em; +} + +.pdfViewer .page .annotTextContent { + z-index: 200; + float: left; + max-width: 20em; + background-color: #FFFF99; + box-shadow: 0px 2px 5px #333; + border-radius: 2px; + padding: 0.6em; + cursor: pointer; +} + +.pdfViewer .page .annotTextContent > h1 { + font-size: 1em; + border-bottom: 1px solid #000000; + padding-bottom: 0.2em; +} + +.pdfViewer .page .annotTextContent > p { + padding-top: 0.2em; +} + +.pdfViewer .page .annotLink > a { + position: absolute; + font-size: 1em; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.pdfViewer .page .annotLink > a /* -ms-a */ { + background: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAA\ + LAAAAAABAAEAAAIBRAA7") 0 0 repeat; +} + +* { + padding: 0; + margin: 0; +} + +html { + height: 100%; + /* Font size is needed to make the activity bar the correct size. */ + font-size: 10px; +} + +body { + height: 100%; + background-color: #404040; + background-image: url(images/texture.png); +} + +body, +input, +button, +select { + font: message-box; + outline: none; +} + +.hidden { + display: none !important; +} +[hidden] { + display: none !important; +} + +#viewerContainer.pdfPresentationMode:-webkit-full-screen { + top: 0px; + border-top: 2px solid transparent; + background-color: #000; + width: 100%; + height: 100%; + overflow: hidden; + cursor: none; + -webkit-user-select: none; +} + +#viewerContainer.pdfPresentationMode:-moz-full-screen { + top: 0px; + border-top: 2px solid transparent; + background-color: #000; + width: 100%; + height: 100%; + overflow: hidden; + cursor: none; + -moz-user-select: none; +} + +#viewerContainer.pdfPresentationMode:-ms-fullscreen { + top: 0px !important; + border-top: 2px solid transparent; + width: 100%; + height: 100%; + overflow: hidden !important; + cursor: none; + -ms-user-select: none; +} + +#viewerContainer.pdfPresentationMode:-ms-fullscreen::-ms-backdrop { + background-color: #000; +} + +#viewerContainer.pdfPresentationMode:fullscreen { + top: 0px; + border-top: 2px solid transparent; + background-color: #000; + width: 100%; + height: 100%; + overflow: hidden; + cursor: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; +} + +.pdfPresentationMode:-webkit-full-screen a:not(.internalLink) { + display: none; +} + +.pdfPresentationMode:-moz-full-screen a:not(.internalLink) { + display: none; +} + +.pdfPresentationMode:-ms-fullscreen a:not(.internalLink) { + display: none !important; +} + +.pdfPresentationMode:fullscreen a:not(.internalLink) { + display: none; +} + +.pdfPresentationMode:-webkit-full-screen .textLayer > div { + cursor: none; +} + +.pdfPresentationMode:-moz-full-screen .textLayer > div { + cursor: none; +} + +.pdfPresentationMode:-ms-fullscreen .textLayer > div { + cursor: none; +} + +.pdfPresentationMode:fullscreen .textLayer > div { + cursor: none; +} + +.pdfPresentationMode.pdfPresentationModeControls > *, +.pdfPresentationMode.pdfPresentationModeControls .textLayer > div { + cursor: default; +} + +/* outer/inner center provides horizontal center */ +.outerCenter { + pointer-events: none; + position: relative; +} +html[dir='ltr'] .outerCenter { + float: right; + right: 50%; +} +html[dir='rtl'] .outerCenter { + float: left; + left: 50%; +} +.innerCenter { + pointer-events: auto; + position: relative; +} +html[dir='ltr'] .innerCenter { + float: right; + right: -50%; +} +html[dir='rtl'] .innerCenter { + float: left; + left: -50%; +} + +#outerContainer { + width: 100%; + height: 100%; + position: relative; +} + +#sidebarContainer { + position: absolute; + top: 0; + bottom: 0; + width: 200px; + visibility: hidden; + -webkit-transition-duration: 200ms; + -webkit-transition-timing-function: ease; + transition-duration: 200ms; + transition-timing-function: ease; + +} +html[dir='ltr'] #sidebarContainer { + -webkit-transition-property: left; + transition-property: left; + left: -200px; +} +html[dir='rtl'] #sidebarContainer { + -webkit-transition-property: right; + transition-property: right; + right: -200px; +} + +#outerContainer.sidebarMoving > #sidebarContainer, +#outerContainer.sidebarOpen > #sidebarContainer { + visibility: visible; +} +html[dir='ltr'] #outerContainer.sidebarOpen > #sidebarContainer { + left: 0px; +} +html[dir='rtl'] #outerContainer.sidebarOpen > #sidebarContainer { + right: 0px; +} + +#mainContainer { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + min-width: 320px; + -webkit-transition-duration: 200ms; + -webkit-transition-timing-function: ease; + transition-duration: 200ms; + transition-timing-function: ease; +} +html[dir='ltr'] #outerContainer.sidebarOpen > #mainContainer { + -webkit-transition-property: left; + transition-property: left; + left: 200px; +} +html[dir='rtl'] #outerContainer.sidebarOpen > #mainContainer { + -webkit-transition-property: right; + transition-property: right; + right: 200px; +} + +#sidebarContent { + top: 32px; + bottom: 0; + overflow: auto; + -webkit-overflow-scrolling: touch; + position: absolute; + width: 200px; + background-color: hsla(0,0%,0%,.1); +} +html[dir='ltr'] #sidebarContent { + left: 0; + box-shadow: inset -1px 0 0 hsla(0,0%,0%,.25); +} +html[dir='rtl'] #sidebarContent { + right: 0; + box-shadow: inset 1px 0 0 hsla(0,0%,0%,.25); +} + +#viewerContainer { + overflow: auto; + -webkit-overflow-scrolling: touch; + position: absolute; + top: 32px; + right: 0; + bottom: 0; + left: 0; + outline: none; +} +html[dir='ltr'] #viewerContainer { + box-shadow: inset 1px 0 0 hsla(0,0%,100%,.05); +} +html[dir='rtl'] #viewerContainer { + box-shadow: inset -1px 0 0 hsla(0,0%,100%,.05); +} + +.toolbar { + position: relative; + left: 0; + right: 0; + z-index: 9999; + cursor: default; +} + +#toolbarContainer { + width: 100%; +} + +#toolbarSidebar { + width: 200px; + height: 32px; + background-color: #424242; /* fallback */ + background-image: url(images/texture.png), + linear-gradient(hsla(0,0%,30%,.99), hsla(0,0%,25%,.95)); +} +html[dir='ltr'] #toolbarSidebar { + box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.25), + inset 0 -1px 0 hsla(0,0%,100%,.05), + 0 1px 0 hsla(0,0%,0%,.15), + 0 0 1px hsla(0,0%,0%,.1); +} +html[dir='rtl'] #toolbarSidebar { + box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.25), + inset 0 1px 0 hsla(0,0%,100%,.05), + 0 1px 0 hsla(0,0%,0%,.15), + 0 0 1px hsla(0,0%,0%,.1); +} + +#toolbarContainer, .findbar, .secondaryToolbar { + position: relative; + height: 32px; + background-color: #474747; /* fallback */ + background-image: url(images/texture.png), + linear-gradient(hsla(0,0%,32%,.99), hsla(0,0%,27%,.95)); +} +html[dir='ltr'] #toolbarContainer, .findbar, .secondaryToolbar { + box-shadow: inset 1px 0 0 hsla(0,0%,100%,.08), + inset 0 1px 1px hsla(0,0%,0%,.15), + inset 0 -1px 0 hsla(0,0%,100%,.05), + 0 1px 0 hsla(0,0%,0%,.15), + 0 1px 1px hsla(0,0%,0%,.1); +} +html[dir='rtl'] #toolbarContainer, .findbar, .secondaryToolbar { + box-shadow: inset -1px 0 0 hsla(0,0%,100%,.08), + inset 0 1px 1px hsla(0,0%,0%,.15), + inset 0 -1px 0 hsla(0,0%,100%,.05), + 0 1px 0 hsla(0,0%,0%,.15), + 0 1px 1px hsla(0,0%,0%,.1); +} + +#toolbarViewer { + height: 32px; +} + +#loadingBar { + position: relative; + width: 100%; + height: 4px; + background-color: #333; + border-bottom: 1px solid #333; +} + +#loadingBar .progress { + position: absolute; + top: 0; + left: 0; + width: 0%; + height: 100%; + background-color: #ddd; + overflow: hidden; + -webkit-transition: width 200ms; + transition: width 200ms; +} + +@-webkit-keyframes progressIndeterminate { + 0% { left: 0%; } + 50% { left: 100%; } + 100% { left: 100%; } +} + +@keyframes progressIndeterminate { + 0% { left: 0%; } + 50% { left: 100%; } + 100% { left: 100%; } +} + +#loadingBar .progress.indeterminate { + background-color: #999; + -webkit-transition: none; + transition: none; +} + +#loadingBar .indeterminate .glimmer { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 50px; + + background-image: linear-gradient(to right, #999 0%, #fff 50%, #999 100%); + background-size: 100% 100%; + background-repeat: no-repeat; + + -webkit-animation: progressIndeterminate 2s linear infinite; + animation: progressIndeterminate 2s linear infinite; +} + +.findbar, .secondaryToolbar { + top: 32px; + position: absolute; + z-index: 10000; + height: 32px; + + min-width: 16px; + padding: 0px 6px 0px 6px; + margin: 4px 2px 4px 2px; + color: hsl(0,0%,85%); + font-size: 12px; + line-height: 14px; + text-align: left; + cursor: default; +} + +html[dir='ltr'] .findbar { + left: 68px; +} + +html[dir='rtl'] .findbar { + right: 68px; +} + +.findbar label { + -webkit-user-select: none; + -moz-user-select: none; +} + +#findInput[data-status="pending"] { + background-image: url(images/loading-small.png); + background-repeat: no-repeat; + background-position: right; +} +html[dir='rtl'] #findInput[data-status="pending"] { + background-position: left; +} + +.secondaryToolbar { + padding: 6px; + height: auto; + z-index: 30000; +} +html[dir='ltr'] .secondaryToolbar { + right: 4px; +} +html[dir='rtl'] .secondaryToolbar { + left: 4px; +} + +#secondaryToolbarButtonContainer { + max-width: 200px; + max-height: 400px; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + margin-bottom: -4px; +} + +.doorHanger, +.doorHangerRight { + border: 1px solid hsla(0,0%,0%,.5); + border-radius: 2px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); +} +.doorHanger:after, .doorHanger:before, +.doorHangerRight:after, .doorHangerRight:before { + bottom: 100%; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} +.doorHanger:after, +.doorHangerRight:after { + border-bottom-color: hsla(0,0%,32%,.99); + border-width: 8px; +} +.doorHanger:before, +.doorHangerRight:before { + border-bottom-color: hsla(0,0%,0%,.5); + border-width: 9px; +} + +html[dir='ltr'] .doorHanger:after, +html[dir='rtl'] .doorHangerRight:after { + left: 13px; + margin-left: -8px; +} + +html[dir='ltr'] .doorHanger:before, +html[dir='rtl'] .doorHangerRight:before { + left: 13px; + margin-left: -9px; +} + +html[dir='rtl'] .doorHanger:after, +html[dir='ltr'] .doorHangerRight:after { + right: 13px; + margin-right: -8px; +} + +html[dir='rtl'] .doorHanger:before, +html[dir='ltr'] .doorHangerRight:before { + right: 13px; + margin-right: -9px; +} + +#findMsg { + font-style: italic; + color: #A6B7D0; +} + +#findInput.notFound { + background-color: rgb(255, 102, 102); +} + +html[dir='ltr'] #toolbarViewerLeft { + margin-left: -1px; +} +html[dir='rtl'] #toolbarViewerRight { + margin-right: -1px; +} + +html[dir='ltr'] #toolbarViewerLeft, +html[dir='rtl'] #toolbarViewerRight { + position: absolute; + top: 0; + left: 0; +} +html[dir='ltr'] #toolbarViewerRight, +html[dir='rtl'] #toolbarViewerLeft { + position: absolute; + top: 0; + right: 0; +} +html[dir='ltr'] #toolbarViewerLeft > *, +html[dir='ltr'] #toolbarViewerMiddle > *, +html[dir='ltr'] #toolbarViewerRight > *, +html[dir='ltr'] .findbar > * { + position: relative; + float: left; +} +html[dir='rtl'] #toolbarViewerLeft > *, +html[dir='rtl'] #toolbarViewerMiddle > *, +html[dir='rtl'] #toolbarViewerRight > *, +html[dir='rtl'] .findbar > * { + position: relative; + float: right; +} + +html[dir='ltr'] .splitToolbarButton { + margin: 3px 2px 4px 0; + display: inline-block; +} +html[dir='rtl'] .splitToolbarButton { + margin: 3px 0 4px 2px; + display: inline-block; +} +html[dir='ltr'] .splitToolbarButton > .toolbarButton { + border-radius: 0; + float: left; +} +html[dir='rtl'] .splitToolbarButton > .toolbarButton { + border-radius: 0; + float: right; +} + +.toolbarButton, +.secondaryToolbarButton, +.overlayButton { + border: 0 none; + background: none; + width: 32px; + height: 25px; +} + +.toolbarButton > span { + display: inline-block; + width: 0; + height: 0; + overflow: hidden; +} + +.toolbarButton[disabled], +.secondaryToolbarButton[disabled], +.overlayButton[disabled] { + opacity: .5; +} + +.toolbarButton.group { + margin-right: 0; +} + +.splitToolbarButton.toggled .toolbarButton { + margin: 0; +} + +.splitToolbarButton:hover > .toolbarButton, +.splitToolbarButton:focus > .toolbarButton, +.splitToolbarButton.toggled > .toolbarButton, +.toolbarButton.textButton { + background-color: hsla(0,0%,0%,.12); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-clip: padding-box; + border: 1px solid hsla(0,0%,0%,.35); + border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); + box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, + 0 0 1px hsla(0,0%,100%,.15) inset, + 0 1px 0 hsla(0,0%,100%,.05); + -webkit-transition-property: background-color, border-color, box-shadow; + -webkit-transition-duration: 150ms; + -webkit-transition-timing-function: ease; + transition-property: background-color, border-color, box-shadow; + transition-duration: 150ms; + transition-timing-function: ease; + +} +.splitToolbarButton > .toolbarButton:hover, +.splitToolbarButton > .toolbarButton:focus, +.dropdownToolbarButton:hover, +.overlayButton:hover, +.toolbarButton.textButton:hover, +.toolbarButton.textButton:focus { + background-color: hsla(0,0%,0%,.2); + box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, + 0 0 1px hsla(0,0%,100%,.15) inset, + 0 0 1px hsla(0,0%,0%,.05); + z-index: 199; +} +.splitToolbarButton > .toolbarButton { + position: relative; +} +html[dir='ltr'] .splitToolbarButton > .toolbarButton:first-child, +html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child { + position: relative; + margin: 0; + margin-right: -1px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; + border-right-color: transparent; +} +html[dir='ltr'] .splitToolbarButton > .toolbarButton:last-child, +html[dir='rtl'] .splitToolbarButton > .toolbarButton:first-child { + position: relative; + margin: 0; + margin-left: -1px; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; + border-left-color: transparent; +} +.splitToolbarButtonSeparator { + padding: 8px 0; + width: 1px; + background-color: hsla(0,0%,0%,.5); + z-index: 99; + box-shadow: 0 0 0 1px hsla(0,0%,100%,.08); + display: inline-block; + margin: 5px 0; +} +html[dir='ltr'] .splitToolbarButtonSeparator { + float: left; +} +html[dir='rtl'] .splitToolbarButtonSeparator { + float: right; +} +.splitToolbarButton:hover > .splitToolbarButtonSeparator, +.splitToolbarButton.toggled > .splitToolbarButtonSeparator { + padding: 12px 0; + margin: 1px 0; + box-shadow: 0 0 0 1px hsla(0,0%,100%,.03); + -webkit-transition-property: padding; + -webkit-transition-duration: 10ms; + -webkit-transition-timing-function: ease; + transition-property: padding; + transition-duration: 10ms; + transition-timing-function: ease; +} + +.toolbarButton, +.dropdownToolbarButton, +.secondaryToolbarButton, +.overlayButton { + min-width: 16px; + padding: 2px 6px 0; + border: 1px solid transparent; + border-radius: 2px; + color: hsla(0,0%,100%,.8); + font-size: 12px; + line-height: 14px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + /* Opera does not support user-select, use <... unselectable="on"> instead */ + cursor: default; + -webkit-transition-property: background-color, border-color, box-shadow; + -webkit-transition-duration: 150ms; + -webkit-transition-timing-function: ease; + transition-property: background-color, border-color, box-shadow; + transition-duration: 150ms; + transition-timing-function: ease; +} + +html[dir='ltr'] .toolbarButton, +html[dir='ltr'] .overlayButton, +html[dir='ltr'] .dropdownToolbarButton { + margin: 3px 2px 4px 0; +} +html[dir='rtl'] .toolbarButton, +html[dir='rtl'] .overlayButton, +html[dir='rtl'] .dropdownToolbarButton { + margin: 3px 0 4px 2px; +} + +.toolbarButton:hover, +.toolbarButton:focus, +.dropdownToolbarButton, +.overlayButton, +.secondaryToolbarButton:hover, +.secondaryToolbarButton:focus { + background-color: hsla(0,0%,0%,.12); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + background-clip: padding-box; + border: 1px solid hsla(0,0%,0%,.35); + border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42); + box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset, + 0 0 1px hsla(0,0%,100%,.15) inset, + 0 1px 0 hsla(0,0%,100%,.05); +} + +.toolbarButton:hover:active, +.overlayButton:hover:active, +.dropdownToolbarButton:hover:active, +.secondaryToolbarButton:hover:active { + background-color: hsla(0,0%,0%,.2); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45); + box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, + 0 0 1px hsla(0,0%,0%,.2) inset, + 0 1px 0 hsla(0,0%,100%,.05); + -webkit-transition-property: background-color, border-color, box-shadow; + -webkit-transition-duration: 10ms; + -webkit-transition-timing-function: linear; + transition-property: background-color, border-color, box-shadow; + transition-duration: 10ms; + transition-timing-function: linear; +} + +.toolbarButton.toggled, +.splitToolbarButton.toggled > .toolbarButton.toggled, +.secondaryToolbarButton.toggled { + background-color: hsla(0,0%,0%,.3); + background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); + border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.45) hsla(0,0%,0%,.5); + box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset, + 0 0 1px hsla(0,0%,0%,.2) inset, + 0 1px 0 hsla(0,0%,100%,.05); + -webkit-transition-property: background-color, border-color, box-shadow; + -webkit-transition-duration: 10ms; + -webkit-transition-timing-function: linear; + transition-property: background-color, border-color, box-shadow; + transition-duration: 10ms; + transition-timing-function: linear; +} + +.toolbarButton.toggled:hover:active, +.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active, +.secondaryToolbarButton.toggled:hover:active { + background-color: hsla(0,0%,0%,.4); + border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.5) hsla(0,0%,0%,.55); + box-shadow: 0 1px 1px hsla(0,0%,0%,.2) inset, + 0 0 1px hsla(0,0%,0%,.3) inset, + 0 1px 0 hsla(0,0%,100%,.05); +} + +.dropdownToolbarButton { + width: 120px; + max-width: 120px; + padding: 3px 2px 2px; + overflow: hidden; + background: url(images/toolbarButton-menuArrows.png) no-repeat; +} +html[dir='ltr'] .dropdownToolbarButton { + background-position: 95%; +} +html[dir='rtl'] .dropdownToolbarButton { + background-position: 5%; +} + +.dropdownToolbarButton > select { + min-width: 140px; + font-size: 12px; + color: hsl(0,0%,95%); + margin: 0; + padding: 0; + border: none; + background: rgba(0,0,0,0); /* Opera does not support 'transparent' +

+ +
+ +
+ + + + + + + + + +
+
+
+
+ +
+ +
+ +
+ +
+ + + +
+
+ + + + + + + + + Current View + + +
+ + +
+
+
+
+ +
+ +
+ + + +
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + +
+
+
+ + + + + + + +
+ + + + + diff --git a/src/main/resources/static/generic/web/viewer.js b/src/main/resources/static/generic/web/viewer.js new file mode 100644 index 0000000..3297eda --- /dev/null +++ b/src/main/resources/static/generic/web/viewer.js @@ -0,0 +1,7614 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * 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. + */ +/* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, ProgressBar, + DownloadManager, getFileName, getPDFFileNameFromURL, + PDFHistory, Preferences, SidebarView, ViewHistory, Stats, + PDFThumbnailViewer, URL, noContextMenuHandler, SecondaryToolbar, + PasswordPrompt, PDFPresentationMode, HandTool, Promise, + PDFDocumentProperties, PDFOutlineView, PDFAttachmentView, + OverlayManager, PDFFindController, PDFFindBar, getVisibleElements, + watchScroll, PDFViewer, PDFRenderingQueue, PresentationModeState, + RenderingStates, DEFAULT_SCALE, UNKNOWN_SCALE, + IGNORE_CURRENT_POSITION_ON_ZOOM: true */ + +'use strict'; + +var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf'; +var DEFAULT_SCALE_DELTA = 1.1; +var MIN_SCALE = 0.25; +var MAX_SCALE = 10.0; +var VIEW_HISTORY_MEMORY = 20; +var SCALE_SELECT_CONTAINER_PADDING = 8; +var SCALE_SELECT_PADDING = 22; +var PAGE_NUMBER_LOADING_INDICATOR = 'visiblePageIsLoading'; +var DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000; + +PDFJS.imageResourcesPath = './images/'; + PDFJS.workerSrc = '../build/pdf.worker.js'; + PDFJS.cMapUrl = '../web/cmaps/'; + PDFJS.cMapPacked = true; + +var mozL10n = document.mozL10n || document.webL10n; + + +var CSS_UNITS = 96.0 / 72.0; +var DEFAULT_SCALE = 'auto'; +var UNKNOWN_SCALE = 0; +var MAX_AUTO_SCALE = 1.25; +var SCROLLBAR_PADDING = 40; +var VERTICAL_PADDING = 5; + +// optimised CSS custom property getter/setter +var CustomStyle = (function CustomStyleClosure() { + + // As noted on: http://www.zachstronaut.com/posts/2009/02/17/ + // animate-css-transforms-firefox-webkit.html + // in some versions of IE9 it is critical that ms appear in this list + // before Moz + var prefixes = ['ms', 'Moz', 'Webkit', 'O']; + var _cache = {}; + + function CustomStyle() {} + + CustomStyle.getProp = function get(propName, element) { + // check cache only when no element is given + if (arguments.length === 1 && typeof _cache[propName] === 'string') { + return _cache[propName]; + } + + element = element || document.documentElement; + var style = element.style, prefixed, uPropName; + + // test standard property first + if (typeof style[propName] === 'string') { + return (_cache[propName] = propName); + } + + // capitalize + uPropName = propName.charAt(0).toUpperCase() + propName.slice(1); + + // test vendor specific properties + for (var i = 0, l = prefixes.length; i < l; i++) { + prefixed = prefixes[i] + uPropName; + if (typeof style[prefixed] === 'string') { + return (_cache[propName] = prefixed); + } + } + + //if all fails then set to undefined + return (_cache[propName] = 'undefined'); + }; + + CustomStyle.setProp = function set(propName, element, str) { + var prop = this.getProp(propName); + if (prop !== 'undefined') { + element.style[prop] = str; + } + }; + + return CustomStyle; +})(); + +function getFileName(url) { + var anchor = url.indexOf('#'); + var query = url.indexOf('?'); + var end = Math.min( + anchor > 0 ? anchor : url.length, + query > 0 ? query : url.length); + return url.substring(url.lastIndexOf('/', end) + 1, end); +} + +/** + * Returns scale factor for the canvas. It makes sense for the HiDPI displays. + * @return {Object} The object with horizontal (sx) and vertical (sy) + scales. The scaled property is set to false if scaling is + not required, true otherwise. + */ +function getOutputScale(ctx) { + var devicePixelRatio = window.devicePixelRatio || 1; + var backingStoreRatio = ctx.webkitBackingStorePixelRatio || + ctx.mozBackingStorePixelRatio || + ctx.msBackingStorePixelRatio || + ctx.oBackingStorePixelRatio || + ctx.backingStorePixelRatio || 1; + var pixelRatio = devicePixelRatio / backingStoreRatio; + return { + sx: pixelRatio, + sy: pixelRatio, + scaled: pixelRatio !== 1 + }; +} + +/** + * Scrolls specified element into view of its parent. + * element {Object} The element to be visible. + * spot {Object} An object with optional top and left properties, + * specifying the offset from the top left edge. + */ +function scrollIntoView(element, spot) { + // Assuming offsetParent is available (it's not available when viewer is in + // hidden iframe or object). We have to scroll: if the offsetParent is not set + // producing the error. See also animationStartedClosure. + var parent = element.offsetParent; + var offsetY = element.offsetTop + element.clientTop; + var offsetX = element.offsetLeft + element.clientLeft; + if (!parent) { + console.error('offsetParent is not set -- cannot scroll'); + return; + } + while (parent.clientHeight === parent.scrollHeight) { + if (parent.dataset._scaleY) { + offsetY /= parent.dataset._scaleY; + offsetX /= parent.dataset._scaleX; + } + offsetY += parent.offsetTop; + offsetX += parent.offsetLeft; + parent = parent.offsetParent; + if (!parent) { + return; // no need to scroll + } + } + if (spot) { + if (spot.top !== undefined) { + offsetY += spot.top; + } + if (spot.left !== undefined) { + offsetX += spot.left; + parent.scrollLeft = offsetX; + } + } + parent.scrollTop = offsetY; +} + +/** + * Helper function to start monitoring the scroll event and converting them into + * PDF.js friendly one: with scroll debounce and scroll direction. + */ +function watchScroll(viewAreaElement, callback) { + var debounceScroll = function debounceScroll(evt) { + if (rAF) { + return; + } + // schedule an invocation of scroll for next animation frame. + rAF = window.requestAnimationFrame(function viewAreaElementScrolled() { + rAF = null; + + var currentY = viewAreaElement.scrollTop; + var lastY = state.lastY; + if (currentY !== lastY) { + state.down = currentY > lastY; + } + state.lastY = currentY; + callback(state); + }); + }; + + var state = { + down: true, + lastY: viewAreaElement.scrollTop, + _eventHandler: debounceScroll + }; + + var rAF = null; + viewAreaElement.addEventListener('scroll', debounceScroll, true); + return state; +} + +/** + * Use binary search to find the index of the first item in a given array which + * passes a given condition. The items are expected to be sorted in the sense + * that if the condition is true for one item in the array, then it is also true + * for all following items. + * + * @returns {Number} Index of the first array element to pass the test, + * or |items.length| if no such element exists. + */ +function binarySearchFirstItem(items, condition) { + var minIndex = 0; + var maxIndex = items.length - 1; + + if (items.length === 0 || !condition(items[maxIndex])) { + return items.length; + } + if (condition(items[minIndex])) { + return minIndex; + } + + while (minIndex < maxIndex) { + var currentIndex = (minIndex + maxIndex) >> 1; + var currentItem = items[currentIndex]; + if (condition(currentItem)) { + maxIndex = currentIndex; + } else { + minIndex = currentIndex + 1; + } + } + return minIndex; /* === maxIndex */ +} + +/** + * Generic helper to find out what elements are visible within a scroll pane. + */ +function getVisibleElements(scrollEl, views, sortByVisibility) { + var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight; + var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth; + + function isElementBottomBelowViewTop(view) { + var element = view.div; + var elementBottom = + element.offsetTop + element.clientTop + element.clientHeight; + return elementBottom > top; + } + + var visible = [], view, element; + var currentHeight, viewHeight, hiddenHeight, percentHeight; + var currentWidth, viewWidth; + var firstVisibleElementInd = (views.length === 0) ? 0 : + binarySearchFirstItem(views, isElementBottomBelowViewTop); + + for (var i = firstVisibleElementInd, ii = views.length; i < ii; i++) { + view = views[i]; + element = view.div; + currentHeight = element.offsetTop + element.clientTop; + viewHeight = element.clientHeight; + + if (currentHeight > bottom) { + break; + } + + currentWidth = element.offsetLeft + element.clientLeft; + viewWidth = element.clientWidth; + if (currentWidth + viewWidth < left || currentWidth > right) { + continue; + } + hiddenHeight = Math.max(0, top - currentHeight) + + Math.max(0, currentHeight + viewHeight - bottom); + percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0; + + visible.push({ + id: view.id, + x: currentWidth, + y: currentHeight, + view: view, + percent: percentHeight + }); + } + + var first = visible[0]; + var last = visible[visible.length - 1]; + + if (sortByVisibility) { + visible.sort(function(a, b) { + var pc = a.percent - b.percent; + if (Math.abs(pc) > 0.001) { + return -pc; + } + return a.id - b.id; // ensure stability + }); + } + return {first: first, last: last, views: visible}; +} + +/** + * Event handler to suppress context menu. + */ +function noContextMenuHandler(e) { + e.preventDefault(); +} + +/** + * Returns the filename or guessed filename from the url (see issue 3455). + * url {String} The original PDF location. + * @return {String} Guessed PDF file name. + */ +function getPDFFileNameFromURL(url) { + var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/; + // SCHEME HOST 1.PATH 2.QUERY 3.REF + // Pattern to get last matching NAME.pdf + var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i; + var splitURI = reURI.exec(url); + var suggestedFilename = reFilename.exec(splitURI[1]) || + reFilename.exec(splitURI[2]) || + reFilename.exec(splitURI[3]); + if (suggestedFilename) { + suggestedFilename = suggestedFilename[0]; + if (suggestedFilename.indexOf('%') !== -1) { + // URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf + try { + suggestedFilename = + reFilename.exec(decodeURIComponent(suggestedFilename))[0]; + } catch(e) { // Possible (extremely rare) errors: + // URIError "Malformed URI", e.g. for "%AA.pdf" + // TypeError "null has no properties", e.g. for "%2F.pdf" + } + } + } + return suggestedFilename || 'document.pdf'; +} + +var ProgressBar = (function ProgressBarClosure() { + + function clamp(v, min, max) { + return Math.min(Math.max(v, min), max); + } + + function ProgressBar(id, opts) { + this.visible = true; + + // Fetch the sub-elements for later. + this.div = document.querySelector(id + ' .progress'); + + // Get the loading bar element, so it can be resized to fit the viewer. + this.bar = this.div.parentNode; + + // Get options, with sensible defaults. + this.height = opts.height || 100; + this.width = opts.width || 100; + this.units = opts.units || '%'; + + // Initialize heights. + this.div.style.height = this.height + this.units; + this.percent = 0; + } + + ProgressBar.prototype = { + + updateBar: function ProgressBar_updateBar() { + if (this._indeterminate) { + this.div.classList.add('indeterminate'); + this.div.style.width = this.width + this.units; + return; + } + + this.div.classList.remove('indeterminate'); + var progressSize = this.width * this._percent / 100; + this.div.style.width = progressSize + this.units; + }, + + get percent() { + return this._percent; + }, + + set percent(val) { + this._indeterminate = isNaN(val); + this._percent = clamp(val, 0, 100); + this.updateBar(); + }, + + setWidth: function ProgressBar_setWidth(viewer) { + if (viewer) { + var container = viewer.parentNode; + var scrollbarWidth = container.offsetWidth - viewer.offsetWidth; + if (scrollbarWidth > 0) { + this.bar.setAttribute('style', 'width: calc(100% - ' + + scrollbarWidth + 'px);'); + } + } + }, + + hide: function ProgressBar_hide() { + if (!this.visible) { + return; + } + this.visible = false; + this.bar.classList.add('hidden'); + document.body.classList.remove('loadingInProgress'); + }, + + show: function ProgressBar_show() { + if (this.visible) { + return; + } + this.visible = true; + document.body.classList.add('loadingInProgress'); + this.bar.classList.remove('hidden'); + } + }; + + return ProgressBar; +})(); + + + +var DEFAULT_PREFERENCES = { + showPreviousViewOnLoad: true, + defaultZoomValue: '', + sidebarViewOnLoad: 0, + enableHandToolOnLoad: false, + enableWebGL: false, + pdfBugEnabled: false, + disableRange: false, + disableStream: false, + disableAutoFetch: false, + disableFontFace: false, + disableTextLayer: false, + useOnlyCssZoom: false +}; + + +var SidebarView = { + NONE: 0, + THUMBS: 1, + OUTLINE: 2, + ATTACHMENTS: 3 +}; + +/** + * Preferences - Utility for storing persistent settings. + * Used for settings that should be applied to all opened documents, + * or every time the viewer is loaded. + */ +var Preferences = { + prefs: Object.create(DEFAULT_PREFERENCES), + isInitializedPromiseResolved: false, + initializedPromise: null, + + /** + * Initialize and fetch the current preference values from storage. + * @return {Promise} A promise that is resolved when the preferences + * have been initialized. + */ + initialize: function preferencesInitialize() { + return this.initializedPromise = + this._readFromStorage(DEFAULT_PREFERENCES).then(function(prefObj) { + this.isInitializedPromiseResolved = true; + if (prefObj) { + this.prefs = prefObj; + } + }.bind(this)); + }, + + /** + * Stub function for writing preferences to storage. + * NOTE: This should be overridden by a build-specific function defined below. + * @param {Object} prefObj The preferences that should be written to storage. + * @return {Promise} A promise that is resolved when the preference values + * have been written. + */ + _writeToStorage: function preferences_writeToStorage(prefObj) { + return Promise.resolve(); + }, + + /** + * Stub function for reading preferences from storage. + * NOTE: This should be overridden by a build-specific function defined below. + * @param {Object} prefObj The preferences that should be read from storage. + * @return {Promise} A promise that is resolved with an {Object} containing + * the preferences that have been read. + */ + _readFromStorage: function preferences_readFromStorage(prefObj) { + return Promise.resolve(); + }, + + /** + * Reset the preferences to their default values and update storage. + * @return {Promise} A promise that is resolved when the preference values + * have been reset. + */ + reset: function preferencesReset() { + return this.initializedPromise.then(function() { + this.prefs = Object.create(DEFAULT_PREFERENCES); + return this._writeToStorage(DEFAULT_PREFERENCES); + }.bind(this)); + }, + + /** + * Replace the current preference values with the ones from storage. + * @return {Promise} A promise that is resolved when the preference values + * have been updated. + */ + reload: function preferencesReload() { + return this.initializedPromise.then(function () { + this._readFromStorage(DEFAULT_PREFERENCES).then(function(prefObj) { + if (prefObj) { + this.prefs = prefObj; + } + }.bind(this)); + }.bind(this)); + }, + + /** + * Set the value of a preference. + * @param {string} name The name of the preference that should be changed. + * @param {boolean|number|string} value The new value of the preference. + * @return {Promise} A promise that is resolved when the value has been set, + * provided that the preference exists and the types match. + */ + set: function preferencesSet(name, value) { + return this.initializedPromise.then(function () { + if (DEFAULT_PREFERENCES[name] === undefined) { + throw new Error('preferencesSet: \'' + name + '\' is undefined.'); + } else if (value === undefined) { + throw new Error('preferencesSet: no value is specified.'); + } + var valueType = typeof value; + var defaultType = typeof DEFAULT_PREFERENCES[name]; + + if (valueType !== defaultType) { + if (valueType === 'number' && defaultType === 'string') { + value = value.toString(); + } else { + throw new Error('Preferences_set: \'' + value + '\' is a \"' + + valueType + '\", expected \"' + defaultType + '\".'); + } + } else { + if (valueType === 'number' && (value | 0) !== value) { + throw new Error('Preferences_set: \'' + value + + '\' must be an \"integer\".'); + } + } + this.prefs[name] = value; + return this._writeToStorage(this.prefs); + }.bind(this)); + }, + + /** + * Get the value of a preference. + * @param {string} name The name of the preference whose value is requested. + * @return {Promise} A promise that is resolved with a {boolean|number|string} + * containing the value of the preference. + */ + get: function preferencesGet(name) { + return this.initializedPromise.then(function () { + var defaultValue = DEFAULT_PREFERENCES[name]; + + if (defaultValue === undefined) { + throw new Error('preferencesGet: \'' + name + '\' is undefined.'); + } else { + var prefValue = this.prefs[name]; + + if (prefValue !== undefined) { + return prefValue; + } + } + return defaultValue; + }.bind(this)); + } +}; + + + +Preferences._writeToStorage = function (prefObj) { + return new Promise(function (resolve) { + localStorage.setItem('pdfjs.preferences', JSON.stringify(prefObj)); + resolve(); + }); +}; + +Preferences._readFromStorage = function (prefObj) { + return new Promise(function (resolve) { + var readPrefs = JSON.parse(localStorage.getItem('pdfjs.preferences')); + resolve(readPrefs); + }); +}; + + +(function mozPrintCallbackPolyfillClosure() { + if ('mozPrintCallback' in document.createElement('canvas')) { + return; + } + // Cause positive result on feature-detection: + HTMLCanvasElement.prototype.mozPrintCallback = undefined; + + var canvases; // During print task: non-live NodeList of elements + var index; // Index of element that is being processed + + var print = window.print; + window.print = function print() { + if (canvases) { + console.warn('Ignored window.print() because of a pending print job.'); + return; + } + try { + dispatchEvent('beforeprint'); + } finally { + canvases = document.querySelectorAll('canvas'); + index = -1; + next(); + } + }; + + function dispatchEvent(eventType) { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent(eventType, false, false, 'custom'); + window.dispatchEvent(event); + } + + function next() { + if (!canvases) { + return; // Print task cancelled by user (state reset in abort()) + } + + renderProgress(); + if (++index < canvases.length) { + var canvas = canvases[index]; + if (typeof canvas.mozPrintCallback === 'function') { + canvas.mozPrintCallback({ + context: canvas.getContext('2d'), + abort: abort, + done: next + }); + } else { + next(); + } + } else { + renderProgress(); + print.call(window); + setTimeout(abort, 20); // Tidy-up + } + } + + function abort() { + if (canvases) { + canvases = null; + renderProgress(); + dispatchEvent('afterprint'); + } + } + + function renderProgress() { + var progressContainer = document.getElementById('mozPrintCallback-shim'); + if (canvases) { + var progress = Math.round(100 * index / canvases.length); + var progressBar = progressContainer.querySelector('progress'); + var progressPerc = progressContainer.querySelector('.relative-progress'); + progressBar.value = progress; + progressPerc.textContent = progress + '%'; + progressContainer.removeAttribute('hidden'); + progressContainer.onclick = abort; + } else { + progressContainer.setAttribute('hidden', ''); + } + } + + var hasAttachEvent = !!document.attachEvent; + + window.addEventListener('keydown', function(event) { + // Intercept Cmd/Ctrl + P in all browsers. + // Also intercept Cmd/Ctrl + Shift + P in Chrome and Opera + if (event.keyCode === 80/*P*/ && (event.ctrlKey || event.metaKey) && + !event.altKey && (!event.shiftKey || window.chrome || window.opera)) { + window.print(); + if (hasAttachEvent) { + // Only attachEvent can cancel Ctrl + P dialog in IE <=10 + // attachEvent is gone in IE11, so the dialog will re-appear in IE11. + return; + } + event.preventDefault(); + if (event.stopImmediatePropagation) { + event.stopImmediatePropagation(); + } else { + event.stopPropagation(); + } + return; + } + if (event.keyCode === 27 && canvases) { // Esc + abort(); + } + }, true); + if (hasAttachEvent) { + document.attachEvent('onkeydown', function(event) { + event = event || window.event; + if (event.keyCode === 80/*P*/ && event.ctrlKey) { + event.keyCode = 0; + return false; + } + }); + } + + if ('onbeforeprint' in window) { + // Do not propagate before/afterprint events when they are not triggered + // from within this polyfill. (FF/IE). + var stopPropagationIfNeeded = function(event) { + if (event.detail !== 'custom' && event.stopImmediatePropagation) { + event.stopImmediatePropagation(); + } + }; + window.addEventListener('beforeprint', stopPropagationIfNeeded, false); + window.addEventListener('afterprint', stopPropagationIfNeeded, false); + } +})(); + + + +var DownloadManager = (function DownloadManagerClosure() { + + function download(blobUrl, filename) { + var a = document.createElement('a'); + if (a.click) { + // Use a.click() if available. Otherwise, Chrome might show + // "Unsafe JavaScript attempt to initiate a navigation change + // for frame with URL" and not open the PDF at all. + // Supported by (not mentioned = untested): + // - Firefox 6 - 19 (4- does not support a.click, 5 ignores a.click) + // - Chrome 19 - 26 (18- does not support a.click) + // - Opera 9 - 12.15 + // - Internet Explorer 6 - 10 + // - Safari 6 (5.1- does not support a.click) + a.href = blobUrl; + a.target = '_parent'; + // Use a.download if available. This increases the likelihood that + // the file is downloaded instead of opened by another PDF plugin. + if ('download' in a) { + a.download = filename; + } + // must be in the document for IE and recent Firefox versions. + // (otherwise .click() is ignored) + (document.body || document.documentElement).appendChild(a); + a.click(); + a.parentNode.removeChild(a); + } else { + if (window.top === window && + blobUrl.split('#')[0] === window.location.href.split('#')[0]) { + // If _parent == self, then opening an identical URL with different + // location hash will only cause a navigation, not a download. + var padCharacter = blobUrl.indexOf('?') === -1 ? '?' : '&'; + blobUrl = blobUrl.replace(/#|$/, padCharacter + '$&'); + } + window.open(blobUrl, '_parent'); + } + } + + function DownloadManager() {} + + DownloadManager.prototype = { + downloadUrl: function DownloadManager_downloadUrl(url, filename) { + if (!PDFJS.isValidUrl(url, true)) { + return; // restricted/invalid URL + } + + download(url + '#pdfjs.action=download', filename); + }, + + downloadData: function DownloadManager_downloadData(data, filename, + contentType) { + if (navigator.msSaveBlob) { // IE10 and above + return navigator.msSaveBlob(new Blob([data], { type: contentType }), + filename); + } + + var blobUrl = PDFJS.createObjectURL(data, contentType); + download(blobUrl, filename); + }, + + download: function DownloadManager_download(blob, url, filename) { + if (!URL) { + // URL.createObjectURL is not supported + this.downloadUrl(url, filename); + return; + } + + if (navigator.msSaveBlob) { + // IE10 / IE11 + if (!navigator.msSaveBlob(blob, filename)) { + this.downloadUrl(url, filename); + } + return; + } + + var blobUrl = URL.createObjectURL(blob); + download(blobUrl, filename); + } + }; + + return DownloadManager; +})(); + + + + + +/** + * View History - This is a utility for saving various view parameters for + * recently opened files. + * + * The way that the view parameters are stored depends on how PDF.js is built, + * for 'node make ' the following cases exist: + * - FIREFOX or MOZCENTRAL - uses sessionStorage. + * - B2G - uses asyncStorage. + * - GENERIC or CHROME - uses localStorage, if it is available. + */ +var ViewHistory = (function ViewHistoryClosure() { + function ViewHistory(fingerprint) { + this.fingerprint = fingerprint; + this.isInitializedPromiseResolved = false; + this.initializedPromise = + this._readFromStorage().then(function (databaseStr) { + this.isInitializedPromiseResolved = true; + + var database = JSON.parse(databaseStr || '{}'); + if (!('files' in database)) { + database.files = []; + } + if (database.files.length >= VIEW_HISTORY_MEMORY) { + database.files.shift(); + } + var index; + for (var i = 0, length = database.files.length; i < length; i++) { + var branch = database.files[i]; + if (branch.fingerprint === this.fingerprint) { + index = i; + break; + } + } + if (typeof index !== 'number') { + index = database.files.push({fingerprint: this.fingerprint}) - 1; + } + this.file = database.files[index]; + this.database = database; + }.bind(this)); + } + + ViewHistory.prototype = { + _writeToStorage: function ViewHistory_writeToStorage() { + return new Promise(function (resolve) { + var databaseStr = JSON.stringify(this.database); + + + + localStorage.setItem('database', databaseStr); + resolve(); + }.bind(this)); + }, + + _readFromStorage: function ViewHistory_readFromStorage() { + return new Promise(function (resolve) { + + + resolve(localStorage.getItem('database')); + }); + }, + + set: function ViewHistory_set(name, val) { + if (!this.isInitializedPromiseResolved) { + return; + } + this.file[name] = val; + return this._writeToStorage(); + }, + + setMultiple: function ViewHistory_setMultiple(properties) { + if (!this.isInitializedPromiseResolved) { + return; + } + for (var name in properties) { + this.file[name] = properties[name]; + } + return this._writeToStorage(); + }, + + get: function ViewHistory_get(name, defaultValue) { + if (!this.isInitializedPromiseResolved) { + return defaultValue; + } + return this.file[name] || defaultValue; + } + }; + + return ViewHistory; +})(); + + +/** + * Creates a "search bar" given a set of DOM elements that act as controls + * for searching or for setting search preferences in the UI. This object + * also sets up the appropriate events for the controls. Actual searching + * is done by PDFFindController. + */ +var PDFFindBar = (function PDFFindBarClosure() { + function PDFFindBar(options) { + this.opened = false; + this.bar = options.bar || null; + this.toggleButton = options.toggleButton || null; + this.findField = options.findField || null; + this.highlightAll = options.highlightAllCheckbox || null; + this.caseSensitive = options.caseSensitiveCheckbox || null; + this.findMsg = options.findMsg || null; + this.findStatusIcon = options.findStatusIcon || null; + this.findPreviousButton = options.findPreviousButton || null; + this.findNextButton = options.findNextButton || null; + this.findController = options.findController || null; + + if (this.findController === null) { + throw new Error('PDFFindBar cannot be used without a ' + + 'PDFFindController instance.'); + } + + // Add event listeners to the DOM elements. + var self = this; + this.toggleButton.addEventListener('click', function() { + self.toggle(); + }); + + this.findField.addEventListener('input', function() { + self.dispatchEvent(''); + }); + + this.bar.addEventListener('keydown', function(evt) { + switch (evt.keyCode) { + case 13: // Enter + if (evt.target === self.findField) { + self.dispatchEvent('again', evt.shiftKey); + } + break; + case 27: // Escape + self.close(); + break; + } + }); + + this.findPreviousButton.addEventListener('click', function() { + self.dispatchEvent('again', true); + }); + + this.findNextButton.addEventListener('click', function() { + self.dispatchEvent('again', false); + }); + + this.highlightAll.addEventListener('click', function() { + self.dispatchEvent('highlightallchange'); + }); + + this.caseSensitive.addEventListener('click', function() { + self.dispatchEvent('casesensitivitychange'); + }); + } + + PDFFindBar.prototype = { + dispatchEvent: function PDFFindBar_dispatchEvent(type, findPrev) { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('find' + type, true, true, { + query: this.findField.value, + caseSensitive: this.caseSensitive.checked, + highlightAll: this.highlightAll.checked, + findPrevious: findPrev + }); + return window.dispatchEvent(event); + }, + + updateUIState: function PDFFindBar_updateUIState(state, previous) { + var notFound = false; + var findMsg = ''; + var status = ''; + + switch (state) { + case FindStates.FIND_FOUND: + break; + + case FindStates.FIND_PENDING: + status = 'pending'; + break; + + case FindStates.FIND_NOTFOUND: + findMsg = mozL10n.get('find_not_found', null, 'Phrase not found'); + notFound = true; + break; + + case FindStates.FIND_WRAPPED: + if (previous) { + findMsg = mozL10n.get('find_reached_top', null, + 'Reached top of document, continued from bottom'); + } else { + findMsg = mozL10n.get('find_reached_bottom', null, + 'Reached end of document, continued from top'); + } + break; + } + + if (notFound) { + this.findField.classList.add('notFound'); + } else { + this.findField.classList.remove('notFound'); + } + + this.findField.setAttribute('data-status', status); + this.findMsg.textContent = findMsg; + }, + + open: function PDFFindBar_open() { + if (!this.opened) { + this.opened = true; + this.toggleButton.classList.add('toggled'); + this.bar.classList.remove('hidden'); + } + this.findField.select(); + this.findField.focus(); + }, + + close: function PDFFindBar_close() { + if (!this.opened) { + return; + } + this.opened = false; + this.toggleButton.classList.remove('toggled'); + this.bar.classList.add('hidden'); + this.findController.active = false; + }, + + toggle: function PDFFindBar_toggle() { + if (this.opened) { + this.close(); + } else { + this.open(); + } + } + }; + return PDFFindBar; +})(); + + +var FindStates = { + FIND_FOUND: 0, + FIND_NOTFOUND: 1, + FIND_WRAPPED: 2, + FIND_PENDING: 3 +}; + +var FIND_SCROLL_OFFSET_TOP = -50; +var FIND_SCROLL_OFFSET_LEFT = -400; + +/** + * Provides "search" or "find" functionality for the PDF. + * This object actually performs the search for a given string. + */ +var PDFFindController = (function PDFFindControllerClosure() { + function PDFFindController(options) { + this.startedTextExtraction = false; + this.extractTextPromises = []; + this.pendingFindMatches = {}; + this.active = false; // If active, find results will be highlighted. + this.pageContents = []; // Stores the text for each page. + this.pageMatches = []; + this.selected = { // Currently selected match. + pageIdx: -1, + matchIdx: -1 + }; + this.offset = { // Where the find algorithm currently is in the document. + pageIdx: null, + matchIdx: null + }; + this.pagesToSearch = null; + this.resumePageIdx = null; + this.state = null; + this.dirtyMatch = false; + this.findTimeout = null; + this.pdfViewer = options.pdfViewer || null; + this.integratedFind = options.integratedFind || false; + this.charactersToNormalize = { + '\u2018': '\'', // Left single quotation mark + '\u2019': '\'', // Right single quotation mark + '\u201A': '\'', // Single low-9 quotation mark + '\u201B': '\'', // Single high-reversed-9 quotation mark + '\u201C': '"', // Left double quotation mark + '\u201D': '"', // Right double quotation mark + '\u201E': '"', // Double low-9 quotation mark + '\u201F': '"', // Double high-reversed-9 quotation mark + '\u00BC': '1/4', // Vulgar fraction one quarter + '\u00BD': '1/2', // Vulgar fraction one half + '\u00BE': '3/4', // Vulgar fraction three quarters + '\u00A0': ' ' // No-break space + }; + this.findBar = options.findBar || null; + + // Compile the regular expression for text normalization once + var replace = Object.keys(this.charactersToNormalize).join(''); + this.normalizationRegex = new RegExp('[' + replace + ']', 'g'); + + var events = [ + 'find', + 'findagain', + 'findhighlightallchange', + 'findcasesensitivitychange' + ]; + + this.firstPagePromise = new Promise(function (resolve) { + this.resolveFirstPage = resolve; + }.bind(this)); + this.handleEvent = this.handleEvent.bind(this); + + for (var i = 0, len = events.length; i < len; i++) { + window.addEventListener(events[i], this.handleEvent); + } + } + + PDFFindController.prototype = { + setFindBar: function PDFFindController_setFindBar(findBar) { + this.findBar = findBar; + }, + + reset: function PDFFindController_reset() { + this.startedTextExtraction = false; + this.extractTextPromises = []; + this.active = false; + }, + + normalize: function PDFFindController_normalize(text) { + var self = this; + return text.replace(this.normalizationRegex, function (ch) { + return self.charactersToNormalize[ch]; + }); + }, + + calcFindMatch: function PDFFindController_calcFindMatch(pageIndex) { + var pageContent = this.normalize(this.pageContents[pageIndex]); + var query = this.normalize(this.state.query); + var caseSensitive = this.state.caseSensitive; + var queryLen = query.length; + + if (queryLen === 0) { + return; // Do nothing: the matches should be wiped out already. + } + + if (!caseSensitive) { + pageContent = pageContent.toLowerCase(); + query = query.toLowerCase(); + } + + var matches = []; + var matchIdx = -queryLen; + while (true) { + matchIdx = pageContent.indexOf(query, matchIdx + queryLen); + if (matchIdx === -1) { + break; + } + matches.push(matchIdx); + } + this.pageMatches[pageIndex] = matches; + this.updatePage(pageIndex); + if (this.resumePageIdx === pageIndex) { + this.resumePageIdx = null; + this.nextPageMatch(); + } + }, + + extractText: function PDFFindController_extractText() { + if (this.startedTextExtraction) { + return; + } + this.startedTextExtraction = true; + + this.pageContents = []; + var extractTextPromisesResolves = []; + var numPages = this.pdfViewer.pagesCount; + for (var i = 0; i < numPages; i++) { + this.extractTextPromises.push(new Promise(function (resolve) { + extractTextPromisesResolves.push(resolve); + })); + } + + var self = this; + function extractPageText(pageIndex) { + self.pdfViewer.getPageTextContent(pageIndex).then( + function textContentResolved(textContent) { + var textItems = textContent.items; + var str = []; + + for (var i = 0, len = textItems.length; i < len; i++) { + str.push(textItems[i].str); + } + + // Store the pageContent as a string. + self.pageContents.push(str.join('')); + + extractTextPromisesResolves[pageIndex](pageIndex); + if ((pageIndex + 1) < self.pdfViewer.pagesCount) { + extractPageText(pageIndex + 1); + } + } + ); + } + extractPageText(0); + }, + + handleEvent: function PDFFindController_handleEvent(e) { + if (this.state === null || e.type !== 'findagain') { + this.dirtyMatch = true; + } + this.state = e.detail; + this.updateUIState(FindStates.FIND_PENDING); + + this.firstPagePromise.then(function() { + this.extractText(); + + clearTimeout(this.findTimeout); + if (e.type === 'find') { + // Only trigger the find action after 250ms of silence. + this.findTimeout = setTimeout(this.nextMatch.bind(this), 250); + } else { + this.nextMatch(); + } + }.bind(this)); + }, + + updatePage: function PDFFindController_updatePage(index) { + if (this.selected.pageIdx === index) { + // If the page is selected, scroll the page into view, which triggers + // rendering the page, which adds the textLayer. Once the textLayer is + // build, it will scroll onto the selected match. + this.pdfViewer.scrollPageIntoView(index + 1); + } + + var page = this.pdfViewer.getPageView(index); + if (page.textLayer) { + page.textLayer.updateMatches(); + } + }, + + nextMatch: function PDFFindController_nextMatch() { + var previous = this.state.findPrevious; + var currentPageIndex = this.pdfViewer.currentPageNumber - 1; + var numPages = this.pdfViewer.pagesCount; + + this.active = true; + + if (this.dirtyMatch) { + // Need to recalculate the matches, reset everything. + this.dirtyMatch = false; + this.selected.pageIdx = this.selected.matchIdx = -1; + this.offset.pageIdx = currentPageIndex; + this.offset.matchIdx = null; + this.hadMatch = false; + this.resumePageIdx = null; + this.pageMatches = []; + var self = this; + + for (var i = 0; i < numPages; i++) { + // Wipe out any previous highlighted matches. + this.updatePage(i); + + // As soon as the text is extracted start finding the matches. + if (!(i in this.pendingFindMatches)) { + this.pendingFindMatches[i] = true; + this.extractTextPromises[i].then(function(pageIdx) { + delete self.pendingFindMatches[pageIdx]; + self.calcFindMatch(pageIdx); + }); + } + } + } + + // If there's no query there's no point in searching. + if (this.state.query === '') { + this.updateUIState(FindStates.FIND_FOUND); + return; + } + + // If we're waiting on a page, we return since we can't do anything else. + if (this.resumePageIdx) { + return; + } + + var offset = this.offset; + // Keep track of how many pages we should maximally iterate through. + this.pagesToSearch = numPages; + // If there's already a matchIdx that means we are iterating through a + // page's matches. + if (offset.matchIdx !== null) { + var numPageMatches = this.pageMatches[offset.pageIdx].length; + if ((!previous && offset.matchIdx + 1 < numPageMatches) || + (previous && offset.matchIdx > 0)) { + // The simple case; we just have advance the matchIdx to select + // the next match on the page. + this.hadMatch = true; + offset.matchIdx = (previous ? offset.matchIdx - 1 : + offset.matchIdx + 1); + this.updateMatch(true); + return; + } + // We went beyond the current page's matches, so we advance to + // the next page. + this.advanceOffsetPage(previous); + } + // Start searching through the page. + this.nextPageMatch(); + }, + + matchesReady: function PDFFindController_matchesReady(matches) { + var offset = this.offset; + var numMatches = matches.length; + var previous = this.state.findPrevious; + + if (numMatches) { + // There were matches for the page, so initialize the matchIdx. + this.hadMatch = true; + offset.matchIdx = (previous ? numMatches - 1 : 0); + this.updateMatch(true); + return true; + } else { + // No matches, so attempt to search the next page. + this.advanceOffsetPage(previous); + if (offset.wrapped) { + offset.matchIdx = null; + if (this.pagesToSearch < 0) { + // No point in wrapping again, there were no matches. + this.updateMatch(false); + // while matches were not found, searching for a page + // with matches should nevertheless halt. + return true; + } + } + // Matches were not found (and searching is not done). + return false; + } + }, + + /** + * The method is called back from the text layer when match presentation + * is updated. + * @param {number} pageIndex - page index. + * @param {number} index - match index. + * @param {Array} elements - text layer div elements array. + * @param {number} beginIdx - start index of the div array for the match. + * @param {number} endIdx - end index of the div array for the match. + */ + updateMatchPosition: function PDFFindController_updateMatchPosition( + pageIndex, index, elements, beginIdx, endIdx) { + if (this.selected.matchIdx === index && + this.selected.pageIdx === pageIndex) { + scrollIntoView(elements[beginIdx], { + top: FIND_SCROLL_OFFSET_TOP, + left: FIND_SCROLL_OFFSET_LEFT + }); + } + }, + + nextPageMatch: function PDFFindController_nextPageMatch() { + if (this.resumePageIdx !== null) { + console.error('There can only be one pending page.'); + } + do { + var pageIdx = this.offset.pageIdx; + var matches = this.pageMatches[pageIdx]; + if (!matches) { + // The matches don't exist yet for processing by "matchesReady", + // so set a resume point for when they do exist. + this.resumePageIdx = pageIdx; + break; + } + } while (!this.matchesReady(matches)); + }, + + advanceOffsetPage: function PDFFindController_advanceOffsetPage(previous) { + var offset = this.offset; + var numPages = this.extractTextPromises.length; + offset.pageIdx = (previous ? offset.pageIdx - 1 : offset.pageIdx + 1); + offset.matchIdx = null; + + this.pagesToSearch--; + + if (offset.pageIdx >= numPages || offset.pageIdx < 0) { + offset.pageIdx = (previous ? numPages - 1 : 0); + offset.wrapped = true; + } + }, + + updateMatch: function PDFFindController_updateMatch(found) { + var state = FindStates.FIND_NOTFOUND; + var wrapped = this.offset.wrapped; + this.offset.wrapped = false; + + if (found) { + var previousPage = this.selected.pageIdx; + this.selected.pageIdx = this.offset.pageIdx; + this.selected.matchIdx = this.offset.matchIdx; + state = (wrapped ? FindStates.FIND_WRAPPED : FindStates.FIND_FOUND); + // Update the currently selected page to wipe out any selected matches. + if (previousPage !== -1 && previousPage !== this.selected.pageIdx) { + this.updatePage(previousPage); + } + } + + this.updateUIState(state, this.state.findPrevious); + if (this.selected.pageIdx !== -1) { + this.updatePage(this.selected.pageIdx); + } + }, + + updateUIState: function PDFFindController_updateUIState(state, previous) { + if (this.integratedFind) { + FirefoxCom.request('updateFindControlState', + { result: state, findPrevious: previous }); + return; + } + if (this.findBar === null) { + throw new Error('PDFFindController is not initialized with a ' + + 'PDFFindBar instance.'); + } + this.findBar.updateUIState(state, previous); + } + }; + return PDFFindController; +})(); + + +var PDFHistory = { + initialized: false, + initialDestination: null, + + /** + * @param {string} fingerprint + * @param {IPDFLinkService} linkService + */ + initialize: function pdfHistoryInitialize(fingerprint, linkService) { + this.initialized = true; + this.reInitialized = false; + this.allowHashChange = true; + this.historyUnlocked = true; + this.isViewerInPresentationMode = false; + + this.previousHash = window.location.hash.substring(1); + this.currentBookmark = ''; + this.currentPage = 0; + this.updatePreviousBookmark = false; + this.previousBookmark = ''; + this.previousPage = 0; + this.nextHashParam = ''; + + this.fingerprint = fingerprint; + this.linkService = linkService; + this.currentUid = this.uid = 0; + this.current = {}; + + var state = window.history.state; + if (this._isStateObjectDefined(state)) { + // This corresponds to navigating back to the document + // from another page in the browser history. + if (state.target.dest) { + this.initialDestination = state.target.dest; + } else { + linkService.setHash(state.target.hash); + } + this.currentUid = state.uid; + this.uid = state.uid + 1; + this.current = state.target; + } else { + // This corresponds to the loading of a new document. + if (state && state.fingerprint && + this.fingerprint !== state.fingerprint) { + // Reinitialize the browsing history when a new document + // is opened in the web viewer. + this.reInitialized = true; + } + this._pushOrReplaceState({ fingerprint: this.fingerprint }, true); + } + + var self = this; + window.addEventListener('popstate', function pdfHistoryPopstate(evt) { + evt.preventDefault(); + evt.stopPropagation(); + + if (!self.historyUnlocked) { + return; + } + if (evt.state) { + // Move back/forward in the history. + self._goTo(evt.state); + } else { + // Handle the user modifying the hash of a loaded document. + self.previousHash = window.location.hash.substring(1); + + // If the history is empty when the hash changes, + // update the previous entry in the browser history. + if (self.uid === 0) { + var previousParams = (self.previousHash && self.currentBookmark && + self.previousHash !== self.currentBookmark) ? + { hash: self.currentBookmark, page: self.currentPage } : + { page: 1 }; + self.historyUnlocked = false; + self.allowHashChange = false; + window.history.back(); + self._pushToHistory(previousParams, false, true); + window.history.forward(); + self.historyUnlocked = true; + } + self._pushToHistory({ hash: self.previousHash }, false, true); + self._updatePreviousBookmark(); + } + }, false); + + function pdfHistoryBeforeUnload() { + var previousParams = self._getPreviousParams(null, true); + if (previousParams) { + var replacePrevious = (!self.current.dest && + self.current.hash !== self.previousHash); + self._pushToHistory(previousParams, false, replacePrevious); + self._updatePreviousBookmark(); + } + // Remove the event listener when navigating away from the document, + // since 'beforeunload' prevents Firefox from caching the document. + window.removeEventListener('beforeunload', pdfHistoryBeforeUnload, false); + } + window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false); + + window.addEventListener('pageshow', function pdfHistoryPageShow(evt) { + // If the entire viewer (including the PDF file) is cached in the browser, + // we need to reattach the 'beforeunload' event listener since + // the 'DOMContentLoaded' event is not fired on 'pageshow'. + window.addEventListener('beforeunload', pdfHistoryBeforeUnload, false); + }, false); + + window.addEventListener('presentationmodechanged', function(e) { + self.isViewerInPresentationMode = !!e.detail.active; + }); + }, + + _isStateObjectDefined: function pdfHistory_isStateObjectDefined(state) { + return (state && state.uid >= 0 && + state.fingerprint && this.fingerprint === state.fingerprint && + state.target && state.target.hash) ? true : false; + }, + + _pushOrReplaceState: function pdfHistory_pushOrReplaceState(stateObj, + replace) { + if (replace) { + window.history.replaceState(stateObj, '', document.URL); + } else { + window.history.pushState(stateObj, '', document.URL); + } + }, + + get isHashChangeUnlocked() { + if (!this.initialized) { + return true; + } + // If the current hash changes when moving back/forward in the history, + // this will trigger a 'popstate' event *as well* as a 'hashchange' event. + // Since the hash generally won't correspond to the exact the position + // stored in the history's state object, triggering the 'hashchange' event + // can thus corrupt the browser history. + // + // When the hash changes during a 'popstate' event, we *only* prevent the + // first 'hashchange' event and immediately reset allowHashChange. + // If it is not reset, the user would not be able to change the hash. + + var temp = this.allowHashChange; + this.allowHashChange = true; + return temp; + }, + + _updatePreviousBookmark: function pdfHistory_updatePreviousBookmark() { + if (this.updatePreviousBookmark && + this.currentBookmark && this.currentPage) { + this.previousBookmark = this.currentBookmark; + this.previousPage = this.currentPage; + this.updatePreviousBookmark = false; + } + }, + + updateCurrentBookmark: function pdfHistoryUpdateCurrentBookmark(bookmark, + pageNum) { + if (this.initialized) { + this.currentBookmark = bookmark.substring(1); + this.currentPage = pageNum | 0; + this._updatePreviousBookmark(); + } + }, + + updateNextHashParam: function pdfHistoryUpdateNextHashParam(param) { + if (this.initialized) { + this.nextHashParam = param; + } + }, + + push: function pdfHistoryPush(params, isInitialBookmark) { + if (!(this.initialized && this.historyUnlocked)) { + return; + } + if (params.dest && !params.hash) { + params.hash = (this.current.hash && this.current.dest && + this.current.dest === params.dest) ? + this.current.hash : + this.linkService.getDestinationHash(params.dest).split('#')[1]; + } + if (params.page) { + params.page |= 0; + } + if (isInitialBookmark) { + var target = window.history.state.target; + if (!target) { + // Invoked when the user specifies an initial bookmark, + // thus setting initialBookmark, when the document is loaded. + this._pushToHistory(params, false); + this.previousHash = window.location.hash.substring(1); + } + this.updatePreviousBookmark = this.nextHashParam ? false : true; + if (target) { + // If the current document is reloaded, + // avoid creating duplicate entries in the history. + this._updatePreviousBookmark(); + } + return; + } + if (this.nextHashParam) { + if (this.nextHashParam === params.hash) { + this.nextHashParam = null; + this.updatePreviousBookmark = true; + return; + } else { + this.nextHashParam = null; + } + } + + if (params.hash) { + if (this.current.hash) { + if (this.current.hash !== params.hash) { + this._pushToHistory(params, true); + } else { + if (!this.current.page && params.page) { + this._pushToHistory(params, false, true); + } + this.updatePreviousBookmark = true; + } + } else { + this._pushToHistory(params, true); + } + } else if (this.current.page && params.page && + this.current.page !== params.page) { + this._pushToHistory(params, true); + } + }, + + _getPreviousParams: function pdfHistory_getPreviousParams(onlyCheckPage, + beforeUnload) { + if (!(this.currentBookmark && this.currentPage)) { + return null; + } else if (this.updatePreviousBookmark) { + this.updatePreviousBookmark = false; + } + if (this.uid > 0 && !(this.previousBookmark && this.previousPage)) { + // Prevent the history from getting stuck in the current state, + // effectively preventing the user from going back/forward in the history. + // + // This happens if the current position in the document didn't change when + // the history was previously updated. The reasons for this are either: + // 1. The current zoom value is such that the document does not need to, + // or cannot, be scrolled to display the destination. + // 2. The previous destination is broken, and doesn't actally point to a + // position within the document. + // (This is either due to a bad PDF generator, or the user making a + // mistake when entering a destination in the hash parameters.) + return null; + } + if ((!this.current.dest && !onlyCheckPage) || beforeUnload) { + if (this.previousBookmark === this.currentBookmark) { + return null; + } + } else if (this.current.page || onlyCheckPage) { + if (this.previousPage === this.currentPage) { + return null; + } + } else { + return null; + } + var params = { hash: this.currentBookmark, page: this.currentPage }; + if (this.isViewerInPresentationMode) { + params.hash = null; + } + return params; + }, + + _stateObj: function pdfHistory_stateObj(params) { + return { fingerprint: this.fingerprint, uid: this.uid, target: params }; + }, + + _pushToHistory: function pdfHistory_pushToHistory(params, + addPrevious, overwrite) { + if (!this.initialized) { + return; + } + if (!params.hash && params.page) { + params.hash = ('page=' + params.page); + } + if (addPrevious && !overwrite) { + var previousParams = this._getPreviousParams(); + if (previousParams) { + var replacePrevious = (!this.current.dest && + this.current.hash !== this.previousHash); + this._pushToHistory(previousParams, false, replacePrevious); + } + } + this._pushOrReplaceState(this._stateObj(params), + (overwrite || this.uid === 0)); + this.currentUid = this.uid++; + this.current = params; + this.updatePreviousBookmark = true; + }, + + _goTo: function pdfHistory_goTo(state) { + if (!(this.initialized && this.historyUnlocked && + this._isStateObjectDefined(state))) { + return; + } + if (!this.reInitialized && state.uid < this.currentUid) { + var previousParams = this._getPreviousParams(true); + if (previousParams) { + this._pushToHistory(this.current, false); + this._pushToHistory(previousParams, false); + this.currentUid = state.uid; + window.history.back(); + return; + } + } + this.historyUnlocked = false; + + if (state.target.dest) { + this.linkService.navigateTo(state.target.dest); + } else { + this.linkService.setHash(state.target.hash); + } + this.currentUid = state.uid; + if (state.uid > this.uid) { + this.uid = state.uid; + } + this.current = state.target; + this.updatePreviousBookmark = true; + + var currentHash = window.location.hash.substring(1); + if (this.previousHash !== currentHash) { + this.allowHashChange = false; + } + this.previousHash = currentHash; + + this.historyUnlocked = true; + }, + + back: function pdfHistoryBack() { + this.go(-1); + }, + + forward: function pdfHistoryForward() { + this.go(1); + }, + + go: function pdfHistoryGo(direction) { + if (this.initialized && this.historyUnlocked) { + var state = window.history.state; + if (direction === -1 && state && state.uid > 0) { + window.history.back(); + } else if (direction === 1 && state && state.uid < (this.uid - 1)) { + window.history.forward(); + } + } + } +}; + + +var SecondaryToolbar = { + opened: false, + previousContainerHeight: null, + newContainerHeight: null, + + initialize: function secondaryToolbarInitialize(options) { + this.toolbar = options.toolbar; + this.buttonContainer = this.toolbar.firstElementChild; + + // Define the toolbar buttons. + this.toggleButton = options.toggleButton; + this.presentationModeButton = options.presentationModeButton; + this.openFile = options.openFile; + this.print = options.print; + this.download = options.download; + this.viewBookmark = options.viewBookmark; + this.firstPage = options.firstPage; + this.lastPage = options.lastPage; + this.pageRotateCw = options.pageRotateCw; + this.pageRotateCcw = options.pageRotateCcw; + this.documentPropertiesButton = options.documentPropertiesButton; + + // Attach the event listeners. + var elements = [ + // Button to toggle the visibility of the secondary toolbar: + { element: this.toggleButton, handler: this.toggle }, + // All items within the secondary toolbar + // (except for toggleHandTool, hand_tool.js is responsible for it): + { element: this.presentationModeButton, + handler: this.presentationModeClick }, + { element: this.openFile, handler: this.openFileClick }, + { element: this.print, handler: this.printClick }, + { element: this.download, handler: this.downloadClick }, + { element: this.viewBookmark, handler: this.viewBookmarkClick }, + { element: this.firstPage, handler: this.firstPageClick }, + { element: this.lastPage, handler: this.lastPageClick }, + { element: this.pageRotateCw, handler: this.pageRotateCwClick }, + { element: this.pageRotateCcw, handler: this.pageRotateCcwClick }, + { element: this.documentPropertiesButton, + handler: this.documentPropertiesClick } + ]; + + for (var item in elements) { + var element = elements[item].element; + if (element) { + element.addEventListener('click', elements[item].handler.bind(this)); + } + } + }, + + // Event handling functions. + presentationModeClick: function secondaryToolbarPresentationModeClick(evt) { + PDFViewerApplication.requestPresentationMode(); + this.close(); + }, + + openFileClick: function secondaryToolbarOpenFileClick(evt) { + document.getElementById('fileInput').click(); + this.close(); + }, + + printClick: function secondaryToolbarPrintClick(evt) { + window.print(); + this.close(); + }, + + downloadClick: function secondaryToolbarDownloadClick(evt) { + PDFViewerApplication.download(); + this.close(); + }, + + viewBookmarkClick: function secondaryToolbarViewBookmarkClick(evt) { + this.close(); + }, + + firstPageClick: function secondaryToolbarFirstPageClick(evt) { + PDFViewerApplication.page = 1; + this.close(); + }, + + lastPageClick: function secondaryToolbarLastPageClick(evt) { + if (PDFViewerApplication.pdfDocument) { + PDFViewerApplication.page = PDFViewerApplication.pagesCount; + } + this.close(); + }, + + pageRotateCwClick: function secondaryToolbarPageRotateCwClick(evt) { + PDFViewerApplication.rotatePages(90); + }, + + pageRotateCcwClick: function secondaryToolbarPageRotateCcwClick(evt) { + PDFViewerApplication.rotatePages(-90); + }, + + documentPropertiesClick: function secondaryToolbarDocumentPropsClick(evt) { + PDFViewerApplication.pdfDocumentProperties.open(); + this.close(); + }, + + // Misc. functions for interacting with the toolbar. + setMaxHeight: function secondaryToolbarSetMaxHeight(container) { + if (!container || !this.buttonContainer) { + return; + } + this.newContainerHeight = container.clientHeight; + if (this.previousContainerHeight === this.newContainerHeight) { + return; + } + this.buttonContainer.setAttribute('style', + 'max-height: ' + (this.newContainerHeight - SCROLLBAR_PADDING) + 'px;'); + this.previousContainerHeight = this.newContainerHeight; + }, + + open: function secondaryToolbarOpen() { + if (this.opened) { + return; + } + this.opened = true; + this.toggleButton.classList.add('toggled'); + this.toolbar.classList.remove('hidden'); + }, + + close: function secondaryToolbarClose(target) { + if (!this.opened) { + return; + } else if (target && !this.toolbar.contains(target)) { + return; + } + this.opened = false; + this.toolbar.classList.add('hidden'); + this.toggleButton.classList.remove('toggled'); + }, + + toggle: function secondaryToolbarToggle() { + if (this.opened) { + this.close(); + } else { + this.open(); + } + } +}; + + +var DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500; // in ms +var DELAY_BEFORE_HIDING_CONTROLS = 3000; // in ms +var ACTIVE_SELECTOR = 'pdfPresentationMode'; +var CONTROLS_SELECTOR = 'pdfPresentationModeControls'; + +/** + * @typedef {Object} PDFPresentationModeOptions + * @property {HTMLDivElement} container - The container for the viewer element. + * @property {HTMLDivElement} viewer - (optional) The viewer element. + * @property {PDFThumbnailViewer} pdfThumbnailViewer - (optional) The thumbnail + * viewer. + * @property {Array} contextMenuItems - (optional) The menuitems that are added + * to the context menu in Presentation Mode. + */ + +/** + * @class + */ +var PDFPresentationMode = (function PDFPresentationModeClosure() { + /** + * @constructs PDFPresentationMode + * @param {PDFPresentationModeOptions} options + */ + function PDFPresentationMode(options) { + this.container = options.container; + this.viewer = options.viewer || options.container.firstElementChild; + this.pdfThumbnailViewer = options.pdfThumbnailViewer || null; + var contextMenuItems = options.contextMenuItems || null; + + this.active = false; + this.args = null; + this.contextMenuOpen = false; + this.mouseScrollTimeStamp = 0; + this.mouseScrollDelta = 0; + + if (contextMenuItems) { + for (var i = 0, ii = contextMenuItems.length; i < ii; i++) { + var item = contextMenuItems[i]; + item.element.addEventListener('click', function (handler) { + this.contextMenuOpen = false; + handler(); + }.bind(this, item.handler)); + } + } + } + + PDFPresentationMode.prototype = { + /** + * Request the browser to enter fullscreen mode. + * @returns {boolean} Indicating if the request was successful. + */ + request: function PDFPresentationMode_request() { + if (this.switchInProgress || this.active || + !this.viewer.hasChildNodes()) { + return false; + } + this._addFullscreenChangeListeners(); + this._setSwitchInProgress(); + this._notifyStateChange(); + + if (this.container.requestFullscreen) { + this.container.requestFullscreen(); + } else if (this.container.mozRequestFullScreen) { + this.container.mozRequestFullScreen(); + } else if (this.container.webkitRequestFullscreen) { + this.container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); + } else if (this.container.msRequestFullscreen) { + this.container.msRequestFullscreen(); + } else { + return false; + } + + this.args = { + page: PDFViewerApplication.page, + previousScale: PDFViewerApplication.currentScaleValue + }; + + return true; + }, + + /** + * Switches page when the user scrolls (using a scroll wheel or a touchpad) + * with large enough motion, to prevent accidental page switches. + * @param {number} delta - The delta value from the mouse event. + */ + mouseScroll: function PDFPresentationMode_mouseScroll(delta) { + if (!this.active) { + return; + } + var MOUSE_SCROLL_COOLDOWN_TIME = 50; + var PAGE_SWITCH_THRESHOLD = 120; + var PageSwitchDirection = { + UP: -1, + DOWN: 1 + }; + + var currentTime = (new Date()).getTime(); + var storedTime = this.mouseScrollTimeStamp; + + // If we've already switched page, avoid accidentally switching again. + if (currentTime > storedTime && + currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) { + return; + } + // If the scroll direction changed, reset the accumulated scroll delta. + if ((this.mouseScrollDelta > 0 && delta < 0) || + (this.mouseScrollDelta < 0 && delta > 0)) { + this._resetMouseScrollState(); + } + this.mouseScrollDelta += delta; + + if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) { + var pageSwitchDirection = (this.mouseScrollDelta > 0) ? + PageSwitchDirection.UP : PageSwitchDirection.DOWN; + var page = PDFViewerApplication.page; + this._resetMouseScrollState(); + + // If we're at the first/last page, we don't need to do anything. + if ((page === 1 && pageSwitchDirection === PageSwitchDirection.UP) || + (page === PDFViewerApplication.pagesCount && + pageSwitchDirection === PageSwitchDirection.DOWN)) { + return; + } + PDFViewerApplication.page = (page + pageSwitchDirection); + this.mouseScrollTimeStamp = currentTime; + } + }, + + get isFullscreen() { + return !!(document.fullscreenElement || + document.mozFullScreen || + document.webkitIsFullScreen || + document.msFullscreenElement); + }, + + /** + * @private + */ + _notifyStateChange: function PDFPresentationMode_notifyStateChange() { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('presentationmodechanged', true, true, { + active: this.active, + switchInProgress: !!this.switchInProgress + }); + window.dispatchEvent(event); + }, + + /** + * Used to initialize a timeout when requesting Presentation Mode, + * i.e. when the browser is requested to enter fullscreen mode. + * This timeout is used to prevent the current page from being scrolled + * partially, or completely, out of view when entering Presentation Mode. + * NOTE: This issue seems limited to certain zoom levels (e.g. page-width). + * @private + */ + _setSwitchInProgress: function PDFPresentationMode_setSwitchInProgress() { + if (this.switchInProgress) { + clearTimeout(this.switchInProgress); + } + this.switchInProgress = setTimeout(function switchInProgressTimeout() { + this._removeFullscreenChangeListeners(); + delete this.switchInProgress; + this._notifyStateChange(); + }.bind(this), DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS); + }, + + /** + * @private + */ + _resetSwitchInProgress: + function PDFPresentationMode_resetSwitchInProgress() { + if (this.switchInProgress) { + clearTimeout(this.switchInProgress); + delete this.switchInProgress; + } + }, + + /** + * @private + */ + _enter: function PDFPresentationMode_enter() { + this.active = true; + this._resetSwitchInProgress(); + this._notifyStateChange(); + this.container.classList.add(ACTIVE_SELECTOR); + + // Ensure that the correct page is scrolled into view when entering + // Presentation Mode, by waiting until fullscreen mode in enabled. + setTimeout(function enterPresentationModeTimeout() { + PDFViewerApplication.page = this.args.page; + PDFViewerApplication.setScale('page-fit', true); + }.bind(this), 0); + + this._addWindowListeners(); + this._showControls(); + this.contextMenuOpen = false; + this.container.setAttribute('contextmenu', 'viewerContextMenu'); + + // Text selection is disabled in Presentation Mode, thus it's not possible + // for the user to deselect text that is selected (e.g. with "Select all") + // when entering Presentation Mode, hence we remove any active selection. + window.getSelection().removeAllRanges(); + }, + + /** + * @private + */ + _exit: function PDFPresentationMode_exit() { + var page = PDFViewerApplication.page; + this.container.classList.remove(ACTIVE_SELECTOR); + + // Ensure that the correct page is scrolled into view when exiting + // Presentation Mode, by waiting until fullscreen mode is disabled. + setTimeout(function exitPresentationModeTimeout() { + this.active = false; + this._removeFullscreenChangeListeners(); + this._notifyStateChange(); + + PDFViewerApplication.setScale(this.args.previousScale, true); + PDFViewerApplication.page = page; + this.args = null; + }.bind(this), 0); + + this._removeWindowListeners(); + this._hideControls(); + this._resetMouseScrollState(); + this.container.removeAttribute('contextmenu'); + this.contextMenuOpen = false; + + if (this.pdfThumbnailViewer) { + this.pdfThumbnailViewer.ensureThumbnailVisible(page); + } + }, + + /** + * @private + */ + _mouseDown: function PDFPresentationMode_mouseDown(evt) { + if (this.contextMenuOpen) { + this.contextMenuOpen = false; + evt.preventDefault(); + return; + } + if (evt.button === 0) { + // Enable clicking of links in presentation mode. Please note: + // Only links pointing to destinations in the current PDF document work. + var isInternalLink = (evt.target.href && + evt.target.classList.contains('internalLink')); + if (!isInternalLink) { + // Unless an internal link was clicked, advance one page. + evt.preventDefault(); + PDFViewerApplication.page += (evt.shiftKey ? -1 : 1); + } + } + }, + + /** + * @private + */ + _contextMenu: function PDFPresentationMode_contextMenu() { + this.contextMenuOpen = true; + }, + + /** + * @private + */ + _showControls: function PDFPresentationMode_showControls() { + if (this.controlsTimeout) { + clearTimeout(this.controlsTimeout); + } else { + this.container.classList.add(CONTROLS_SELECTOR); + } + this.controlsTimeout = setTimeout(function showControlsTimeout() { + this.container.classList.remove(CONTROLS_SELECTOR); + delete this.controlsTimeout; + }.bind(this), DELAY_BEFORE_HIDING_CONTROLS); + }, + + /** + * @private + */ + _hideControls: function PDFPresentationMode_hideControls() { + if (!this.controlsTimeout) { + return; + } + clearTimeout(this.controlsTimeout); + this.container.classList.remove(CONTROLS_SELECTOR); + delete this.controlsTimeout; + }, + + /** + * Resets the properties used for tracking mouse scrolling events. + * @private + */ + _resetMouseScrollState: + function PDFPresentationMode_resetMouseScrollState() { + this.mouseScrollTimeStamp = 0; + this.mouseScrollDelta = 0; + }, + + /** + * @private + */ + _addWindowListeners: function PDFPresentationMode_addWindowListeners() { + this.showControlsBind = this._showControls.bind(this); + this.mouseDownBind = this._mouseDown.bind(this); + this.resetMouseScrollStateBind = this._resetMouseScrollState.bind(this); + this.contextMenuBind = this._contextMenu.bind(this); + + window.addEventListener('mousemove', this.showControlsBind); + window.addEventListener('mousedown', this.mouseDownBind); + window.addEventListener('keydown', this.resetMouseScrollStateBind); + window.addEventListener('contextmenu', this.contextMenuBind); + }, + + /** + * @private + */ + _removeWindowListeners: + function PDFPresentationMode_removeWindowListeners() { + window.removeEventListener('mousemove', this.showControlsBind); + window.removeEventListener('mousedown', this.mouseDownBind); + window.removeEventListener('keydown', this.resetMouseScrollStateBind); + window.removeEventListener('contextmenu', this.contextMenuBind); + + delete this.showControlsBind; + delete this.mouseDownBind; + delete this.resetMouseScrollStateBind; + delete this.contextMenuBind; + }, + + /** + * @private + */ + _fullscreenChange: function PDFPresentationMode_fullscreenChange() { + if (this.isFullscreen) { + this._enter(); + } else { + this._exit(); + } + }, + + /** + * @private + */ + _addFullscreenChangeListeners: + function PDFPresentationMode_addFullscreenChangeListeners() { + this.fullscreenChangeBind = this._fullscreenChange.bind(this); + + window.addEventListener('fullscreenchange', this.fullscreenChangeBind); + window.addEventListener('mozfullscreenchange', this.fullscreenChangeBind); + window.addEventListener('webkitfullscreenchange', + this.fullscreenChangeBind); + window.addEventListener('MSFullscreenChange', this.fullscreenChangeBind); + }, + + /** + * @private + */ + _removeFullscreenChangeListeners: + function PDFPresentationMode_removeFullscreenChangeListeners() { + window.removeEventListener('fullscreenchange', this.fullscreenChangeBind); + window.removeEventListener('mozfullscreenchange', + this.fullscreenChangeBind); + window.removeEventListener('webkitfullscreenchange', + this.fullscreenChangeBind); + window.removeEventListener('MSFullscreenChange', + this.fullscreenChangeBind); + + delete this.fullscreenChangeBind; + } + }; + + return PDFPresentationMode; +})(); + + +/* Copyright 2013 Rob Wu + * https://github.com/Rob--W/grab-to-pan.js + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +var GrabToPan = (function GrabToPanClosure() { + /** + * Construct a GrabToPan instance for a given HTML element. + * @param options.element {Element} + * @param options.ignoreTarget {function} optional. See `ignoreTarget(node)` + * @param options.onActiveChanged {function(boolean)} optional. Called + * when grab-to-pan is (de)activated. The first argument is a boolean that + * shows whether grab-to-pan is activated. + */ + function GrabToPan(options) { + this.element = options.element; + this.document = options.element.ownerDocument; + if (typeof options.ignoreTarget === 'function') { + this.ignoreTarget = options.ignoreTarget; + } + this.onActiveChanged = options.onActiveChanged; + + // Bind the contexts to ensure that `this` always points to + // the GrabToPan instance. + this.activate = this.activate.bind(this); + this.deactivate = this.deactivate.bind(this); + this.toggle = this.toggle.bind(this); + this._onmousedown = this._onmousedown.bind(this); + this._onmousemove = this._onmousemove.bind(this); + this._endPan = this._endPan.bind(this); + + // This overlay will be inserted in the document when the mouse moves during + // a grab operation, to ensure that the cursor has the desired appearance. + var overlay = this.overlay = document.createElement('div'); + overlay.className = 'grab-to-pan-grabbing'; + } + GrabToPan.prototype = { + /** + * Class name of element which can be grabbed + */ + CSS_CLASS_GRAB: 'grab-to-pan-grab', + + /** + * Bind a mousedown event to the element to enable grab-detection. + */ + activate: function GrabToPan_activate() { + if (!this.active) { + this.active = true; + this.element.addEventListener('mousedown', this._onmousedown, true); + this.element.classList.add(this.CSS_CLASS_GRAB); + if (this.onActiveChanged) { + this.onActiveChanged(true); + } + } + }, + + /** + * Removes all events. Any pending pan session is immediately stopped. + */ + deactivate: function GrabToPan_deactivate() { + if (this.active) { + this.active = false; + this.element.removeEventListener('mousedown', this._onmousedown, true); + this._endPan(); + this.element.classList.remove(this.CSS_CLASS_GRAB); + if (this.onActiveChanged) { + this.onActiveChanged(false); + } + } + }, + + toggle: function GrabToPan_toggle() { + if (this.active) { + this.deactivate(); + } else { + this.activate(); + } + }, + + /** + * Whether to not pan if the target element is clicked. + * Override this method to change the default behaviour. + * + * @param node {Element} The target of the event + * @return {boolean} Whether to not react to the click event. + */ + ignoreTarget: function GrabToPan_ignoreTarget(node) { + // Use matchesSelector to check whether the clicked element + // is (a child of) an input element / link + return node[matchesSelector]( + 'a[href], a[href] *, input, textarea, button, button *, select, option' + ); + }, + + /** + * @private + */ + _onmousedown: function GrabToPan__onmousedown(event) { + if (event.button !== 0 || this.ignoreTarget(event.target)) { + return; + } + if (event.originalTarget) { + try { + /* jshint expr:true */ + event.originalTarget.tagName; + } catch (e) { + // Mozilla-specific: element is a scrollbar (XUL element) + return; + } + } + + this.scrollLeftStart = this.element.scrollLeft; + this.scrollTopStart = this.element.scrollTop; + this.clientXStart = event.clientX; + this.clientYStart = event.clientY; + this.document.addEventListener('mousemove', this._onmousemove, true); + this.document.addEventListener('mouseup', this._endPan, true); + // When a scroll event occurs before a mousemove, assume that the user + // dragged a scrollbar (necessary for Opera Presto, Safari and IE) + // (not needed for Chrome/Firefox) + this.element.addEventListener('scroll', this._endPan, true); + event.preventDefault(); + event.stopPropagation(); + this.document.documentElement.classList.add(this.CSS_CLASS_GRABBING); + + var focusedElement = document.activeElement; + if (focusedElement && !focusedElement.contains(event.target)) { + focusedElement.blur(); + } + }, + + /** + * @private + */ + _onmousemove: function GrabToPan__onmousemove(event) { + this.element.removeEventListener('scroll', this._endPan, true); + if (isLeftMouseReleased(event)) { + this._endPan(); + return; + } + var xDiff = event.clientX - this.clientXStart; + var yDiff = event.clientY - this.clientYStart; + this.element.scrollTop = this.scrollTopStart - yDiff; + this.element.scrollLeft = this.scrollLeftStart - xDiff; + if (!this.overlay.parentNode) { + document.body.appendChild(this.overlay); + } + }, + + /** + * @private + */ + _endPan: function GrabToPan__endPan() { + this.element.removeEventListener('scroll', this._endPan, true); + this.document.removeEventListener('mousemove', this._onmousemove, true); + this.document.removeEventListener('mouseup', this._endPan, true); + if (this.overlay.parentNode) { + this.overlay.parentNode.removeChild(this.overlay); + } + } + }; + + // Get the correct (vendor-prefixed) name of the matches method. + var matchesSelector; + ['webkitM', 'mozM', 'msM', 'oM', 'm'].some(function(prefix) { + var name = prefix + 'atches'; + if (name in document.documentElement) { + matchesSelector = name; + } + name += 'Selector'; + if (name in document.documentElement) { + matchesSelector = name; + } + return matchesSelector; // If found, then truthy, and [].some() ends. + }); + + // Browser sniffing because it's impossible to feature-detect + // whether event.which for onmousemove is reliable + var isNotIEorIsIE10plus = !document.documentMode || document.documentMode > 9; + var chrome = window.chrome; + var isChrome15OrOpera15plus = chrome && (chrome.webstore || chrome.app); + // ^ Chrome 15+ ^ Opera 15+ + var isSafari6plus = /Apple/.test(navigator.vendor) && + /Version\/([6-9]\d*|[1-5]\d+)/.test(navigator.userAgent); + + /** + * Whether the left mouse is not pressed. + * @param event {MouseEvent} + * @return {boolean} True if the left mouse button is not pressed. + * False if unsure or if the left mouse button is pressed. + */ + function isLeftMouseReleased(event) { + if ('buttons' in event && isNotIEorIsIE10plus) { + // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-buttons + // Firefox 15+ + // Internet Explorer 10+ + return !(event.buttons | 1); + } + if (isChrome15OrOpera15plus || isSafari6plus) { + // Chrome 14+ + // Opera 15+ + // Safari 6.0+ + return event.which === 0; + } + } + + return GrabToPan; +})(); + +var HandTool = { + initialize: function handToolInitialize(options) { + var toggleHandTool = options.toggleHandTool; + this.handTool = new GrabToPan({ + element: options.container, + onActiveChanged: function(isActive) { + if (!toggleHandTool) { + return; + } + if (isActive) { + toggleHandTool.title = + mozL10n.get('hand_tool_disable.title', null, 'Disable hand tool'); + toggleHandTool.firstElementChild.textContent = + mozL10n.get('hand_tool_disable_label', null, 'Disable hand tool'); + } else { + toggleHandTool.title = + mozL10n.get('hand_tool_enable.title', null, 'Enable hand tool'); + toggleHandTool.firstElementChild.textContent = + mozL10n.get('hand_tool_enable_label', null, 'Enable hand tool'); + } + } + }); + if (toggleHandTool) { + toggleHandTool.addEventListener('click', this.toggle.bind(this), false); + + window.addEventListener('localized', function (evt) { + Preferences.get('enableHandToolOnLoad').then(function resolved(value) { + if (value) { + this.handTool.activate(); + } + }.bind(this), function rejected(reason) {}); + }.bind(this)); + + window.addEventListener('presentationmodechanged', function (evt) { + if (evt.detail.switchInProgress) { + return; + } + if (evt.detail.active) { + this.enterPresentationMode(); + } else { + this.exitPresentationMode(); + } + }.bind(this)); + } + }, + + toggle: function handToolToggle() { + this.handTool.toggle(); + SecondaryToolbar.close(); + }, + + enterPresentationMode: function handToolEnterPresentationMode() { + if (this.handTool.active) { + this.wasActive = true; + this.handTool.deactivate(); + } + }, + + exitPresentationMode: function handToolExitPresentationMode() { + if (this.wasActive) { + this.wasActive = null; + this.handTool.activate(); + } + } +}; + + +var OverlayManager = { + overlays: {}, + active: null, + + /** + * @param {string} name The name of the overlay that is registered. This must + * be equal to the ID of the overlay's DOM element. + * @param {function} callerCloseMethod (optional) The method that, if present, + * will call OverlayManager.close from the Object + * registering the overlay. Access to this method is + * necessary in order to run cleanup code when e.g. + * the overlay is force closed. The default is null. + * @param {boolean} canForceClose (optional) Indicates if opening the overlay + * will close an active overlay. The default is false. + * @returns {Promise} A promise that is resolved when the overlay has been + * registered. + */ + register: function overlayManagerRegister(name, + callerCloseMethod, canForceClose) { + return new Promise(function (resolve) { + var element, container; + if (!name || !(element = document.getElementById(name)) || + !(container = element.parentNode)) { + throw new Error('Not enough parameters.'); + } else if (this.overlays[name]) { + throw new Error('The overlay is already registered.'); + } + this.overlays[name] = { element: element, + container: container, + callerCloseMethod: (callerCloseMethod || null), + canForceClose: (canForceClose || false) }; + resolve(); + }.bind(this)); + }, + + /** + * @param {string} name The name of the overlay that is unregistered. + * @returns {Promise} A promise that is resolved when the overlay has been + * unregistered. + */ + unregister: function overlayManagerUnregister(name) { + return new Promise(function (resolve) { + if (!this.overlays[name]) { + throw new Error('The overlay does not exist.'); + } else if (this.active === name) { + throw new Error('The overlay cannot be removed while it is active.'); + } + delete this.overlays[name]; + + resolve(); + }.bind(this)); + }, + + /** + * @param {string} name The name of the overlay that should be opened. + * @returns {Promise} A promise that is resolved when the overlay has been + * opened. + */ + open: function overlayManagerOpen(name) { + return new Promise(function (resolve) { + if (!this.overlays[name]) { + throw new Error('The overlay does not exist.'); + } else if (this.active) { + if (this.overlays[name].canForceClose) { + this._closeThroughCaller(); + } else if (this.active === name) { + throw new Error('The overlay is already active.'); + } else { + throw new Error('Another overlay is currently active.'); + } + } + this.active = name; + this.overlays[this.active].element.classList.remove('hidden'); + this.overlays[this.active].container.classList.remove('hidden'); + + window.addEventListener('keydown', this._keyDown); + resolve(); + }.bind(this)); + }, + + /** + * @param {string} name The name of the overlay that should be closed. + * @returns {Promise} A promise that is resolved when the overlay has been + * closed. + */ + close: function overlayManagerClose(name) { + return new Promise(function (resolve) { + if (!this.overlays[name]) { + throw new Error('The overlay does not exist.'); + } else if (!this.active) { + throw new Error('The overlay is currently not active.'); + } else if (this.active !== name) { + throw new Error('Another overlay is currently active.'); + } + this.overlays[this.active].container.classList.add('hidden'); + this.overlays[this.active].element.classList.add('hidden'); + this.active = null; + + window.removeEventListener('keydown', this._keyDown); + resolve(); + }.bind(this)); + }, + + /** + * @private + */ + _keyDown: function overlayManager_keyDown(evt) { + var self = OverlayManager; + if (self.active && evt.keyCode === 27) { // Esc key. + self._closeThroughCaller(); + evt.preventDefault(); + } + }, + + /** + * @private + */ + _closeThroughCaller: function overlayManager_closeThroughCaller() { + if (this.overlays[this.active].callerCloseMethod) { + this.overlays[this.active].callerCloseMethod(); + } + if (this.active) { + this.close(this.active); + } + } +}; + + +var PasswordPrompt = { + overlayName: null, + updatePassword: null, + reason: null, + passwordField: null, + passwordText: null, + passwordSubmit: null, + passwordCancel: null, + + initialize: function secondaryToolbarInitialize(options) { + this.overlayName = options.overlayName; + this.passwordField = options.passwordField; + this.passwordText = options.passwordText; + this.passwordSubmit = options.passwordSubmit; + this.passwordCancel = options.passwordCancel; + + // Attach the event listeners. + this.passwordSubmit.addEventListener('click', + this.verifyPassword.bind(this)); + + this.passwordCancel.addEventListener('click', this.close.bind(this)); + + this.passwordField.addEventListener('keydown', function (e) { + if (e.keyCode === 13) { // Enter key + this.verifyPassword(); + } + }.bind(this)); + + OverlayManager.register(this.overlayName, this.close.bind(this), true); + }, + + open: function passwordPromptOpen() { + OverlayManager.open(this.overlayName).then(function () { + this.passwordField.focus(); + + var promptString = mozL10n.get('password_label', null, + 'Enter the password to open this PDF file.'); + + if (this.reason === PDFJS.PasswordResponses.INCORRECT_PASSWORD) { + promptString = mozL10n.get('password_invalid', null, + 'Invalid password. Please try again.'); + } + + this.passwordText.textContent = promptString; + }.bind(this)); + }, + + close: function passwordPromptClose() { + OverlayManager.close(this.overlayName).then(function () { + this.passwordField.value = ''; + }.bind(this)); + }, + + verifyPassword: function passwordPromptVerifyPassword() { + var password = this.passwordField.value; + if (password && password.length > 0) { + this.close(); + return this.updatePassword(password); + } + } +}; + + +/** + * @typedef {Object} PDFDocumentPropertiesOptions + * @property {string} overlayName - Name/identifier for the overlay. + * @property {Object} fields - Names and elements of the overlay's fields. + * @property {HTMLButtonElement} closeButton - Button for closing the overlay. + */ + +/** + * @class + */ +var PDFDocumentProperties = (function PDFDocumentPropertiesClosure() { + /** + * @constructs PDFDocumentProperties + * @param {PDFDocumentPropertiesOptions} options + */ + function PDFDocumentProperties(options) { + this.fields = options.fields; + this.overlayName = options.overlayName; + + this.rawFileSize = 0; + this.url = null; + this.pdfDocument = null; + + // Bind the event listener for the Close button. + if (options.closeButton) { + options.closeButton.addEventListener('click', this.close.bind(this)); + } + + this.dataAvailablePromise = new Promise(function (resolve) { + this.resolveDataAvailable = resolve; + }.bind(this)); + + OverlayManager.register(this.overlayName, this.close.bind(this)); + } + + PDFDocumentProperties.prototype = { + /** + * Open the document properties overlay. + */ + open: function PDFDocumentProperties_open() { + Promise.all([OverlayManager.open(this.overlayName), + this.dataAvailablePromise]).then(function () { + this._getProperties(); + }.bind(this)); + }, + + /** + * Close the document properties overlay. + */ + close: function PDFDocumentProperties_close() { + OverlayManager.close(this.overlayName); + }, + + /** + * Set the file size of the PDF document. This method is used to + * update the file size in the document properties overlay once it + * is known so we do not have to wait until the entire file is loaded. + * + * @param {number} fileSize - The file size of the PDF document. + */ + setFileSize: function PDFDocumentProperties_setFileSize(fileSize) { + if (fileSize > 0) { + this.rawFileSize = fileSize; + } + }, + + /** + * Set a reference to the PDF document and the URL in order + * to populate the overlay fields with the document properties. + * Note that the overlay will contain no information if this method + * is not called. + * + * @param {Object} pdfDocument - A reference to the PDF document. + * @param {string} url - The URL of the document. + */ + setDocumentAndUrl: + function PDFDocumentProperties_setDocumentAndUrl(pdfDocument, url) { + this.pdfDocument = pdfDocument; + this.url = url; + this.resolveDataAvailable(); + }, + + /** + * @private + */ + _getProperties: function PDFDocumentProperties_getProperties() { + if (!OverlayManager.active) { + // If the dialog was closed before dataAvailablePromise was resolved, + // don't bother updating the properties. + return; + } + // Get the file size (if it hasn't already been set). + this.pdfDocument.getDownloadInfo().then(function(data) { + if (data.length === this.rawFileSize) { + return; + } + this.setFileSize(data.length); + this._updateUI(this.fields['fileSize'], this._parseFileSize()); + }.bind(this)); + + // Get the document properties. + this.pdfDocument.getMetadata().then(function(data) { + var content = { + 'fileName': getPDFFileNameFromURL(this.url), + 'fileSize': this._parseFileSize(), + 'title': data.info.Title, + 'author': data.info.Author, + 'subject': data.info.Subject, + 'keywords': data.info.Keywords, + 'creationDate': this._parseDate(data.info.CreationDate), + 'modificationDate': this._parseDate(data.info.ModDate), + 'creator': data.info.Creator, + 'producer': data.info.Producer, + 'version': data.info.PDFFormatVersion, + 'pageCount': this.pdfDocument.numPages + }; + + // Show the properties in the dialog. + for (var identifier in content) { + this._updateUI(this.fields[identifier], content[identifier]); + } + }.bind(this)); + }, + + /** + * @private + */ + _updateUI: function PDFDocumentProperties_updateUI(field, content) { + if (field && content !== undefined && content !== '') { + field.textContent = content; + } + }, + + /** + * @private + */ + _parseFileSize: function PDFDocumentProperties_parseFileSize() { + var fileSize = this.rawFileSize, kb = fileSize / 1024; + if (!kb) { + + } else if (kb < 1024) { + return mozL10n.get('document_properties_kb', { + size_kb: (+kb.toPrecision(3)).toLocaleString(), + size_b: fileSize.toLocaleString() + }, '{{size_kb}} KB ({{size_b}} bytes)'); + } else { + return mozL10n.get('document_properties_mb', { + size_mb: (+(kb / 1024).toPrecision(3)).toLocaleString(), + size_b: fileSize.toLocaleString() + }, '{{size_mb}} MB ({{size_b}} bytes)'); + } + }, + + /** + * @private + */ + _parseDate: function PDFDocumentProperties_parseDate(inputDate) { + // This is implemented according to the PDF specification, but note that + // Adobe Reader doesn't handle changing the date to universal time + // and doesn't use the user's time zone (they're effectively ignoring + // the HH' and mm' parts of the date string). + var dateToParse = inputDate; + if (dateToParse === undefined) { + return ''; + } + + // Remove the D: prefix if it is available. + if (dateToParse.substring(0,2) === 'D:') { + dateToParse = dateToParse.substring(2); + } + + // Get all elements from the PDF date string. + // JavaScript's Date object expects the month to be between + // 0 and 11 instead of 1 and 12, so we're correcting for this. + var year = parseInt(dateToParse.substring(0,4), 10); + var month = parseInt(dateToParse.substring(4,6), 10) - 1; + var day = parseInt(dateToParse.substring(6,8), 10); + var hours = parseInt(dateToParse.substring(8,10), 10); + var minutes = parseInt(dateToParse.substring(10,12), 10); + var seconds = parseInt(dateToParse.substring(12,14), 10); + var utRel = dateToParse.substring(14,15); + var offsetHours = parseInt(dateToParse.substring(15,17), 10); + var offsetMinutes = parseInt(dateToParse.substring(18,20), 10); + + // As per spec, utRel = 'Z' means equal to universal time. + // The other cases ('-' and '+') have to be handled here. + if (utRel === '-') { + hours += offsetHours; + minutes += offsetMinutes; + } else if (utRel === '+') { + hours -= offsetHours; + minutes -= offsetMinutes; + } + + // Return the new date format from the user's locale. + var date = new Date(Date.UTC(year, month, day, hours, minutes, seconds)); + var dateString = date.toLocaleDateString(); + var timeString = date.toLocaleTimeString(); + return mozL10n.get('document_properties_date_string', + {date: dateString, time: timeString}, + '{{date}}, {{time}}'); + } + }; + + return PDFDocumentProperties; +})(); + + +var PresentationModeState = { + UNKNOWN: 0, + NORMAL: 1, + CHANGING: 2, + FULLSCREEN: 3, +}; + +var IGNORE_CURRENT_POSITION_ON_ZOOM = false; +var DEFAULT_CACHE_SIZE = 10; + + +var CLEANUP_TIMEOUT = 30000; + +var RenderingStates = { + INITIAL: 0, + RUNNING: 1, + PAUSED: 2, + FINISHED: 3 +}; + +/** + * Controls rendering of the views for pages and thumbnails. + * @class + */ +var PDFRenderingQueue = (function PDFRenderingQueueClosure() { + /** + * @constructs + */ + function PDFRenderingQueue() { + this.pdfViewer = null; + this.pdfThumbnailViewer = null; + this.onIdle = null; + + this.highestPriorityPage = null; + this.idleTimeout = null; + this.printing = false; + this.isThumbnailViewEnabled = false; + } + + PDFRenderingQueue.prototype = /** @lends PDFRenderingQueue.prototype */ { + /** + * @param {PDFViewer} pdfViewer + */ + setViewer: function PDFRenderingQueue_setViewer(pdfViewer) { + this.pdfViewer = pdfViewer; + }, + + /** + * @param {PDFThumbnailViewer} pdfThumbnailViewer + */ + setThumbnailViewer: + function PDFRenderingQueue_setThumbnailViewer(pdfThumbnailViewer) { + this.pdfThumbnailViewer = pdfThumbnailViewer; + }, + + /** + * @param {IRenderableView} view + * @returns {boolean} + */ + isHighestPriority: function PDFRenderingQueue_isHighestPriority(view) { + return this.highestPriorityPage === view.renderingId; + }, + + renderHighestPriority: function + PDFRenderingQueue_renderHighestPriority(currentlyVisiblePages) { + if (this.idleTimeout) { + clearTimeout(this.idleTimeout); + this.idleTimeout = null; + } + + // Pages have a higher priority than thumbnails, so check them first. + if (this.pdfViewer.forceRendering(currentlyVisiblePages)) { + return; + } + // No pages needed rendering so check thumbnails. + if (this.pdfThumbnailViewer && this.isThumbnailViewEnabled) { + if (this.pdfThumbnailViewer.forceRendering()) { + return; + } + } + + if (this.printing) { + // If printing is currently ongoing do not reschedule cleanup. + return; + } + + if (this.onIdle) { + this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT); + } + }, + + getHighestPriority: function + PDFRenderingQueue_getHighestPriority(visible, views, scrolledDown) { + // The state has changed figure out which page has the highest priority to + // render next (if any). + // Priority: + // 1 visible pages + // 2 if last scrolled down page after the visible pages + // 2 if last scrolled up page before the visible pages + var visibleViews = visible.views; + + var numVisible = visibleViews.length; + if (numVisible === 0) { + return false; + } + for (var i = 0; i < numVisible; ++i) { + var view = visibleViews[i].view; + if (!this.isViewFinished(view)) { + return view; + } + } + + // All the visible views have rendered, try to render next/previous pages. + if (scrolledDown) { + var nextPageIndex = visible.last.id; + // ID's start at 1 so no need to add 1. + if (views[nextPageIndex] && + !this.isViewFinished(views[nextPageIndex])) { + return views[nextPageIndex]; + } + } else { + var previousPageIndex = visible.first.id - 2; + if (views[previousPageIndex] && + !this.isViewFinished(views[previousPageIndex])) { + return views[previousPageIndex]; + } + } + // Everything that needs to be rendered has been. + return null; + }, + + /** + * @param {IRenderableView} view + * @returns {boolean} + */ + isViewFinished: function PDFRenderingQueue_isViewFinished(view) { + return view.renderingState === RenderingStates.FINISHED; + }, + + /** + * Render a page or thumbnail view. This calls the appropriate function + * based on the views state. If the view is already rendered it will return + * false. + * @param {IRenderableView} view + */ + renderView: function PDFRenderingQueue_renderView(view) { + var state = view.renderingState; + switch (state) { + case RenderingStates.FINISHED: + return false; + case RenderingStates.PAUSED: + this.highestPriorityPage = view.renderingId; + view.resume(); + break; + case RenderingStates.RUNNING: + this.highestPriorityPage = view.renderingId; + break; + case RenderingStates.INITIAL: + this.highestPriorityPage = view.renderingId; + var continueRendering = function () { + this.renderHighestPriority(); + }.bind(this); + view.draw().then(continueRendering, continueRendering); + break; + } + return true; + }, + }; + + return PDFRenderingQueue; +})(); + + +var TEXT_LAYER_RENDER_DELAY = 200; // ms + +/** + * @typedef {Object} PDFPageViewOptions + * @property {HTMLDivElement} container - The viewer element. + * @property {number} id - The page unique ID (normally its number). + * @property {number} scale - The page scale display. + * @property {PageViewport} defaultViewport - The page viewport. + * @property {PDFRenderingQueue} renderingQueue - The rendering queue object. + * @property {IPDFTextLayerFactory} textLayerFactory + * @property {IPDFAnnotationsLayerFactory} annotationsLayerFactory + */ + +/** + * @class + * @implements {IRenderableView} + */ +var PDFPageView = (function PDFPageViewClosure() { + /** + * @constructs PDFPageView + * @param {PDFPageViewOptions} options + */ + function PDFPageView(options) { + var container = options.container; + var id = options.id; + var scale = options.scale; + var defaultViewport = options.defaultViewport; + var renderingQueue = options.renderingQueue; + var textLayerFactory = options.textLayerFactory; + var annotationsLayerFactory = options.annotationsLayerFactory; + + this.id = id; + this.renderingId = 'page' + id; + + this.rotation = 0; + this.scale = scale || 1.0; + this.viewport = defaultViewport; + this.pdfPageRotate = defaultViewport.rotation; + this.hasRestrictedScaling = false; + + this.renderingQueue = renderingQueue; + this.textLayerFactory = textLayerFactory; + this.annotationsLayerFactory = annotationsLayerFactory; + + this.renderingState = RenderingStates.INITIAL; + this.resume = null; + + this.onBeforeDraw = null; + this.onAfterDraw = null; + + this.textLayer = null; + + this.zoomLayer = null; + + this.annotationLayer = null; + + var div = document.createElement('div'); + div.id = 'pageContainer' + this.id; + div.className = 'page'; + div.style.width = Math.floor(this.viewport.width) + 'px'; + div.style.height = Math.floor(this.viewport.height) + 'px'; + div.setAttribute('data-page-number', this.id); + this.div = div; + + container.appendChild(div); + } + + PDFPageView.prototype = { + setPdfPage: function PDFPageView_setPdfPage(pdfPage) { + this.pdfPage = pdfPage; + this.pdfPageRotate = pdfPage.rotate; + var totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = pdfPage.getViewport(this.scale * CSS_UNITS, + totalRotation); + this.stats = pdfPage.stats; + this.reset(); + }, + + destroy: function PDFPageView_destroy() { + this.zoomLayer = null; + this.reset(); + if (this.pdfPage) { + this.pdfPage.destroy(); + } + }, + + reset: function PDFPageView_reset(keepAnnotations) { + if (this.renderTask) { + this.renderTask.cancel(); + } + this.resume = null; + this.renderingState = RenderingStates.INITIAL; + + var div = this.div; + div.style.width = Math.floor(this.viewport.width) + 'px'; + div.style.height = Math.floor(this.viewport.height) + 'px'; + + var childNodes = div.childNodes; + var currentZoomLayer = this.zoomLayer || null; + var currentAnnotationNode = (keepAnnotations && this.annotationLayer && + this.annotationLayer.div) || null; + for (var i = childNodes.length - 1; i >= 0; i--) { + var node = childNodes[i]; + if (currentZoomLayer === node || currentAnnotationNode === node) { + continue; + } + div.removeChild(node); + } + div.removeAttribute('data-loaded'); + + if (keepAnnotations) { + if (this.annotationLayer) { + // Hide annotationLayer until all elements are resized + // so they are not displayed on the already-resized page + this.annotationLayer.hide(); + } + } else { + this.annotationLayer = null; + } + + if (this.canvas) { + // Zeroing the width and height causes Firefox to release graphics + // resources immediately, which can greatly reduce memory consumption. + this.canvas.width = 0; + this.canvas.height = 0; + delete this.canvas; + } + + this.loadingIconDiv = document.createElement('div'); + this.loadingIconDiv.className = 'loadingIcon'; + div.appendChild(this.loadingIconDiv); + }, + + update: function PDFPageView_update(scale, rotation) { + this.scale = scale || this.scale; + + if (typeof rotation !== 'undefined') { + this.rotation = rotation; + } + + var totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = this.viewport.clone({ + scale: this.scale * CSS_UNITS, + rotation: totalRotation + }); + + var isScalingRestricted = false; + if (this.canvas && PDFJS.maxCanvasPixels > 0) { + var ctx = this.canvas.getContext('2d'); + var outputScale = getOutputScale(ctx); + var pixelsInViewport = this.viewport.width * this.viewport.height; + var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport); + if (((Math.floor(this.viewport.width) * outputScale.sx) | 0) * + ((Math.floor(this.viewport.height) * outputScale.sy) | 0) > + PDFJS.maxCanvasPixels) { + isScalingRestricted = true; + } + } + + if (this.canvas && + (PDFJS.useOnlyCssZoom || + (this.hasRestrictedScaling && isScalingRestricted))) { + this.cssTransform(this.canvas, true); + return; + } else if (this.canvas && !this.zoomLayer) { + this.zoomLayer = this.canvas.parentNode; + this.zoomLayer.style.position = 'absolute'; + } + if (this.zoomLayer) { + this.cssTransform(this.zoomLayer.firstChild); + } + this.reset(true); + }, + + /** + * Called when moved in the parent's container. + */ + updatePosition: function PDFPageView_updatePosition() { + if (this.textLayer) { + this.textLayer.render(TEXT_LAYER_RENDER_DELAY); + } + }, + + cssTransform: function PDFPageView_transform(canvas, redrawAnnotations) { + // Scale canvas, canvas wrapper, and page container. + var width = this.viewport.width; + var height = this.viewport.height; + var div = this.div; + canvas.style.width = canvas.parentNode.style.width = div.style.width = + Math.floor(width) + 'px'; + canvas.style.height = canvas.parentNode.style.height = div.style.height = + Math.floor(height) + 'px'; + // The canvas may have been originally rotated, rotate relative to that. + var relativeRotation = this.viewport.rotation - canvas._viewport.rotation; + var absRotation = Math.abs(relativeRotation); + var scaleX = 1, scaleY = 1; + if (absRotation === 90 || absRotation === 270) { + // Scale x and y because of the rotation. + scaleX = height / width; + scaleY = width / height; + } + var cssTransform = 'rotate(' + relativeRotation + 'deg) ' + + 'scale(' + scaleX + ',' + scaleY + ')'; + CustomStyle.setProp('transform', canvas, cssTransform); + + if (this.textLayer) { + // Rotating the text layer is more complicated since the divs inside the + // the text layer are rotated. + // TODO: This could probably be simplified by drawing the text layer in + // one orientation then rotating overall. + var textLayerViewport = this.textLayer.viewport; + var textRelativeRotation = this.viewport.rotation - + textLayerViewport.rotation; + var textAbsRotation = Math.abs(textRelativeRotation); + var scale = width / textLayerViewport.width; + if (textAbsRotation === 90 || textAbsRotation === 270) { + scale = width / textLayerViewport.height; + } + var textLayerDiv = this.textLayer.textLayerDiv; + var transX, transY; + switch (textAbsRotation) { + case 0: + transX = transY = 0; + break; + case 90: + transX = 0; + transY = '-' + textLayerDiv.style.height; + break; + case 180: + transX = '-' + textLayerDiv.style.width; + transY = '-' + textLayerDiv.style.height; + break; + case 270: + transX = '-' + textLayerDiv.style.width; + transY = 0; + break; + default: + console.error('Bad rotation value.'); + break; + } + CustomStyle.setProp('transform', textLayerDiv, + 'rotate(' + textAbsRotation + 'deg) ' + + 'scale(' + scale + ', ' + scale + ') ' + + 'translate(' + transX + ', ' + transY + ')'); + CustomStyle.setProp('transformOrigin', textLayerDiv, '0% 0%'); + } + + if (redrawAnnotations && this.annotationLayer) { + this.annotationLayer.setupAnnotations(this.viewport); + } + }, + + get width() { + return this.viewport.width; + }, + + get height() { + return this.viewport.height; + }, + + getPagePoint: function PDFPageView_getPagePoint(x, y) { + return this.viewport.convertToPdfPoint(x, y); + }, + + draw: function PDFPageView_draw() { + if (this.renderingState !== RenderingStates.INITIAL) { + console.error('Must be in new state before drawing'); + } + + this.renderingState = RenderingStates.RUNNING; + + var pdfPage = this.pdfPage; + var viewport = this.viewport; + var div = this.div; + // Wrap the canvas so if it has a css transform for highdpi the overflow + // will be hidden in FF. + var canvasWrapper = document.createElement('div'); + canvasWrapper.style.width = div.style.width; + canvasWrapper.style.height = div.style.height; + canvasWrapper.classList.add('canvasWrapper'); + + var canvas = document.createElement('canvas'); + canvas.id = 'page' + this.id; + canvasWrapper.appendChild(canvas); + if (this.annotationLayer) { + // annotationLayer needs to stay on top + div.insertBefore(canvasWrapper, this.annotationLayer.div); + } else { + div.appendChild(canvasWrapper); + } + this.canvas = canvas; + + var ctx = canvas.getContext('2d'); + var outputScale = getOutputScale(ctx); + + if (PDFJS.useOnlyCssZoom) { + var actualSizeViewport = viewport.clone({ scale: CSS_UNITS }); + // Use a scale that will make the canvas be the original intended size + // of the page. + outputScale.sx *= actualSizeViewport.width / viewport.width; + outputScale.sy *= actualSizeViewport.height / viewport.height; + outputScale.scaled = true; + } + + if (PDFJS.maxCanvasPixels > 0) { + var pixelsInViewport = viewport.width * viewport.height; + var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport); + if (outputScale.sx > maxScale || outputScale.sy > maxScale) { + outputScale.sx = maxScale; + outputScale.sy = maxScale; + outputScale.scaled = true; + this.hasRestrictedScaling = true; + } else { + this.hasRestrictedScaling = false; + } + } + + canvas.width = (Math.floor(viewport.width) * outputScale.sx) | 0; + canvas.height = (Math.floor(viewport.height) * outputScale.sy) | 0; + canvas.style.width = Math.floor(viewport.width) + 'px'; + canvas.style.height = Math.floor(viewport.height) + 'px'; + // Add the viewport so it's known what it was originally drawn with. + canvas._viewport = viewport; + + var textLayerDiv = null; + var textLayer = null; + if (this.textLayerFactory) { + textLayerDiv = document.createElement('div'); + textLayerDiv.className = 'textLayer'; + textLayerDiv.style.width = canvas.style.width; + textLayerDiv.style.height = canvas.style.height; + if (this.annotationLayer) { + // annotationLayer needs to stay on top + div.insertBefore(textLayerDiv, this.annotationLayer.div); + } else { + div.appendChild(textLayerDiv); + } + + textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, + this.id - 1, + this.viewport); + } + this.textLayer = textLayer; + + if (outputScale.scaled) { + // Used by the mozCurrentTransform polyfill in src/display/canvas.js. + ctx._transformMatrix = [outputScale.sx, 0, 0, outputScale.sy, 0, 0]; + ctx.scale(outputScale.sx, outputScale.sy); + } + + var resolveRenderPromise, rejectRenderPromise; + var promise = new Promise(function (resolve, reject) { + resolveRenderPromise = resolve; + rejectRenderPromise = reject; + }); + + // Rendering area + + var self = this; + function pageViewDrawCallback(error) { + // The renderTask may have been replaced by a new one, so only remove + // the reference to the renderTask if it matches the one that is + // triggering this callback. + if (renderTask === self.renderTask) { + self.renderTask = null; + } + + if (error === 'cancelled') { + rejectRenderPromise(error); + return; + } + + self.renderingState = RenderingStates.FINISHED; + + if (self.loadingIconDiv) { + div.removeChild(self.loadingIconDiv); + delete self.loadingIconDiv; + } + + if (self.zoomLayer) { + div.removeChild(self.zoomLayer); + self.zoomLayer = null; + } + + self.error = error; + self.stats = pdfPage.stats; + if (self.onAfterDraw) { + self.onAfterDraw(); + } + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('pagerendered', true, true, { + pageNumber: self.id + }); + div.dispatchEvent(event); + // This custom event is deprecated, and will be removed in the future, + // please use the |pagerendered| event instead. + var deprecatedEvent = document.createEvent('CustomEvent'); + deprecatedEvent.initCustomEvent('pagerender', true, true, { + pageNumber: pdfPage.pageNumber + }); + div.dispatchEvent(deprecatedEvent); + + if (!error) { + resolveRenderPromise(undefined); + } else { + rejectRenderPromise(error); + } + } + + var renderContinueCallback = null; + if (this.renderingQueue) { + renderContinueCallback = function renderContinueCallback(cont) { + if (!self.renderingQueue.isHighestPriority(self)) { + self.renderingState = RenderingStates.PAUSED; + self.resume = function resumeCallback() { + self.renderingState = RenderingStates.RUNNING; + cont(); + }; + return; + } + cont(); + }; + } + + var renderContext = { + canvasContext: ctx, + viewport: this.viewport, + // intent: 'default', // === 'display' + continueCallback: renderContinueCallback + }; + var renderTask = this.renderTask = this.pdfPage.render(renderContext); + + this.renderTask.promise.then( + function pdfPageRenderCallback() { + pageViewDrawCallback(null); + if (textLayer) { + self.pdfPage.getTextContent().then( + function textContentResolved(textContent) { + textLayer.setTextContent(textContent); + textLayer.render(TEXT_LAYER_RENDER_DELAY); + } + ); + } + }, + function pdfPageRenderError(error) { + pageViewDrawCallback(error); + } + ); + + if (this.annotationsLayerFactory) { + if (!this.annotationLayer) { + this.annotationLayer = this.annotationsLayerFactory. + createAnnotationsLayerBuilder(div, this.pdfPage); + } + this.annotationLayer.setupAnnotations(this.viewport); + } + div.setAttribute('data-loaded', true); + + if (self.onBeforeDraw) { + self.onBeforeDraw(); + } + return promise; + }, + + beforePrint: function PDFPageView_beforePrint() { + var pdfPage = this.pdfPage; + + var viewport = pdfPage.getViewport(1); + // Use the same hack we use for high dpi displays for printing to get + // better output until bug 811002 is fixed in FF. + var PRINT_OUTPUT_SCALE = 2; + var canvas = document.createElement('canvas'); + + // The logical size of the canvas. + canvas.width = Math.floor(viewport.width) * PRINT_OUTPUT_SCALE; + canvas.height = Math.floor(viewport.height) * PRINT_OUTPUT_SCALE; + + // The rendered size of the canvas, relative to the size of canvasWrapper. + canvas.style.width = (PRINT_OUTPUT_SCALE * 100) + '%'; + canvas.style.height = (PRINT_OUTPUT_SCALE * 100) + '%'; + + var cssScale = 'scale(' + (1 / PRINT_OUTPUT_SCALE) + ', ' + + (1 / PRINT_OUTPUT_SCALE) + ')'; + CustomStyle.setProp('transform' , canvas, cssScale); + CustomStyle.setProp('transformOrigin' , canvas, '0% 0%'); + + var printContainer = document.getElementById('printContainer'); + var canvasWrapper = document.createElement('div'); + canvasWrapper.style.width = viewport.width + 'pt'; + canvasWrapper.style.height = viewport.height + 'pt'; + canvasWrapper.appendChild(canvas); + printContainer.appendChild(canvasWrapper); + + canvas.mozPrintCallback = function(obj) { + var ctx = obj.context; + + ctx.save(); + ctx.fillStyle = 'rgb(255, 255, 255)'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.restore(); + // Used by the mozCurrentTransform polyfill in src/display/canvas.js. + ctx._transformMatrix = + [PRINT_OUTPUT_SCALE, 0, 0, PRINT_OUTPUT_SCALE, 0, 0]; + ctx.scale(PRINT_OUTPUT_SCALE, PRINT_OUTPUT_SCALE); + + var renderContext = { + canvasContext: ctx, + viewport: viewport, + intent: 'print' + }; + + pdfPage.render(renderContext).promise.then(function() { + // Tell the printEngine that rendering this canvas/page has finished. + obj.done(); + }, function(error) { + console.error(error); + // Tell the printEngine that rendering this canvas/page has failed. + // This will make the print proces stop. + if ('abort' in obj) { + obj.abort(); + } else { + obj.done(); + } + }); + }; + }, + }; + + return PDFPageView; +})(); + + +var MAX_TEXT_DIVS_TO_RENDER = 100000; + +var NonWhitespaceRegexp = /\S/; + +function isAllWhitespace(str) { + return !NonWhitespaceRegexp.test(str); +} + +/** + * @typedef {Object} TextLayerBuilderOptions + * @property {HTMLDivElement} textLayerDiv - The text layer container. + * @property {number} pageIndex - The page index. + * @property {PageViewport} viewport - The viewport of the text layer. + * @property {PDFFindController} findController + */ + +/** + * TextLayerBuilder provides text-selection functionality for the PDF. + * It does this by creating overlay divs over the PDF text. These divs + * contain text that matches the PDF text they are overlaying. This object + * also provides a way to highlight text that is being searched for. + * @class + */ +var TextLayerBuilder = (function TextLayerBuilderClosure() { + function TextLayerBuilder(options) { + this.textLayerDiv = options.textLayerDiv; + this.renderingDone = false; + this.divContentDone = false; + this.pageIdx = options.pageIndex; + this.pageNumber = this.pageIdx + 1; + this.matches = []; + this.viewport = options.viewport; + this.textDivs = []; + this.findController = options.findController || null; + } + + TextLayerBuilder.prototype = { + _finishRendering: function TextLayerBuilder_finishRendering() { + this.renderingDone = true; + + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('textlayerrendered', true, true, { + pageNumber: this.pageNumber + }); + this.textLayerDiv.dispatchEvent(event); + }, + + renderLayer: function TextLayerBuilder_renderLayer() { + var textLayerFrag = document.createDocumentFragment(); + var textDivs = this.textDivs; + var textDivsLength = textDivs.length; + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + + // No point in rendering many divs as it would make the browser + // unusable even after the divs are rendered. + if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) { + this._finishRendering(); + return; + } + + var lastFontSize; + var lastFontFamily; + for (var i = 0; i < textDivsLength; i++) { + var textDiv = textDivs[i]; + if (textDiv.dataset.isWhitespace !== undefined) { + continue; + } + + var fontSize = textDiv.style.fontSize; + var fontFamily = textDiv.style.fontFamily; + + // Only build font string and set to context if different from last. + if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) { + ctx.font = fontSize + ' ' + fontFamily; + lastFontSize = fontSize; + lastFontFamily = fontFamily; + } + + var width = ctx.measureText(textDiv.textContent).width; + if (width > 0) { + textLayerFrag.appendChild(textDiv); + var transform; + if (textDiv.dataset.canvasWidth !== undefined) { + // Dataset values come of type string. + var textScale = textDiv.dataset.canvasWidth / width; + transform = 'scaleX(' + textScale + ')'; + } else { + transform = ''; + } + var rotation = textDiv.dataset.angle; + if (rotation) { + transform = 'rotate(' + rotation + 'deg) ' + transform; + } + if (transform) { + CustomStyle.setProp('transform' , textDiv, transform); + } + } + } + + this.textLayerDiv.appendChild(textLayerFrag); + this._finishRendering(); + this.updateMatches(); + }, + + /** + * Renders the text layer. + * @param {number} timeout (optional) if specified, the rendering waits + * for specified amount of ms. + */ + render: function TextLayerBuilder_render(timeout) { + if (!this.divContentDone || this.renderingDone) { + return; + } + + if (this.renderTimer) { + clearTimeout(this.renderTimer); + this.renderTimer = null; + } + + if (!timeout) { // Render right away + this.renderLayer(); + } else { // Schedule + var self = this; + this.renderTimer = setTimeout(function() { + self.renderLayer(); + self.renderTimer = null; + }, timeout); + } + }, + + appendText: function TextLayerBuilder_appendText(geom, styles) { + var style = styles[geom.fontName]; + var textDiv = document.createElement('div'); + this.textDivs.push(textDiv); + if (isAllWhitespace(geom.str)) { + textDiv.dataset.isWhitespace = true; + return; + } + var tx = PDFJS.Util.transform(this.viewport.transform, geom.transform); + var angle = Math.atan2(tx[1], tx[0]); + if (style.vertical) { + angle += Math.PI / 2; + } + var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3])); + var fontAscent = fontHeight; + if (style.ascent) { + fontAscent = style.ascent * fontAscent; + } else if (style.descent) { + fontAscent = (1 + style.descent) * fontAscent; + } + + var left; + var top; + if (angle === 0) { + left = tx[4]; + top = tx[5] - fontAscent; + } else { + left = tx[4] + (fontAscent * Math.sin(angle)); + top = tx[5] - (fontAscent * Math.cos(angle)); + } + textDiv.style.left = left + 'px'; + textDiv.style.top = top + 'px'; + textDiv.style.fontSize = fontHeight + 'px'; + textDiv.style.fontFamily = style.fontFamily; + + textDiv.textContent = geom.str; + // |fontName| is only used by the Font Inspector. This test will succeed + // when e.g. the Font Inspector is off but the Stepper is on, but it's + // not worth the effort to do a more accurate test. + if (PDFJS.pdfBug) { + textDiv.dataset.fontName = geom.fontName; + } + // Storing into dataset will convert number into string. + if (angle !== 0) { + textDiv.dataset.angle = angle * (180 / Math.PI); + } + // We don't bother scaling single-char text divs, because it has very + // little effect on text highlighting. This makes scrolling on docs with + // lots of such divs a lot faster. + if (textDiv.textContent.length > 1) { + if (style.vertical) { + textDiv.dataset.canvasWidth = geom.height * this.viewport.scale; + } else { + textDiv.dataset.canvasWidth = geom.width * this.viewport.scale; + } + } + }, + + setTextContent: function TextLayerBuilder_setTextContent(textContent) { + this.textContent = textContent; + + var textItems = textContent.items; + for (var i = 0, len = textItems.length; i < len; i++) { + this.appendText(textItems[i], textContent.styles); + } + this.divContentDone = true; + }, + + convertMatches: function TextLayerBuilder_convertMatches(matches) { + var i = 0; + var iIndex = 0; + var bidiTexts = this.textContent.items; + var end = bidiTexts.length - 1; + var queryLen = (this.findController === null ? + 0 : this.findController.state.query.length); + var ret = []; + + for (var m = 0, len = matches.length; m < len; m++) { + // Calculate the start position. + var matchIdx = matches[m]; + + // Loop over the divIdxs. + while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) { + iIndex += bidiTexts[i].str.length; + i++; + } + + if (i === bidiTexts.length) { + console.error('Could not find a matching mapping'); + } + + var match = { + begin: { + divIdx: i, + offset: matchIdx - iIndex + } + }; + + // Calculate the end position. + matchIdx += queryLen; + + // Somewhat the same array as above, but use > instead of >= to get + // the end position right. + while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) { + iIndex += bidiTexts[i].str.length; + i++; + } + + match.end = { + divIdx: i, + offset: matchIdx - iIndex + }; + ret.push(match); + } + + return ret; + }, + + renderMatches: function TextLayerBuilder_renderMatches(matches) { + // Early exit if there is nothing to render. + if (matches.length === 0) { + return; + } + + var bidiTexts = this.textContent.items; + var textDivs = this.textDivs; + var prevEnd = null; + var pageIdx = this.pageIdx; + var isSelectedPage = (this.findController === null ? + false : (pageIdx === this.findController.selected.pageIdx)); + var selectedMatchIdx = (this.findController === null ? + -1 : this.findController.selected.matchIdx); + var highlightAll = (this.findController === null ? + false : this.findController.state.highlightAll); + var infinity = { + divIdx: -1, + offset: undefined + }; + + function beginText(begin, className) { + var divIdx = begin.divIdx; + textDivs[divIdx].textContent = ''; + appendTextToDiv(divIdx, 0, begin.offset, className); + } + + function appendTextToDiv(divIdx, fromOffset, toOffset, className) { + var div = textDivs[divIdx]; + var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset); + var node = document.createTextNode(content); + if (className) { + var span = document.createElement('span'); + span.className = className; + span.appendChild(node); + div.appendChild(span); + return; + } + div.appendChild(node); + } + + var i0 = selectedMatchIdx, i1 = i0 + 1; + if (highlightAll) { + i0 = 0; + i1 = matches.length; + } else if (!isSelectedPage) { + // Not highlighting all and this isn't the selected page, so do nothing. + return; + } + + for (var i = i0; i < i1; i++) { + var match = matches[i]; + var begin = match.begin; + var end = match.end; + var isSelected = (isSelectedPage && i === selectedMatchIdx); + var highlightSuffix = (isSelected ? ' selected' : ''); + + if (this.findController) { + this.findController.updateMatchPosition(pageIdx, i, textDivs, + begin.divIdx, end.divIdx); + } + + // Match inside new div. + if (!prevEnd || begin.divIdx !== prevEnd.divIdx) { + // If there was a previous div, then add the text at the end. + if (prevEnd !== null) { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset); + } + // Clear the divs and set the content until the starting point. + beginText(begin); + } else { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset); + } + + if (begin.divIdx === end.divIdx) { + appendTextToDiv(begin.divIdx, begin.offset, end.offset, + 'highlight' + highlightSuffix); + } else { + appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, + 'highlight begin' + highlightSuffix); + for (var n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) { + textDivs[n0].className = 'highlight middle' + highlightSuffix; + } + beginText(end, 'highlight end' + highlightSuffix); + } + prevEnd = end; + } + + if (prevEnd) { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset); + } + }, + + updateMatches: function TextLayerBuilder_updateMatches() { + // Only show matches when all rendering is done. + if (!this.renderingDone) { + return; + } + + // Clear all matches. + var matches = this.matches; + var textDivs = this.textDivs; + var bidiTexts = this.textContent.items; + var clearedUntilDivIdx = -1; + + // Clear all current matches. + for (var i = 0, len = matches.length; i < len; i++) { + var match = matches[i]; + var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx); + for (var n = begin, end = match.end.divIdx; n <= end; n++) { + var div = textDivs[n]; + div.textContent = bidiTexts[n].str; + div.className = ''; + } + clearedUntilDivIdx = match.end.divIdx + 1; + } + + if (this.findController === null || !this.findController.active) { + return; + } + + // Convert the matches on the page controller into the match format + // used for the textLayer. + this.matches = this.convertMatches(this.findController === null ? + [] : (this.findController.pageMatches[this.pageIdx] || [])); + this.renderMatches(this.matches); + } + }; + return TextLayerBuilder; +})(); + +/** + * @constructor + * @implements IPDFTextLayerFactory + */ +function DefaultTextLayerFactory() {} +DefaultTextLayerFactory.prototype = { + /** + * @param {HTMLDivElement} textLayerDiv + * @param {number} pageIndex + * @param {PageViewport} viewport + * @returns {TextLayerBuilder} + */ + createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport) { + return new TextLayerBuilder({ + textLayerDiv: textLayerDiv, + pageIndex: pageIndex, + viewport: viewport + }); + } +}; + + +/** + * @typedef {Object} AnnotationsLayerBuilderOptions + * @property {HTMLDivElement} pageDiv + * @property {PDFPage} pdfPage + * @property {IPDFLinkService} linkService + */ + +/** + * @class + */ +var AnnotationsLayerBuilder = (function AnnotationsLayerBuilderClosure() { + /** + * @param {AnnotationsLayerBuilderOptions} options + * @constructs AnnotationsLayerBuilder + */ + function AnnotationsLayerBuilder(options) { + this.pageDiv = options.pageDiv; + this.pdfPage = options.pdfPage; + this.linkService = options.linkService; + + this.div = null; + } + AnnotationsLayerBuilder.prototype = + /** @lends AnnotationsLayerBuilder.prototype */ { + + /** + * @param {PageViewport} viewport + */ + setupAnnotations: + function AnnotationsLayerBuilder_setupAnnotations(viewport) { + function bindLink(link, dest) { + link.href = linkService.getDestinationHash(dest); + link.onclick = function annotationsLayerBuilderLinksOnclick() { + if (dest) { + linkService.navigateTo(dest); + } + return false; + }; + if (dest) { + link.className = 'internalLink'; + } + } + + function bindNamedAction(link, action) { + link.href = linkService.getAnchorUrl(''); + link.onclick = function annotationsLayerBuilderNamedActionOnClick() { + linkService.executeNamedAction(action); + return false; + }; + link.className = 'internalLink'; + } + + var linkService = this.linkService; + var pdfPage = this.pdfPage; + var self = this; + + pdfPage.getAnnotations().then(function (annotationsData) { + viewport = viewport.clone({ dontFlip: true }); + var transform = viewport.transform; + var transformStr = 'matrix(' + transform.join(',') + ')'; + var data, element, i, ii; + + if (self.div) { + // If an annotationLayer already exists, refresh its children's + // transformation matrices + for (i = 0, ii = annotationsData.length; i < ii; i++) { + data = annotationsData[i]; + element = self.div.querySelector( + '[data-annotation-id="' + data.id + '"]'); + if (element) { + CustomStyle.setProp('transform', element, transformStr); + } + } + // See PDFPageView.reset() + self.div.removeAttribute('hidden'); + } else { + for (i = 0, ii = annotationsData.length; i < ii; i++) { + data = annotationsData[i]; + if (!data || !data.hasHtml) { + continue; + } + + element = PDFJS.AnnotationUtils.getHtmlElement(data, + pdfPage.commonObjs); + element.setAttribute('data-annotation-id', data.id); + if (typeof mozL10n !== 'undefined') { + mozL10n.translate(element); + } + + var rect = data.rect; + var view = pdfPage.view; + rect = PDFJS.Util.normalizeRect([ + rect[0], + view[3] - rect[1] + view[1], + rect[2], + view[3] - rect[3] + view[1] + ]); + element.style.left = rect[0] + 'px'; + element.style.top = rect[1] + 'px'; + element.style.position = 'absolute'; + + CustomStyle.setProp('transform', element, transformStr); + var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px'; + CustomStyle.setProp('transformOrigin', element, transformOriginStr); + + if (data.subtype === 'Link' && !data.url) { + var link = element.getElementsByTagName('a')[0]; + if (link) { + if (data.action) { + bindNamedAction(link, data.action); + } else { + bindLink(link, ('dest' in data) ? data.dest : null); + } + } + } + + if (!self.div) { + var annotationLayerDiv = document.createElement('div'); + annotationLayerDiv.className = 'annotationLayer'; + self.pageDiv.appendChild(annotationLayerDiv); + self.div = annotationLayerDiv; + } + + self.div.appendChild(element); + } + } + }); + }, + + hide: function () { + if (!this.div) { + return; + } + this.div.setAttribute('hidden', 'true'); + } + }; + return AnnotationsLayerBuilder; +})(); + +/** + * @constructor + * @implements IPDFAnnotationsLayerFactory + */ +function DefaultAnnotationsLayerFactory() {} +DefaultAnnotationsLayerFactory.prototype = { + /** + * @param {HTMLDivElement} pageDiv + * @param {PDFPage} pdfPage + * @returns {AnnotationsLayerBuilder} + */ + createAnnotationsLayerBuilder: function (pageDiv, pdfPage) { + return new AnnotationsLayerBuilder({ + pageDiv: pageDiv, + pdfPage: pdfPage + }); + } +}; + + +/** + * @typedef {Object} PDFViewerOptions + * @property {HTMLDivElement} container - The container for the viewer element. + * @property {HTMLDivElement} viewer - (optional) The viewer element. + * @property {IPDFLinkService} linkService - The navigation/linking service. + * @property {PDFRenderingQueue} renderingQueue - (optional) The rendering + * queue object. + * @property {boolean} removePageBorders - (optional) Removes the border shadow + * around the pages. The default is false. + */ + +/** + * Simple viewer control to display PDF content/pages. + * @class + * @implements {IRenderableView} + */ +var PDFViewer = (function pdfViewer() { + function PDFPageViewBuffer(size) { + var data = []; + this.push = function cachePush(view) { + var i = data.indexOf(view); + if (i >= 0) { + data.splice(i, 1); + } + data.push(view); + if (data.length > size) { + data.shift().destroy(); + } + }; + this.resize = function (newSize) { + size = newSize; + while (data.length > size) { + data.shift().destroy(); + } + }; + } + + /** + * @constructs PDFViewer + * @param {PDFViewerOptions} options + */ + function PDFViewer(options) { + this.container = options.container; + this.viewer = options.viewer || options.container.firstElementChild; + this.linkService = options.linkService || new SimpleLinkService(this); + this.removePageBorders = options.removePageBorders || false; + + this.defaultRenderingQueue = !options.renderingQueue; + if (this.defaultRenderingQueue) { + // Custom rendering queue is not specified, using default one + this.renderingQueue = new PDFRenderingQueue(); + this.renderingQueue.setViewer(this); + } else { + this.renderingQueue = options.renderingQueue; + } + + this.scroll = watchScroll(this.container, this._scrollUpdate.bind(this)); + this.updateInProgress = false; + this.presentationModeState = PresentationModeState.UNKNOWN; + this._resetView(); + + if (this.removePageBorders) { + this.viewer.classList.add('removePageBorders'); + } + } + + PDFViewer.prototype = /** @lends PDFViewer.prototype */{ + get pagesCount() { + return this._pages.length; + }, + + getPageView: function (index) { + return this._pages[index]; + }, + + get currentPageNumber() { + return this._currentPageNumber; + }, + + set currentPageNumber(val) { + if (!this.pdfDocument) { + this._currentPageNumber = val; + return; + } + + var event = document.createEvent('UIEvents'); + event.initUIEvent('pagechange', true, true, window, 0); + event.updateInProgress = this.updateInProgress; + + if (!(0 < val && val <= this.pagesCount)) { + event.pageNumber = this._currentPageNumber; + event.previousPageNumber = val; + this.container.dispatchEvent(event); + return; + } + + event.previousPageNumber = this._currentPageNumber; + this._currentPageNumber = val; + event.pageNumber = val; + this.container.dispatchEvent(event); + }, + + /** + * @returns {number} + */ + get currentScale() { + return this._currentScale; + }, + + /** + * @param {number} val - Scale of the pages in percents. + */ + set currentScale(val) { + if (isNaN(val)) { + throw new Error('Invalid numeric scale'); + } + if (!this.pdfDocument) { + this._currentScale = val; + this._currentScaleValue = val.toString(); + return; + } + this._setScale(val, false); + }, + + /** + * @returns {string} + */ + get currentScaleValue() { + return this._currentScaleValue; + }, + + /** + * @param val - The scale of the pages (in percent or predefined value). + */ + set currentScaleValue(val) { + if (!this.pdfDocument) { + this._currentScale = isNaN(val) ? UNKNOWN_SCALE : val; + this._currentScaleValue = val; + return; + } + this._setScale(val, false); + }, + + /** + * @returns {number} + */ + get pagesRotation() { + return this._pagesRotation; + }, + + /** + * @param {number} rotation - The rotation of the pages (0, 90, 180, 270). + */ + set pagesRotation(rotation) { + this._pagesRotation = rotation; + + for (var i = 0, l = this._pages.length; i < l; i++) { + var pageView = this._pages[i]; + pageView.update(pageView.scale, rotation); + } + + this._setScale(this._currentScaleValue, true); + }, + + /** + * @param pdfDocument {PDFDocument} + */ + setDocument: function (pdfDocument) { + if (this.pdfDocument) { + this._resetView(); + } + + this.pdfDocument = pdfDocument; + if (!pdfDocument) { + return; + } + + var pagesCount = pdfDocument.numPages; + var pagesRefMap = this.pagesRefMap = {}; + var self = this; + + var resolvePagesPromise; + var pagesPromise = new Promise(function (resolve) { + resolvePagesPromise = resolve; + }); + this.pagesPromise = pagesPromise; + pagesPromise.then(function () { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('pagesloaded', true, true, { + pagesCount: pagesCount + }); + self.container.dispatchEvent(event); + }); + + var isOnePageRenderedResolved = false; + var resolveOnePageRendered = null; + var onePageRendered = new Promise(function (resolve) { + resolveOnePageRendered = resolve; + }); + this.onePageRendered = onePageRendered; + + var bindOnAfterAndBeforeDraw = function (pageView) { + pageView.onBeforeDraw = function pdfViewLoadOnBeforeDraw() { + // Add the page to the buffer at the start of drawing. That way it can + // be evicted from the buffer and destroyed even if we pause its + // rendering. + self._buffer.push(this); + }; + // when page is painted, using the image as thumbnail base + pageView.onAfterDraw = function pdfViewLoadOnAfterDraw() { + if (!isOnePageRenderedResolved) { + isOnePageRenderedResolved = true; + resolveOnePageRendered(); + } + }; + }; + + var firstPagePromise = pdfDocument.getPage(1); + this.firstPagePromise = firstPagePromise; + + // Fetch a single page so we can get a viewport that will be the default + // viewport for all pages + return firstPagePromise.then(function(pdfPage) { + var scale = this._currentScale || 1.0; + var viewport = pdfPage.getViewport(scale * CSS_UNITS); + for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) { + var textLayerFactory = null; + if (!PDFJS.disableTextLayer) { + textLayerFactory = this; + } + var pageView = new PDFPageView({ + container: this.viewer, + id: pageNum, + scale: scale, + defaultViewport: viewport.clone(), + renderingQueue: this.renderingQueue, + textLayerFactory: textLayerFactory, + annotationsLayerFactory: this + }); + bindOnAfterAndBeforeDraw(pageView); + this._pages.push(pageView); + } + + // Fetch all the pages since the viewport is needed before printing + // starts to create the correct size canvas. Wait until one page is + // rendered so we don't tie up too many resources early on. + onePageRendered.then(function () { + if (!PDFJS.disableAutoFetch) { + var getPagesLeft = pagesCount; + for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) { + pdfDocument.getPage(pageNum).then(function (pageNum, pdfPage) { + var pageView = self._pages[pageNum - 1]; + if (!pageView.pdfPage) { + pageView.setPdfPage(pdfPage); + } + var refStr = pdfPage.ref.num + ' ' + pdfPage.ref.gen + ' R'; + pagesRefMap[refStr] = pageNum; + getPagesLeft--; + if (!getPagesLeft) { + resolvePagesPromise(); + } + }.bind(null, pageNum)); + } + } else { + // XXX: Printing is semi-broken with auto fetch disabled. + resolvePagesPromise(); + } + }); + + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('pagesinit', true, true, null); + self.container.dispatchEvent(event); + + if (this.defaultRenderingQueue) { + this.update(); + } + + if (this.findController) { + this.findController.resolveFirstPage(); + } + }.bind(this)); + }, + + _resetView: function () { + this._pages = []; + this._currentPageNumber = 1; + this._currentScale = UNKNOWN_SCALE; + this._currentScaleValue = null; + this._buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE); + this._location = null; + this._pagesRotation = 0; + this._pagesRequests = []; + + var container = this.viewer; + while (container.hasChildNodes()) { + container.removeChild(container.lastChild); + } + }, + + _scrollUpdate: function () { + if (this.pagesCount === 0) { + return; + } + this.update(); + for (var i = 0, ii = this._pages.length; i < ii; i++) { + this._pages[i].updatePosition(); + } + }, + + _setScaleDispatchEvent: function pdfViewer_setScaleDispatchEvent( + newScale, newValue, preset) { + var event = document.createEvent('UIEvents'); + event.initUIEvent('scalechange', true, true, window, 0); + event.scale = newScale; + if (preset) { + event.presetValue = newValue; + } + this.container.dispatchEvent(event); + }, + + _setScaleUpdatePages: function pdfViewer_setScaleUpdatePages( + newScale, newValue, noScroll, preset) { + this._currentScaleValue = newValue; + if (newScale === this._currentScale) { + if (preset) { + this._setScaleDispatchEvent(newScale, newValue, true); + } + return; + } + + for (var i = 0, ii = this._pages.length; i < ii; i++) { + this._pages[i].update(newScale); + } + this._currentScale = newScale; + + if (!noScroll) { + var page = this._currentPageNumber, dest; + if (this._location && !IGNORE_CURRENT_POSITION_ON_ZOOM && + !(this.isInPresentationMode || this.isChangingPresentationMode)) { + page = this._location.pageNumber; + dest = [null, { name: 'XYZ' }, this._location.left, + this._location.top, null]; + } + this.scrollPageIntoView(page, dest); + } + + this._setScaleDispatchEvent(newScale, newValue, preset); + }, + + _setScale: function pdfViewer_setScale(value, noScroll) { + if (value === 'custom') { + return; + } + var scale = parseFloat(value); + + if (scale > 0) { + this._setScaleUpdatePages(scale, value, noScroll, false); + } else { + var currentPage = this._pages[this._currentPageNumber - 1]; + if (!currentPage) { + return; + } + var hPadding = (this.isInPresentationMode || this.removePageBorders) ? + 0 : SCROLLBAR_PADDING; + var vPadding = (this.isInPresentationMode || this.removePageBorders) ? + 0 : VERTICAL_PADDING; + var pageWidthScale = (this.container.clientWidth - hPadding) / + currentPage.width * currentPage.scale; + var pageHeightScale = (this.container.clientHeight - vPadding) / + currentPage.height * currentPage.scale; + switch (value) { + case 'page-actual': + scale = 1; + break; + case 'page-width': + scale = pageWidthScale; + break; + case 'page-height': + scale = pageHeightScale; + break; + case 'page-fit': + scale = Math.min(pageWidthScale, pageHeightScale); + break; + case 'auto': + var isLandscape = (currentPage.width > currentPage.height); + // For pages in landscape mode, fit the page height to the viewer + // *unless* the page would thus become too wide to fit horizontally. + var horizontalScale = isLandscape ? + Math.min(pageHeightScale, pageWidthScale) : pageWidthScale; + scale = Math.min(MAX_AUTO_SCALE, horizontalScale); + break; + default: + console.error('pdfViewSetScale: \'' + value + + '\' is an unknown zoom value.'); + return; + } + this._setScaleUpdatePages(scale, value, noScroll, true); + } + }, + + /** + * Scrolls page into view. + * @param {number} pageNumber + * @param {Array} dest - (optional) original PDF destination array: + * + */ + scrollPageIntoView: function PDFViewer_scrollPageIntoView(pageNumber, + dest) { + var pageView = this._pages[pageNumber - 1]; + + if (this.isInPresentationMode) { + if (this.linkService.page !== pageView.id) { + // Avoid breaking getVisiblePages in presentation mode. + this.linkService.page = pageView.id; + return; + } + dest = null; + // Fixes the case when PDF has different page sizes. + this._setScale(this.currentScaleValue, true); + } + if (!dest) { + scrollIntoView(pageView.div); + return; + } + + var x = 0, y = 0; + var width = 0, height = 0, widthScale, heightScale; + var changeOrientation = (pageView.rotation % 180 === 0 ? false : true); + var pageWidth = (changeOrientation ? pageView.height : pageView.width) / + pageView.scale / CSS_UNITS; + var pageHeight = (changeOrientation ? pageView.width : pageView.height) / + pageView.scale / CSS_UNITS; + var scale = 0; + switch (dest[1].name) { + case 'XYZ': + x = dest[2]; + y = dest[3]; + scale = dest[4]; + // If x and/or y coordinates are not supplied, default to + // _top_ left of the page (not the obvious bottom left, + // since aligning the bottom of the intended page with the + // top of the window is rarely helpful). + x = x !== null ? x : 0; + y = y !== null ? y : pageHeight; + break; + case 'Fit': + case 'FitB': + scale = 'page-fit'; + break; + case 'FitH': + case 'FitBH': + y = dest[2]; + scale = 'page-width'; + break; + case 'FitV': + case 'FitBV': + x = dest[2]; + width = pageWidth; + height = pageHeight; + scale = 'page-height'; + break; + case 'FitR': + x = dest[2]; + y = dest[3]; + width = dest[4] - x; + height = dest[5] - y; + var viewerContainer = this.container; + var hPadding = this.removePageBorders ? 0 : SCROLLBAR_PADDING; + var vPadding = this.removePageBorders ? 0 : VERTICAL_PADDING; + + widthScale = (viewerContainer.clientWidth - hPadding) / + width / CSS_UNITS; + heightScale = (viewerContainer.clientHeight - vPadding) / + height / CSS_UNITS; + scale = Math.min(Math.abs(widthScale), Math.abs(heightScale)); + break; + default: + return; + } + + if (scale && scale !== this.currentScale) { + this.currentScaleValue = scale; + } else if (this.currentScale === UNKNOWN_SCALE) { + this.currentScaleValue = DEFAULT_SCALE; + } + + if (scale === 'page-fit' && !dest[4]) { + scrollIntoView(pageView.div); + return; + } + + var boundingRect = [ + pageView.viewport.convertToViewportPoint(x, y), + pageView.viewport.convertToViewportPoint(x + width, y + height) + ]; + var left = Math.min(boundingRect[0][0], boundingRect[1][0]); + var top = Math.min(boundingRect[0][1], boundingRect[1][1]); + + scrollIntoView(pageView.div, { left: left, top: top }); + }, + + _updateLocation: function (firstPage) { + var currentScale = this._currentScale; + var currentScaleValue = this._currentScaleValue; + var normalizedScaleValue = + parseFloat(currentScaleValue) === currentScale ? + Math.round(currentScale * 10000) / 100 : currentScaleValue; + + var pageNumber = firstPage.id; + var pdfOpenParams = '#page=' + pageNumber; + pdfOpenParams += '&zoom=' + normalizedScaleValue; + var currentPageView = this._pages[pageNumber - 1]; + var container = this.container; + var topLeft = currentPageView.getPagePoint( + (container.scrollLeft - firstPage.x), + (container.scrollTop - firstPage.y)); + var intLeft = Math.round(topLeft[0]); + var intTop = Math.round(topLeft[1]); + pdfOpenParams += ',' + intLeft + ',' + intTop; + + this._location = { + pageNumber: pageNumber, + scale: normalizedScaleValue, + top: intTop, + left: intLeft, + pdfOpenParams: pdfOpenParams + }; + }, + + update: function () { + var visible = this._getVisiblePages(); + var visiblePages = visible.views; + if (visiblePages.length === 0) { + return; + } + + this.updateInProgress = true; + + var suggestedCacheSize = Math.max(DEFAULT_CACHE_SIZE, + 2 * visiblePages.length + 1); + this._buffer.resize(suggestedCacheSize); + + this.renderingQueue.renderHighestPriority(visible); + + var currentId = this.currentPageNumber; + var firstPage = visible.first; + + for (var i = 0, ii = visiblePages.length, stillFullyVisible = false; + i < ii; ++i) { + var page = visiblePages[i]; + + if (page.percent < 100) { + break; + } + if (page.id === currentId) { + stillFullyVisible = true; + break; + } + } + + if (!stillFullyVisible) { + currentId = visiblePages[0].id; + } + + if (!this.isInPresentationMode) { + this.currentPageNumber = currentId; + } + + this._updateLocation(firstPage); + + this.updateInProgress = false; + + var event = document.createEvent('UIEvents'); + event.initUIEvent('updateviewarea', true, true, window, 0); + event.location = this._location; + this.container.dispatchEvent(event); + }, + + containsElement: function (element) { + return this.container.contains(element); + }, + + focus: function () { + this.container.focus(); + }, + + get isInPresentationMode() { + return this.presentationModeState === PresentationModeState.FULLSCREEN; + }, + + get isChangingPresentationMode() { + return this.PresentationModeState === PresentationModeState.CHANGING; + }, + + get isHorizontalScrollbarEnabled() { + return (this.isInPresentationMode ? + false : (this.container.scrollWidth > this.container.clientWidth)); + }, + + _getVisiblePages: function () { + if (!this.isInPresentationMode) { + return getVisibleElements(this.container, this._pages, true); + } else { + // The algorithm in getVisibleElements doesn't work in all browsers and + // configurations when presentation mode is active. + var visible = []; + var currentPage = this._pages[this._currentPageNumber - 1]; + visible.push({ id: currentPage.id, view: currentPage }); + return { first: currentPage, last: currentPage, views: visible }; + } + }, + + cleanup: function () { + for (var i = 0, ii = this._pages.length; i < ii; i++) { + if (this._pages[i] && + this._pages[i].renderingState !== RenderingStates.FINISHED) { + this._pages[i].reset(); + } + } + }, + + /** + * @param {PDFPageView} pageView + * @returns {PDFPage} + * @private + */ + _ensurePdfPageLoaded: function (pageView) { + if (pageView.pdfPage) { + return Promise.resolve(pageView.pdfPage); + } + var pageNumber = pageView.id; + if (this._pagesRequests[pageNumber]) { + return this._pagesRequests[pageNumber]; + } + var promise = this.pdfDocument.getPage(pageNumber).then( + function (pdfPage) { + pageView.setPdfPage(pdfPage); + this._pagesRequests[pageNumber] = null; + return pdfPage; + }.bind(this)); + this._pagesRequests[pageNumber] = promise; + return promise; + }, + + forceRendering: function (currentlyVisiblePages) { + var visiblePages = currentlyVisiblePages || this._getVisiblePages(); + var pageView = this.renderingQueue.getHighestPriority(visiblePages, + this._pages, + this.scroll.down); + if (pageView) { + this._ensurePdfPageLoaded(pageView).then(function () { + this.renderingQueue.renderView(pageView); + }.bind(this)); + return true; + } + return false; + }, + + getPageTextContent: function (pageIndex) { + return this.pdfDocument.getPage(pageIndex + 1).then(function (page) { + return page.getTextContent(); + }); + }, + + /** + * @param {HTMLDivElement} textLayerDiv + * @param {number} pageIndex + * @param {PageViewport} viewport + * @returns {TextLayerBuilder} + */ + createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport) { + return new TextLayerBuilder({ + textLayerDiv: textLayerDiv, + pageIndex: pageIndex, + viewport: viewport, + findController: this.isInPresentationMode ? null : this.findController + }); + }, + + /** + * @param {HTMLDivElement} pageDiv + * @param {PDFPage} pdfPage + * @returns {AnnotationsLayerBuilder} + */ + createAnnotationsLayerBuilder: function (pageDiv, pdfPage) { + return new AnnotationsLayerBuilder({ + pageDiv: pageDiv, + pdfPage: pdfPage, + linkService: this.linkService + }); + }, + + setFindController: function (findController) { + this.findController = findController; + }, + }; + + return PDFViewer; +})(); + +var SimpleLinkService = (function SimpleLinkServiceClosure() { + function SimpleLinkService(pdfViewer) { + this.pdfViewer = pdfViewer; + } + SimpleLinkService.prototype = { + /** + * @returns {number} + */ + get page() { + return this.pdfViewer.currentPageNumber; + }, + /** + * @param {number} value + */ + set page(value) { + this.pdfViewer.currentPageNumber = value; + }, + /** + * @param dest - The PDF destination object. + */ + navigateTo: function (dest) {}, + /** + * @param dest - The PDF destination object. + * @returns {string} The hyperlink to the PDF object. + */ + getDestinationHash: function (dest) { + return '#'; + }, + /** + * @param hash - The PDF parameters/hash. + * @returns {string} The hyperlink to the PDF object. + */ + getAnchorUrl: function (hash) { + return '#'; + }, + /** + * @param {string} hash + */ + setHash: function (hash) {}, + /** + * @param {string} action + */ + executeNamedAction: function (action) {}, + }; + return SimpleLinkService; +})(); + + +var THUMBNAIL_SCROLL_MARGIN = -19; + + +var THUMBNAIL_WIDTH = 98; // px +var THUMBNAIL_CANVAS_BORDER_WIDTH = 1; // px + +/** + * @typedef {Object} PDFThumbnailViewOptions + * @property {HTMLDivElement} container - The viewer element. + * @property {number} id - The thumbnail's unique ID (normally its number). + * @property {PageViewport} defaultViewport - The page viewport. + * @property {IPDFLinkService} linkService - The navigation/linking service. + * @property {PDFRenderingQueue} renderingQueue - The rendering queue object. + */ + +/** + * @class + * @implements {IRenderableView} + */ +var PDFThumbnailView = (function PDFThumbnailViewClosure() { + function getTempCanvas(width, height) { + var tempCanvas = PDFThumbnailView.tempImageCache; + if (!tempCanvas) { + tempCanvas = document.createElement('canvas'); + PDFThumbnailView.tempImageCache = tempCanvas; + } + tempCanvas.width = width; + tempCanvas.height = height; + + // Since this is a temporary canvas, we need to fill the canvas with a white + // background ourselves. |_getPageDrawContext| uses CSS rules for this. + var ctx = tempCanvas.getContext('2d'); + ctx.save(); + ctx.fillStyle = 'rgb(255, 255, 255)'; + ctx.fillRect(0, 0, width, height); + ctx.restore(); + return tempCanvas; + } + + /** + * @constructs PDFThumbnailView + * @param {PDFThumbnailViewOptions} options + */ + function PDFThumbnailView(options) { + var container = options.container; + var id = options.id; + var defaultViewport = options.defaultViewport; + var linkService = options.linkService; + var renderingQueue = options.renderingQueue; + + this.id = id; + this.renderingId = 'thumbnail' + id; + + this.pdfPage = null; + this.rotation = 0; + this.viewport = defaultViewport; + this.pdfPageRotate = defaultViewport.rotation; + + this.linkService = linkService; + this.renderingQueue = renderingQueue; + + this.hasImage = false; + this.resume = null; + this.renderingState = RenderingStates.INITIAL; + + this.pageWidth = this.viewport.width; + this.pageHeight = this.viewport.height; + this.pageRatio = this.pageWidth / this.pageHeight; + + this.canvasWidth = THUMBNAIL_WIDTH; + this.canvasHeight = (this.canvasWidth / this.pageRatio) | 0; + this.scale = this.canvasWidth / this.pageWidth; + + var anchor = document.createElement('a'); + anchor.href = linkService.getAnchorUrl('#page=' + id); + anchor.title = mozL10n.get('thumb_page_title', {page: id}, 'Page {{page}}'); + anchor.onclick = function stopNavigation() { + linkService.page = id; + return false; + }; + + var div = document.createElement('div'); + div.id = 'thumbnailContainer' + id; + div.className = 'thumbnail'; + this.div = div; + + if (id === 1) { + // Highlight the thumbnail of the first page when no page number is + // specified (or exists in cache) when the document is loaded. + div.classList.add('selected'); + } + + var ring = document.createElement('div'); + ring.className = 'thumbnailSelectionRing'; + var borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; + ring.style.width = this.canvasWidth + borderAdjustment + 'px'; + ring.style.height = this.canvasHeight + borderAdjustment + 'px'; + this.ring = ring; + + div.appendChild(ring); + anchor.appendChild(div); + container.appendChild(anchor); + } + + PDFThumbnailView.prototype = { + setPdfPage: function PDFThumbnailView_setPdfPage(pdfPage) { + this.pdfPage = pdfPage; + this.pdfPageRotate = pdfPage.rotate; + var totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = pdfPage.getViewport(1, totalRotation); + this.reset(); + }, + + reset: function PDFThumbnailView_reset() { + if (this.renderTask) { + this.renderTask.cancel(); + } + this.hasImage = false; + this.resume = null; + this.renderingState = RenderingStates.INITIAL; + + this.pageWidth = this.viewport.width; + this.pageHeight = this.viewport.height; + this.pageRatio = this.pageWidth / this.pageHeight; + + this.canvasHeight = (this.canvasWidth / this.pageRatio) | 0; + this.scale = (this.canvasWidth / this.pageWidth); + + this.div.removeAttribute('data-loaded'); + var ring = this.ring; + var childNodes = ring.childNodes; + for (var i = childNodes.length - 1; i >= 0; i--) { + ring.removeChild(childNodes[i]); + } + var borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; + ring.style.width = this.canvasWidth + borderAdjustment + 'px'; + ring.style.height = this.canvasHeight + borderAdjustment + 'px'; + + if (this.canvas) { + // Zeroing the width and height causes Firefox to release graphics + // resources immediately, which can greatly reduce memory consumption. + this.canvas.width = 0; + this.canvas.height = 0; + delete this.canvas; + } + }, + + update: function PDFThumbnailView_update(rotation) { + if (typeof rotation !== 'undefined') { + this.rotation = rotation; + } + var totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = this.viewport.clone({ + scale: 1, + rotation: totalRotation + }); + this.reset(); + }, + + /** + * @private + */ + _getPageDrawContext: + function PDFThumbnailView_getPageDrawContext(noCtxScale) { + var canvas = document.createElement('canvas'); + canvas.id = this.renderingId; + + canvas.className = 'thumbnailImage'; + canvas.setAttribute('aria-label', mozL10n.get('thumb_page_canvas', + {page: this.id}, 'Thumbnail of Page {{page}}')); + + this.canvas = canvas; + this.div.setAttribute('data-loaded', true); + this.ring.appendChild(canvas); + + var ctx = canvas.getContext('2d'); + var outputScale = getOutputScale(ctx); + canvas.width = (this.canvasWidth * outputScale.sx) | 0; + canvas.height = (this.canvasHeight * outputScale.sy) | 0; + canvas.style.width = this.canvasWidth + 'px'; + canvas.style.height = this.canvasHeight + 'px'; + if (!noCtxScale && outputScale.scaled) { + ctx.scale(outputScale.sx, outputScale.sy); + } + return ctx; + }, + + draw: function PDFThumbnailView_draw() { + if (this.renderingState !== RenderingStates.INITIAL) { + console.error('Must be in new state before drawing'); + } + if (this.hasImage) { + return Promise.resolve(undefined); + } + this.hasImage = true; + this.renderingState = RenderingStates.RUNNING; + + var resolveRenderPromise, rejectRenderPromise; + var promise = new Promise(function (resolve, reject) { + resolveRenderPromise = resolve; + rejectRenderPromise = reject; + }); + + var self = this; + function thumbnailDrawCallback(error) { + // The renderTask may have been replaced by a new one, so only remove + // the reference to the renderTask if it matches the one that is + // triggering this callback. + if (renderTask === self.renderTask) { + self.renderTask = null; + } + if (error === 'cancelled') { + rejectRenderPromise(error); + return; + } + self.renderingState = RenderingStates.FINISHED; + + if (!error) { + resolveRenderPromise(undefined); + } else { + rejectRenderPromise(error); + } + } + + var ctx = this._getPageDrawContext(); + var drawViewport = this.viewport.clone({ scale: this.scale }); + var renderContinueCallback = function renderContinueCallback(cont) { + if (!self.renderingQueue.isHighestPriority(self)) { + self.renderingState = RenderingStates.PAUSED; + self.resume = function resumeCallback() { + self.renderingState = RenderingStates.RUNNING; + cont(); + }; + return; + } + cont(); + }; + + var renderContext = { + canvasContext: ctx, + viewport: drawViewport, + continueCallback: renderContinueCallback + }; + var renderTask = this.renderTask = this.pdfPage.render(renderContext); + + renderTask.promise.then( + function pdfPageRenderCallback() { + thumbnailDrawCallback(null); + }, + function pdfPageRenderError(error) { + thumbnailDrawCallback(error); + } + ); + return promise; + }, + + setImage: function PDFThumbnailView_setImage(pageView) { + var img = pageView.canvas; + if (this.hasImage || !img) { + return; + } + if (!this.pdfPage) { + this.setPdfPage(pageView.pdfPage); + } + this.hasImage = true; + this.renderingState = RenderingStates.FINISHED; + + var ctx = this._getPageDrawContext(true); + var canvas = ctx.canvas; + + if (img.width <= 2 * canvas.width) { + ctx.drawImage(img, 0, 0, img.width, img.height, + 0, 0, canvas.width, canvas.height); + return; + } + // drawImage does an awful job of rescaling the image, doing it gradually. + var MAX_NUM_SCALING_STEPS = 3; + var reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS; + var reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS; + var reducedImage = getTempCanvas(reducedWidth, reducedHeight); + var reducedImageCtx = reducedImage.getContext('2d'); + + while (reducedWidth > img.width || reducedHeight > img.height) { + reducedWidth >>= 1; + reducedHeight >>= 1; + } + reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, + 0, 0, reducedWidth, reducedHeight); + while (reducedWidth > 2 * canvas.width) { + reducedImageCtx.drawImage(reducedImage, + 0, 0, reducedWidth, reducedHeight, + 0, 0, reducedWidth >> 1, reducedHeight >> 1); + reducedWidth >>= 1; + reducedHeight >>= 1; + } + ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, + 0, 0, canvas.width, canvas.height); + } + }; + + return PDFThumbnailView; +})(); + +PDFThumbnailView.tempImageCache = null; + + +/** + * @typedef {Object} PDFThumbnailViewerOptions + * @property {HTMLDivElement} container - The container for the thumbnail + * elements. + * @property {IPDFLinkService} linkService - The navigation/linking service. + * @property {PDFRenderingQueue} renderingQueue - The rendering queue object. + */ + +/** + * Simple viewer control to display thumbnails for pages. + * @class + * @implements {IRenderableView} + */ +var PDFThumbnailViewer = (function PDFThumbnailViewerClosure() { + /** + * @constructs PDFThumbnailViewer + * @param {PDFThumbnailViewerOptions} options + */ + function PDFThumbnailViewer(options) { + this.container = options.container; + this.renderingQueue = options.renderingQueue; + this.linkService = options.linkService; + + this.scroll = watchScroll(this.container, this._scrollUpdated.bind(this)); + this._resetView(); + } + + PDFThumbnailViewer.prototype = { + /** + * @private + */ + _scrollUpdated: function PDFThumbnailViewer_scrollUpdated() { + this.renderingQueue.renderHighestPriority(); + }, + + getThumbnail: function PDFThumbnailViewer_getThumbnail(index) { + return this.thumbnails[index]; + }, + + /** + * @private + */ + _getVisibleThumbs: function PDFThumbnailViewer_getVisibleThumbs() { + return getVisibleElements(this.container, this.thumbnails); + }, + + scrollThumbnailIntoView: + function PDFThumbnailViewer_scrollThumbnailIntoView(page) { + var selected = document.querySelector('.thumbnail.selected'); + if (selected) { + selected.classList.remove('selected'); + } + var thumbnail = document.getElementById('thumbnailContainer' + page); + if (thumbnail) { + thumbnail.classList.add('selected'); + } + var visibleThumbs = this._getVisibleThumbs(); + var numVisibleThumbs = visibleThumbs.views.length; + + // If the thumbnail isn't currently visible, scroll it into view. + if (numVisibleThumbs > 0) { + var first = visibleThumbs.first.id; + // Account for only one thumbnail being visible. + var last = (numVisibleThumbs > 1 ? visibleThumbs.last.id : first); + if (page <= first || page >= last) { + scrollIntoView(thumbnail, { top: THUMBNAIL_SCROLL_MARGIN }); + } + } + }, + + get pagesRotation() { + return this._pagesRotation; + }, + + set pagesRotation(rotation) { + this._pagesRotation = rotation; + for (var i = 0, l = this.thumbnails.length; i < l; i++) { + var thumb = this.thumbnails[i]; + thumb.update(rotation); + } + }, + + cleanup: function PDFThumbnailViewer_cleanup() { + var tempCanvas = PDFThumbnailView.tempImageCache; + if (tempCanvas) { + // Zeroing the width and height causes Firefox to release graphics + // resources immediately, which can greatly reduce memory consumption. + tempCanvas.width = 0; + tempCanvas.height = 0; + } + PDFThumbnailView.tempImageCache = null; + }, + + /** + * @private + */ + _resetView: function PDFThumbnailViewer_resetView() { + this.thumbnails = []; + this._pagesRotation = 0; + this._pagesRequests = []; + }, + + setDocument: function PDFThumbnailViewer_setDocument(pdfDocument) { + if (this.pdfDocument) { + // cleanup of the elements and views + var thumbsView = this.container; + while (thumbsView.hasChildNodes()) { + thumbsView.removeChild(thumbsView.lastChild); + } + this._resetView(); + } + + this.pdfDocument = pdfDocument; + if (!pdfDocument) { + return Promise.resolve(); + } + + return pdfDocument.getPage(1).then(function (firstPage) { + var pagesCount = pdfDocument.numPages; + var viewport = firstPage.getViewport(1.0); + for (var pageNum = 1; pageNum <= pagesCount; ++pageNum) { + var thumbnail = new PDFThumbnailView({ + container: this.container, + id: pageNum, + defaultViewport: viewport.clone(), + linkService: this.linkService, + renderingQueue: this.renderingQueue + }); + this.thumbnails.push(thumbnail); + } + }.bind(this)); + }, + + /** + * @param {PDFPageView} pageView + * @returns {PDFPage} + * @private + */ + _ensurePdfPageLoaded: + function PDFThumbnailViewer_ensurePdfPageLoaded(thumbView) { + if (thumbView.pdfPage) { + return Promise.resolve(thumbView.pdfPage); + } + var pageNumber = thumbView.id; + if (this._pagesRequests[pageNumber]) { + return this._pagesRequests[pageNumber]; + } + var promise = this.pdfDocument.getPage(pageNumber).then( + function (pdfPage) { + thumbView.setPdfPage(pdfPage); + this._pagesRequests[pageNumber] = null; + return pdfPage; + }.bind(this)); + this._pagesRequests[pageNumber] = promise; + return promise; + }, + + ensureThumbnailVisible: + function PDFThumbnailViewer_ensureThumbnailVisible(page) { + // Ensure that the thumbnail of the current page is visible + // when switching from another view. + scrollIntoView(document.getElementById('thumbnailContainer' + page)); + }, + + forceRendering: function () { + var visibleThumbs = this._getVisibleThumbs(); + var thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, + this.thumbnails, + this.scroll.down); + if (thumbView) { + this._ensurePdfPageLoaded(thumbView).then(function () { + this.renderingQueue.renderView(thumbView); + }.bind(this)); + return true; + } + return false; + } + }; + + return PDFThumbnailViewer; +})(); + + +/** + * @typedef {Object} PDFOutlineViewOptions + * @property {HTMLDivElement} container - The viewer element. + * @property {Array} outline - An array of outline objects. + * @property {IPDFLinkService} linkService - The navigation/linking service. + */ + +/** + * @class + */ +var PDFOutlineView = (function PDFOutlineViewClosure() { + /** + * @constructs PDFOutlineView + * @param {PDFOutlineViewOptions} options + */ + function PDFOutlineView(options) { + this.container = options.container; + this.outline = options.outline; + this.linkService = options.linkService; + } + + PDFOutlineView.prototype = { + reset: function PDFOutlineView_reset() { + var container = this.container; + while (container.firstChild) { + container.removeChild(container.firstChild); + } + }, + + /** + * @private + */ + _dispatchEvent: function PDFOutlineView_dispatchEvent(outlineCount) { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('outlineloaded', true, true, { + outlineCount: outlineCount + }); + this.container.dispatchEvent(event); + }, + + /** + * @private + */ + _bindLink: function PDFOutlineView_bindLink(element, item) { + var linkService = this.linkService; + element.href = linkService.getDestinationHash(item.dest); + element.onclick = function goToDestination(e) { + linkService.navigateTo(item.dest); + return false; + }; + }, + + render: function PDFOutlineView_render() { + var outline = this.outline; + var outlineCount = 0; + + this.reset(); + + if (!outline) { + this._dispatchEvent(outlineCount); + return; + } + + var queue = [{ parent: this.container, items: this.outline }]; + while (queue.length > 0) { + var levelData = queue.shift(); + for (var i = 0, len = levelData.items.length; i < len; i++) { + var item = levelData.items[i]; + var div = document.createElement('div'); + div.className = 'outlineItem'; + var element = document.createElement('a'); + this._bindLink(element, item); + element.textContent = item.title; + div.appendChild(element); + + if (item.items.length > 0) { + var itemsDiv = document.createElement('div'); + itemsDiv.className = 'outlineItems'; + div.appendChild(itemsDiv); + queue.push({ parent: itemsDiv, items: item.items }); + } + + levelData.parent.appendChild(div); + outlineCount++; + } + } + + this._dispatchEvent(outlineCount); + } + }; + + return PDFOutlineView; +})(); + + +/** + * @typedef {Object} PDFAttachmentViewOptions + * @property {HTMLDivElement} container - The viewer element. + * @property {Array} attachments - An array of attachment objects. + * @property {DownloadManager} downloadManager - The download manager. + */ + +/** + * @class + */ +var PDFAttachmentView = (function PDFAttachmentViewClosure() { + /** + * @constructs PDFAttachmentView + * @param {PDFAttachmentViewOptions} options + */ + function PDFAttachmentView(options) { + this.container = options.container; + this.attachments = options.attachments; + this.downloadManager = options.downloadManager; + } + + PDFAttachmentView.prototype = { + reset: function PDFAttachmentView_reset() { + var container = this.container; + while (container.firstChild) { + container.removeChild(container.firstChild); + } + }, + + /** + * @private + */ + _dispatchEvent: function PDFAttachmentView_dispatchEvent(attachmentsCount) { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('attachmentsloaded', true, true, { + attachmentsCount: attachmentsCount + }); + this.container.dispatchEvent(event); + }, + + /** + * @private + */ + _bindLink: function PDFAttachmentView_bindLink(button, content, filename) { + button.onclick = function downloadFile(e) { + this.downloadManager.downloadData(content, filename, ''); + return false; + }.bind(this); + }, + + render: function PDFAttachmentView_render() { + var attachments = this.attachments; + var attachmentsCount = 0; + + this.reset(); + + if (!attachments) { + this._dispatchEvent(attachmentsCount); + return; + } + + var names = Object.keys(attachments).sort(function(a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()); + }); + attachmentsCount = names.length; + + for (var i = 0; i < attachmentsCount; i++) { + var item = attachments[names[i]]; + var filename = getFileName(item.filename); + var div = document.createElement('div'); + div.className = 'attachmentsItem'; + var button = document.createElement('button'); + this._bindLink(button, item.content, filename); + button.textContent = filename; + div.appendChild(button); + this.container.appendChild(div); + } + + this._dispatchEvent(attachmentsCount); + } + }; + + return PDFAttachmentView; +})(); + + +var PDFViewerApplication = { + initialBookmark: document.location.hash.substring(1), + initialized: false, + fellback: false, + pdfDocument: null, + sidebarOpen: false, + printing: false, + /** @type {PDFViewer} */ + pdfViewer: null, + /** @type {PDFThumbnailViewer} */ + pdfThumbnailViewer: null, + /** @type {PDFRenderingQueue} */ + pdfRenderingQueue: null, + /** @type {PDFPresentationMode} */ + pdfPresentationMode: null, + /** @type {PDFDocumentProperties} */ + pdfDocumentProperties: null, + pageRotation: 0, + updateScaleControls: true, + isInitialViewSet: false, + animationStartedPromise: null, + preferenceSidebarViewOnLoad: SidebarView.NONE, + preferencePdfBugEnabled: false, + preferenceShowPreviousViewOnLoad: true, + preferenceDefaultZoomValue: '', + isViewerEmbedded: (window.parent !== window), + url: '', + + // called once when the document is loaded + initialize: function pdfViewInitialize() { + var pdfRenderingQueue = new PDFRenderingQueue(); + pdfRenderingQueue.onIdle = this.cleanup.bind(this); + this.pdfRenderingQueue = pdfRenderingQueue; + + var container = document.getElementById('viewerContainer'); + var viewer = document.getElementById('viewer'); + this.pdfViewer = new PDFViewer({ + container: container, + viewer: viewer, + renderingQueue: pdfRenderingQueue, + linkService: this + }); + pdfRenderingQueue.setViewer(this.pdfViewer); + + var thumbnailContainer = document.getElementById('thumbnailView'); + this.pdfThumbnailViewer = new PDFThumbnailViewer({ + container: thumbnailContainer, + renderingQueue: pdfRenderingQueue, + linkService: this + }); + pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer); + + Preferences.initialize(); + + this.findController = new PDFFindController({ + pdfViewer: this.pdfViewer, + integratedFind: this.supportsIntegratedFind + }); + this.pdfViewer.setFindController(this.findController); + + this.findBar = new PDFFindBar({ + bar: document.getElementById('findbar'), + toggleButton: document.getElementById('viewFind'), + findField: document.getElementById('findInput'), + highlightAllCheckbox: document.getElementById('findHighlightAll'), + caseSensitiveCheckbox: document.getElementById('findMatchCase'), + findMsg: document.getElementById('findMsg'), + findStatusIcon: document.getElementById('findStatusIcon'), + findPreviousButton: document.getElementById('findPrevious'), + findNextButton: document.getElementById('findNext'), + findController: this.findController + }); + + this.findController.setFindBar(this.findBar); + + HandTool.initialize({ + container: container, + toggleHandTool: document.getElementById('toggleHandTool') + }); + + this.pdfDocumentProperties = new PDFDocumentProperties({ + overlayName: 'documentPropertiesOverlay', + closeButton: document.getElementById('documentPropertiesClose'), + fields: { + 'fileName': document.getElementById('fileNameField'), + 'fileSize': document.getElementById('fileSizeField'), + 'title': document.getElementById('titleField'), + 'author': document.getElementById('authorField'), + 'subject': document.getElementById('subjectField'), + 'keywords': document.getElementById('keywordsField'), + 'creationDate': document.getElementById('creationDateField'), + 'modificationDate': document.getElementById('modificationDateField'), + 'creator': document.getElementById('creatorField'), + 'producer': document.getElementById('producerField'), + 'version': document.getElementById('versionField'), + 'pageCount': document.getElementById('pageCountField') + } + }); + + SecondaryToolbar.initialize({ + toolbar: document.getElementById('secondaryToolbar'), + toggleButton: document.getElementById('secondaryToolbarToggle'), + presentationModeButton: + document.getElementById('secondaryPresentationMode'), + openFile: document.getElementById('secondaryOpenFile'), + print: document.getElementById('secondaryPrint'), + download: document.getElementById('secondaryDownload'), + viewBookmark: document.getElementById('secondaryViewBookmark'), + firstPage: document.getElementById('firstPage'), + lastPage: document.getElementById('lastPage'), + pageRotateCw: document.getElementById('pageRotateCw'), + pageRotateCcw: document.getElementById('pageRotateCcw'), + documentPropertiesButton: document.getElementById('documentProperties') + }); + + if (this.supportsFullscreen) { + var toolbar = SecondaryToolbar; + this.pdfPresentationMode = new PDFPresentationMode({ + container: container, + viewer: viewer, + pdfThumbnailViewer: this.pdfThumbnailViewer, + contextMenuItems: [ + { element: document.getElementById('contextFirstPage'), + handler: toolbar.firstPageClick.bind(toolbar) }, + { element: document.getElementById('contextLastPage'), + handler: toolbar.lastPageClick.bind(toolbar) }, + { element: document.getElementById('contextPageRotateCw'), + handler: toolbar.pageRotateCwClick.bind(toolbar) }, + { element: document.getElementById('contextPageRotateCcw'), + handler: toolbar.pageRotateCcwClick.bind(toolbar) } + ] + }); + } + + PasswordPrompt.initialize({ + overlayName: 'passwordOverlay', + passwordField: document.getElementById('password'), + passwordText: document.getElementById('passwordText'), + passwordSubmit: document.getElementById('passwordSubmit'), + passwordCancel: document.getElementById('passwordCancel') + }); + + var self = this; + var initializedPromise = Promise.all([ + Preferences.get('enableWebGL').then(function resolved(value) { + PDFJS.disableWebGL = !value; + }), + Preferences.get('sidebarViewOnLoad').then(function resolved(value) { + self.preferenceSidebarViewOnLoad = value; + }), + Preferences.get('pdfBugEnabled').then(function resolved(value) { + self.preferencePdfBugEnabled = value; + }), + Preferences.get('showPreviousViewOnLoad').then(function resolved(value) { + self.preferenceShowPreviousViewOnLoad = value; + }), + Preferences.get('defaultZoomValue').then(function resolved(value) { + self.preferenceDefaultZoomValue = value; + }), + Preferences.get('disableTextLayer').then(function resolved(value) { + if (PDFJS.disableTextLayer === true) { + return; + } + PDFJS.disableTextLayer = value; + }), + Preferences.get('disableRange').then(function resolved(value) { + if (PDFJS.disableRange === true) { + return; + } + PDFJS.disableRange = value; + }), + Preferences.get('disableAutoFetch').then(function resolved(value) { + PDFJS.disableAutoFetch = value; + }), + Preferences.get('disableFontFace').then(function resolved(value) { + if (PDFJS.disableFontFace === true) { + return; + } + PDFJS.disableFontFace = value; + }), + Preferences.get('useOnlyCssZoom').then(function resolved(value) { + PDFJS.useOnlyCssZoom = value; + }) + // TODO move more preferences and other async stuff here + ]).catch(function (reason) { }); + + return initializedPromise.then(function () { + PDFViewerApplication.initialized = true; + }); + }, + + zoomIn: function pdfViewZoomIn(ticks) { + var newScale = this.pdfViewer.currentScale; + do { + newScale = (newScale * DEFAULT_SCALE_DELTA).toFixed(2); + newScale = Math.ceil(newScale * 10) / 10; + newScale = Math.min(MAX_SCALE, newScale); + } while (--ticks > 0 && newScale < MAX_SCALE); + this.setScale(newScale, true); + }, + + zoomOut: function pdfViewZoomOut(ticks) { + var newScale = this.pdfViewer.currentScale; + do { + newScale = (newScale / DEFAULT_SCALE_DELTA).toFixed(2); + newScale = Math.floor(newScale * 10) / 10; + newScale = Math.max(MIN_SCALE, newScale); + } while (--ticks > 0 && newScale > MIN_SCALE); + this.setScale(newScale, true); + }, + + get currentScaleValue() { + return this.pdfViewer.currentScaleValue; + }, + + get pagesCount() { + return this.pdfDocument.numPages; + }, + + set page(val) { + this.pdfViewer.currentPageNumber = val; + }, + + get page() { + return this.pdfViewer.currentPageNumber; + }, + + get supportsPrinting() { + var canvas = document.createElement('canvas'); + var value = 'mozPrintCallback' in canvas; + + return PDFJS.shadow(this, 'supportsPrinting', value); + }, + + get supportsFullscreen() { + var doc = document.documentElement; + var support = !!(doc.requestFullscreen || doc.mozRequestFullScreen || + doc.webkitRequestFullScreen || doc.msRequestFullscreen); + + if (document.fullscreenEnabled === false || + document.mozFullScreenEnabled === false || + document.webkitFullscreenEnabled === false || + document.msFullscreenEnabled === false) { + support = false; + } + if (support && PDFJS.disableFullscreen === true) { + support = false; + } + + return PDFJS.shadow(this, 'supportsFullscreen', support); + }, + + get supportsIntegratedFind() { + var support = false; + + return PDFJS.shadow(this, 'supportsIntegratedFind', support); + }, + + get supportsDocumentFonts() { + var support = true; + + return PDFJS.shadow(this, 'supportsDocumentFonts', support); + }, + + get supportsDocumentColors() { + var support = true; + + return PDFJS.shadow(this, 'supportsDocumentColors', support); + }, + + get loadingBar() { + var bar = new ProgressBar('#loadingBar', {}); + + return PDFJS.shadow(this, 'loadingBar', bar); + }, + + + setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) { + this.url = url; + try { + this.setTitle(decodeURIComponent(getFileName(url)) || url); + } catch (e) { + // decodeURIComponent may throw URIError, + // fall back to using the unprocessed url in that case + this.setTitle(url); + } + }, + + setTitle: function pdfViewSetTitle(title) { + if (this.isViewerEmbedded) { + // Embedded PDF viewers should not be changing their parent page's title. + + } + //document.title = title; + }, + + close: function pdfViewClose() { + var errorWrapper = document.getElementById('errorWrapper'); + errorWrapper.setAttribute('hidden', 'true'); + + if (!this.pdfDocument) { + return; + } + + this.pdfDocument.destroy(); + this.pdfDocument = null; + + this.pdfThumbnailViewer.setDocument(null); + this.pdfViewer.setDocument(null); + + if (typeof PDFBug !== 'undefined') { + PDFBug.cleanup(); + } + }, + + // TODO(mack): This function signature should really be pdfViewOpen(url, args) + open: function pdfViewOpen(file, scale, password, + pdfDataRangeTransport, args) { + if (this.pdfDocument) { + // Reload the preferences if a document was previously opened. + Preferences.reload(); + } + this.close(); + + var parameters = {password: password}; + if (typeof file === 'string') { // URL + this.setTitleUsingUrl(file); + parameters.url = file; + } else if (file && 'byteLength' in file) { // ArrayBuffer + parameters.data = file; + } else if (file.url && file.originalUrl) { + this.setTitleUsingUrl(file.originalUrl); + parameters.url = file.url; + } + if (args) { + for (var prop in args) { + parameters[prop] = args[prop]; + } + } + + var self = this; + self.loading = true; + self.downloadComplete = false; + + var passwordNeeded = function passwordNeeded(updatePassword, reason) { + PasswordPrompt.updatePassword = updatePassword; + PasswordPrompt.reason = reason; + PasswordPrompt.open(); + }; + + function getDocumentProgress(progressData) { + self.progress(progressData.loaded / progressData.total); + } + + PDFJS.getDocument(parameters, pdfDataRangeTransport, passwordNeeded, + getDocumentProgress).then( + function getDocumentCallback(pdfDocument) { + self.load(pdfDocument, scale); + self.loading = false; + }, + function getDocumentError(exception) { + var message = exception && exception.message; + var loadingErrorMessage = mozL10n.get('loading_error', null, + 'An error occurred while loading the PDF.'); + + if (exception instanceof PDFJS.InvalidPDFException) { + // change error message also for other builds + loadingErrorMessage = mozL10n.get('invalid_file_error', null, + 'Invalid or corrupted PDF file.'); + } else if (exception instanceof PDFJS.MissingPDFException) { + // special message for missing PDF's + loadingErrorMessage = mozL10n.get('missing_file_error', null, + 'Missing PDF file.'); + } else if (exception instanceof PDFJS.UnexpectedResponseException) { + loadingErrorMessage = mozL10n.get('unexpected_response_error', null, + 'Unexpected server response.'); + } + + var moreInfo = { + message: message + }; + self.error(loadingErrorMessage, moreInfo); + self.loading = false; + } + ); + + if (args && args.length) { + PDFViewerApplication.pdfDocumentProperties.setFileSize(args.length); + } + }, + + download: function pdfViewDownload() { + function downloadByUrl() { + downloadManager.downloadUrl(url, filename); + } + + var url = this.url.split('#')[0]; + var filename = getPDFFileNameFromURL(url); + var downloadManager = new DownloadManager(); + downloadManager.onerror = function (err) { + // This error won't really be helpful because it's likely the + // fallback won't work either (or is already open). + PDFViewerApplication.error('PDF failed to download.'); + }; + + if (!this.pdfDocument) { // the PDF is not ready yet + downloadByUrl(); + return; + } + + if (!this.downloadComplete) { // the PDF is still downloading + downloadByUrl(); + return; + } + + this.pdfDocument.getData().then( + function getDataSuccess(data) { + var blob = PDFJS.createBlob(data, 'application/pdf'); + downloadManager.download(blob, url, filename); + }, + downloadByUrl // Error occurred try downloading with just the url. + ).then(null, downloadByUrl); + }, + + fallback: function pdfViewFallback(featureId) { + }, + + navigateTo: function pdfViewNavigateTo(dest) { + var destString = ''; + var self = this; + + var goToDestination = function(destRef) { + self.pendingRefStr = null; + // dest array looks like that: + var pageNumber = destRef instanceof Object ? + self.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : + (destRef + 1); + if (pageNumber) { + if (pageNumber > self.pagesCount) { + pageNumber = self.pagesCount; + } + self.pdfViewer.scrollPageIntoView(pageNumber, dest); + + // Update the browsing history. + PDFHistory.push({ dest: dest, hash: destString, page: pageNumber }); + } else { + self.pdfDocument.getPageIndex(destRef).then(function (pageIndex) { + var pageNum = pageIndex + 1; + self.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] = pageNum; + goToDestination(destRef); + }); + } + }; + + var destinationPromise; + if (typeof dest === 'string') { + destString = dest; + destinationPromise = this.pdfDocument.getDestination(dest); + } else { + destinationPromise = Promise.resolve(dest); + } + destinationPromise.then(function(destination) { + dest = destination; + if (!(destination instanceof Array)) { + return; // invalid destination + } + goToDestination(destination[0]); + }); + }, + + executeNamedAction: function pdfViewExecuteNamedAction(action) { + // See PDF reference, table 8.45 - Named action + switch (action) { + case 'GoToPage': + document.getElementById('pageNumber').focus(); + break; + + case 'GoBack': + PDFHistory.back(); + break; + + case 'GoForward': + PDFHistory.forward(); + break; + + case 'Find': + if (!this.supportsIntegratedFind) { + this.findBar.toggle(); + } + break; + + case 'NextPage': + this.page++; + break; + + case 'PrevPage': + this.page--; + break; + + case 'LastPage': + this.page = this.pagesCount; + break; + + case 'FirstPage': + this.page = 1; + break; + + default: + break; // No action according to spec + } + }, + + getDestinationHash: function pdfViewGetDestinationHash(dest) { + if (typeof dest === 'string') { + return this.getAnchorUrl('#' + escape(dest)); + } + if (dest instanceof Array) { + var destRef = dest[0]; // see navigateTo method for dest format + var pageNumber = destRef instanceof Object ? + this.pagesRefMap[destRef.num + ' ' + destRef.gen + ' R'] : + (destRef + 1); + if (pageNumber) { + var pdfOpenParams = this.getAnchorUrl('#page=' + pageNumber); + var destKind = dest[1]; + if (typeof destKind === 'object' && 'name' in destKind && + destKind.name === 'XYZ') { + var scale = (dest[4] || this.currentScaleValue); + var scaleNumber = parseFloat(scale); + if (scaleNumber) { + scale = scaleNumber * 100; + } + pdfOpenParams += '&zoom=' + scale; + if (dest[2] || dest[3]) { + pdfOpenParams += ',' + (dest[2] || 0) + ',' + (dest[3] || 0); + } + } + return pdfOpenParams; + } + } + return ''; + }, + + /** + * Prefix the full url on anchor links to make sure that links are resolved + * relative to the current URL instead of the one defined in . + * @param {String} anchor The anchor hash, including the #. + */ + getAnchorUrl: function getAnchorUrl(anchor) { + return anchor; + }, + + /** + * Show the error box. + * @param {String} message A message that is human readable. + * @param {Object} moreInfo (optional) Further information about the error + * that is more technical. Should have a 'message' + * and optionally a 'stack' property. + */ + error: function pdfViewError(message, moreInfo) { + var moreInfoText = mozL10n.get('error_version_info', + {version: PDFJS.version || '?', build: PDFJS.build || '?'}, + 'PDF.js v{{version}} (build: {{build}})') + '\n'; + if (moreInfo) { + moreInfoText += + mozL10n.get('error_message', {message: moreInfo.message}, + 'Message: {{message}}'); + if (moreInfo.stack) { + moreInfoText += '\n' + + mozL10n.get('error_stack', {stack: moreInfo.stack}, + 'Stack: {{stack}}'); + } else { + if (moreInfo.filename) { + moreInfoText += '\n' + + mozL10n.get('error_file', {file: moreInfo.filename}, + 'File: {{file}}'); + } + if (moreInfo.lineNumber) { + moreInfoText += '\n' + + mozL10n.get('error_line', {line: moreInfo.lineNumber}, + 'Line: {{line}}'); + } + } + } + + var errorWrapper = document.getElementById('errorWrapper'); + errorWrapper.removeAttribute('hidden'); + + var errorMessage = document.getElementById('errorMessage'); + errorMessage.textContent = message; + + var closeButton = document.getElementById('errorClose'); + closeButton.onclick = function() { + errorWrapper.setAttribute('hidden', 'true'); + }; + + var errorMoreInfo = document.getElementById('errorMoreInfo'); + var moreInfoButton = document.getElementById('errorShowMore'); + var lessInfoButton = document.getElementById('errorShowLess'); + moreInfoButton.onclick = function() { + errorMoreInfo.removeAttribute('hidden'); + moreInfoButton.setAttribute('hidden', 'true'); + lessInfoButton.removeAttribute('hidden'); + errorMoreInfo.style.height = errorMoreInfo.scrollHeight + 'px'; + }; + lessInfoButton.onclick = function() { + errorMoreInfo.setAttribute('hidden', 'true'); + moreInfoButton.removeAttribute('hidden'); + lessInfoButton.setAttribute('hidden', 'true'); + }; + moreInfoButton.oncontextmenu = noContextMenuHandler; + lessInfoButton.oncontextmenu = noContextMenuHandler; + closeButton.oncontextmenu = noContextMenuHandler; + moreInfoButton.removeAttribute('hidden'); + lessInfoButton.setAttribute('hidden', 'true'); + errorMoreInfo.value = moreInfoText; + }, + + progress: function pdfViewProgress(level) { + var percent = Math.round(level * 100); + // When we transition from full request to range requests, it's possible + // that we discard some of the loaded data. This can cause the loading + // bar to move backwards. So prevent this by only updating the bar if it + // increases. + if (percent > this.loadingBar.percent || isNaN(percent)) { + this.loadingBar.percent = percent; + + // When disableAutoFetch is enabled, it's not uncommon for the entire file + // to never be fetched (depends on e.g. the file structure). In this case + // the loading bar will not be completely filled, nor will it be hidden. + // To prevent displaying a partially filled loading bar permanently, we + // hide it when no data has been loaded during a certain amount of time. + if (PDFJS.disableAutoFetch && percent) { + if (this.disableAutoFetchLoadingBarTimeout) { + clearTimeout(this.disableAutoFetchLoadingBarTimeout); + this.disableAutoFetchLoadingBarTimeout = null; + } + this.loadingBar.show(); + + this.disableAutoFetchLoadingBarTimeout = setTimeout(function () { + this.loadingBar.hide(); + this.disableAutoFetchLoadingBarTimeout = null; + }.bind(this), DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT); + } + } + }, + + load: function pdfViewLoad(pdfDocument, scale) { + var self = this; + scale = scale || UNKNOWN_SCALE; + + this.findController.reset(); + + this.pdfDocument = pdfDocument; + + this.pdfDocumentProperties.setDocumentAndUrl(pdfDocument, this.url); + + var downloadedPromise = pdfDocument.getDownloadInfo().then(function() { + self.downloadComplete = true; + self.loadingBar.hide(); + }); + + var pagesCount = pdfDocument.numPages; + document.getElementById('numPages').textContent = + mozL10n.get('page_of', {pageCount: pagesCount}, 'of {{pageCount}}'); + document.getElementById('pageNumber').max = pagesCount; + + var id = this.documentFingerprint = pdfDocument.fingerprint; + var store = this.store = new ViewHistory(id); + + var pdfViewer = this.pdfViewer; + pdfViewer.currentScale = scale; + pdfViewer.setDocument(pdfDocument); + var firstPagePromise = pdfViewer.firstPagePromise; + var pagesPromise = pdfViewer.pagesPromise; + var onePageRendered = pdfViewer.onePageRendered; + + this.pageRotation = 0; + this.isInitialViewSet = false; + this.pagesRefMap = pdfViewer.pagesRefMap; + + this.pdfThumbnailViewer.setDocument(pdfDocument); + + firstPagePromise.then(function(pdfPage) { + downloadedPromise.then(function () { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('documentload', true, true, {}); + window.dispatchEvent(event); + }); + + self.loadingBar.setWidth(document.getElementById('viewer')); + + if (!PDFJS.disableHistory && !self.isViewerEmbedded) { + // The browsing history is only enabled when the viewer is standalone, + // i.e. not when it is embedded in a web page. + if (!self.preferenceShowPreviousViewOnLoad && window.history.state) { + window.history.replaceState(null, ''); + } + PDFHistory.initialize(self.documentFingerprint, self); + } + + store.initializedPromise.then(function resolved() { + var storedHash = null; + if (self.preferenceShowPreviousViewOnLoad && + store.get('exists', false)) { + var pageNum = store.get('page', '1'); + var zoom = self.preferenceDefaultZoomValue || + store.get('zoom', self.pdfViewer.currentScale); + var left = store.get('scrollLeft', '0'); + var top = store.get('scrollTop', '0'); + + storedHash = 'page=' + pageNum + '&zoom=' + zoom + ',' + + left + ',' + top; + } else if (self.preferenceDefaultZoomValue) { + storedHash = 'page=1&zoom=' + self.preferenceDefaultZoomValue; + } + self.setInitialView(storedHash, scale); + + // Make all navigation keys work on document load, + // unless the viewer is embedded in a web page. + if (!self.isViewerEmbedded) { + self.pdfViewer.focus(); + } + }, function rejected(reason) { + console.error(reason); + self.setInitialView(null, scale); + }); + }); + + pagesPromise.then(function() { + if (self.supportsPrinting) { + pdfDocument.getJavaScript().then(function(javaScript) { + if (javaScript.length) { + console.warn('Warning: JavaScript is not supported'); + self.fallback(PDFJS.UNSUPPORTED_FEATURES.javaScript); + } + // Hack to support auto printing. + var regex = /\bprint\s*\(/g; + for (var i = 0, ii = javaScript.length; i < ii; i++) { + var js = javaScript[i]; + if (js && regex.test(js)) { + setTimeout(function() { + window.print(); + }); + return; + } + } + }); + } + }); + + // outline depends on pagesRefMap + var promises = [pagesPromise, this.animationStartedPromise]; + Promise.all(promises).then(function() { + pdfDocument.getOutline().then(function(outline) { + var container = document.getElementById('outlineView'); + self.outline = new PDFOutlineView({ + container: container, + outline: outline, + linkService: self + }); + self.outline.render(); + document.getElementById('viewOutline').disabled = !outline; + + if (!outline && !container.classList.contains('hidden')) { + self.switchSidebarView('thumbs'); + } + if (outline && + self.preferenceSidebarViewOnLoad === SidebarView.OUTLINE) { + self.switchSidebarView('outline', true); + } + }); + pdfDocument.getAttachments().then(function(attachments) { + var container = document.getElementById('attachmentsView'); + self.attachments = new PDFAttachmentView({ + container: container, + attachments: attachments, + downloadManager: new DownloadManager() + }); + self.attachments.render(); + document.getElementById('viewAttachments').disabled = !attachments; + + if (!attachments && !container.classList.contains('hidden')) { + self.switchSidebarView('thumbs'); + } + if (attachments && + self.preferenceSidebarViewOnLoad === SidebarView.ATTACHMENTS) { + self.switchSidebarView('attachments', true); + } + }); + }); + + if (self.preferenceSidebarViewOnLoad === SidebarView.THUMBS) { + Promise.all([firstPagePromise, onePageRendered]).then(function () { + self.switchSidebarView('thumbs', true); + }); + } + + pdfDocument.getMetadata().then(function(data) { + var info = data.info, metadata = data.metadata; + self.documentInfo = info; + self.metadata = metadata; + + // Provides some basic debug information + console.log('PDF ' + pdfDocument.fingerprint + ' [' + + info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() + + ' / ' + (info.Creator || '-').trim() + ']' + + ' (PDF.js: ' + (PDFJS.version || '-') + + (!PDFJS.disableWebGL ? ' [WebGL]' : '') + ')'); + + var pdfTitle; + if (metadata && metadata.has('dc:title')) { + var title = metadata.get('dc:title'); + // Ghostscript sometimes return 'Untitled', sets the title to 'Untitled' + if (title !== 'Untitled') { + pdfTitle = title; + } + } + + if (!pdfTitle && info && info['Title']) { + pdfTitle = info['Title']; + } + + if (pdfTitle) { + self.setTitle(pdfTitle + ' - ' + document.title); + } + + if (info.IsAcroFormPresent) { + console.warn('Warning: AcroForm/XFA is not supported'); + self.fallback(PDFJS.UNSUPPORTED_FEATURES.forms); + } + + }); + }, + + setInitialView: function pdfViewSetInitialView(storedHash, scale) { + this.isInitialViewSet = true; + + // When opening a new file (when one is already loaded in the viewer): + // Reset 'currentPageNumber', since otherwise the page's scale will be wrong + // if 'currentPageNumber' is larger than the number of pages in the file. + document.getElementById('pageNumber').value = + this.pdfViewer.currentPageNumber = 1; + + if (PDFHistory.initialDestination) { + this.navigateTo(PDFHistory.initialDestination); + PDFHistory.initialDestination = null; + } else if (this.initialBookmark) { + this.setHash(this.initialBookmark); + PDFHistory.push({ hash: this.initialBookmark }, !!this.initialBookmark); + this.initialBookmark = null; + } else if (storedHash) { + this.setHash(storedHash); + } else if (scale) { + this.setScale(scale, true); + this.page = 1; + } + + if (this.pdfViewer.currentScale === UNKNOWN_SCALE) { + // Scale was not initialized: invalid bookmark or scale was not specified. + // Setting the default one. + this.setScale(DEFAULT_SCALE, true); + } + }, + + cleanup: function pdfViewCleanup() { + this.pdfViewer.cleanup(); + this.pdfThumbnailViewer.cleanup(); + this.pdfDocument.cleanup(); + }, + + forceRendering: function pdfViewForceRendering() { + this.pdfRenderingQueue.printing = this.printing; + this.pdfRenderingQueue.isThumbnailViewEnabled = this.sidebarOpen; + this.pdfRenderingQueue.renderHighestPriority(); + }, + + setHash: function pdfViewSetHash(hash) { + if (!this.isInitialViewSet) { + this.initialBookmark = hash; + return; + } + if (!hash) { + return; + } + + if (hash.indexOf('=') >= 0) { + var params = this.parseQueryString(hash); + // borrowing syntax from "Parameters for Opening PDF Files" + if ('nameddest' in params) { + PDFHistory.updateNextHashParam(params.nameddest); + this.navigateTo(params.nameddest); + return; + } + var pageNumber, dest; + if ('page' in params) { + pageNumber = (params.page | 0) || 1; + } + if ('zoom' in params) { + // Build the destination array. + var zoomArgs = params.zoom.split(','); // scale,left,top + var zoomArg = zoomArgs[0]; + var zoomArgNumber = parseFloat(zoomArg); + + if (zoomArg.indexOf('Fit') === -1) { + // If the zoomArg is a number, it has to get divided by 100. If it's + // a string, it should stay as it is. + dest = [null, { name: 'XYZ' }, + zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null, + zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null, + (zoomArgNumber ? zoomArgNumber / 100 : zoomArg)]; + } else { + if (zoomArg === 'Fit' || zoomArg === 'FitB') { + dest = [null, { name: zoomArg }]; + } else if ((zoomArg === 'FitH' || zoomArg === 'FitBH') || + (zoomArg === 'FitV' || zoomArg === 'FitBV')) { + dest = [null, { name: zoomArg }, + zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null]; + } else if (zoomArg === 'FitR') { + if (zoomArgs.length !== 5) { + console.error('pdfViewSetHash: ' + + 'Not enough parameters for \'FitR\'.'); + } else { + dest = [null, { name: zoomArg }, + (zoomArgs[1] | 0), (zoomArgs[2] | 0), + (zoomArgs[3] | 0), (zoomArgs[4] | 0)]; + } + } else { + console.error('pdfViewSetHash: \'' + zoomArg + + '\' is not a valid zoom value.'); + } + } + } + if (dest) { + this.pdfViewer.scrollPageIntoView(pageNumber || this.page, dest); + } else if (pageNumber) { + this.page = pageNumber; // simple page + } + if ('pagemode' in params) { + if (params.pagemode === 'thumbs' || params.pagemode === 'bookmarks' || + params.pagemode === 'attachments') { + this.switchSidebarView((params.pagemode === 'bookmarks' ? + 'outline' : params.pagemode), true); + } else if (params.pagemode === 'none' && this.sidebarOpen) { + document.getElementById('sidebarToggle').click(); + } + } + } else if (/^\d+$/.test(hash)) { // page number + this.page = hash; + } else { // named destination + PDFHistory.updateNextHashParam(unescape(hash)); + this.navigateTo(unescape(hash)); + } + }, + + refreshThumbnailViewer: function pdfViewRefreshThumbnailViewer() { + var pdfViewer = this.pdfViewer; + var thumbnailViewer = this.pdfThumbnailViewer; + + // set thumbnail images of rendered pages + var pagesCount = pdfViewer.pagesCount; + for (var pageIndex = 0; pageIndex < pagesCount; pageIndex++) { + var pageView = pdfViewer.getPageView(pageIndex); + if (pageView && pageView.renderingState === RenderingStates.FINISHED) { + var thumbnailView = thumbnailViewer.getThumbnail(pageIndex); + thumbnailView.setImage(pageView); + } + } + + thumbnailViewer.scrollThumbnailIntoView(this.page); + }, + + switchSidebarView: function pdfViewSwitchSidebarView(view, openSidebar) { + if (openSidebar && !this.sidebarOpen) { + document.getElementById('sidebarToggle').click(); + } + var thumbsView = document.getElementById('thumbnailView'); + var outlineView = document.getElementById('outlineView'); + var attachmentsView = document.getElementById('attachmentsView'); + + var thumbsButton = document.getElementById('viewThumbnail'); + var outlineButton = document.getElementById('viewOutline'); + var attachmentsButton = document.getElementById('viewAttachments'); + + switch (view) { + case 'thumbs': + var wasAnotherViewVisible = thumbsView.classList.contains('hidden'); + + thumbsButton.classList.add('toggled'); + outlineButton.classList.remove('toggled'); + attachmentsButton.classList.remove('toggled'); + thumbsView.classList.remove('hidden'); + outlineView.classList.add('hidden'); + attachmentsView.classList.add('hidden'); + + this.forceRendering(); + + if (wasAnotherViewVisible) { + this.pdfThumbnailViewer.ensureThumbnailVisible(this.page); + } + break; + + case 'outline': + thumbsButton.classList.remove('toggled'); + outlineButton.classList.add('toggled'); + attachmentsButton.classList.remove('toggled'); + thumbsView.classList.add('hidden'); + outlineView.classList.remove('hidden'); + attachmentsView.classList.add('hidden'); + + if (outlineButton.getAttribute('disabled')) { + return; + } + break; + + case 'attachments': + thumbsButton.classList.remove('toggled'); + outlineButton.classList.remove('toggled'); + attachmentsButton.classList.add('toggled'); + thumbsView.classList.add('hidden'); + outlineView.classList.add('hidden'); + attachmentsView.classList.remove('hidden'); + + if (attachmentsButton.getAttribute('disabled')) { + return; + } + break; + } + }, + + // Helper function to parse query string (e.g. ?param1=value&parm2=...). + parseQueryString: function pdfViewParseQueryString(query) { + var parts = query.split('&'); + var params = {}; + for (var i = 0, ii = parts.length; i < ii; ++i) { + var param = parts[i].split('='); + var key = param[0].toLowerCase(); + var value = param.length > 1 ? param[1] : null; + params[decodeURIComponent(key)] = decodeURIComponent(value); + } + return params; + }, + + beforePrint: function pdfViewSetupBeforePrint() { + if (!this.supportsPrinting) { + var printMessage = mozL10n.get('printing_not_supported', null, + 'Warning: Printing is not fully supported by this browser.'); + this.error(printMessage); + return; + } + + var alertNotReady = false; + var i, ii; + if (!this.pagesCount) { + alertNotReady = true; + } else { + for (i = 0, ii = this.pagesCount; i < ii; ++i) { + if (!this.pdfViewer.getPageView(i).pdfPage) { + alertNotReady = true; + break; + } + } + } + if (alertNotReady) { + var notReadyMessage = mozL10n.get('printing_not_ready', null, + 'Warning: The PDF is not fully loaded for printing.'); + window.alert(notReadyMessage); + return; + } + + this.printing = true; + this.forceRendering(); + + var body = document.querySelector('body'); + body.setAttribute('data-mozPrintCallback', true); + + if (!this.hasEqualPageSizes) { + console.warn('Not all pages have the same size. The printed result ' + + 'may be incorrect!'); + } + + // Insert a @page + size rule to make sure that the page size is correctly + // set. Note that we assume that all pages have the same size, because + // variable-size pages are not supported yet (at least in Chrome & Firefox). + // TODO(robwu): Use named pages when size calculation bugs get resolved + // (e.g. https://crbug.com/355116) AND when support for named pages is + // added (http://www.w3.org/TR/css3-page/#using-named-pages). + // In browsers where @page + size is not supported (such as Firefox, + // https://bugzil.la/851441), the next stylesheet will be ignored and the + // user has to select the correct paper size in the UI if wanted. + this.pageStyleSheet = document.createElement('style'); + var pageSize = this.pdfViewer.getPageView(0).pdfPage.getViewport(1); + this.pageStyleSheet.textContent = + // "size: " is what we need. But also add "A4" because + // Firefox incorrectly reports support for the other value. + '@supports ((size:A4) and (size:1pt 1pt)) {' + + '@page { size: ' + pageSize.width + 'pt ' + pageSize.height + 'pt;}' + + // The canvas and each ancestor node must have a height of 100% to make + // sure that each canvas is printed on exactly one page. + '#printContainer {height:100%}' + + '#printContainer > div {width:100% !important;height:100% !important;}' + + '}'; + body.appendChild(this.pageStyleSheet); + + for (i = 0, ii = this.pagesCount; i < ii; ++i) { + this.pdfViewer.getPageView(i).beforePrint(); + } + + }, + + // Whether all pages of the PDF have the same width and height. + get hasEqualPageSizes() { + var firstPage = this.pdfViewer.getPageView(0); + for (var i = 1, ii = this.pagesCount; i < ii; ++i) { + var pageView = this.pdfViewer.getPageView(i); + if (pageView.width !== firstPage.width || + pageView.height !== firstPage.height) { + return false; + } + } + return true; + }, + + afterPrint: function pdfViewSetupAfterPrint() { + var div = document.getElementById('printContainer'); + while (div.hasChildNodes()) { + div.removeChild(div.lastChild); + } + + if (this.pageStyleSheet && this.pageStyleSheet.parentNode) { + this.pageStyleSheet.parentNode.removeChild(this.pageStyleSheet); + this.pageStyleSheet = null; + } + + this.printing = false; + this.forceRendering(); + }, + + setScale: function (value, resetAutoSettings) { + this.updateScaleControls = !!resetAutoSettings; + this.pdfViewer.currentScaleValue = value; + this.updateScaleControls = true; + }, + + rotatePages: function pdfViewRotatePages(delta) { + var pageNumber = this.page; + this.pageRotation = (this.pageRotation + 360 + delta) % 360; + this.pdfViewer.pagesRotation = this.pageRotation; + this.pdfThumbnailViewer.pagesRotation = this.pageRotation; + + this.forceRendering(); + + this.pdfViewer.scrollPageIntoView(pageNumber); + }, + + requestPresentationMode: function pdfViewRequestPresentationMode() { + if (!this.pdfPresentationMode) { + return; + } + this.pdfPresentationMode.request(); + }, + + /** + * @param {number} delta - The delta value from the mouse event. + */ + scrollPresentationMode: function pdfViewScrollPresentationMode(delta) { + if (!this.pdfPresentationMode) { + return; + } + this.pdfPresentationMode.mouseScroll(delta); + } +}; +window.PDFView = PDFViewerApplication; // obsolete name, using it as an alias + + +function webViewerLoad(evt) { + PDFViewerApplication.initialize().then(webViewerInitialized); +} + +function webViewerInitialized() { + var queryString = document.location.search.substring(1); + var params = PDFViewerApplication.parseQueryString(queryString); + var file = 'file' in params ? params.file : DEFAULT_URL; + + var fileInput = document.createElement('input'); + fileInput.id = 'fileInput'; + fileInput.className = 'fileInput'; + fileInput.setAttribute('type', 'file'); + fileInput.oncontextmenu = noContextMenuHandler; + document.body.appendChild(fileInput); + + if (!window.File || !window.FileReader || !window.FileList || !window.Blob) { + document.getElementById('openFile').setAttribute('hidden', 'true'); + document.getElementById('secondaryOpenFile').setAttribute('hidden', 'true'); + } else { + document.getElementById('fileInput').value = null; + } + + var locale = PDFJS.locale || navigator.language; + + if (PDFViewerApplication.preferencePdfBugEnabled) { + // Special debugging flags in the hash section of the URL. + var hash = document.location.hash.substring(1); + var hashParams = PDFViewerApplication.parseQueryString(hash); + + if ('disableworker' in hashParams) { + PDFJS.disableWorker = (hashParams['disableworker'] === 'true'); + } + if ('disablerange' in hashParams) { + PDFJS.disableRange = (hashParams['disablerange'] === 'true'); + } + if ('disablestream' in hashParams) { + PDFJS.disableStream = (hashParams['disablestream'] === 'true'); + } + if ('disableautofetch' in hashParams) { + PDFJS.disableAutoFetch = (hashParams['disableautofetch'] === 'true'); + } + if ('disablefontface' in hashParams) { + PDFJS.disableFontFace = (hashParams['disablefontface'] === 'true'); + } + if ('disablehistory' in hashParams) { + PDFJS.disableHistory = (hashParams['disablehistory'] === 'true'); + } + if ('webgl' in hashParams) { + PDFJS.disableWebGL = (hashParams['webgl'] !== 'true'); + } + if ('useonlycsszoom' in hashParams) { + PDFJS.useOnlyCssZoom = (hashParams['useonlycsszoom'] === 'true'); + } + if ('verbosity' in hashParams) { + PDFJS.verbosity = hashParams['verbosity'] | 0; + } + if ('ignorecurrentpositiononzoom' in hashParams) { + IGNORE_CURRENT_POSITION_ON_ZOOM = + (hashParams['ignorecurrentpositiononzoom'] === 'true'); + } + if ('locale' in hashParams) { + locale = hashParams['locale']; + } + if ('textlayer' in hashParams) { + switch (hashParams['textlayer']) { + case 'off': + PDFJS.disableTextLayer = true; + break; + case 'visible': + case 'shadow': + case 'hover': + var viewer = document.getElementById('viewer'); + viewer.classList.add('textLayer-' + hashParams['textlayer']); + break; + } + } + if ('pdfbug' in hashParams) { + PDFJS.pdfBug = true; + var pdfBug = hashParams['pdfbug']; + var enabled = pdfBug.split(','); + PDFBug.enable(enabled); + PDFBug.init(); + } + } + + mozL10n.setLanguage(locale); + + if (!PDFViewerApplication.supportsPrinting) { + document.getElementById('print').classList.add('hidden'); + document.getElementById('secondaryPrint').classList.add('hidden'); + } + + if (!PDFViewerApplication.supportsFullscreen) { + document.getElementById('presentationMode').classList.add('hidden'); + document.getElementById('secondaryPresentationMode'). + classList.add('hidden'); + } + + if (PDFViewerApplication.supportsIntegratedFind) { + document.getElementById('viewFind').classList.add('hidden'); + } + + // Listen for unsupported features to trigger the fallback UI. + PDFJS.UnsupportedManager.listen( + PDFViewerApplication.fallback.bind(PDFViewerApplication)); + + // Suppress context menus for some controls + document.getElementById('scaleSelect').oncontextmenu = noContextMenuHandler; + + var mainContainer = document.getElementById('mainContainer'); + var outerContainer = document.getElementById('outerContainer'); + mainContainer.addEventListener('transitionend', function(e) { + if (e.target === mainContainer) { + var event = document.createEvent('UIEvents'); + event.initUIEvent('resize', false, false, window, 0); + window.dispatchEvent(event); + outerContainer.classList.remove('sidebarMoving'); + } + }, true); + + document.getElementById('sidebarToggle').addEventListener('click', + function() { + this.classList.toggle('toggled'); + outerContainer.classList.add('sidebarMoving'); + outerContainer.classList.toggle('sidebarOpen'); + PDFViewerApplication.sidebarOpen = + outerContainer.classList.contains('sidebarOpen'); + if (PDFViewerApplication.sidebarOpen) { + PDFViewerApplication.refreshThumbnailViewer(); + } + PDFViewerApplication.forceRendering(); + }); + + document.getElementById('viewThumbnail').addEventListener('click', + function() { + PDFViewerApplication.switchSidebarView('thumbs'); + }); + + document.getElementById('viewOutline').addEventListener('click', + function() { + PDFViewerApplication.switchSidebarView('outline'); + }); + + document.getElementById('viewAttachments').addEventListener('click', + function() { + PDFViewerApplication.switchSidebarView('attachments'); + }); + + document.getElementById('previous').addEventListener('click', + function() { + PDFViewerApplication.page--; + }); + + document.getElementById('next').addEventListener('click', + function() { + PDFViewerApplication.page++; + }); + + document.getElementById('zoomIn').addEventListener('click', + function() { + PDFViewerApplication.zoomIn(); + }); + + document.getElementById('zoomOut').addEventListener('click', + function() { + PDFViewerApplication.zoomOut(); + }); + + document.getElementById('pageNumber').addEventListener('click', function() { + this.select(); + }); + + document.getElementById('pageNumber').addEventListener('change', function() { + // Handle the user inputting a floating point number. + PDFViewerApplication.page = (this.value | 0); + + if (this.value !== (this.value | 0).toString()) { + this.value = PDFViewerApplication.page; + } + }); + + document.getElementById('scaleSelect').addEventListener('change', + function() { + PDFViewerApplication.setScale(this.value, false); + }); + + document.getElementById('presentationMode').addEventListener('click', + SecondaryToolbar.presentationModeClick.bind(SecondaryToolbar)); + + document.getElementById('openFile').addEventListener('click', + SecondaryToolbar.openFileClick.bind(SecondaryToolbar)); + + document.getElementById('print').addEventListener('click', + SecondaryToolbar.printClick.bind(SecondaryToolbar)); + + document.getElementById('download').addEventListener('click', + SecondaryToolbar.downloadClick.bind(SecondaryToolbar)); + + + if (file && file.lastIndexOf('file:', 0) === 0) { + // file:-scheme. Load the contents in the main thread because QtWebKit + // cannot load file:-URLs in a Web Worker. file:-URLs are usually loaded + // very quickly, so there is no need to set up progress event listeners. + PDFViewerApplication.setTitleUsingUrl(file); + var xhr = new XMLHttpRequest(); + xhr.onload = function() { + PDFViewerApplication.open(new Uint8Array(xhr.response), 0); + }; + try { + xhr.open('GET', file); + xhr.responseType = 'arraybuffer'; + xhr.send(); + } catch (e) { + PDFViewerApplication.error(mozL10n.get('loading_error', null, + 'An error occurred while loading the PDF.'), e); + } + return; + } + + if (file) { + PDFViewerApplication.open(file, 0); + } +} + +document.addEventListener('DOMContentLoaded', webViewerLoad, true); + +document.addEventListener('pagerendered', function (e) { + var pageNumber = e.detail.pageNumber; + var pageIndex = pageNumber - 1; + var pageView = PDFViewerApplication.pdfViewer.getPageView(pageIndex); + + if (PDFViewerApplication.sidebarOpen) { + var thumbnailView = PDFViewerApplication.pdfThumbnailViewer. + getThumbnail(pageIndex); + thumbnailView.setImage(pageView); + } + + if (PDFJS.pdfBug && Stats.enabled && pageView.stats) { + Stats.add(pageNumber, pageView.stats); + } + + if (pageView.error) { + PDFViewerApplication.error(mozL10n.get('rendering_error', null, + 'An error occurred while rendering the page.'), pageView.error); + } + + // If the page is still visible when it has finished rendering, + // ensure that the page number input loading indicator is hidden. + if (pageNumber === PDFViewerApplication.page) { + var pageNumberInput = document.getElementById('pageNumber'); + pageNumberInput.classList.remove(PAGE_NUMBER_LOADING_INDICATOR); + } + +}, true); + +document.addEventListener('textlayerrendered', function (e) { + var pageIndex = e.detail.pageNumber - 1; + var pageView = PDFViewerApplication.pdfViewer.getPageView(pageIndex); + +}, true); + +window.addEventListener('presentationmodechanged', function (e) { + var active = e.detail.active; + var switchInProgress = e.detail.switchInProgress; + PDFViewerApplication.pdfViewer.presentationModeState = + switchInProgress ? PresentationModeState.CHANGING : + active ? PresentationModeState.FULLSCREEN : PresentationModeState.NORMAL; +}); + +function updateViewarea() { + if (!PDFViewerApplication.initialized) { + return; + } + PDFViewerApplication.pdfViewer.update(); +} + +window.addEventListener('updateviewarea', function (evt) { + if (!PDFViewerApplication.initialized) { + return; + } + var location = evt.location; + + PDFViewerApplication.store.initializedPromise.then(function() { + PDFViewerApplication.store.setMultiple({ + 'exists': true, + 'page': location.pageNumber, + 'zoom': location.scale, + 'scrollLeft': location.left, + 'scrollTop': location.top + }).catch(function() { + // unable to write to storage + }); + }); + var href = PDFViewerApplication.getAnchorUrl(location.pdfOpenParams); + document.getElementById('viewBookmark').href = href; + document.getElementById('secondaryViewBookmark').href = href; + + // Update the current bookmark in the browsing history. + PDFHistory.updateCurrentBookmark(location.pdfOpenParams, location.pageNumber); + + // Show/hide the loading indicator in the page number input element. + var pageNumberInput = document.getElementById('pageNumber'); + var currentPage = + PDFViewerApplication.pdfViewer.getPageView(PDFViewerApplication.page - 1); + + if (currentPage.renderingState === RenderingStates.FINISHED) { + pageNumberInput.classList.remove(PAGE_NUMBER_LOADING_INDICATOR); + } else { + pageNumberInput.classList.add(PAGE_NUMBER_LOADING_INDICATOR); + } +}, true); + +window.addEventListener('resize', function webViewerResize(evt) { + if (PDFViewerApplication.initialized && + (document.getElementById('pageAutoOption').selected || + /* Note: the scale is constant for |pageActualOption|. */ + document.getElementById('pageFitOption').selected || + document.getElementById('pageWidthOption').selected)) { + var selectedScale = document.getElementById('scaleSelect').value; + PDFViewerApplication.setScale(selectedScale, false); + } + updateViewarea(); + + // Set the 'max-height' CSS property of the secondary toolbar. + SecondaryToolbar.setMaxHeight(document.getElementById('viewerContainer')); +}); + +window.addEventListener('hashchange', function webViewerHashchange(evt) { + if (PDFHistory.isHashChangeUnlocked) { + PDFViewerApplication.setHash(document.location.hash.substring(1)); + } +}); + +window.addEventListener('change', function webViewerChange(evt) { + var files = evt.target.files; + if (!files || files.length === 0) { + return; + } + var file = files[0]; + + if (!PDFJS.disableCreateObjectURL && + typeof URL !== 'undefined' && URL.createObjectURL) { + PDFViewerApplication.open(URL.createObjectURL(file), 0); + } else { + // Read the local file into a Uint8Array. + var fileReader = new FileReader(); + fileReader.onload = function webViewerChangeFileReaderOnload(evt) { + var buffer = evt.target.result; + var uint8Array = new Uint8Array(buffer); + PDFViewerApplication.open(uint8Array, 0); + }; + fileReader.readAsArrayBuffer(file); + } + + PDFViewerApplication.setTitleUsingUrl(file.name); + + // URL does not reflect proper document location - hiding some icons. + document.getElementById('viewBookmark').setAttribute('hidden', 'true'); + document.getElementById('secondaryViewBookmark'). + setAttribute('hidden', 'true'); + document.getElementById('download').setAttribute('hidden', 'true'); + document.getElementById('secondaryDownload').setAttribute('hidden', 'true'); +}, true); + +function selectScaleOption(value) { + var options = document.getElementById('scaleSelect').options; + var predefinedValueFound = false; + for (var i = 0; i < options.length; i++) { + var option = options[i]; + if (option.value !== value) { + option.selected = false; + continue; + } + option.selected = true; + predefinedValueFound = true; + } + return predefinedValueFound; +} + +window.addEventListener('localized', function localized(evt) { + document.getElementsByTagName('html')[0].dir = mozL10n.getDirection(); + + PDFViewerApplication.animationStartedPromise.then(function() { + // Adjust the width of the zoom box to fit the content. + // Note: If the window is narrow enough that the zoom box is not visible, + // we temporarily show it to be able to adjust its width. + var container = document.getElementById('scaleSelectContainer'); + if (container.clientWidth === 0) { + container.setAttribute('style', 'display: inherit;'); + } + if (container.clientWidth > 0) { + var select = document.getElementById('scaleSelect'); + select.setAttribute('style', 'min-width: inherit;'); + var width = select.clientWidth + SCALE_SELECT_CONTAINER_PADDING; + select.setAttribute('style', 'min-width: ' + + (width + SCALE_SELECT_PADDING) + 'px;'); + container.setAttribute('style', 'min-width: ' + width + 'px; ' + + 'max-width: ' + width + 'px;'); + } + + // Set the 'max-height' CSS property of the secondary toolbar. + SecondaryToolbar.setMaxHeight(document.getElementById('viewerContainer')); + }); +}, true); + +window.addEventListener('scalechange', function scalechange(evt) { + document.getElementById('zoomOut').disabled = (evt.scale === MIN_SCALE); + document.getElementById('zoomIn').disabled = (evt.scale === MAX_SCALE); + + var customScaleOption = document.getElementById('customScaleOption'); + customScaleOption.selected = false; + + if (!PDFViewerApplication.updateScaleControls && + (document.getElementById('pageAutoOption').selected || + document.getElementById('pageActualOption').selected || + document.getElementById('pageFitOption').selected || + document.getElementById('pageWidthOption').selected)) { + updateViewarea(); + return; + } + + if (evt.presetValue) { + selectScaleOption(evt.presetValue); + updateViewarea(); + return; + } + + var predefinedValueFound = selectScaleOption('' + evt.scale); + if (!predefinedValueFound) { + var customScale = Math.round(evt.scale * 10000) / 100; + customScaleOption.textContent = + mozL10n.get('page_scale_percent', { scale: customScale }, '{{scale}}%'); + customScaleOption.selected = true; + } + updateViewarea(); +}, true); + +window.addEventListener('pagechange', function pagechange(evt) { + var page = evt.pageNumber; + if (evt.previousPageNumber !== page) { + document.getElementById('pageNumber').value = page; + if (PDFViewerApplication.sidebarOpen) { + PDFViewerApplication.pdfThumbnailViewer.scrollThumbnailIntoView(page); + } + } + var numPages = PDFViewerApplication.pagesCount; + + document.getElementById('previous').disabled = (page <= 1); + document.getElementById('next').disabled = (page >= numPages); + + document.getElementById('firstPage').disabled = (page <= 1); + document.getElementById('lastPage').disabled = (page >= numPages); + + // we need to update stats + if (PDFJS.pdfBug && Stats.enabled) { + var pageView = PDFViewerApplication.pdfViewer.getPageView(page - 1); + if (pageView.stats) { + Stats.add(page, pageView.stats); + } + } + + // checking if the this.page was called from the updateViewarea function + if (evt.updateInProgress) { + return; + } + // Avoid scrolling the first page during loading + if (this.loading && page === 1) { + return; + } + PDFViewerApplication.pdfViewer.scrollPageIntoView(page); +}, true); + +function handleMouseWheel(evt) { + var MOUSE_WHEEL_DELTA_FACTOR = 40; + var ticks = (evt.type === 'DOMMouseScroll') ? -evt.detail : + evt.wheelDelta / MOUSE_WHEEL_DELTA_FACTOR; + var direction = (ticks < 0) ? 'zoomOut' : 'zoomIn'; + + if (PDFViewerApplication.pdfViewer.isInPresentationMode) { + evt.preventDefault(); + PDFViewerApplication.scrollPresentationMode(ticks * + MOUSE_WHEEL_DELTA_FACTOR); + } else if (evt.ctrlKey || evt.metaKey) { + // Only zoom the pages, not the entire viewer. + evt.preventDefault(); + PDFViewerApplication[direction](Math.abs(ticks)); + } +} + +window.addEventListener('DOMMouseScroll', handleMouseWheel); +window.addEventListener('mousewheel', handleMouseWheel); + +window.addEventListener('click', function click(evt) { + if (SecondaryToolbar.opened && + PDFViewerApplication.pdfViewer.containsElement(evt.target)) { + SecondaryToolbar.close(); + } +}, false); + +window.addEventListener('keydown', function keydown(evt) { + if (OverlayManager.active) { + return; + } + + var handled = false; + var cmd = (evt.ctrlKey ? 1 : 0) | + (evt.altKey ? 2 : 0) | + (evt.shiftKey ? 4 : 0) | + (evt.metaKey ? 8 : 0); + + var pdfViewer = PDFViewerApplication.pdfViewer; + var isViewerInPresentationMode = pdfViewer && pdfViewer.isInPresentationMode; + + // First, handle the key bindings that are independent whether an input + // control is selected or not. + if (cmd === 1 || cmd === 8 || cmd === 5 || cmd === 12) { + // either CTRL or META key with optional SHIFT. + switch (evt.keyCode) { + case 70: // f + if (!PDFViewerApplication.supportsIntegratedFind) { + PDFViewerApplication.findBar.open(); + handled = true; + } + break; + case 71: // g + if (!PDFViewerApplication.supportsIntegratedFind) { + PDFViewerApplication.findBar.dispatchEvent('again', + cmd === 5 || cmd === 12); + handled = true; + } + break; + case 61: // FF/Mac '=' + case 107: // FF '+' and '=' + case 187: // Chrome '+' + case 171: // FF with German keyboard + if (!isViewerInPresentationMode) { + PDFViewerApplication.zoomIn(); + } + handled = true; + break; + case 173: // FF/Mac '-' + case 109: // FF '-' + case 189: // Chrome '-' + if (!isViewerInPresentationMode) { + PDFViewerApplication.zoomOut(); + } + handled = true; + break; + case 48: // '0' + case 96: // '0' on Numpad of Swedish keyboard + if (!isViewerInPresentationMode) { + // keeping it unhandled (to restore page zoom to 100%) + setTimeout(function () { + // ... and resetting the scale after browser adjusts its scale + PDFViewerApplication.setScale(DEFAULT_SCALE, true); + }); + handled = false; + } + break; + } + } + + // CTRL or META without shift + if (cmd === 1 || cmd === 8) { + switch (evt.keyCode) { + case 83: // s + PDFViewerApplication.download(); + handled = true; + break; + } + } + + // CTRL+ALT or Option+Command + if (cmd === 3 || cmd === 10) { + switch (evt.keyCode) { + case 80: // p + PDFViewerApplication.requestPresentationMode(); + handled = true; + break; + case 71: // g + // focuses input#pageNumber field + document.getElementById('pageNumber').select(); + handled = true; + break; + } + } + + if (handled) { + evt.preventDefault(); + return; + } + + // Some shortcuts should not get handled if a control/input element + // is selected. + var curElement = document.activeElement || document.querySelector(':focus'); + var curElementTagName = curElement && curElement.tagName.toUpperCase(); + if (curElementTagName === 'INPUT' || + curElementTagName === 'TEXTAREA' || + curElementTagName === 'SELECT') { + // Make sure that the secondary toolbar is closed when Escape is pressed. + if (evt.keyCode !== 27) { // 'Esc' + return; + } + } + + if (cmd === 0) { // no control key pressed at all. + switch (evt.keyCode) { + case 38: // up arrow + case 33: // pg up + case 8: // backspace + if (!isViewerInPresentationMode && + PDFViewerApplication.currentScaleValue !== 'page-fit') { + break; + } + /* in presentation mode */ + /* falls through */ + case 37: // left arrow + // horizontal scrolling using arrow keys + if (pdfViewer.isHorizontalScrollbarEnabled) { + break; + } + /* falls through */ + case 75: // 'k' + case 80: // 'p' + PDFViewerApplication.page--; + handled = true; + break; + case 27: // esc key + if (SecondaryToolbar.opened) { + SecondaryToolbar.close(); + handled = true; + } + if (!PDFViewerApplication.supportsIntegratedFind && + PDFViewerApplication.findBar.opened) { + PDFViewerApplication.findBar.close(); + handled = true; + } + break; + case 40: // down arrow + case 34: // pg down + case 32: // spacebar + if (!isViewerInPresentationMode && + PDFViewerApplication.currentScaleValue !== 'page-fit') { + break; + } + /* falls through */ + case 39: // right arrow + // horizontal scrolling using arrow keys + if (pdfViewer.isHorizontalScrollbarEnabled) { + break; + } + /* falls through */ + case 74: // 'j' + case 78: // 'n' + PDFViewerApplication.page++; + handled = true; + break; + + case 36: // home + if (isViewerInPresentationMode || PDFViewerApplication.page > 1) { + PDFViewerApplication.page = 1; + handled = true; + } + break; + case 35: // end + if (isViewerInPresentationMode || (PDFViewerApplication.pdfDocument && + PDFViewerApplication.page < PDFViewerApplication.pagesCount)) { + PDFViewerApplication.page = PDFViewerApplication.pagesCount; + handled = true; + } + break; + + case 72: // 'h' + if (!isViewerInPresentationMode) { + HandTool.toggle(); + } + break; + case 82: // 'r' + PDFViewerApplication.rotatePages(90); + break; + } + } + + if (cmd === 4) { // shift-key + switch (evt.keyCode) { + case 32: // spacebar + if (!isViewerInPresentationMode && + PDFViewerApplication.currentScaleValue !== 'page-fit') { + break; + } + PDFViewerApplication.page--; + handled = true; + break; + + case 82: // 'r' + PDFViewerApplication.rotatePages(-90); + break; + } + } + + if (!handled && !isViewerInPresentationMode) { + // 33=Page Up 34=Page Down 35=End 36=Home + // 37=Left 38=Up 39=Right 40=Down + if (evt.keyCode >= 33 && evt.keyCode <= 40 && + !pdfViewer.containsElement(curElement)) { + // The page container is not focused, but a page navigation key has been + // pressed. Change the focus to the viewer container to make sure that + // navigation by keyboard works as expected. + pdfViewer.focus(); + } + // 32=Spacebar + if (evt.keyCode === 32 && curElementTagName !== 'BUTTON' && + !pdfViewer.containsElement(curElement)) { + pdfViewer.focus(); + } + } + + if (cmd === 2) { // alt-key + switch (evt.keyCode) { + case 37: // left arrow + if (isViewerInPresentationMode) { + PDFHistory.back(); + handled = true; + } + break; + case 39: // right arrow + if (isViewerInPresentationMode) { + PDFHistory.forward(); + handled = true; + } + break; + } + } + + if (handled) { + evt.preventDefault(); + } +}); + +window.addEventListener('beforeprint', function beforePrint(evt) { + PDFViewerApplication.beforePrint(); +}); + +window.addEventListener('afterprint', function afterPrint(evt) { + PDFViewerApplication.afterPrint(); +}); + +(function animationStartedClosure() { + // The offsetParent is not set until the pdf.js iframe or object is visible. + // Waiting for first animation. + PDFViewerApplication.animationStartedPromise = new Promise( + function (resolve) { + window.requestAnimationFrame(resolve); + }); +})(); + + diff --git a/src/main/resources/static/view/userlist.html b/src/main/resources/static/view/userlist.html new file mode 100644 index 0000000..14fb4f6 --- /dev/null +++ b/src/main/resources/static/view/userlist.html @@ -0,0 +1,122 @@ + + + + + iview example + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/demo3.ftl b/src/main/resources/templates/demo3.ftl new file mode 100644 index 0000000..d75badc --- /dev/null +++ b/src/main/resources/templates/demo3.ftl @@ -0,0 +1,17 @@ + + + +Spring Boot FreeMarker + + + Freemarker HTML

+ + Sessionid: ${sessionid!}

+ + + <#list userList as item> + ${item!}
+ +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/pdfPreviewIframe.ftl b/src/main/resources/templates/pdfPreviewIframe.ftl new file mode 100644 index 0000000..e92d4a9 --- /dev/null +++ b/src/main/resources/templates/pdfPreviewIframe.ftl @@ -0,0 +1,30 @@ +<#assign base=springMacroRequestContext.getContextUrl("")> + + + + + + + +PDF预览 + + + + + diff --git a/src/main/resources/templates/thirdLogin.ftl b/src/main/resources/templates/thirdLogin.ftl new file mode 100644 index 0000000..dd3ab8a --- /dev/null +++ b/src/main/resources/templates/thirdLogin.ftl @@ -0,0 +1,28 @@ + + + + + + + 第三方登录 + + +登陆中... + + + \ No newline at end of file diff --git a/src/test/java/com/nd/NursingModuleApplicationTests.java b/src/test/java/com/nd/NursingModuleApplicationTests.java new file mode 100644 index 0000000..74f733a --- /dev/null +++ b/src/test/java/com/nd/NursingModuleApplicationTests.java @@ -0,0 +1,13 @@ +package com.nd; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class NursingModuleApplicationTests { + + @Test + void contextLoads() { + } + +}