Aspose.Slides for Java21.10去除水印和数量限制

303 阅读3分钟

源码分析

1. 下载Aspose.Slides for Java21.10官方jar包

2. 开始分析

  1. 调用授权方法
InputStream is = new FileInputStream("..license.xml");
License license = new License();
license.setLicense(is);
复制代码

license.xml文件内容这里是个过期的文件主要是格式

<License>
    <Data>
        <Products>
            <Product>Aspose.Total for Java</Product>
            <Product>Aspose.Words for Java</Product>
        </Products>
        <EditionType>Enterprise</EditionType>
        <SubscriptionExpiry>20991231</SubscriptionExpiry>
        <LicenseExpiry>20991231</LicenseExpiry>
        <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
    </Data>
    <Signature>
        sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=
    </Signature>
</License>
复制代码
  1. 分析License类的setLicense方法找到关键代码
public final void setLicense(InputStream stream) throws AsposeLicenseException {
    try {
        ByteArrayInputStream var2 = null;
        if (stream != null) {
            ByteArrayOutputStream var3 = new ByteArrayOutputStream();
            byte[] var4 = new byte[1024];

            int var5;
            while((var5 = stream.read(var4)) > 0) {
                var3.write(var4, 0, var5);
            }

            var3.flush();
            var2 = new ByteArrayInputStream(var3.toByteArray());
        }

        public var7 = new public();
        var7.do(var2);
    } catch (IOException var6) {
        throw new InvalidOperationException("License stream is not available for reading");
    }
}

public final void setLicense(String namePath) throws AsposeLicenseException {
    FileInputStream var2 = null;

    try {
        if (null != namePath && !"".equals(namePath)) {
            var2 = new FileInputStream(namePath);
        }

        this.setLicense((InputStream)var2);
    } catch (FileNotFoundException var9) {
        try {
            String var4 = DOMResourcesUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            if (null != var4) {
                String var5 = URLDecoder.decode(var4, "UTF-8");
                File var6 = new File(var5);
                var2 = new FileInputStream(var6.getParentFile().getPath() + File.separator + namePath);
            }

            this.setLicense((InputStream)var2);
        } catch (FileNotFoundException var7) {
            throw new InvalidOperationException("License stream is not available for reading");
        } catch (UnsupportedEncodingException var8) {
            throw new InvalidOperationException("License stream is not available for reading");
        }
    }

}
复制代码

看下来发现setLicense的两个重载方法最终都调用了43行var7.do(var2); 也就是public类里的 do方法,由于publicdo是修饰符,所以先找到上方导入的public类路径
import com.aspose.slides.internal.of.public;,然后进入到依赖引用的of目录去搜索找到

image.png 进入public类看到do方法

public final void do(InputStream var1) {
    if (var1 != null) {
        this.if(var1);
        this.for(this.for);
        for(this.do);
        do(this.int);
        if(this.new);
        try = this;
        native.do(try);
    } else {
        try = null;
        native.do(try);
    }

}
复制代码

看到这个内容,有些头大很多都是修饰符还有个native,不过还好public文件不大,整个类扫视一遍发现了关键的信息

private static void do(Node var0, Node var1, String[] var2) {
    try {
        String var3 = var0 != null ? do(var0) : "";
        byte[] var4 = var3.getBytes("UTF-16LE");
        String var5 = var1 != null ? var1.getFirstChild().getNodeValue() : "";
        byte[] var6 = com.aspose.slides.internal.of.try.do(var5);
        PublicKey var7 = null;

        try {
            KeyFactory var8 = KeyFactory.getInstance("RSA");
            RSAPublicKeySpec var9 = long.do(if(var2), var6);
            var7 = var8.generatePublic(var9);
        } catch (Exception var10) {
            (new const() {
            }).do((new switch() {
            }).if, var10);
        }

        Signature var12;
        if (var6.length == 128) {
            var12 = Signature.getInstance("SHA1withRSA");
            var12.initVerify(var7);
            var12.update(var4);
            do(var12, var6);
        } else {
            var12 = Signature.getInstance("SHA256withRSA");
            var12.initVerify(var7);
            var12.update(var4);
            do(var12, var6);
        }
    } catch (Exception var11) {
        (new const() {
        }).do((new switch() {
        }).int, var11);
    }

}
复制代码

方法里面带有RSA这种加密的关键词,所以推测这里就是验证用的方法,解决也是老方法不知道干什么的也不清楚最终执行的,直接把内容清空。

3. 分析结果

  • 修改private static void do(Node var0, Node var1, String[] var2)方法为
private static void do(Node var0, Node var1, String[] var2) {
}
复制代码

执行操作

1. 添加Javassist修改class字节码文件

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.28.0-GA</version>
</dependency>
复制代码

2. 添加修改方法

/**
 * 修改slides.jar包里面的校验
 */
public static void modifyPptJar() {
    try {
        //这一步是完整的jar包路径,选择自己解压的jar目录
        ClassPool.getDefault().insertClassPath("D:\aspose-slides-21.10-java\lib\aspose-slides-21.10-jdk16.jar");
        CtClass zzZJJClass = ClassPool.getDefault().getCtClass("com.aspose.slides.internal.of.public");
        CtMethod[] methodA = zzZJJClass.getDeclaredMethods();
        for (CtMethod ctMethod : methodA) {
            CtClass[] ps = ctMethod.getParameterTypes();
            if (ps.length == 3 && ctMethod.getName().equals("do")) {
                System.out.println("ps[0].getName==" + ps[0].getName());
                ctMethod.setBody("{}");
            }
        }
        //这一步就是将破译完的代码放在桌面上
        zzZJJClass.writeFile("C:\Users\roc\Desktop\");
    } catch (Exception e) {
        System.out.println("错误==" + e);
    }
}
复制代码

运行修改方法后会在桌面生成 com 修改后的文件夹

3. 修改jar包里面的数据

为了不修改原jar包建议复制一份重命名。

  1. 打开jar包将桌面com文件夹覆盖到jar包com文件夹

image.png 2. 删除jar包里面的.RSA.SF文件

image.png

4. 重新导入修改后的jar包进行测试

  1. maven移除旧的jar包,导入修改后的jar包
  2. 调用测试方法进行测试转换后的文件是否去除水印和数量限制成功
String sourceFile = "D:\b.pptx";//输入的文件
String targetFile = "D:\转换后.pdf";//输出的文件
/**
 * PPT转PDF操作
 *
 * @param sourceFile 源文件
 * @param targetFile 目标文件
 */
public static void PptToPdf(String sourceFile, String targetFile) {
    try {
        long old = System.currentTimeMillis();
        FileOutputStream os = new FileOutputStream(targetFile);
        Presentation ppt = new Presentation(sourceFile);//加载源文件数据
        ppt.save(os, com.aspose.slides.SaveFormat.Pdf);//设置转换文件类型并转换
        os.close();
        long now = System.currentTimeMillis();
        System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒");  //转化用时
    } catch (Exception e) {
        e.printStackTrace();
    }
}
复制代码

声明

本方法只做个人研究学习使用,切勿用于商用。

其他参考


作者:Aroc
链接:juejin.cn/post/703441… 来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。