From f48d2e6cacb1e6fe8d65d7b9fe4335c1266d24ca Mon Sep 17 00:00:00 2001 From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com> Date: Mon, 17 Nov 2025 12:20:45 +0800 Subject: [PATCH] manger: fmt code --- .../sukisu/ultra/ui/util/HanziToPinyin.java | 572 ------------------ .../com/sukisu/ultra/ui/util/HanziToPinyin.kt | 522 ++++++++++++++++ .../ultra/ui/viewmodel/ModuleViewModel.kt | 2 +- .../ultra/ui/viewmodel/SuperUserViewModel.kt | 2 +- .../sukisu/ultra/ui/webui/AppIconUtil.java | 47 -- .../com/sukisu/ultra/ui/webui/AppIconUtil.kt | 47 ++ .../com/sukisu/ultra/ui/webui/MimeUtil.java | 88 --- .../com/sukisu/ultra/ui/webui/MimeUtil.kt | 77 +++ .../ultra/ui/webui/SuFilePathHandler.java | 188 ------ .../ultra/ui/webui/SuFilePathHandler.kt | 108 ++++ 10 files changed, 756 insertions(+), 897 deletions(-) delete mode 100644 manager/app/src/main/java/com/sukisu/ultra/ui/util/HanziToPinyin.java create mode 100644 manager/app/src/main/java/com/sukisu/ultra/ui/util/HanziToPinyin.kt delete mode 100644 manager/app/src/main/java/com/sukisu/ultra/ui/webui/AppIconUtil.java create mode 100644 manager/app/src/main/java/com/sukisu/ultra/ui/webui/AppIconUtil.kt delete mode 100644 manager/app/src/main/java/com/sukisu/ultra/ui/webui/MimeUtil.java create mode 100644 manager/app/src/main/java/com/sukisu/ultra/ui/webui/MimeUtil.kt delete mode 100644 manager/app/src/main/java/com/sukisu/ultra/ui/webui/SuFilePathHandler.java create mode 100644 manager/app/src/main/java/com/sukisu/ultra/ui/webui/SuFilePathHandler.kt diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/util/HanziToPinyin.java b/manager/app/src/main/java/com/sukisu/ultra/ui/util/HanziToPinyin.java deleted file mode 100644 index fe1ebe69..00000000 --- a/manager/app/src/main/java/com/sukisu/ultra/ui/util/HanziToPinyin.java +++ /dev/null @@ -1,572 +0,0 @@ -package com.sukisu.ultra.ui.util; -/* - * Copyright (C) 2009 The Android Open Source Project - * - * 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. - */ - -import android.text.TextUtils; -import android.util.Log; - -import java.text.Collator; -import java.util.ArrayList; -import java.util.Locale; - -/** - * An object to convert Chinese character to its corresponding pinyin string. For characters with - * multiple possible pinyin string, only one is selected according to collator. Polyphone is not - * supported in this implementation. This class is implemented to achieve the best runtime - * performance and minimum runtime resources with tolerable sacrifice of accuracy. This - * implementation highly depends on zh_CN ICU collation data and must be always synchronized with - * ICU. - *
- * Currently this file is aligned to zh.txt in ICU 4.6 - */ -@SuppressWarnings("SizeReplaceableByIsEmpty") -public record HanziToPinyin(boolean mHasChinaCollator) { - private static final String TAG = "HanziToPinyin"; - - // Turn on this flag when we want to check internal data structure. - private static final boolean DEBUG = false; - - /** - * Unihans array. - *
- * Each unihans is the first one within same pinyin when collator is zh_CN. - */ - public static final char[] UNIHANS = { - '阿', '哎', '安', '肮', '凹', '八', - '挀', '扳', '邦', '勹', '陂', '奔', - '伻', '屄', '边', '灬', '憋', '汃', - '冫', '癶', '峬', '嚓', '偲', '参', - '仓', '撡', '冊', '嵾', '曽', '曾', - '層', '叉', '芆', '辿', '伥', '抄', - '车', '抻', '沈', '沉', '阷', '吃', - '充', '抽', '出', '欻', '揣', '巛', - '刅', '吹', '旾', '逴', '呲', '匆', - '凑', '粗', '汆', '崔', '邨', '搓', - '咑', '呆', '丹', '当', '刀', '嘚', - '扥', '灯', '氐', '嗲', '甸', '刁', - '爹', '丁', '丟', '东', '吺', '厾', - '耑', '襨', '吨', '多', '妸', '诶', - '奀', '鞥', '儿', '发', '帆', '匚', - '飞', '分', '丰', '覅', '仏', '紑', - '伕', '旮', '侅', '甘', '冈', '皋', - '戈', '给', '根', '刯', '工', '勾', - '估', '瓜', '乖', '关', '光', '归', - '丨', '呙', '哈', '咍', '佄', '夯', - '茠', '诃', '黒', '拫', '亨', '噷', - '叿', '齁', '乯', '花', '怀', '犿', - '巟', '灰', '昏', '吙', '丌', '加', - '戋', '江', '艽', '阶', '巾', '坕', - '冂', '丩', '凥', '姢', '噘', '军', - '咔', '开', '刊', '忼', '尻', '匼', - '肎', '劥', '空', '抠', '扝', '夸', - '蒯', '宽', '匡', '亏', '坤', '扩', - '垃', '来', '兰', '啷', '捞', '肋', - '勒', '崚', '刕', '俩', '奁', '良', - '撩', '列', '拎', '刢', '溜', '囖', - '龙', '瞜', '噜', '娈', '畧', '抡', - '罗', '呣', '妈', '埋', '嫚', '牤', - '猫', '么', '呅', '门', '甿', '咪', - '宀', '喵', '乜', '民', '名', '谬', - '摸', '哞', '毪', '嗯', '拏', '腉', - '囡', '囔', '孬', '疒', '娞', '恁', - '能', '妮', '拈', '嬢', '鸟', '捏', - '囜', '宁', '妞', '农', '羺', '奴', - '奻', '疟', '黁', '郍', '喔', '讴', - '妑', '拍', '眅', '乓', '抛', '呸', - '喷', '匉', '丕', '囨', '剽', '氕', - '姘', '乒', '钋', '剖', '仆', '七', - '掐', '千', '呛', '悄', '癿', '亲', - '狅', '芎', '丘', '区', '峑', '缺', - '夋', '呥', '穣', '娆', '惹', '人', - '扔', '日', '茸', '厹', '邚', '挼', - '堧', '婑', '瞤', '捼', '仨', '毢', - '三', '桒', '掻', '閪', '森', '僧', - '杀', '筛', '山', '伤', '弰', '奢', - '申', '莘', '敒', '升', '尸', '収', - '书', '刷', '衰', '闩', '双', '谁', - '吮', '说', '厶', '忪', '捜', '苏', - '狻', '夊', '孙', '唆', '他', '囼', - '坍', '汤', '夲', '忑', '熥', '剔', - '天', '旫', '帖', '厅', '囲', '偷', - '凸', '湍', '推', '吞', '乇', '穵', - '歪', '弯', '尣', '危', '昷', '翁', - '挝', '乌', '夕', '虲', '仚', '乡', - '灱', '些', '心', '星', '凶', '休', - '吁', '吅', '削', '坃', '丫', '恹', - '央', '幺', '倻', '一', '囙', '应', - '哟', '佣', '优', '扜', '囦', '曰', - '晕', '筠', '筼', '帀', '災', '兂', - '匨', '傮', '则', '贼', '怎', '増', - '扎', '捚', '沾', '张', '长', '長', - '佋', '蜇', '贞', '争', '之', '峙', - '庢', '中', '州', '朱', '抓', '拽', - '专', '妆', '隹', '宒', '卓', '乲', - '宗', '邹', '租', '钻', '厜', '尊', - '昨', '兙', '鿃', '鿄'}; - - /** - * Pinyin array. - *
- * Each pinyin is corresponding to unihans of same
- * offset in the unihans array.
- */
- public static final byte[][] PINYINS = {
- {65, 0, 0, 0, 0, 0}, {65, 73, 0, 0, 0, 0},
- {65, 78, 0, 0, 0, 0}, {65, 78, 71, 0, 0, 0},
- {65, 79, 0, 0, 0, 0}, {66, 65, 0, 0, 0, 0},
- {66, 65, 73, 0, 0, 0}, {66, 65, 78, 0, 0, 0},
- {66, 65, 78, 71, 0, 0}, {66, 65, 79, 0, 0, 0},
- {66, 69, 73, 0, 0, 0}, {66, 69, 78, 0, 0, 0},
- {66, 69, 78, 71, 0, 0}, {66, 73, 0, 0, 0, 0},
- {66, 73, 65, 78, 0, 0}, {66, 73, 65, 79, 0, 0},
- {66, 73, 69, 0, 0, 0}, {66, 73, 78, 0, 0, 0},
- {66, 73, 78, 71, 0, 0}, {66, 79, 0, 0, 0, 0},
- {66, 85, 0, 0, 0, 0}, {67, 65, 0, 0, 0, 0},
- {67, 65, 73, 0, 0, 0}, {67, 65, 78, 0, 0, 0},
- {67, 65, 78, 71, 0, 0}, {67, 65, 79, 0, 0, 0},
- {67, 69, 0, 0, 0, 0}, {67, 69, 78, 0, 0, 0},
- {67, 69, 78, 71, 0, 0}, {90, 69, 78, 71, 0, 0},
- {67, 69, 78, 71, 0, 0}, {67, 72, 65, 0, 0, 0},
- {67, 72, 65, 73, 0, 0}, {67, 72, 65, 78, 0, 0},
- {67, 72, 65, 78, 71, 0}, {67, 72, 65, 79, 0, 0},
- {67, 72, 69, 0, 0, 0}, {67, 72, 69, 78, 0, 0},
- {83, 72, 69, 78, 0, 0}, {67, 72, 69, 78, 0, 0},
- {67, 72, 69, 78, 71, 0}, {67, 72, 73, 0, 0, 0},
- {67, 72, 79, 78, 71, 0}, {67, 72, 79, 85, 0, 0},
- {67, 72, 85, 0, 0, 0}, {67, 72, 85, 65, 0, 0},
- {67, 72, 85, 65, 73, 0}, {67, 72, 85, 65, 78, 0},
- {67, 72, 85, 65, 78, 71}, {67, 72, 85, 73, 0, 0},
- {67, 72, 85, 78, 0, 0}, {67, 72, 85, 79, 0, 0},
- {67, 73, 0, 0, 0, 0}, {67, 79, 78, 71, 0, 0},
- {67, 79, 85, 0, 0, 0}, {67, 85, 0, 0, 0, 0},
- {67, 85, 65, 78, 0, 0}, {67, 85, 73, 0, 0, 0},
- {67, 85, 78, 0, 0, 0}, {67, 85, 79, 0, 0, 0},
- {68, 65, 0, 0, 0, 0}, {68, 65, 73, 0, 0, 0},
- {68, 65, 78, 0, 0, 0}, {68, 65, 78, 71, 0, 0},
- {68, 65, 79, 0, 0, 0}, {68, 69, 0, 0, 0, 0},
- {68, 69, 78, 0, 0, 0}, {68, 69, 78, 71, 0, 0},
- {68, 73, 0, 0, 0, 0}, {68, 73, 65, 0, 0, 0},
- {68, 73, 65, 78, 0, 0}, {68, 73, 65, 79, 0, 0},
- {68, 73, 69, 0, 0, 0}, {68, 73, 78, 71, 0, 0},
- {68, 73, 85, 0, 0, 0}, {68, 79, 78, 71, 0, 0},
- {68, 79, 85, 0, 0, 0}, {68, 85, 0, 0, 0, 0},
- {68, 85, 65, 78, 0, 0}, {68, 85, 73, 0, 0, 0},
- {68, 85, 78, 0, 0, 0}, {68, 85, 79, 0, 0, 0},
- {69, 0, 0, 0, 0, 0}, {69, 73, 0, 0, 0, 0},
- {69, 78, 0, 0, 0, 0}, {69, 78, 71, 0, 0, 0},
- {69, 82, 0, 0, 0, 0}, {70, 65, 0, 0, 0, 0},
- {70, 65, 78, 0, 0, 0}, {70, 65, 78, 71, 0, 0},
- {70, 69, 73, 0, 0, 0}, {70, 69, 78, 0, 0, 0},
- {70, 69, 78, 71, 0, 0}, {70, 73, 65, 79, 0, 0},
- {70, 79, 0, 0, 0, 0}, {70, 79, 85, 0, 0, 0},
- {70, 85, 0, 0, 0, 0}, {71, 65, 0, 0, 0, 0},
- {71, 65, 73, 0, 0, 0}, {71, 65, 78, 0, 0, 0},
- {71, 65, 78, 71, 0, 0}, {71, 65, 79, 0, 0, 0},
- {71, 69, 0, 0, 0, 0}, {71, 69, 73, 0, 0, 0},
- {71, 69, 78, 0, 0, 0}, {71, 69, 78, 71, 0, 0},
- {71, 79, 78, 71, 0, 0}, {71, 79, 85, 0, 0, 0},
- {71, 85, 0, 0, 0, 0}, {71, 85, 65, 0, 0, 0},
- {71, 85, 65, 73, 0, 0}, {71, 85, 65, 78, 0, 0},
- {71, 85, 65, 78, 71, 0}, {71, 85, 73, 0, 0, 0},
- {71, 85, 78, 0, 0, 0}, {71, 85, 79, 0, 0, 0},
- {72, 65, 0, 0, 0, 0}, {72, 65, 73, 0, 0, 0},
- {72, 65, 78, 0, 0, 0}, {72, 65, 78, 71, 0, 0},
- {72, 65, 79, 0, 0, 0}, {72, 69, 0, 0, 0, 0},
- {72, 69, 73, 0, 0, 0}, {72, 69, 78, 0, 0, 0},
- {72, 69, 78, 71, 0, 0}, {72, 77, 0, 0, 0, 0},
- {72, 79, 78, 71, 0, 0}, {72, 79, 85, 0, 0, 0},
- {72, 85, 0, 0, 0, 0}, {72, 85, 65, 0, 0, 0},
- {72, 85, 65, 73, 0, 0}, {72, 85, 65, 78, 0, 0},
- {72, 85, 65, 78, 71, 0}, {72, 85, 73, 0, 0, 0},
- {72, 85, 78, 0, 0, 0}, {72, 85, 79, 0, 0, 0},
- {74, 73, 0, 0, 0, 0}, {74, 73, 65, 0, 0, 0},
- {74, 73, 65, 78, 0, 0}, {74, 73, 65, 78, 71, 0},
- {74, 73, 65, 79, 0, 0}, {74, 73, 69, 0, 0, 0},
- {74, 73, 78, 0, 0, 0}, {74, 73, 78, 71, 0, 0},
- {74, 73, 79, 78, 71, 0}, {74, 73, 85, 0, 0, 0},
- {74, 85, 0, 0, 0, 0}, {74, 85, 65, 78, 0, 0},
- {74, 85, 69, 0, 0, 0}, {74, 85, 78, 0, 0, 0},
- {75, 65, 0, 0, 0, 0}, {75, 65, 73, 0, 0, 0},
- {75, 65, 78, 0, 0, 0}, {75, 65, 78, 71, 0, 0},
- {75, 65, 79, 0, 0, 0}, {75, 69, 0, 0, 0, 0},
- {75, 69, 78, 0, 0, 0}, {75, 69, 78, 71, 0, 0},
- {75, 79, 78, 71, 0, 0}, {75, 79, 85, 0, 0, 0},
- {75, 85, 0, 0, 0, 0}, {75, 85, 65, 0, 0, 0},
- {75, 85, 65, 73, 0, 0}, {75, 85, 65, 78, 0, 0},
- {75, 85, 65, 78, 71, 0}, {75, 85, 73, 0, 0, 0},
- {75, 85, 78, 0, 0, 0}, {75, 85, 79, 0, 0, 0},
- {76, 65, 0, 0, 0, 0}, {76, 65, 73, 0, 0, 0},
- {76, 65, 78, 0, 0, 0}, {76, 65, 78, 71, 0, 0},
- {76, 65, 79, 0, 0, 0}, {76, 69, 0, 0, 0, 0},
- {76, 69, 73, 0, 0, 0}, {76, 69, 78, 71, 0, 0},
- {76, 73, 0, 0, 0, 0}, {76, 73, 65, 0, 0, 0},
- {76, 73, 65, 78, 0, 0}, {76, 73, 65, 78, 71, 0},
- {76, 73, 65, 79, 0, 0}, {76, 73, 69, 0, 0, 0},
- {76, 73, 78, 0, 0, 0}, {76, 73, 78, 71, 0, 0},
- {76, 73, 85, 0, 0, 0}, {76, 79, 0, 0, 0, 0},
- {76, 79, 78, 71, 0, 0}, {76, 79, 85, 0, 0, 0},
- {76, 85, 0, 0, 0, 0}, {76, 85, 65, 78, 0, 0},
- {76, 85, 69, 0, 0, 0}, {76, 85, 78, 0, 0, 0},
- {76, 85, 79, 0, 0, 0}, {77, 0, 0, 0, 0, 0},
- {77, 65, 0, 0, 0, 0}, {77, 65, 73, 0, 0, 0},
- {77, 65, 78, 0, 0, 0}, {77, 65, 78, 71, 0, 0},
- {77, 65, 79, 0, 0, 0}, {77, 69, 0, 0, 0, 0},
- {77, 69, 73, 0, 0, 0}, {77, 69, 78, 0, 0, 0},
- {77, 69, 78, 71, 0, 0}, {77, 73, 0, 0, 0, 0},
- {77, 73, 65, 78, 0, 0}, {77, 73, 65, 79, 0, 0},
- {77, 73, 69, 0, 0, 0}, {77, 73, 78, 0, 0, 0},
- {77, 73, 78, 71, 0, 0}, {77, 73, 85, 0, 0, 0},
- {77, 79, 0, 0, 0, 0}, {77, 79, 85, 0, 0, 0},
- {77, 85, 0, 0, 0, 0}, {78, 0, 0, 0, 0, 0},
- {78, 65, 0, 0, 0, 0}, {78, 65, 73, 0, 0, 0},
- {78, 65, 78, 0, 0, 0}, {78, 65, 78, 71, 0, 0},
- {78, 65, 79, 0, 0, 0}, {78, 69, 0, 0, 0, 0},
- {78, 69, 73, 0, 0, 0}, {78, 69, 78, 0, 0, 0},
- {78, 69, 78, 71, 0, 0}, {78, 73, 0, 0, 0, 0},
- {78, 73, 65, 78, 0, 0}, {78, 73, 65, 78, 71, 0},
- {78, 73, 65, 79, 0, 0}, {78, 73, 69, 0, 0, 0},
- {78, 73, 78, 0, 0, 0}, {78, 73, 78, 71, 0, 0},
- {78, 73, 85, 0, 0, 0}, {78, 79, 78, 71, 0, 0},
- {78, 79, 85, 0, 0, 0}, {78, 85, 0, 0, 0, 0},
- {78, 85, 65, 78, 0, 0}, {78, 85, 69, 0, 0, 0},
- {78, 85, 78, 0, 0, 0}, {78, 85, 79, 0, 0, 0},
- {79, 0, 0, 0, 0, 0}, {79, 85, 0, 0, 0, 0},
- {80, 65, 0, 0, 0, 0}, {80, 65, 73, 0, 0, 0},
- {80, 65, 78, 0, 0, 0}, {80, 65, 78, 71, 0, 0},
- {80, 65, 79, 0, 0, 0}, {80, 69, 73, 0, 0, 0},
- {80, 69, 78, 0, 0, 0}, {80, 69, 78, 71, 0, 0},
- {80, 73, 0, 0, 0, 0}, {80, 73, 65, 78, 0, 0},
- {80, 73, 65, 79, 0, 0}, {80, 73, 69, 0, 0, 0},
- {80, 73, 78, 0, 0, 0}, {80, 73, 78, 71, 0, 0},
- {80, 79, 0, 0, 0, 0}, {80, 79, 85, 0, 0, 0},
- {80, 85, 0, 0, 0, 0}, {81, 73, 0, 0, 0, 0},
- {81, 73, 65, 0, 0, 0}, {81, 73, 65, 78, 0, 0},
- {81, 73, 65, 78, 71, 0}, {81, 73, 65, 79, 0, 0},
- {81, 73, 69, 0, 0, 0}, {81, 73, 78, 0, 0, 0},
- {81, 73, 78, 71, 0, 0}, {81, 73, 79, 78, 71, 0},
- {81, 73, 85, 0, 0, 0}, {81, 85, 0, 0, 0, 0},
- {81, 85, 65, 78, 0, 0}, {81, 85, 69, 0, 0, 0},
- {81, 85, 78, 0, 0, 0}, {82, 65, 78, 0, 0, 0},
- {82, 65, 78, 71, 0, 0}, {82, 65, 79, 0, 0, 0},
- {82, 69, 0, 0, 0, 0}, {82, 69, 78, 0, 0, 0},
- {82, 69, 78, 71, 0, 0}, {82, 73, 0, 0, 0, 0},
- {82, 79, 78, 71, 0, 0}, {82, 79, 85, 0, 0, 0},
- {82, 85, 0, 0, 0, 0}, {82, 85, 65, 0, 0, 0},
- {82, 85, 65, 78, 0, 0}, {82, 85, 73, 0, 0, 0},
- {82, 85, 78, 0, 0, 0}, {82, 85, 79, 0, 0, 0},
- {83, 65, 0, 0, 0, 0}, {83, 65, 73, 0, 0, 0},
- {83, 65, 78, 0, 0, 0}, {83, 65, 78, 71, 0, 0},
- {83, 65, 79, 0, 0, 0}, {83, 69, 0, 0, 0, 0},
- {83, 69, 78, 0, 0, 0}, {83, 69, 78, 71, 0, 0},
- {83, 72, 65, 0, 0, 0}, {83, 72, 65, 73, 0, 0},
- {83, 72, 65, 78, 0, 0}, {83, 72, 65, 78, 71, 0},
- {83, 72, 65, 79, 0, 0}, {83, 72, 69, 0, 0, 0},
- {83, 72, 69, 78, 0, 0}, {88, 73, 78, 0, 0, 0},
- {83, 72, 69, 78, 0, 0}, {83, 72, 69, 78, 71, 0},
- {83, 72, 73, 0, 0, 0}, {83, 72, 79, 85, 0, 0},
- {83, 72, 85, 0, 0, 0}, {83, 72, 85, 65, 0, 0},
- {83, 72, 85, 65, 73, 0}, {83, 72, 85, 65, 78, 0},
- {83, 72, 85, 65, 78, 71}, {83, 72, 85, 73, 0, 0},
- {83, 72, 85, 78, 0, 0}, {83, 72, 85, 79, 0, 0},
- {83, 73, 0, 0, 0, 0}, {83, 79, 78, 71, 0, 0},
- {83, 79, 85, 0, 0, 0}, {83, 85, 0, 0, 0, 0},
- {83, 85, 65, 78, 0, 0}, {83, 85, 73, 0, 0, 0},
- {83, 85, 78, 0, 0, 0}, {83, 85, 79, 0, 0, 0},
- {84, 65, 0, 0, 0, 0}, {84, 65, 73, 0, 0, 0},
- {84, 65, 78, 0, 0, 0}, {84, 65, 78, 71, 0, 0},
- {84, 65, 79, 0, 0, 0}, {84, 69, 0, 0, 0, 0},
- {84, 69, 78, 71, 0, 0}, {84, 73, 0, 0, 0, 0},
- {84, 73, 65, 78, 0, 0}, {84, 73, 65, 79, 0, 0},
- {84, 73, 69, 0, 0, 0}, {84, 73, 78, 71, 0, 0},
- {84, 79, 78, 71, 0, 0}, {84, 79, 85, 0, 0, 0},
- {84, 85, 0, 0, 0, 0}, {84, 85, 65, 78, 0, 0},
- {84, 85, 73, 0, 0, 0}, {84, 85, 78, 0, 0, 0},
- {84, 85, 79, 0, 0, 0}, {87, 65, 0, 0, 0, 0},
- {87, 65, 73, 0, 0, 0}, {87, 65, 78, 0, 0, 0},
- {87, 65, 78, 71, 0, 0}, {87, 69, 73, 0, 0, 0},
- {87, 69, 78, 0, 0, 0}, {87, 69, 78, 71, 0, 0},
- {87, 79, 0, 0, 0, 0}, {87, 85, 0, 0, 0, 0},
- {88, 73, 0, 0, 0, 0}, {88, 73, 65, 0, 0, 0},
- {88, 73, 65, 78, 0, 0}, {88, 73, 65, 78, 71, 0},
- {88, 73, 65, 79, 0, 0}, {88, 73, 69, 0, 0, 0},
- {88, 73, 78, 0, 0, 0}, {88, 73, 78, 71, 0, 0},
- {88, 73, 79, 78, 71, 0}, {88, 73, 85, 0, 0, 0},
- {88, 85, 0, 0, 0, 0}, {88, 85, 65, 78, 0, 0},
- {88, 85, 69, 0, 0, 0}, {88, 85, 78, 0, 0, 0},
- {89, 65, 0, 0, 0, 0}, {89, 65, 78, 0, 0, 0},
- {89, 65, 78, 71, 0, 0}, {89, 65, 79, 0, 0, 0},
- {89, 69, 0, 0, 0, 0}, {89, 73, 0, 0, 0, 0},
- {89, 73, 78, 0, 0, 0}, {89, 73, 78, 71, 0, 0},
- {89, 79, 0, 0, 0, 0}, {89, 79, 78, 71, 0, 0},
- {89, 79, 85, 0, 0, 0}, {89, 85, 0, 0, 0, 0},
- {89, 85, 65, 78, 0, 0}, {89, 85, 69, 0, 0, 0},
- {89, 85, 78, 0, 0, 0}, {74, 85, 78, 0, 0, 0},
- {89, 85, 78, 0, 0, 0}, {90, 65, 0, 0, 0, 0},
- {90, 65, 73, 0, 0, 0}, {90, 65, 78, 0, 0, 0},
- {90, 65, 78, 71, 0, 0}, {90, 65, 79, 0, 0, 0},
- {90, 69, 0, 0, 0, 0}, {90, 69, 73, 0, 0, 0},
- {90, 69, 78, 0, 0, 0}, {90, 69, 78, 71, 0, 0},
- {90, 72, 65, 0, 0, 0}, {90, 72, 65, 73, 0, 0},
- {90, 72, 65, 78, 0, 0}, {90, 72, 65, 78, 71, 0},
- {67, 72, 65, 78, 71, 0}, {90, 72, 65, 78, 71, 0},
- {90, 72, 65, 79, 0, 0}, {90, 72, 69, 0, 0, 0},
- {90, 72, 69, 78, 0, 0}, {90, 72, 69, 78, 71, 0},
- {90, 72, 73, 0, 0, 0}, {83, 72, 73, 0, 0, 0},
- {90, 72, 73, 0, 0, 0}, {90, 72, 79, 78, 71, 0},
- {90, 72, 79, 85, 0, 0}, {90, 72, 85, 0, 0, 0},
- {90, 72, 85, 65, 0, 0}, {90, 72, 85, 65, 73, 0},
- {90, 72, 85, 65, 78, 0}, {90, 72, 85, 65, 78, 71},
- {90, 72, 85, 73, 0, 0}, {90, 72, 85, 78, 0, 0},
- {90, 72, 85, 79, 0, 0}, {90, 73, 0, 0, 0, 0},
- {90, 79, 78, 71, 0, 0}, {90, 79, 85, 0, 0, 0},
- {90, 85, 0, 0, 0, 0}, {90, 85, 65, 78, 0, 0},
- {90, 85, 73, 0, 0, 0}, {90, 85, 78, 0, 0, 0},
- {90, 85, 79, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
- {83, 72, 65, 78, 0, 0}, {0, 0, 0, 0, 0, 0}};
-
- /**
- * First and last Chinese character with known Pinyin according to zh collation
- */
- private static final String FIRST_PINYIN_UNIHAN = "阿";
- private static final String LAST_PINYIN_UNIHAN = "鿿";
-
- private static final Collator COLLATOR = Collator.getInstance(Locale.CHINA);
-
- private static HanziToPinyin sInstance;
-
- public static class Token {
- /**
- * Separator between target string for each source char
- */
- public static final String SEPARATOR = " ";
-
- public static final int LATIN = 1;
- public static final int PINYIN = 2;
- public static final int UNKNOWN = 3;
-
- public Token() {
- }
-
- public Token(int type, String source, String target) {
- this.type = type;
- this.source = source;
- this.target = target;
- }
-
- /**
- * Type of this token, ASCII, PINYIN or UNKNOWN.
- */
- public int type;
- /**
- * Original string before translation.
- */
- public String source;
- /**
- * Translated string of source. For Han, target is corresponding Pinyin. Otherwise target is
- * original string in source.
- */
- public String target;
- }
-
- public static HanziToPinyin getInstance() {
- synchronized (HanziToPinyin.class) {
- if (sInstance != null) {
- return sInstance;
- }
- // Check if zh_CN collation data is available
- final Locale[] locale = Collator.getAvailableLocales();
- for (Locale value : locale) {
- if (value.equals(Locale.CHINA) || value.getLanguage().contains("zh")) {
- // Do self validation just once.
- if (DEBUG) {
- Log.d(TAG, "Self validation. Result: " + doSelfValidation());
- }
- sInstance = new HanziToPinyin(true);
- return sInstance;
- }
- }
- if (sInstance == null) {//这个判断是用于处理国产ROM的兼容性问题
- if (Locale.CHINA.equals(Locale.getDefault())) {
- sInstance = new HanziToPinyin(true);
- return sInstance;
- }
- }
- Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled");
- sInstance = new HanziToPinyin(false);
- return sInstance;
- }
- }
-
- /**
- * Validate if our internal table has some wrong value.
- *
- * @return true when the table looks correct.
- */
- private static boolean doSelfValidation() {
- char lastChar = UNIHANS[0];
- String lastString = Character.toString(lastChar);
- for (char c : UNIHANS) {
- if (lastChar == c) {
- continue;
- }
- final String curString = Character.toString(c);
- int cmp = COLLATOR.compare(lastString, curString);
- if (cmp >= 0) {
- Log.e(TAG, "Internal error in Unihan table. " + "The last string \"" + lastString
- + "\" is greater than current string \"" + curString + "\".");
- return false;
- }
- lastString = curString;
- }
- return true;
- }
-
- private Token getToken(char character) {
- Token token = new Token();
- final String letter = Character.toString(character);
- token.source = letter;
- int offset = -1;
- int cmp;
- if (character < 256) {
- token.type = Token.LATIN;
- token.target = letter;
- return token;
- } else {
- cmp = COLLATOR.compare(letter, FIRST_PINYIN_UNIHAN);
- if (cmp < 0) {
- token.type = Token.UNKNOWN;
- token.target = letter;
- return token;
- } else if (cmp == 0) {
- token.type = Token.PINYIN;
- offset = 0;
- } else {
- cmp = COLLATOR.compare(letter, LAST_PINYIN_UNIHAN);
- if (cmp > 0) {
- token.type = Token.UNKNOWN;
- token.target = letter;
- return token;
- } else if (cmp == 0) {
- token.type = Token.PINYIN;
- offset = UNIHANS.length - 1;
- }
- }
- }
-
- token.type = Token.PINYIN;
- if (offset < 0) {
- int begin = 0;
- int end = UNIHANS.length - 1;
- while (begin <= end) {
- offset = (begin + end) / 2;
- final String unihan = Character.toString(UNIHANS[offset]);
- cmp = COLLATOR.compare(letter, unihan);
- if (cmp == 0) {
- break;
- } else if (cmp > 0) {
- begin = offset + 1;
- } else {
- end = offset - 1;
- }
- }
- }
- if (cmp < 0) {
- offset--;
- }
- StringBuilder pinyin = new StringBuilder();
- for (int j = 0; j < PINYINS[offset].length && PINYINS[offset][j] != 0; j++) {
- pinyin.append((char) PINYINS[offset][j]);
- }
- token.target = pinyin.toString();
- if (TextUtils.isEmpty(token.target)) {
- token.type = Token.UNKNOWN;
- token.target = token.source;
- }
- return token;
- }
-
- /**
- * Convert the input to a array of tokens. The sequence of ASCII or Unknown characters without
- * space will be put into a Token, One Hanzi character which has pinyin will be treated as a
- * Token. If these is no China collator, the empty token array is returned.
- */
- public ArrayList
- * To avoid leaking user or app data to the web, make sure to choose {@code directory}
- * carefully, and assume any file under this directory could be accessed by any web page subject
- * to same-origin rules.
- *
- * A typical usage would be like:
- *
- * Note: Any future addition to this list will be considered breaking changes to the API.
- */
- private static final String[] FORBIDDEN_DATA_DIRS =
- new String[] {"/data/data", "/data/system"};
-
- @NonNull
- private final File mDirectory;
-
- private final Shell mShell;
-
- /**
- * Creates PathHandler for app's internal storage.
- * The directory to be exposed must be inside either the application's internal data
- * directory {@link Context#getDataDir} or cache directory {@link Context#getCacheDir}.
- * External storage is not supported for security reasons, as other apps with
- * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} may be able to modify the
- * files.
- *
- * Exposing the entire data or cache directory is not permitted, to avoid accidentally
- * exposing sensitive application files to the web. Certain existing subdirectories of
- * {@link Context#getDataDir} are also not permitted as they are often sensitive.
- * These files are ({@code "app_webview/"}, {@code "databases/"}, {@code "lib/"},
- * {@code "shared_prefs/"} and {@code "code_cache/"}).
- *
- * The application should typically use a dedicated subdirectory for the files it intends to
- * expose and keep them separate from other files.
- *
- * @param directory the absolute path of the exposed app internal storage directory from
- * which files can be loaded.
- * @throws IllegalArgumentException if the directory is not allowed.
- */
- public SuFilePathHandler(@NonNull File directory, Shell rootShell) {
- try {
- mDirectory = new File(getCanonicalDirPath(directory));
- if (!isAllowedInternalStorageDir()) {
- throw new IllegalArgumentException("The given directory \"" + directory
- + "\" doesn't exist under an allowed app internal storage directory");
- }
- mShell = rootShell;
- } catch (IOException e) {
- throw new IllegalArgumentException(
- "Failed to resolve the canonical path for the given directory: "
- + directory.getPath(), e);
- }
- }
-
- private boolean isAllowedInternalStorageDir() throws IOException {
- String dir = getCanonicalDirPath(mDirectory);
-
- for (String forbiddenPath : FORBIDDEN_DATA_DIRS) {
- if (dir.startsWith(forbiddenPath)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Opens the requested file from the exposed data directory.
- *
- * The matched prefix path used shouldn't be a prefix of a real web path. Thus, if the
- * requested file cannot be found or is outside the mounted directory a
- * {@link WebResourceResponse} object with a {@code null} {@link InputStream} will be
- * returned instead of {@code null}. This saves the time of falling back to network and
- * trying to resolve a path that doesn't exist. A {@link WebResourceResponse} with
- * {@code null} {@link InputStream} will be received as an HTTP response with status code
- * {@code 404} and no body.
- *
- * The MIME type for the file will be determined from the file's extension using
- * {@link java.net.URLConnection#guessContentTypeFromName}. Developers should ensure that
- * files are named using standard file extensions. If the file does not have a
- * recognised extension, {@code "text/plain"} will be used by default.
- *
- * @param path the suffix path to be handled.
- * @return {@link WebResourceResponse} for the requested file.
- */
- @Override
- @WorkerThread
- @NonNull
- public WebResourceResponse handle(@NonNull String path) {
- try {
- File file = getCanonicalFileIfChild(mDirectory, path);
- if (file != null) {
- InputStream is = openFile(file, mShell);
- String mimeType = guessMimeType(path);
- return new WebResourceResponse(mimeType, null, is);
- } else {
- Log.e(TAG, String.format(
- "The requested file: %s is outside the mounted directory: %s", path,
- mDirectory));
- }
- } catch (IOException e) {
- Log.e(TAG, "Error opening the requested path: " + path, e);
- }
- return new WebResourceResponse(null, null, null);
- }
-
- public static String getCanonicalDirPath(@NonNull File file) throws IOException {
- String canonicalPath = file.getCanonicalPath();
- if (!canonicalPath.endsWith("/")) canonicalPath += "/";
- return canonicalPath;
- }
-
- public static File getCanonicalFileIfChild(@NonNull File parent, @NonNull String child)
- throws IOException {
- String parentCanonicalPath = getCanonicalDirPath(parent);
- String childCanonicalPath = new File(parent, child).getCanonicalPath();
- if (childCanonicalPath.startsWith(parentCanonicalPath)) {
- return new File(childCanonicalPath);
- }
- return null;
- }
-
- @NonNull
- private static InputStream handleSvgzStream(@NonNull String path,
- @NonNull InputStream stream) throws IOException {
- return path.endsWith(".svgz") ? new GZIPInputStream(stream) : stream;
- }
-
- public static InputStream openFile(@NonNull File file, @NonNull Shell shell) throws IOException {
- SuFile suFile = new SuFile(file.getAbsolutePath());
- suFile.setShell(shell);
- InputStream fis = SuFileInputStream.open(suFile);
- return handleSvgzStream(file.getPath(), fis);
- }
-
- /**
- * Use {@link MimeUtil#getMimeFromFileName} to guess MIME type or return the
- * {@link #DEFAULT_MIME_TYPE} if it can't guess.
- *
- * @param filePath path of the file to guess its MIME type.
- * @return MIME type guessed from file extension or {@link #DEFAULT_MIME_TYPE}.
- */
- @NonNull
- public static String guessMimeType(@NonNull String filePath) {
- String mimeType = MimeUtil.getMimeFromFileName(filePath);
- return mimeType == null ? DEFAULT_MIME_TYPE : mimeType;
- }
-}
diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/webui/SuFilePathHandler.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/webui/SuFilePathHandler.kt
new file mode 100644
index 00000000..ab97e636
--- /dev/null
+++ b/manager/app/src/main/java/com/sukisu/ultra/ui/webui/SuFilePathHandler.kt
@@ -0,0 +1,108 @@
+package com.sukisu.ultra.ui.webui
+
+import android.util.Log
+import android.webkit.WebResourceResponse
+import androidx.annotation.WorkerThread
+import androidx.webkit.WebViewAssetLoader
+import com.topjohnwu.superuser.Shell
+import com.topjohnwu.superuser.io.SuFile
+import com.topjohnwu.superuser.io.SuFileInputStream
+import java.io.File
+import java.io.IOException
+import java.io.InputStream
+import java.util.zip.GZIPInputStream
+
+class SuFilePathHandler(
+ directory: File,
+ private val mShell: Shell
+) : WebViewAssetLoader.PathHandler {
+
+ private val mDirectory: File
+
+ init {
+ try {
+ mDirectory = File(getCanonicalDirPath(directory))
+ if (!isAllowedInternalStorageDir()) {
+ throw IllegalArgumentException(
+ "The given directory \"$directory\" doesn't exist under an allowed app internal storage directory"
+ )
+ }
+ } catch (e: IOException) {
+ throw IllegalArgumentException(
+ "Failed to resolve the canonical path for the given directory: ${directory.path}",
+ e
+ )
+ }
+ }
+
+ private fun isAllowedInternalStorageDir(): Boolean {
+ return try {
+ val dir = getCanonicalDirPath(mDirectory)
+ FORBIDDEN_DATA_DIRS.none { dir.startsWith(it) }
+ } catch (_: IOException) {
+ false
+ }
+ }
+
+ @WorkerThread
+ override fun handle(path: String): WebResourceResponse {
+ try {
+ val file = getCanonicalFileIfChild(mDirectory, path)
+ if (file != null) {
+ val inputStream = openFile(file, mShell)
+ val mimeType = guessMimeType(path)
+ return WebResourceResponse(mimeType, null, inputStream)
+ } else {
+ Log.e(
+ TAG,
+ "The requested file: $path is outside the mounted directory: $mDirectory"
+ )
+ }
+ } catch (e: IOException) {
+ Log.e(TAG, "Error opening the requested path: $path", e)
+ }
+ return WebResourceResponse(null, null, null)
+ }
+
+ companion object {
+ private const val TAG = "SuFilePathHandler"
+ const val DEFAULT_MIME_TYPE = "text/plain"
+
+ private val FORBIDDEN_DATA_DIRS = arrayOf("/data/data", "/data/system")
+
+ fun getCanonicalDirPath(file: File): String {
+ val canonicalPath = file.canonicalPath
+ return if (!canonicalPath.endsWith("/")) "$canonicalPath/" else canonicalPath
+ }
+
+ fun getCanonicalFileIfChild(parent: File, child: String): File? {
+ return try {
+ val parentCanonicalPath = getCanonicalDirPath(parent)
+ val childCanonicalPath = File(parent, child).canonicalPath
+ if (childCanonicalPath.startsWith(parentCanonicalPath)) {
+ File(childCanonicalPath)
+ } else {
+ null
+ }
+ } catch (_: IOException) {
+ null
+ }
+ }
+
+ private fun handleSvgzStream(path: String, stream: InputStream): InputStream {
+ return if (path.endsWith(".svgz")) GZIPInputStream(stream) else stream
+ }
+
+ fun openFile(file: File, shell: Shell): InputStream {
+ val suFile = SuFile(file.absolutePath).apply {
+ setShell(shell)
+ }
+ val fis = SuFileInputStream.open(suFile)
+ return handleSvgzStream(file.path, fis)
+ }
+
+ fun guessMimeType(filePath: String): String {
+ return MimeUtil.getMimeFromFileName(filePath) ?: DEFAULT_MIME_TYPE
+ }
+ }
+}
- * File publicDir = new File(context.getFilesDir(), "public");
- * // Host "files/public/" in app's data directory under:
- * // http://appassets.androidplatform.net/public/...
- * WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
- * .addPathHandler("/public/", new InternalStoragePathHandler(context, publicDir))
- * .build();
- *
- */
-public final class SuFilePathHandler implements WebViewAssetLoader.PathHandler {
- private static final String TAG = "SuFilePathHandler";
-
- /**
- * Default value to be used as MIME type if guessing MIME type failed.
- */
- public static final String DEFAULT_MIME_TYPE = "text/plain";
-
- /**
- * Forbidden subdirectories of {@link Context#getDataDir} that cannot be exposed by this
- * handler. They are forbidden as they often contain sensitive information.
- *