From e359b5c75e192e03870ae6c201c065740dc13016 Mon Sep 17 00:00:00 2001 From: mhsanaei Date: Tue, 29 Oct 2024 12:50:25 +0100 Subject: [PATCH] removed - XTLS Security because its too old and no one use it anymore --- sub/subService.go | 67 +-------- web/assets/js/model/xray.js | 199 --------------------------- web/html/xui/client_bulk_modal.html | 9 -- web/html/xui/form/client.html | 6 - web/html/xui/form/tls_settings.html | 18 +-- web/html/xui/form/xtls_settings.html | 58 -------- web/html/xui/inbound_info_modal.html | 9 -- web/html/xui/inbound_modal.html | 9 -- web/html/xui/inbounds.html | 1 - web/translation/translate.en_US.toml | 2 - web/translation/translate.es_ES.toml | 2 - web/translation/translate.fa_IR.toml | 2 - web/translation/translate.id_ID.toml | 2 - web/translation/translate.pt_BR.toml | 2 - web/translation/translate.ru_RU.toml | 2 - web/translation/translate.tr_TR.toml | 2 - web/translation/translate.uk_UA.toml | 2 - web/translation/translate.vi_VN.toml | 2 - web/translation/translate.zh_CN.toml | 2 - web/translation/translate.zh_TW.toml | 2 - 20 files changed, 3 insertions(+), 395 deletions(-) delete mode 100644 web/html/xui/form/xtls_settings.html diff --git a/sub/subService.go b/sub/subService.go index 33d2e06594..2838e93247 100644 --- a/sub/subService.go +++ b/sub/subService.go @@ -452,38 +452,7 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string { } } - if security == "xtls" { - params["security"] = "xtls" - xtlsSetting, _ := stream["xtlsSettings"].(map[string]interface{}) - alpns, _ := xtlsSetting["alpn"].([]interface{}) - var alpn []string - for _, a := range alpns { - alpn = append(alpn, a.(string)) - } - if len(alpn) > 0 { - params["alpn"] = strings.Join(alpn, ",") - } - if sniValue, ok := searchKey(xtlsSetting, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } - xtlsSettings, _ := searchKey(xtlsSetting, "settings") - if xtlsSetting != nil { - if fpValue, ok := searchKey(xtlsSettings, "fingerprint"); ok { - params["fp"], _ = fpValue.(string) - } - if insecure, ok := searchKey(xtlsSettings, "allowInsecure"); ok { - if insecure.(bool) { - params["allowInsecure"] = "1" - } - } - } - - if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { - params["flow"] = clients[clientIndex].Flow - } - } - - if security != "tls" && security != "reality" && security != "xtls" { + if security != "tls" && security != "reality" { params["security"] = "none" } @@ -676,39 +645,7 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string } } - if security == "xtls" { - params["security"] = "xtls" - xtlsSetting, _ := stream["xtlsSettings"].(map[string]interface{}) - alpns, _ := xtlsSetting["alpn"].([]interface{}) - var alpn []string - for _, a := range alpns { - alpn = append(alpn, a.(string)) - } - if len(alpn) > 0 { - params["alpn"] = strings.Join(alpn, ",") - } - if sniValue, ok := searchKey(xtlsSetting, "serverName"); ok { - params["sni"], _ = sniValue.(string) - } - - xtlsSettings, _ := searchKey(xtlsSetting, "settings") - if xtlsSetting != nil { - if fpValue, ok := searchKey(xtlsSettings, "fingerprint"); ok { - params["fp"], _ = fpValue.(string) - } - if insecure, ok := searchKey(xtlsSettings, "allowInsecure"); ok { - if insecure.(bool) { - params["allowInsecure"] = "1" - } - } - } - - if streamNetwork == "tcp" && len(clients[clientIndex].Flow) > 0 { - params["flow"] = clients[clientIndex].Flow - } - } - - if security != "tls" && security != "reality" && security != "xtls" { + if security != "tls" && security != "reality" { params["security"] = "none" } diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index 209a3140c2..b7d68dd83e 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -21,11 +21,6 @@ const SSMethods = { BLAKE3_CHACHA20_POLY1305: '2022-blake3-chacha20-poly1305', }; -const XTLS_FLOW_CONTROL = { - ORIGIN: "xtls-rprx-origin", - DIRECT: "xtls-rprx-direct", -}; - const TLS_FLOW_CONTROL = { VISION: "xtls-rprx-vision", VISION_UDP443: "xtls-rprx-vision-udp443", @@ -120,7 +115,6 @@ const USERS_SECURITY = { Object.freeze(Protocols); Object.freeze(SSMethods); -Object.freeze(XTLS_FLOW_CONTROL); Object.freeze(TLS_FLOW_CONTROL); Object.freeze(TLS_VERSION_OPTION); Object.freeze(TLS_CIPHER_OPTION); @@ -755,137 +749,6 @@ TlsStreamSettings.Settings = class extends XrayCommonClass { } }; -class XtlsStreamSettings extends XrayCommonClass { - constructor( - serverName = '', - certificates = [new XtlsStreamSettings.Cert()], - alpn = [ALPN_OPTION.H3, ALPN_OPTION.H2, ALPN_OPTION.HTTP1], - settings = new XtlsStreamSettings.Settings() - ) { - super(); - this.sni = serverName; - this.certs = certificates; - this.alpn = alpn; - this.settings = settings; - } - - addCert() { - this.certs.push(new XtlsStreamSettings.Cert()); - } - - removeCert(index) { - this.certs.splice(index, 1); - } - - static fromJson(json = {}) { - let certs; - let settings; - if (!ObjectUtil.isEmpty(json.certificates)) { - certs = json.certificates.map(cert => XtlsStreamSettings.Cert.fromJson(cert)); - } - - if (!ObjectUtil.isEmpty(json.settings)) { - settings = new XtlsStreamSettings.Settings(json.settings.allowInsecure, json.settings.serverName); - } - return new XtlsStreamSettings( - json.serverName, - certs, - json.alpn, - settings, - ); - } - - toJson() { - return { - serverName: this.sni, - certificates: XtlsStreamSettings.toJsonArray(this.certs), - alpn: this.alpn, - settings: this.settings, - }; - } -} - -XtlsStreamSettings.Cert = class extends XrayCommonClass { - constructor( - useFile = true, - certificateFile = '', - keyFile = '', - certificate = '', - key = '', - ocspStapling = 3600, - oneTimeLoading = false, - usage = USAGE_OPTION.ENCIPHERMENT - ) { - super(); - this.useFile = useFile; - this.certFile = certificateFile; - this.keyFile = keyFile; - this.cert = Array.isArray(certificate) ? certificate.join('\n') : certificate; - this.key = Array.isArray(key) ? key.join('\n') : key; - this.ocspStapling = ocspStapling; - this.oneTimeLoading = oneTimeLoading; - this.usage = usage; - } - - static fromJson(json = {}) { - if ('certificateFile' in json && 'keyFile' in json) { - return new XtlsStreamSettings.Cert( - true, - json.certificateFile, - json.keyFile, '', '', - json.ocspStapling, - json.oneTimeLoading, - json.usage, - ); - } else { - return new XtlsStreamSettings.Cert( - false, '', '', - json.certificate.join('\n'), - json.key.join('\n'), - json.ocspStapling, - json.oneTimeLoading, - json.usage, - ); - } - } - - toJson() { - if (this.useFile) { - return { - certificateFile: this.certFile, - keyFile: this.keyFile, - ocspStapling: this.ocspStapling, - oneTimeLoading: this.oneTimeLoading, - usage: this.usage, - }; - } else { - return { - certificate: this.cert.split('\n'), - key: this.key.split('\n'), - ocspStapling: this.ocspStapling, - oneTimeLoading: this.oneTimeLoading, - usage: this.usage, - }; - } - } -}; - -XtlsStreamSettings.Settings = class extends XrayCommonClass { - constructor(allowInsecure = false) { - super(); - this.allowInsecure = allowInsecure; - } - static fromJson(json = {}) { - return new XtlsStreamSettings.Settings( - json.allowInsecure, - ); - } - toJson() { - return { - allowInsecure: this.allowInsecure, - }; - } -}; class RealityStreamSettings extends XrayCommonClass { constructor( @@ -1071,7 +934,6 @@ class StreamSettings extends XrayCommonClass { security = 'none', externalProxy = [], tlsSettings = new TlsStreamSettings(), - xtlsSettings = new XtlsStreamSettings(), realitySettings = new RealityStreamSettings(), tcpSettings = new TcpStreamSettings(), kcpSettings = new KcpStreamSettings(), @@ -1087,7 +949,6 @@ class StreamSettings extends XrayCommonClass { this.security = security; this.externalProxy = externalProxy; this.tls = tlsSettings; - this.xtls = xtlsSettings; this.reality = realitySettings; this.tcp = tcpSettings; this.kcp = kcpSettings; @@ -1111,18 +972,6 @@ class StreamSettings extends XrayCommonClass { } } - get isXtls() { - return this.security === "xtls"; - } - - set isXtls(isXtls) { - if (isXtls) { - this.security = 'xtls'; - } else { - this.security = 'none'; - } - } - //for Reality get isReality() { return this.security === "reality"; @@ -1150,7 +999,6 @@ class StreamSettings extends XrayCommonClass { json.security, json.externalProxy, TlsStreamSettings.fromJson(json.tlsSettings), - XtlsStreamSettings.fromJson(json.xtlsSettings), RealityStreamSettings.fromJson(json.realitySettings), TcpStreamSettings.fromJson(json.tcpSettings), KcpStreamSettings.fromJson(json.kcpSettings), @@ -1170,7 +1018,6 @@ class StreamSettings extends XrayCommonClass { security: this.security, externalProxy: this.externalProxy, tlsSettings: this.isTls ? this.tls.toJson() : undefined, - xtlsSettings: this.isXtls ? this.xtls.toJson() : undefined, realitySettings: this.isReality ? this.reality.toJson() : undefined, tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined, kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined, @@ -1283,18 +1130,6 @@ class Inbound extends XrayCommonClass { } } - get xtls() { - return this.stream.security === 'xtls'; - } - - set xtls(isXtls) { - if (isXtls) { - this.stream.security = 'xtls'; - } else { - this.stream.security = 'none'; - } - } - get network() { return this.stream.network; } @@ -1349,7 +1184,6 @@ class Inbound extends XrayCommonClass { get serverName() { if (this.stream.isTls) return this.stream.tls.sni; - if (this.stream.isXtls) return this.stream.xtls.sni; if (this.stream.isReality) return this.stream.reality.serverNames; return ""; } @@ -1428,11 +1262,6 @@ class Inbound extends XrayCommonClass { return ["tcp", "http", "grpc"].includes(this.network); } - canEnableXtls() { - if (![Protocols.VLESS, Protocols.TROJAN].includes(this.protocol)) return false; - return this.network === "tcp"; - } - canEnableStream() { return [Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol); } @@ -1592,18 +1421,6 @@ class Inbound extends XrayCommonClass { } } - else if (security === 'xtls') { - params.set("security", "xtls"); - params.set("alpn", this.stream.xtls.alpn); - if (this.stream.xtls.settings.allowInsecure) { - params.set("allowInsecure", "1"); - } - if (!ObjectUtil.isEmpty(this.stream.xtls.sni)) { - params.set("sni", this.stream.xtls.sni); - } - params.set("flow", flow); - } - else if (security === 'reality') { params.set("security", "reality"); params.set("pbk", this.stream.reality.settings.publicKey); @@ -1801,18 +1618,6 @@ class Inbound extends XrayCommonClass { } } - else if (security === 'xtls') { - params.set("security", "xtls"); - params.set("alpn", this.stream.xtls.alpn); - if (this.stream.xtls.settings.allowInsecure) { - params.set("allowInsecure", "1"); - } - if (!ObjectUtil.isEmpty(this.stream.xtls.sni)) { - params.set("sni", this.stream.xtls.sni); - } - params.set("flow", flow); - } - else { params.set("security", "none"); } @@ -2273,7 +2078,6 @@ Inbound.TrojanSettings = class extends Inbound.Settings { Inbound.TrojanSettings.Trojan = class extends XrayCommonClass { constructor( password = RandomUtil.randomSeq(10), - flow = '', email = RandomUtil.randomLowerAndNum(8), limitIp = 0, totalGB = 0, @@ -2285,7 +2089,6 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass { ) { super(); this.password = password; - this.flow = flow; this.email = email; this.limitIp = limitIp; this.totalGB = totalGB; @@ -2299,7 +2102,6 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass { toJson() { return { password: this.password, - flow: this.flow, email: this.email, limitIp: this.limitIp, totalGB: this.totalGB, @@ -2314,7 +2116,6 @@ Inbound.TrojanSettings.Trojan = class extends XrayCommonClass { static fromJson(json = {}) { return new Inbound.TrojanSettings.Trojan( json.password, - json.flow, json.email, json.limitIp, json.totalGB, diff --git a/web/html/xui/client_bulk_modal.html b/web/html/xui/client_bulk_modal.html index c4e33bb162..671c55c352 100644 --- a/web/html/xui/client_bulk_modal.html +++ b/web/html/xui/client_bulk_modal.html @@ -39,12 +39,6 @@ [[ key ]] - - - {{ i18n "none" }} - [[ key ]] - - - - - diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index d10d0f3c8f..ceceabd54f 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "The IPs history log. (to enable inbound after disabling, clear the log)" "IPLimitlogclear" = "Clear The Log" "setDefaultCert" = "Set Cert from Panel" -"xtlsDesc" = "Xray must be v1.7.5" -"realityDesc" = "Xray must be v1.8.0+" "telegramDesc" = "Please provide Telegram Chat ID. (use '/id' command in the bot) or (@userinfobot)" "subscriptionDesc" = "To find your subscription URL, navigate to the 'Details'. Additionally, you can use the same name for several clients." "info" = "Info" diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml index 68797735af..b9af32725e 100644 --- a/web/translation/translate.es_ES.toml +++ b/web/translation/translate.es_ES.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "Registro de historial de IPs (antes de habilitar la entrada después de que haya sido desactivada por el límite de IP, debes borrar el registro)." "IPLimitlogclear" = "Limpiar el Registro" "setDefaultCert" = "Establecer certificado desde el panel" -"xtlsDesc" = "La versión del núcleo de Xray debe ser 1.7.5" -"realityDesc" = "La versión del núcleo de Xray debe ser 1.8.0 o superior." "telegramDesc" = "Por favor, proporciona el ID de Chat de Telegram. (usa el comando '/id' en el bot) o (@userinfobot)" "subscriptionDesc" = "Puedes encontrar tu enlace de suscripción en Detalles, también puedes usar el mismo nombre para varias configuraciones." "info" = "Info" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index cc8930289f..c7fad84e34 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "گزارش تاریخچه آی‌پی. برای فعال کردن ورودی پس از غیرفعال شدن، گزارش را پاک کنید" "IPLimitlogclear" = "پاک کردن گزارش‌ها" "setDefaultCert" = "استفاده از گواهی پنل" -"xtlsDesc" = "ایکس‌ری باید 1.7.5 باشد" -"realityDesc" = "ایکس‌ری باید +1.8.0 باشد" "telegramDesc" = "لطفا شناسه گفتگوی تلگرام را وارد کنید. (از دستور '/id' در ربات استفاده کنید) یا (@userinfobot)" "subscriptionDesc" = "شما می‌توانید لینک سابسکربپشن خودرا در 'جزئیات' پیدا کنید، همچنین می‌توانید از همین نام برای چندین کاربر استفاده‌کنید" "info" = "اطلاعات" diff --git a/web/translation/translate.id_ID.toml b/web/translation/translate.id_ID.toml index e785c26b02..85f8f967ca 100644 --- a/web/translation/translate.id_ID.toml +++ b/web/translation/translate.id_ID.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "Log histori IP. (untuk mengaktifkan masuk setelah menonaktifkan, hapus log)" "IPLimitlogclear" = "Hapus Log" "setDefaultCert" = "Atur Sertifikat dari Panel" -"xtlsDesc" = "Xray harus versi 1.7.5" -"realityDesc" = "Xray harus versi 1.8.0+" "telegramDesc" = "Harap berikan ID Obrolan Telegram. (gunakan perintah '/id' di bot) atau (@userinfobot)" "subscriptionDesc" = "Untuk menemukan URL langganan Anda, buka 'Rincian'. Selain itu, Anda dapat menggunakan nama yang sama untuk beberapa klien." "info" = "Info" diff --git a/web/translation/translate.pt_BR.toml b/web/translation/translate.pt_BR.toml index bbe2bd24cb..5effdecbd7 100644 --- a/web/translation/translate.pt_BR.toml +++ b/web/translation/translate.pt_BR.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "O histórico de IPs. (para ativar o inbound após a desativação, limpe o log)" "IPLimitlogclear" = "Limpar o Log" "setDefaultCert" = "Definir Certificado pelo Painel" -"xtlsDesc" = "O Xray deve ser v1.7.5" -"realityDesc" = "O Xray deve ser v1.8.0+" "telegramDesc" = "Por favor, forneça o ID do Chat do Telegram. (use o comando '/id' no bot) ou (@userinfobot)" "subscriptionDesc" = "Para encontrar seu URL de assinatura, navegue até 'Detalhes'. Além disso, você pode usar o mesmo nome para vários clientes." "info" = "Informações" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index c056e3ef3a..f185ca3d96 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "Лог IP-адресов (перед включением лога IP-адресов, вы должны очистить список)" "IPLimitlogclear" = "Очистить лог" "setDefaultCert" = "Установить сертификат с панели" -"xtlsDesc" = "Версия Xray должна быть не ниже 1.7.5" -"realityDesc" = "Версия Xray должна быть не ниже 1.8.0" "telegramDesc" = "Пожалуйста, укажите ID чата Telegram. (используйте команду '/id' в боте) или (@userinfobot)" "subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее', также вы можете использовать одно и то же имя для нескольких конфигураций" "info" = "Информация" diff --git a/web/translation/translate.tr_TR.toml b/web/translation/translate.tr_TR.toml index ecaf2bab2a..bee64b0f13 100644 --- a/web/translation/translate.tr_TR.toml +++ b/web/translation/translate.tr_TR.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "IP geçmiş günlüğü. (devre dışı bırakıldıktan sonra gelini etkinleştirmek için günlüğü temizleyin)" "IPLimitlogclear" = "Günlüğü Temizle" "setDefaultCert" = "Panelden Sertifikayı Ayarla" -"xtlsDesc" = "Xray v1.7.5 olmalıdır" -"realityDesc" = "Xray v1.8.0+ olmalıdır" "telegramDesc" = "Lütfen Telegram Sohbet Kimliği sağlayın. (botta '/id' komutunu kullanın) veya (@userinfobot)" "subscriptionDesc" = "Abonelik URL'inizi bulmak için 'Detaylar'a gidin. Ayrıca, aynı adı birden fazla müşteri için kullanabilirsiniz." "info" = "Bilgi" diff --git a/web/translation/translate.uk_UA.toml b/web/translation/translate.uk_UA.toml index 2e584f0e2e..791d2154e7 100644 --- a/web/translation/translate.uk_UA.toml +++ b/web/translation/translate.uk_UA.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "Журнал історії IP-адрес. (щоб увімкнути вхідну після вимкнення, очистіть журнал)" "IPLimitlogclear" = "Очистити журнал" "setDefaultCert" = "Установити сертифікат з панелі" -"xtlsDesc" = "Xray має бути v1.7.5" -"realityDesc" = "Xray має бути v1.8.0+" "telegramDesc" = "Будь ласка, вкажіть ID чату Telegram. (використовуйте команду '/id' у боті) або (@userinfobot)" "subscriptionDesc" = "Щоб знайти URL-адресу вашої підписки, перейдіть до «Деталі». Крім того, ви можете використовувати одне ім'я для кількох клієнтів." "info" = "Інформація" diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml index bb5c00f820..cd750891ab 100644 --- a/web/translation/translate.vi_VN.toml +++ b/web/translation/translate.vi_VN.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "Lịch sử đăng nhập IP (trước khi kích hoạt điểm vào sau khi bị vô hiệu hóa bởi giới hạn IP, bạn nên xóa lịch sử)." "IPLimitlogclear" = "Xóa Lịch sử" "setDefaultCert" = "Đặt chứng chỉ từ bảng điều khiển" -"xtlsDesc" = "Xray core cần phiên bản 1.7.5" -"realityDesc" = "Xray core cần phiên bản 1.8.0 hoặc cao hơn." "telegramDesc" = "Vui lòng cung cấp ID Trò chuyện Telegram. (sử dụng lệnh '/id' trong bot) hoặc (@userinfobot)" "subscriptionDesc" = "Bạn có thể tìm liên kết gói đăng ký của mình trong Chi tiết, cũng như bạn có thể sử dụng cùng tên cho nhiều cấu hình khác nhau" "info" = "Thông tin" diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml index 35062b30af..b5f5cce1ad 100644 --- a/web/translation/translate.zh_CN.toml +++ b/web/translation/translate.zh_CN.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "IP 历史日志(要启用被禁用的入站流量,请清除日志)" "IPLimitlogclear" = "清除日志" "setDefaultCert" = "从面板设置证书" -"xtlsDesc" = "Xray 核心需要 1.7.5" -"realityDesc" = "Xray 核心需要 1.8.0 及以上版本" "telegramDesc" = "请提供Telegram聊天ID。(在机器人中使用'/id'命令)或(@userinfobot" "subscriptionDesc" = "要找到你的订阅 URL,请导航到“详细信息”。此外,你可以为多个客户端使用相同的名称。" "info" = "信息" diff --git a/web/translation/translate.zh_TW.toml b/web/translation/translate.zh_TW.toml index a7382769a8..466b2b82b0 100644 --- a/web/translation/translate.zh_TW.toml +++ b/web/translation/translate.zh_TW.toml @@ -178,8 +178,6 @@ "IPLimitlogDesc" = "IP 歷史日誌(要啟用被禁用的入站流量,請清除日誌)" "IPLimitlogclear" = "清除日誌" "setDefaultCert" = "從面板設定證書" -"xtlsDesc" = "Xray 核心需要 1.7.5" -"realityDesc" = "Xray 核心需要 1.8.0 及以上版本" "telegramDesc" = "請提供Telegram聊天ID。(在機器人中使用'/id'命令)或(@userinfobot" "subscriptionDesc" = "要找到你的訂閱 URL,請導航到“詳細資訊”。此外,你可以為多個客戶端使用相同的名稱。" "info" = "資訊"