xiongzhu пре 4 година
родитељ
комит
9b9ea781db

+ 11 - 0
config/collect.json

@@ -0,0 +1,11 @@
+{
+    "enable": false,
+    "name": "o2oa.izouma.com",
+    "password": "",
+    "title": "江西军民融合办公平台",
+    "footer": "江西军民融合办公平台",
+    "appUrl": "https://app.o2oa.net/download/download.html",
+    "server": "o2oa.izouma.com",
+    "port": 20080,
+    "sslEnable": false
+}

+ 10 - 0
config/externalDataSources.json

@@ -0,0 +1,10 @@
+[
+    {
+        "url": "jdbc:mysql://192.168.50.10:3306/o2oa?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8",
+        "username": "root",
+        "password": "123456",
+        "includes": [],
+        "excludes": [],
+        "enable": true
+    }
+]

+ 188 - 0
config/node_127.0.0.1.json

@@ -0,0 +1,188 @@
+{
+    "enable": true,
+    "isPrimaryCenter": true,
+    "center": {
+        "enable": true,
+        "order": 0,
+        "sslEnable": false,
+        "redeploy": true,
+        "port": 20030,
+        "httpProtocol": "",
+        "proxyHost": "",
+        "proxyPort": 20030,
+        "scanInterval": 0,
+        "configApiEnable": true,
+        "statEnable": true,
+        "statExclusions": "*.js,*.gif,*.jpg,*.png,*.css,*.ico",
+        "maxFormContent": 20,
+        "exposeJest": true,
+        "persistentConnectionsEnable": true,
+        "###enable": "是否启用###",
+        "###order": "center节点顺序,顺序排列0,1,2...###",
+        "###sslEnable": "是否启用ssl传输加密,如果启用将使用config/keystore文件作为密钥文件.使用config/token.json文件中的sslKeyStorePassword字段为密钥密码,sslKeyManagerPassword为管理密码.###",
+        "###redeploy": "每次启动是否重新部署所有应用.###",
+        "###port": "端口,center服务器端口,默认20030###",
+        "###httpProtocol": "对外http访问协议,http/https###",
+        "###proxyHost": "代理主机,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.###",
+        "###proxyPort": "代理端口,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.###",
+        "###scanInterval": "重新扫描war包时间间隔(秒)###",
+        "###config": "其他参数###",
+        "###configApiEnable": "允许通过Api修改config###",
+        "###statEnable": "启用统计,默认启用统计.###",
+        "###statExclusions": "统计忽略路径,默认忽略*.js,*.gif,*.jpg,*.png,*.css,*.ico###",
+        "###maxFormContent": "最大提交数据限制(M),限制有所上传的内容大小,包括附件.###",
+        "###exposeJest": "暴露jest接口.###",
+        "###persistentConnectionsEnable": "是否启用长连接,默认false.###"
+    },
+    "application": {
+        "enable": true,
+        "port": 20020,
+        "sslEnable": false,
+        "proxyHost": "",
+        "proxyPort": 20020,
+        "redeploy": true,
+        "scanInterval": 0,
+        "includes": [],
+        "excludes": [],
+        "weights": [],
+        "scheduleWeights": [],
+        "statEnable": true,
+        "statExclusions": "*.js,*.gif,*.jpg,*.png,*.css,*.ico",
+        "maxFormContent": 20,
+        "exposeJest": true,
+        "maxThread": 500,
+        "persistentConnectionsEnable": true,
+        "###enable": "是否启用###",
+        "###port": "http/https端口,负责向前端提供数据访问接口.默认为20020端口.###",
+        "###sslEnable": "是否启用ssl传输加密,如果启用将使用config/keystore文件作为密钥文件.使用config/token.json文件中的sslKeyStorePassword字段为密钥密码,sslKeyManagerPassword为管理密码.###",
+        "###proxyHost": "代理主机,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.###",
+        "###proxyPort": "代理端口,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.###",
+        "###redeploy": "每次启动是否重载全部应用.###",
+        "###scanInterval": "应用reload扫描间隔,<0 表示不会reload应用,扫描到应用文件发生了变化.###",
+        "###includes": "承载的应用,在集群环境下可以选择仅承载部分应用以降低服务器负载,可以使用*作为通配符.###",
+        "###excludes": "选择不承载的应用,和includes的值配合使用可以选择或者排除承载的应用,可以使用*作为通配符.###",
+        "###weights": "设置应用的Web访问权重,在集群环境中,一个应用可以部署多个实例提供负载均衡.通过合计占比来分配应用占比.###",
+        "###scheduleWeights": "设置应用的定时任务权重,在集群环境中,一个应用可以部署多个实例提供负载均衡.通过合计占比来分配应用占比.###",
+        "###statEnable": "启用统计,默认启用统计.###",
+        "###statExclusions": "统计忽略路径,默认忽略*.js,*.gif,*.jpg,*.png,*.css,*.ico###",
+        "###maxFormContent": "最大提交数据限制(M),限制有所上传的内容大小,包括附件.###",
+        "###exposeJest": "暴露jest接口.###",
+        "###maxThread": "最大http线程数.###",
+        "###persistentConnectionsEnable": "是否启用长连接,默认true.###"
+    },
+    "web": {
+        "enable": true,
+        "sslEnable": false,
+        "proxyHost": "",
+        "weight": 100,
+        "dirAllowed": false,
+        "statEnable": false,
+        "statExclusions": "*.gif,*.jpg,*.png,*.ico",
+        "cacheControlMaxAge": 0,
+        "persistentConnectionsEnable": true,
+        "###enable": "是否启用###",
+        "###port": "http/https端口,用户输入网址后实际访问的第一个端口.http协议默认为80端口,https默认为443端口.###",
+        "###sslEnable": "是否启用ssl传输加密,如果启用将使用config/keystore文件作为密钥文件.使用config/token.json文件中的sslKeyStorePassword字段为密钥密码,sslKeyManagerPassword为管理密码.###",
+        "###proxyHost": "代理主机,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问地址.###",
+        "###proxyPort": "代理端口,当服务器是通过apache/nginx等代理服务器映射到公网或者通过路由器做端口映射,在这样的情况下需要设置此地址以标明公网访问端口.###",
+        "###weight": "设置权重.当前没有作用,###",
+        "###dirAllowed": "允许浏览目录,###",
+        "###statEnable": "启用统计,默认启用统计.###",
+        "###statExclusions": "统计忽略路径,默认忽略*.gif,*.jpg,*.png,*.ico###",
+        "###cacheControlMaxAge": "服务器max-age缓存时间(秒)###",
+        "###proxyCenterEnable": "是否启用center服务器代理.###",
+        "###proxyApplicationEnable": "是否启用application服务器代理###",
+        "###persistentConnectionsEnable": "是否启用长连接,默认true.###",
+        "port": 8080
+    },
+    "data": {
+        "enable": false,
+        "tcpPort": 20050,
+        "webPort": 20051,
+        "includes": [],
+        "excludes": [],
+        "jmxEnable": false,
+        "cacheSize": 512,
+        "logLevel": "WARN",
+        "maxTotal": 50,
+        "maxIdle": 0,
+        "statEnable": true,
+        "statFilter": "mergeStat",
+        "slowSqlMillis": 2000,
+        "lockTimeout": 120000,
+        "###enable": "是否启用,如果没有可用的externalDataSources.json文件,那么默认会在节点中启用本地的H2数据库作为默认的数据库.###",
+        "###tcpPort": "H2数据库jdbc连接端口,登录的用户名:sa,密码为xadmin的密码.数据库创建在/o2server/local/repository/data/X.mv.db,一旦数据库文件被创建,那么该数据库的密码被创建.###",
+        "###webPort": "H2数据库web端口,H2提供一个web端的client,此端口为web端client的访问端口.用户名sa,密码为xadmin数据库初始创建的密码.###",
+        "###includes": "设置此数据库存储的类,默认情况下存储所有类型,如果需要对每个类进行单独的控制以达到高性能,可以将不同的类存储到不同的节点上提高性能.可以使用通配符*###",
+        "###excludes": "在此节点上不存储的类,和includes一起设置实际存储的类,可以使用通配符*###",
+        "###jmxEnable": "是否启动jmx,如果启用,可以通过本地的jmx客户端进行访问,不支持远程jmx客户端.###",
+        "###cacheSize": "H2数据库缓存大小,设置H2用于作为缓存的内存大小,以M作为单位,这里默认为512M.###",
+        "###logLevel": "默认日志级别,FATAL, ERROR, WARN, INFO, TRACE. 完整的配置为DefaultLevel=WARN, Tool=TRACE, Enhance=TRACE, METADATA=TRACE, Runtime=TRACE, Query=TRACE, DataCache=TRACE, JDBC=TRACE, SQL=TRACE###",
+        "###maxTotal": "最大使用连接数###",
+        "###maxIdle": "最大空闲连接数###",
+        "###statEnable": "启用统计,默认启用###",
+        "###statFilter": "统计方式配置,默认mergeStat###",
+        "###slowSqlMillis": "执行缓慢sql毫秒数,默认2000毫秒,执行缓慢的sql将被单独记录.###",
+        "###lockTimeout": "默认锁超时时间()毫秒).###"
+    },
+    "storage": {
+        "enable": true,
+        "port": 20040,
+        "sslEnable": false,
+        "name": "251",
+        "accounts": [],
+        "prefix": "",
+        "deepPath": false,
+        "###enable": "是否启用,对于二进制流文件,比如附件,图片等存储在单独的文件服务器中,可以支持多种文件服务器,默认情况下使用ftp服务器作为文件服务器,每个节点可以启动一个文件服务器以提供高性能.###",
+        "###port": "ftp服务器端口,此端口可以不对外开放,仅有ApplicationServer进行访问,并不直接对用户提供服务.###",
+        "###sslEnable": "是否启用ssl传输加密,如果启用将使用config/keystore文件作为密钥文件.使用config/token.json文件中的sslKeyStorePassword字段为密钥密码,sslKeyManagerPassword为管理密码.###",
+        "###name": "名称,多个节点中不能重名,默认为251.###",
+        "###accounts": "二进制流文件是分多个账号分段存储的,可以单独设置每个分类的存储配置,一般不需要设置.###",
+        "###passivePorts": "ftp传输有主动和被动之分,如果使用了被动传输,设置被动端口范围,默认为29000-30000.###",
+        "###prefix": "路径前缀.###",
+        "###deepPath": "使用更深的路径###"
+    },
+    "logLevel": "warn",
+    "dumpData": {
+        "enable": false,
+        "cron": "",
+        "size": 7,
+        "path": "",
+        "###enable": "是否启用,默认禁用.###",
+        "###cron": "定时任务cron表达式,默认每天凌晨2点进行备份.###",
+        "###size": "最大保留份数,超过将自动删除最久的数据.###",
+        "###path": "备份路径###"
+    },
+    "restoreData": {
+        "enable": false,
+        "cron": "",
+        "path": "",
+        "###enable": "是否启用.###",
+        "###cron": "定时任务cron表达式###",
+        "###path": "恢复路径###"
+    },
+    "nodeAgentEnable": true,
+    "nodeAgentPort": 20010,
+    "nodeAgentEncrypt": true,
+    "quickStartWebApp": false,
+    "autoStart": true,
+    "###enable": "是否启用###",
+    "###isPrimaryCenter": "是否是center节点,仅允许存在一个center节点###",
+    "###center": "Center服务器配置###",
+    "###application": "Application服务器配置###",
+    "###web": "Web服务器配置###",
+    "###data": "Data服务器配置###",
+    "###storage": "Storage服务器配置###",
+    "###logLevel": "日志级别,默认当前节点的slf4j日志级别,通过系统变量\"org.slf4j.simpleLogger.defaultLogLevel\"设置到当前jvm中.###",
+    "###dumpData": "定时数据导出配置###",
+    "###restoreData": "定时数据导入配置###",
+    "###logSize": "日志文件保留天数.###",
+    "###auditLogSize": "审计日志文件保留天数.###",
+    "###nodeAgentEnable": "是否启用节点代理###",
+    "###nodeAgentPort": "是否启用节点端口###",
+    "###nodeAgentEncrypt": "是否启用节点代理加密###",
+    "###quickStartWebApp": "是否使用快速应用部署###",
+    "###banner": "服务器控制台启动标识###",
+    "###autoStart": "是否自动启动###",
+    "###eraseContentEnable": "是否允许使用擦除数据功能###"
+}

