博客

  • dom4j 的 proguard-rules 配置分享

    前言

    有用户反馈 UpgradeAll 的 F-Droid 配置无法解析,查看日志后发现 dom4j 部分报错。但是直接 debug 无法复现,只有 release 混淆才会出错。

    排错

    原始错误

    2022-09-06 11:35:33 ClientProxyApi E/ClientProxyApi: org.dom4j.InvalidXPathException: Invalid XPath expression: .//application[@id="com.nextcloud.client"] org.jaxen.saxpath.base.XPathReader
    	at org.dom4j.xpath.DefaultXPath.parse(DefaultXPath.java:355)
    	at org.dom4j.xpath.DefaultXPath.<init>(DefaultXPath.java:59)
    	at org.dom4j.DocumentFactory.createXPath(DocumentFactory.java:222)
    	at org.dom4j.tree.AbstractNode.createXPath(AbstractNode.java:202)
    	at org.dom4j.tree.AbstractNode.selectSingleNode(AbstractNode.java:178)
    	at net.xzos.upgradeall.core.websdk.api.client_proxy.hubs.FDroid.getRelease(FDroid.kt:32)
    	at net.xzos.upgradeall.core.websdk.api.client_proxy.ClientProxyApi.getAppReleaseList(ClientProxyApi.kt:55)
    	at net.xzos.upgradeall.core.websdk.api.ServerApi$getAppReleaseList$value$1$1.invoke(ServerApi.kt:57)
    	at net.xzos.upgradeall.core.websdk.api.ServerApi$getAppReleaseList$value$1$1.invoke(ServerApi.kt:57)
    	at net.xzos.upgradeall.core.websdk.api.ServerApiKt.callOrBack(ServerApi.kt:97)
    	at net.xzos.upgradeall.core.websdk.api.ServerApiKt.access$callOrBack(ServerApi.kt:1)
    	at net.xzos.upgradeall.core.websdk.api.ServerApi$getAppReleaseList$value$1.invoke(ServerApi.kt:57)
    	at net.xzos.upgradeall.core.websdk.api.ServerApi$getAppReleaseList$value$1.invoke(ServerApi.kt:56)
    	at net.xzos.upgradeall.core.utils.data_cache.DataCacheManager.get(DataCacheManager.kt:47)
    	at net.xzos.upgradeall.core.utils.data_cache.DataCacheManager.get$default(DataCacheManager.kt:37)
    	at net.xzos.upgradeall.core.websdk.api.ServerApi.getAppReleaseList(ServerApi.kt:56)
    	at net.xzos.upgradeall.core.websdk.api.ServerApiProxy.getAppReleaseList(ServerApiProxy.kt:27)
    	at net.xzos.upgradeall.core.module.Hub.getAppReleaseList$core_debug(Hub.kt:124)
    	at net.xzos.upgradeall.core.module.app.data.DataGetter.renewVersionList(DataGetter.kt:48)
    	at net.xzos.upgradeall.core.module.app.data.DataGetter.doGetVersionList(DataGetter.kt:34)
    	at net.xzos.upgradeall.core.module.app.data.DataGetter.getVersionList(DataGetter.kt:29)
    	at net.xzos.upgradeall.core.module.app.data.DataGetter.doUpdate(DataGetter.kt:41)
    	at net.xzos.upgradeall.core.module.app.data.DataGetter.update(DataGetter.kt:24)
    	at net.xzos.upgradeall.core.module.app.Updater.update(Updater.kt:59)
    	at net.xzos.upgradeall.core.module.app.App.update(App.kt:74)
    	at net.xzos.upgradeall.core.manager.AppManager.renewApp(AppManager.kt:183)
    	at net.xzos.upgradeall.core.manager.AppManager$renewAppList$5$1.invokeSuspend(AppManager.kt:166)
    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    	at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
    	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
    	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)

    原始错误分析

    看见 org.dom4j.InvalidXPathException: Invalid XPath expression: 的第一反应就是 XPath 写错了,这里的 XPath 是 .//application[@id="com.nextcloud.client"],所以,按照菜鸟教程,修改为 //application[@id="com.nextcloud.client"],解决方法无效。

    直接搜索 org.dom4j.InvalidXPathException: Invalid XPath expression: 关键词,从 Why does dom4j throw InvalidXPathException for a valid XPath only in my test environment? 得知可能是 Dom4j 隐藏了原始错误。

    尝试取消混淆后 Dom4j 正常运行,所以排除是 release 混淆之外的错误。

    编写混淆规则

    鉴于对 DOM4J 进行源码修改过于复杂,所以并未选择修改,而是尝试分析 XPath 出错的可能,考虑到混淆后出错,添加 consumer-rules(这里是因为处于模块中)取消对 Dom4j 的混淆。

    现存的混淆规则

    在 Dom4j 的 Issues 列表中搜索关键词 proguard 发现有相同问题,回答中的 -dontwarn org.dom4j.** 只能忽略 gradle 编译时的警告,自欺欺人行为,忽略。

    参考 news-readerproguard-rules.txt 添加,测试的错误日志同上,错误并未解决。

    -keep class org.dom4j.** { *; }
    -keep interface org.dom4j.** { *; }

    指定 XML 驱动

    在网上还有另一种说法 dom4j 问题解决Can‘t create default XMLReader; is system property org.xml.sax.driver set groovy,手动指定 SaxReader 驱动。

    参考 porting to Android: why am I getting “Can’t create default XMLReader; is system property org.xml.sax.driver set?”? 添加代码:

    System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");

    编译得到的软件时而可用时而报错,后预计为 gradle 编译混淆原因,因此 rebuild 后测试,均失败。

    手动排除 Dom4j 依赖

    所以考虑到应该只是混淆规则的问题,进行范围排除(这里使用了 Android Studio 补全判断项目有哪些库)

    -keep class org.** { *; }
    -keep class com.** { *; }
    -keep class java.** { *; }
    -keep class javax.** { *; }
    -keep class net.** { *; }

    测试发现错误排除。故尝试一个个取消,检查软件运行状态。这里需要注意在修改后 rebuild 整个项目,因为 gradle 可能会偷懒不混淆刚刚取消不混淆的项目。

    最终测试出:

    -keep class javax.** { *; }
    -keep class org.** { *; }

    proguard-rules 配置

    得到上面的 javax 与 org,在 Dom4j 项目库中使用 Github 的代码搜索 import 依赖,最终得到以下规则:

    -keep class org.dom4j.** { *; }
    -keep interface org.dom4j.** { *; }
    -keep class javax.xml.** { *; }
    -keep class org.w3c.** { *; }
    -keep class org.xml.** { *; }
    -keep class org.xmlpull.** { *; }
    -keep class org.jaxen.** { *; }

    解决。

  • exa 仅显示点文件

    exa 是一个 ls 程序的替代品,旨在提供更加友好与多彩的用户界面,其期望与 bat 相似。

    背景

    在简单尝试 exa 后,我决定 alias 替换 ls 来体验一段时间,然后发现 ls -al --ignore="[^.]*" 命令无法被直接替换,因为 exa 没有 ignore 接口。

    测试命令

    在查找文档后,发现 exa 拥有基于 glob 语法的过滤(文档的 Filtering 节)。

    所以仅显示点文件的命令应该是

    exa -la --ignore-glob="[!.]*"

    其中,!意指不包括。

    添加 alias

    最后,我修改后的 rc 文件为(color 只是为了方便之后切换回 ls,exa 默认开启)

    alias ls='exa'
    alias l.='exa -la --ignore-glob="[!.]*"'
    alias ll='ls --color=auto -l'
    alias la='ls --color=auto -la'
  • Pipewire 多设备输出

    今天想和朋友一起听歌,把ta的蓝牙耳机连到电脑上后发现 KDE 界面只能设置一个音频输出端口。想起来上次 Steam Link 的经验,决定使用 Pipewire 实现这个功能。

    参考资料:
    https://xzos.net/steam-for-linux-no-sound-when-streaming/
    https://bbs.archlinux.org/viewtopic.php?pid=1986792#p1986792
    1. 查找音频设备
    $ pw-link -o
    Midi-Bridge:Midi Through:(capture_0) Midi Through Port-0
    v4l2_input.pci-0000_00_14.0-usb-0_6_1.0:out_0
    alsa_output.pci-0000_00_1f.3.analog-stereo:monitor_FL
    alsa_output.pci-0000_00_1f.3.analog-stereo:monitor_FR
    alsa_input.pci-0000_00_1f.3.analog-stereo:capture_FL
    alsa_input.pci-0000_00_1f.3.analog-stereo:capture_FR
    easyeffects_sink:monitor_FL
    easyeffects_sink:monitor_FR
    easyeffects_source:capture_FL
    $ pw-link -o
    Midi-Bridge:Midi Through:(capture_0) Midi Through Port-0
    v4l2_input.pci-0000_00_14.0-usb-0_6_1.0:out_0
    alsa_output.pci-0000_00_1f.3.analog-stereo:monitor_FL
    alsa_output.pci-0000_00_1f.3.analog-stereo:monitor_FR
    alsa_input.pci-0000_00_1f.3.analog-stereo:capture_FL
    alsa_input.pci-0000_00_1f.3.analog-stereo:capture_FR
    easyeffects_sink:monitor_FL
    easyeffects_sink:monitor_FR
    easyeffects_source:capture_FL
    easyeffects_source:capture_FR
    ee_soe_output_level:output_FL
    ee_soe_output_level:output_FR
    ee_soe_spectrum:output_FL
    ee_soe_spectrum:output_FR
    ee_soe_equalizer:output_FL
    ee_soe_equalizer:output_FR
    ee_soe_convolver:output_FL
    ee_soe_convolver:output_FR
    ee_sie_output_level:output_FL
    ee_sie_output_level:output_FR
    ee_sie_spectrum:output_FL
    ee_sie_spectrum:output_FR
    Audacious:output_FL
    Audacious:output_FR
    steam:output_FL
    steam:output_FR
    bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:monitor_FL
    bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:monitor_FReasyeffects_source:capture_FR
    ee_soe_output_level:output_FL
    ee_soe_output_level:output_FR
    ee_soe_spectrum:output_FL
    ee_soe_spectrum:output_FR
    ee_soe_equalizer:output_FL
    ee_soe_equalizer:output_FR
    ee_soe_convolver:output_FL
    ee_soe_convolver:output_FR
    ee_sie_output_level:output_FL
    ee_sie_output_level:output_FR
    ee_sie_spectrum:output_FL
    ee_sie_spectrum:output_FR
    Audacious:output_FL
    Audacious:output_FR
    steam:output_FL
    steam:output_FR
    bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:monitor_FL
    bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:monitor_FR

    确认希望使用的音频设备为 alsa_output.pci-0000_00_1f.3.analog-stereobluez_output.84_AB_26_A6_8A_6A.a2dp-sink

    2. 连接创建虚拟设备

    $ pactl load-module module-null-sink media.class=Audio/Sink sink_name=Simultaneous channel_map=stereo
    536870913  # 模块 ID,不用记

    3. 连接设备

    # 顺序不影响结果
    $ pw-link Simultaneous:monitor_FL bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:playback_FL
    $ pw-link Simultaneous:monitor_FR bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:playback_FR
    $ pw-link Simultaneous:monitor_FL alsa_output.pci-0000_00_1f.3.analog-stereo:playback_FL
    $ pw-link Simultaneous:monitor_FR alsa_output.pci-0000_00_1f.3.analog-stereo:playback_FR

    4. 去 KDE 设置里选择

    KDE 音频设置界面

    5. 卸载模块

    用完后可以卸载模块

    $ pactl unload-module module-null-sink
  • DP-3T 保护隐私的“健康码”

    人们总是选择并相信符合直觉的解释与方案,这导致了平庸

    DP-3T,一个保护隐私的接触者追踪软件,就好象健康码

    健康码,从全知全能的视角出发来“保护”每个人,这几乎可以预测一定会发生老大哥事件。

    而另一方面,从最小知识出发,基于随机 ID 与地理位置的 P2P(蓝牙)则避免了这些。

    这不符合人类作为个体的直觉,但加密货币的出现证明了这种实现的基础。

    更进一步的,参考加密货币的“价值网络”与“行为创造价值”的“权益证明”。我认为,我们可以引入加密货币的代币奖励机制,避免用户重置 ID。同时,用区块记录的方式计时与发放时间积分,保证用户手机尽力在线(除不可抗力导致的断网)与14天的检测期。

  • Steam for Linux no sound when streaming

    When I use Steam Link to play my game which is running in my ArchLinux PC, I find steam only catch microphone and ignore the sound output of PC. (Fixed on my ArchLinux PC at 2022-09-15)

    Github Issue: [Remote Play] No sound when streaming #6606
    (更多…)
  • 修改一个历史提交的父提交

    在半年前,合并热修复分支时,合并方向弄反了,导致热修复分支成为了新的主分支。但一直没有什么办法,今天重拾起来,尝试去修复。

    (更多…)
  • ArchLinux 配置指南

    这是一个导航页面,它记录了我的配置过程,你可以按照页面的顺序配置,也可以只搜寻信息。

    (更多…)
  • 使用 Linux 游玩尼尔机械纪元

    这里以 steam平台上运行的 尼尔机械纪元 为例,硬件平台为 Intel + Nvidia

    一般来说,大部分 Windows 游戏都可以通过 wine 运行。
    (更多…)
🌍 Language