+ 24 - 0
config/person.json

@@ -0,0 +1,24 @@
+{
+    "MAX_PASSWORDPERIOD": 3650,
+    "captchaLogin": false,
+    "codeLogin": false,
+    "bindLogin": false,
+    "faceLogin": false,
+    "password": "123456",
+    "passwordPeriod": 0,
+    "passwordRegex": "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$",
+    "passwordRegexHint": "6位以上,包含数字和字母.",
+    "register": "disable",
+    "superPermission": true,
+    "mobileRegex": "(^(\\+)?0{0,2}852\\d{8}$)|(^(\\+)?0{0,2}853\\d{8}$)|(^(\\+)?0{0,2}886\\d{9}$)|(^1(3|4|5|6|7|8|9)\\d{9}$)",
+    "loginPage": {
+        "enable": false,
+        "portal": "",
+        "page": ""
+    },
+    "failureInterval": 10,
+    "failureCount": 5,
+    "tokenExpiredMinutes": 21600,
+    "tokenCookieHttpOnly": false,
+    "personUnitOrderByAsc": true
+}

+ 14 - 54
gulpfile.js

@@ -1505,60 +1505,20 @@ if (os.platform().indexOf("win") == -1) {
 }
 
 function make_def_config(cb) {
-    let configDir = path.resolve(__dirname, "target", "o2server", "config");
-    if (!fs.existsSync(configDir)) {
-        fs.mkdirSync(configDir);
-    }
-    let serverConfig = require("./serverConfig.json");
-    let nodeConfig = JSON.parse(
-        fs.readFileSync(
-            path.resolve(
-                __dirname,
-                "target",
-                "o2server",
-                "configSample",
-                "node_127.0.0.1.json"
-            )
-        )
-    );
-    nodeConfig.data.enable = false;
-    nodeConfig.web.port = serverConfig.port;
-    fs.writeFileSync(
-        path.resolve(
-            __dirname,
-            "target",
-            "o2server",
-            "config",
-            "node_127.0.0.1.json"
-        ),
-        JSON.stringify(nodeConfig, null, 4)
-    );
-
-    let externalDataSources = JSON.parse(
-        fs.readFileSync(
-            path.resolve(
-                __dirname,
-                "target",
-                "o2server",
-                "configSample",
-                "externalDataSources.json"
-            )
-        )
-    );
-    externalDataSources[0].url = serverConfig.dataSource.url;
-    externalDataSources[0].username = serverConfig.dataSource.username;
-    externalDataSources[0].password = serverConfig.dataSource.password;
-    fs.writeFileSync(
-        path.resolve(
-            __dirname,
-            "target",
-            "o2server",
-            "config",
-            "externalDataSources.json"
-        ),
-        JSON.stringify(externalDataSources, null, 4)
-    );
-
+    fs.readdirSync(path.resolve(__dirname, "config")).forEach((child) => {
+        if (/.+\.json/.test(child)) {
+            fs.copyFileSync(
+                path.resolve(__dirname, "config", child),
+                path.resolve(
+                    __dirname,
+                    "target",
+                    "o2server",
+                    "config",
+                    child
+                )
+            );
+        }
+    });
     let manifest = fs
         .readFileSync(
             path.resolve(

+ 1 - 1
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/attachment/ActionDocToPDFWorkOrWorkCompleted.java

@@ -288,7 +288,7 @@ class ActionDocToPDFWorkOrWorkCompleted extends BaseAction {
             // So a human would want to position a signature (x,y) units from the
             // top left of the displayed page, and the field has a horizontal width and a vertical height
             // regardless of page rotation.
-            Rectangle2D humanRect = new Rectangle2D.Float(340, 500, 150, 150);
+            Rectangle2D humanRect = new Rectangle2D.Float(360, 370, 150, 150);
 
             signing.signPDF(pdfFile, signedPdfFile, humanRect, null, "Signature1");
 

+ 92 - 132
o2server/x_processplatform_assemble_surface/src/main/java/com/x/processplatform/assemble/surface/jaxrs/attachment/signature/CreateVisibleSignature2.java

@@ -19,6 +19,7 @@ package com.x.processplatform.assemble.surface.jaxrs.attachment.signature;
 import java.awt.Color;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -65,6 +66,8 @@ import org.bouncycastle.asn1.x500.X500Name;
 import org.bouncycastle.asn1.x500.style.BCStyle;
 import org.bouncycastle.asn1.x500.style.IETFUtils;
 
+import javax.imageio.ImageIO;
+
 /**
  * This is a second example for visual signing a pdf. It doesn't use the "design pattern" influenced
  * PDVisibleSignDesigner, and doesn't create its complex multilevel forms described in the Adobe
@@ -76,42 +79,37 @@ import org.bouncycastle.asn1.x500.style.IETFUtils;
  * @author Vakhtang Koroghlishvili
  * @author Tilman Hausherr
  */
-public class CreateVisibleSignature2 extends CreateSignatureBase
-{
+public class CreateVisibleSignature2 extends CreateSignatureBase {
     private SignatureOptions signatureOptions;
-    private boolean lateExternalSigning = false;
-    private File imageFile = null;
+    private boolean          lateExternalSigning = false;
+    private File             imageFile           = null;
 
     /**
      * Initialize the signature creator with a keystore (pkcs12) and pin that
      * should be used for the signature.
      *
      * @param keystore is a pkcs12 keystore.
-     * @param pin is the pin for the keystore / private key
-     * @throws KeyStoreException if the keystore has not been initialized (loaded)
-     * @throws NoSuchAlgorithmException if the algorithm for recovering the key cannot be found
+     * @param pin      is the pin for the keystore / private key
+     * @throws KeyStoreException         if the keystore has not been initialized (loaded)
+     * @throws NoSuchAlgorithmException  if the algorithm for recovering the key cannot be found
      * @throws UnrecoverableKeyException if the given password is wrong
-     * @throws CertificateException if the certificate is not valid as signing time
-     * @throws IOException if no certificate could be found
+     * @throws CertificateException      if the certificate is not valid as signing time
+     * @throws IOException               if no certificate could be found
      */
     public CreateVisibleSignature2(KeyStore keystore, char[] pin)
-            throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, IOException, CertificateException
-    {
+            throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, IOException, CertificateException {
         super(keystore, pin);
     }
 
-    public File getImageFile()
-    {
+    public File getImageFile() {
         return imageFile;
     }
 
-    public void setImageFile(File imageFile)
-    {
+    public void setImageFile(File imageFile) {
         this.imageFile = imageFile;
     }
 
-    public boolean isLateExternalSigning()
-    {
+    public boolean isLateExternalSigning() {
         return lateExternalSigning;
     }
 
@@ -122,39 +120,35 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
      *
      * @param lateExternalSigning
      */
-    public void setLateExternalSigning(boolean lateExternalSigning)
-    {
+    public void setLateExternalSigning(boolean lateExternalSigning) {
         this.lateExternalSigning = lateExternalSigning;
     }
 
     /**
      * Sign pdf file and create new file that ends with "_signed.pdf".
      *
-     * @param inputFile The source pdf document file.
+     * @param inputFile  The source pdf document file.
      * @param signedFile The file to be signed.
-     * @param humanRect rectangle from a human viewpoint (coordinates start at top left)
-     * @param tsaUrl optional TSA url
+     * @param humanRect  rectangle from a human viewpoint (coordinates start at top left)
+     * @param tsaUrl     optional TSA url
      * @throws IOException
      */
-    public void signPDF(File inputFile, File signedFile, Rectangle2D humanRect, String tsaUrl) throws IOException
-    {
+    public void signPDF(File inputFile, File signedFile, Rectangle2D humanRect, String tsaUrl) throws IOException {
         this.signPDF(inputFile, signedFile, humanRect, tsaUrl, null);
     }
 
     /**
      * Sign pdf file and create new file that ends with "_signed.pdf".
      *
-     * @param inputFile The source pdf document file.
-     * @param signedFile The file to be signed.
-     * @param humanRect rectangle from a human viewpoint (coordinates start at top left)
-     * @param tsaUrl optional TSA url
+     * @param inputFile          The source pdf document file.
+     * @param signedFile         The file to be signed.
+     * @param humanRect          rectangle from a human viewpoint (coordinates start at top left)
+     * @param tsaUrl             optional TSA url
      * @param signatureFieldName optional name of an existing (unsigned) signature field
      * @throws IOException
      */
-    public void signPDF(File inputFile, File signedFile, Rectangle2D humanRect, String tsaUrl, String signatureFieldName) throws IOException
-    {
-        if (inputFile == null || !inputFile.exists())
-        {
+    public void signPDF(File inputFile, File signedFile, Rectangle2D humanRect, String tsaUrl, String signatureFieldName) throws IOException {
+        if (inputFile == null || !inputFile.exists()) {
             throw new IOException("Document for signing does not exist");
         }
 
@@ -165,8 +159,7 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
 
         PDDocument doc = PDDocument.load(inputFile);
         int accessPermissions = SigUtils.getMDPPermission(doc);
-        if (accessPermissions == 1)
-        {
+        if (accessPermissions == 1) {
             throw new IllegalStateException("No changes to the document are permitted due to DocMDP transform parameters dictionary");
         }
         // Note that PDFBox has a bug that visual signing on certified files with permission 2
@@ -178,23 +171,19 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
         PDRectangle rect = null;
 
         // sign a PDF with an existing empty signature, as created by the CreateEmptySignatureForm example.
-        if (acroForm != null)
-        {
+        if (acroForm != null) {
             signature = findExistingSignature(acroForm, signatureFieldName);
-            if (signature != null)
-            {
+            if (signature != null) {
                 rect = acroForm.getField(signatureFieldName).getWidgets().get(0).getRectangle();
             }
         }
 
-        if (signature == null)
-        {
+        if (signature == null) {
             // create signature dictionary
             signature = new PDSignature();
         }
 
-        if (rect == null)
-        {
+        if (rect == null) {
             rect = createSignatureRectangle(doc, humanRect);
         }
 
@@ -202,26 +191,21 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
         // can be done only if version is at least 1.5 and if not already set
         // doing this on a PDF/A-1b file fails validation by Adobe preflight (PDFBOX-3821)
         // PDF/A-1b requires PDF version 1.4 max, so don't increase the version on such files.
-        if (doc.getVersion() >= 1.5f && accessPermissions == 0)
-        {
+        if (doc.getVersion() >= 1.5f && accessPermissions == 0) {
             SigUtils.setMDPPermission(doc, signature, 2);
         }
 
-        if (acroForm != null && acroForm.getNeedAppearances())
-        {
+        if (acroForm != null && acroForm.getNeedAppearances()) {
             // PDFBOX-3738 NeedAppearances true results in visible signature becoming invisible 
             // with Adobe Reader
-            if (acroForm.getFields().isEmpty())
-            {
+            if (acroForm.getFields().isEmpty()) {
                 // we can safely delete it if there are no fields
                 acroForm.getCOSObject().removeItem(COSName.NEED_APPEARANCES);
                 // note that if you've set MDP permissions, the removal of this item
                 // may result in Adobe Reader claiming that the document has been changed.
                 // and/or that field content won't be displayed properly.
                 // ==> decide what you prefer and adjust your code accordingly.
-            }
-            else
-            {
+            } else {
                 System.out.println("/NeedAppearances is set, signature may be ignored by Adobe Reader");
             }
         }
@@ -245,11 +229,10 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
         // register signature dictionary and sign interface
         signatureOptions = new SignatureOptions();
         signatureOptions.setVisualSignature(createVisualSignatureTemplate(doc, 0, rect, signature));
-        signatureOptions.setPage(0);
+        signatureOptions.setPage(doc.getNumberOfPages() - 1);
         doc.addSignature(signature, signatureInterface, signatureOptions);
 
-        if (isExternalSigning())
-        {
+        if (isExternalSigning()) {
             ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(fos);
             // invoke external signature service
             byte[] cmsSignature = sign(externalSigning.getContent());
@@ -263,8 +246,7 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
             // then open the file with PDFBox, find the field with findExistingSignature() or
             // PDDocument.getLastSignatureDictionary() and get the ByteRange from there.
             // Close the file and then write the signature as explained earlier in this comment.
-            if (isLateExternalSigning())
-            {
+            if (isLateExternalSigning()) {
                 // this saves the file with a 0 signature
                 externalSigning.setSignature(new byte[0]);
 
@@ -276,20 +258,16 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
                 raf.seek(offset);
                 raf.write(Hex.getBytes(cmsSignature));
                 raf.close();
-            }
-            else
-            {
+            } else {
                 // set signature bytes received from the service and save the file
                 externalSigning.setSignature(cmsSignature);
             }
-        }
-        else
-        {
+        } else {
             // write incremental (only for signing purpose)
             doc.saveIncremental(fos);
         }
         doc.close();
-        
+
         // Do not close signatureOptions before saving, because some COSStream objects within
         // are transferred to the signed document.
         // Do not allow signatureOptions get out of scope before saving, because then the COSDocument
@@ -298,8 +276,7 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
         IOUtils.closeQuietly(signatureOptions);
     }
 
-    private PDRectangle createSignatureRectangle(PDDocument doc, Rectangle2D humanRect)
-    {
+    private PDRectangle createSignatureRectangle(PDDocument doc, Rectangle2D humanRect) {
         float x = (float) humanRect.getX();
         float y = (float) humanRect.getY();
         float width = (float) humanRect.getWidth();
@@ -308,8 +285,7 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
         PDRectangle pageRect = page.getCropBox();
         PDRectangle rect = new PDRectangle();
         // signing should be at the same position regardless of page rotation.
-        switch (page.getRotation())
-        {
+        switch (page.getRotation()) {
             case 90:
                 rect.setLowerLeftY(x);
                 rect.setUpperRightY(x + width);
@@ -341,8 +317,7 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
 
     // create a template PDF document with empty signature and return it as a stream.
     private InputStream createVisualSignatureTemplate(PDDocument srcDoc, int pageNum,
-            PDRectangle rect, PDSignature signature) throws IOException
-    {
+                                                      PDRectangle rect, PDSignature signature) throws IOException {
         PDDocument doc = new PDDocument();
 
         PDPage page = new PDPage(srcDoc.getPage(pageNum).getMediaBox());
@@ -368,11 +343,11 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
         PDRectangle bbox = new PDRectangle(rect.getWidth(), rect.getHeight());
         float height = bbox.getHeight();
         Matrix initialScale = null;
-        switch (srcDoc.getPage(pageNum).getRotation())
-        {
+        switch (srcDoc.getPage(pageNum).getRotation()) {
             case 90:
                 form.setMatrix(AffineTransform.getQuadrantRotateInstance(1));
-                initialScale = Matrix.getScaleInstance(bbox.getWidth() / bbox.getHeight(), bbox.getHeight() / bbox.getWidth());
+                initialScale = Matrix
+                        .getScaleInstance(bbox.getWidth() / bbox.getHeight(), bbox.getHeight() / bbox.getWidth());
                 height = bbox.getWidth();
                 break;
             case 180:
@@ -380,7 +355,8 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
                 break;
             case 270:
                 form.setMatrix(AffineTransform.getQuadrantRotateInstance(3));
-                initialScale = Matrix.getScaleInstance(bbox.getWidth() / bbox.getHeight(), bbox.getHeight() / bbox.getWidth());
+                initialScale = Matrix
+                        .getScaleInstance(bbox.getWidth() / bbox.getHeight(), bbox.getHeight() / bbox.getWidth());
                 height = bbox.getWidth();
                 break;
             case 0:
@@ -402,55 +378,53 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
         // for 90° and 270° scale ratio of width / height
         // not really sure about this
         // why does scale have no effect when done in the form matrix???
-        if (initialScale != null)
-        {
+        if (initialScale != null) {
             cs.transform(initialScale);
         }
 
         // show background (just for debugging, to see the rect size + position)
-        cs.setNonStrokingColor(Color.yellow);
         cs.addRect(-5000, -5000, 10000, 10000);
-        cs.fill();
 
-        if (imageFile != null)
-        {
+        if (imageFile != null) {
             // show background image
             // save and restore graphics if the image is too large and needs to be scaled
             cs.saveGraphicsState();
-            cs.transform(Matrix.getScaleInstance(0.25f, 0.25f));
+            BufferedImage image = ImageIO.read(imageFile);
+            cs.transform(Matrix.getScaleInstance(rect.getWidth() / (float) image.getWidth(),
+                    rect.getHeight() / (float) image.getHeight()));
             PDImageXObject img = PDImageXObject.createFromFileByExtension(imageFile, doc);
             cs.drawImage(img, 0, 0);
             cs.restoreGraphicsState();
         }
 
         // show text
-        float fontSize = 10;
-        float leading = fontSize * 1.5f;
-        cs.beginText();
-        cs.setFont(font, fontSize);
-        cs.setNonStrokingColor(Color.black);
-        cs.newLineAtOffset(fontSize, height - leading);
-        cs.setLeading(leading);
-
-        X509Certificate cert = (X509Certificate) getCertificateChain()[0];
-
-        // https://stackoverflow.com/questions/2914521/
-        X500Name x500Name = new X500Name(cert.getSubjectX500Principal().getName());
-        RDN cn = x500Name.getRDNs(BCStyle.CN)[0];
-        String name = IETFUtils.valueToString(cn.getFirst().getValue());
-
-        // See https://stackoverflow.com/questions/12575990
-        // for better date formatting
-        String date = signature.getSignDate().getTime().toString();
-        String reason = signature.getReason();
-
+//        float fontSize = 10;
+//        float leading = fontSize * 1.5f;
+//        cs.beginText();
+//        cs.setFont(font, fontSize);
+//        cs.setNonStrokingColor(Color.black);
+//        cs.newLineAtOffset(fontSize, height - leading);
+//        cs.setLeading(leading);
+//
+//        X509Certificate cert = (X509Certificate) getCertificateChain()[0];
+//
+//        // https://stackoverflow.com/questions/2914521/
+//        X500Name x500Name = new X500Name(cert.getSubjectX500Principal().getName());
+//        RDN cn = x500Name.getRDNs(BCStyle.CN)[0];
+//        String name = IETFUtils.valueToString(cn.getFirst().getValue());
+//
+//        // See https://stackoverflow.com/questions/12575990
+//        // for better date formatting
+//        String date = signature.getSignDate().getTime().toString();
+//        String reason = signature.getReason();
+//
 //        cs.showText("Signer: " + name);
 //        cs.newLine();
 //        cs.showText(date);
 //        cs.newLine();
 //        cs.showText("Reason: " + reason);
-
-        cs.endText();
+//
+//        cs.endText();
 
         cs.close();
 
@@ -462,27 +436,21 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
     }
 
     // Find an existing signature (assumed to be empty). You will usually not need this.
-    private PDSignature findExistingSignature(PDAcroForm acroForm, String sigFieldName)
-    {
+    private PDSignature findExistingSignature(PDAcroForm acroForm, String sigFieldName) {
         PDSignature signature = null;
         PDSignatureField signatureField;
-        if (acroForm != null)
-        {
+        if (acroForm != null) {
             signatureField = (PDSignatureField) acroForm.getField(sigFieldName);
-            if (signatureField != null)
-            {
+            if (signatureField != null) {
                 // retrieve signature dictionary
                 signature = signatureField.getSignature();
-                if (signature == null)
-                {
+                if (signature == null) {
                     signature = new PDSignature();
                     // after solving PDFBOX-3524
                     // signatureField.setValue(signature)
                     // until then:
                     signatureField.getCOSObject().setItem(COSName.V, signature);
-                }
-                else
-                {
+                } else {
                     throw new IllegalStateException("The signature field " + sigFieldName + " is already signed.");
                 }
             }
@@ -505,10 +473,8 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
      * @throws java.security.UnrecoverableKeyException
      */
     public static void main(String[] args) throws KeyStoreException, CertificateException,
-            IOException, NoSuchAlgorithmException, UnrecoverableKeyException
-    {
-        if (args.length < 3)
-        {
+            IOException, NoSuchAlgorithmException, UnrecoverableKeyException {
+        if (args.length < 3) {
             usage();
             System.exit(1);
         }
@@ -517,20 +483,16 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
         // External signing is needed if you are using an external signing service, e.g. to sign
         // several files at once.
         boolean externalSig = false;
-        for (int i = 0; i < args.length; i++)
-        {
-            if (args[i].equals("-tsa"))
-            {
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("-tsa")) {
                 i++;
-                if (i >= args.length)
-                {
+                if (i >= args.length) {
                     usage();
                     System.exit(1);
                 }
                 tsaUrl = args[i];
             }
-            if (args[i].equals("-e"))
-            {
+            if (args[i].equals("-e")) {
                 externalSig = true;
             }
         }
@@ -544,8 +506,7 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
 
         CreateVisibleSignature2 signing = new CreateVisibleSignature2(keystore, pin.clone());
 
-        if (args.length >= 4 && !"-tsa".equals(args[3]))
-        {
+        if (args.length >= 4 && !"-tsa".equals(args[3])) {
             signing.setImageFile(new File(args[3]));
         }
 
@@ -569,13 +530,12 @@ public class CreateVisibleSignature2 extends CreateSignatureBase
     /**
      * This will print the usage for this program.
      */
-    private static void usage()
-    {
+    private static void usage() {
         System.err.println("Usage: java " + CreateVisibleSignature2.class.getName()
                 + " <pkcs12-keystore-file> <pin> <input-pdf> <sign-image>\n" + "" +
-                           "options:\n" +
-                           "  -tsa <url>    sign timestamp using the given TSA server\n"+
-                           "  -e            sign using external signature creation scenario");
+                "options:\n" +
+                "  -tsa <url>    sign timestamp using the given TSA server\n" +
+                "  -e            sign using external signature creation scenario");
 
         // generate pkcs12-keystore-file with
         // keytool -storepass 123456 -storetype PKCS12 -keystore file.p12 -genkey -alias client -keyalg RSA

BIN
o2server/x_processplatform_assemble_surface/src/main/resources/sig.png


BIN
o2server/x_processplatform_assemble_surface/src/main/resources/sig.tiff


+ 1 - 1
o2web/source/x_component_process_Xform/Documenteditor.js

@@ -3033,7 +3033,7 @@ MWF.xApplication.process.Xform.Documenteditor = MWF.APPDocumenteditor =  new Cla
 
             var fileName = docNmae || this.json.toWordFilename || "$doc";
             var n = fileName.lastIndexOf(".");
-            if (n==-1) fileName = fileName+".doc";
+            if (n==-1) fileName = fileName+".pdf";
 
             var body = {
                 "fileName": fileName,