【问题标题】:How to decode URL-encoded string in shell?如何在 shell 中解码 URL 编码的字符串?
【发布时间】:2011-09-09 04:36:08
【问题描述】:

我有一个文件,其中包含已编码的用户代理列表。 例如:

Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en

我想要一个 shell 脚本,它可以读取这个文件并用解码后的字符串写入一个新文件。

Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en

我一直在尝试使用这个示例来实现它,但到目前为止它还没有工作。

$ echo -e "$(echo "%31+%32%0A%33+%34" | sed 'y/+/ /; s/%/\\x/g')"

我的脚本如下所示:

#!/bin/bash
for f in *.log; do
  echo -e "$(cat $f | sed 'y/+/ /; s/%/\x/g')" > y.log
done

【问题讨论】:

  • 第 5 行:'x' 应该被双重转义(s/%/\x/g -> s/%/\\x/g
  • 感谢您的指点。将尝试双重转义。当我从其他地方复制它时,不知道我是如何错过它的。会更新。

标签: bash shell awk sed urldecode


【解决方案1】:

正如@barti_ddu 在 cmets 中所说,\x“应该被[双重]转义”。

% echo -e "$(echo "Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en" | sed 'y/+/ /; s/%/\\x/g')"
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en

我不会把 Bash 和 sed 混在一起,而是用 Python 来完成。这是一个粗略的方法:

#!/usr/bin/env python

import glob
import os
import urllib

for logfile in glob.glob(os.path.join('.', '*.log')):
    with open(logfile) as current:
        new_log_filename = logfile + '.new'
        with open(new_log_filename, 'w') as new_log_file:
            for url in current:
                unquoted = urllib.unquote(url.strip())
                new_log_file.write(unquoted + '\n')

【讨论】:

  • 感谢脚本。如果失败,将再给 sed 版本一次并采用 python 路线。我在某处读到 sed 方法更快。真的吗。我将每小时处理几 GB 大小的文件,并且可以利用所有优势。
  • @user785717:希望这对你有用。我不知道哪个会在您的数据上表现更好。 time 是你的朋友。
【解决方案2】:

这似乎对我有用。

#!/bin/bash
urldecode(){
  echo -e "$(sed 's/+/ /g;s/%\(..\)/\\x\1/g;')"
}

for f in /opt/logs/*.log; do
    name=${f##/*/}
    cat $f | urldecode > /opt/logs/processed/$HOSTNAME.$name
done

用空格替换 '+',用 '\x' 转义符替换 % 符号,并让 echo 使用 '-e' 选项解释 \x 转义符不起作用。出于某种原因,cat 命令将 % 符号打印为它自己的编码形式 %25。所以 sed 只是简单地将 %25 替换为 \x25。当使用 -e 选项时,它只是将 \x25 评估为 % 并且输出与原始相同。

追踪:

原文: Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en

sed: Mozilla\x252F5.0\x2520\x2528Macintosh\x253B\x2520U\x253B\x2520Intel\x2520Mac\x2520OS\x2520X\x252010.6\x253B\x2520en

echo -e: Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en

修复:基本忽略sed中%后面的2个字符。

sed: Mozilla\x2F5.0\x20\x28Macintosh\x3B\x20U\x3B\x20Intel\x20Mac\x20OS\x20X\x2010.6\x3B\x20en

echo -e: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en

经过大量测试后,不确定这会导致什么并发症,但目前可行。

【讨论】:

  • 有效,但在\\x 之后应该有一个\1,例如echo -e "$(sed 's/+/ /g;s/%\(..\)/\\x\1/g;')"
  • 正如@svante 所写,\1 不见了。我已经编辑了答案以包含它。 (加上一些小的格式/语法更改,以满足 6 个字符的最小编辑要求。)
  • 对我来说最好的答案。简单,从 STDIN 获取输入,不使用特殊工具。
  • 对于 POSIX 兼容版本,请使用 printf '%b\n' 而不是 echo -e
【解决方案3】:

在本机 Bash 中执行此操作的 Bash 脚本 (original source):

LANG=C

urlencode() {
    local l=${#1}
    for (( i = 0 ; i < l ; i++ )); do
        local c=${1:i:1}
        case "$c" in
            [a-zA-Z0-9.~_-]) printf "$c" ;;
            ' ') printf + ;;
            *) printf '%%%.2X' "'$c"
        esac
    done
}

urldecode() {
    local data=${1//+/ }
    printf '%b' "${data//%/\x}"
}

如果要对文件内容进行urldecode,只需将文件内容作为参数。

这是一个测试,如果解码后的编码文件内容不同(如果它运行几秒钟,脚本可能正常工作),它将停止运行:

while true
  do cat /dev/urandom | tr -d '\0' | head -c1000 > /tmp/tmp;
     A="$(cat /tmp/tmp; printf x)"
     A=${A%x}
     A=$(urlencode "$A")
     urldecode "$A" > /tmp/tmp2
     cmp /tmp/tmp /tmp/tmp2
     if [ $? != 0 ]
       then break
     fi
done

【讨论】:

  • 请注意,您的 urldecode 假定数据不包含反斜杠。
  • @StephaneChazelas:我认为正确的 % 编码字符串中不允许使用反斜杠
【解决方案4】:

如果你的服务器上安装了 php,你可以“cat”甚至“tail”任何文件,使用 url 编码的字符串非常容易。

tail -f nginx.access.log | php -R 'echo urldecode($argn)."\n";'

【讨论】:

【解决方案5】:

如果您是 python 开发人员,这可能更可取:

对于 Python 3.x(默认):

echo -n "%21%20" | python3 -c "import sys; from urllib.parse import unquote; print(unquote(sys.stdin.read()));"

对于 Python 2.x(已弃用):

echo -n "%21%20" | python -c "import sys, urllib as ul; print ul.unquote(sys.stdin.read());"

urllib 非常擅长处理 URL 解析

【讨论】:

  • 很好,但我会稍作改动以使用 argv 并使用 is 作为别名。下面是一个编码示例: alias encode='python2 -c "import sys, urllib as ul; print ul.quote(sys.argv[1]);"'
  • 针对 python 3 修改:echo "%21%20" | python -c "import sys; from urllib.parse import unquote; print(unquote(sys.stdin.read()));"
  • 如果要将+转为空白,对于python2,可以使用unquote_plus()
  • 与所有其他解决方案不同,这在交互式 shell 中很实用
  • function urldecode() { python -c "import sys; from urllib.parse import unquote; print(unquote(sys.argv[1]));" $1 }
【解决方案6】:

这是一个在纯 bash 中完成的解决方案,其中输入和输出是 bash 变量。它将“+”解码为空格并处理“%20”空格以及其他 % 编码的字符。

#!/bin/bash
#here is text that contains both '+' for spaces and a %20
text="hello+space+1%202"
decoded=$(echo -e `echo $text | sed 's/+/ /g;s/%/\\\\x/g;'`)
echo decoded=$decoded

【讨论】:

  • sed 不是纯 Bash;这会产生另一个进程。
【解决方案7】:
perl -pi.back -e 'y/+/ /;s/%([\da-f]{2})/pack H2,$1/gie' ./*.log

使用-i 就地更新文件(一些sed 实现从perl 借用了该文件),.back 作为备份扩展名。

s/x/y/ex 替换为y perl 代码的e值。

本例中的 perl 代码使用pack$1(正则表达式中的第一个括号对)中捕获的十六进制数打包为相应的字符。

pack 的替代方法是使用chr(hex($1))

perl -pi.back -e 'y/+/ /;s/%([\da-f]{2})/chr hex $1/gie' ./*.log

如果可用,您也可以使用来自URI::Escapeuri_unescape()

perl -pi.back -MURI::Escape -e 'y/+/ /;$_=uri_unescape$_' ./*.log

【讨论】:

  • 这个例子再多解释几句就更好了。
【解决方案8】:

使用 GNU awk:

LC_ALL=C gawk -vRS='%[[:xdigit:]]{2}' '
  RT {RT = sprintf("%c",strtonum("0x" substr(RT, 2)))}
  {gsub(/\+/," ");printf "%s", $0 RT}'

将在标准输入上采用 URI 编码并在标准输出上打印解码输出。

我们将记录分隔符设置为匹配%XX 序列的正则表达式。在 GNU awk 中,匹配它的输入存储在 RT 特殊变量中。我们从那里提取十六进制数字,附加到“0x”以将strnum() 转换为一个数字,然后传递给sprintf("%c"),在C 语言环境中它将转换为相应的字节值。

【讨论】:

    【解决方案9】:

    只是想分享这个其他解决方案,纯 bash:

    encoded_string="Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en"
    printf -v encoded_string "%b" "${encoded_string//\%/\x}"
    echo $encoded_string
    

    【讨论】:

      【解决方案10】:

      Python 答案的略微修改版本,它在单行中接受输入和输出文件。

      cat inputfile.txt | python -c "import sys, urllib as ul; print ul.unquote(sys.stdin.read());" > ouputfile.txt
      

      【讨论】:

        【解决方案11】:
        $ uenc='H%C3%B6he %C3%BCber%20dem%20Meeresspiegel'
        $ utf8=$(printf "${uenc//%/\\x}")
        $ echo $utf8
        Höhe über dem Meeresspiegel
        $
        

        【讨论】:

        • 虽然此代码可能会回答问题,但提供有关 why 和/或 如何 回答问题的额外上下文将显着改善其长期价值。请edit你的答案添加一些解释。
        【解决方案12】:
        $ uenc='H%C3%B6he %C3%BCber%20dem%20Meeresspiegel'
        $ utf8=$(echo -e "${uenc//%/\\x}")
        $ echo $utf8
        Höhe über dem Meeresspiegel
        $
        

        【讨论】:

        • 虽然此代码可能会回答问题,但提供有关 why 和/或 如何 回答问题的额外上下文将显着改善其长期价值。请edit你的答案添加一些解释。
        【解决方案13】:

        这是一个简单的单行解决方案。

        $ function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
        

        它可能看起来像 perl :) 但它只是纯粹的 bash。没有 awks,没有 seds ......没有开销。使用 : 内置、特殊参数、模式替换和内置 echo 的 -e 选项将十六进制代码转换为字符。有关详细信息,请参阅 bash 的联机帮助页。您可以将此功能用作单独的命令

        $ urldecode https%3A%2F%2Fgoogle.com%2Fsearch%3Fq%3Durldecode%2Bbash
        https://google.com/search?q=urldecode+bash
        

        或者在变量赋值中,像这样:

        $ x="http%3A%2F%2Fstackoverflow.com%2Fsearch%3Fq%3Durldecode%2Bbash"
        $ y=$(urldecode "$x")
        $ echo "$y"
        http://stackoverflow.com/search?q=urldecode+bash
        

        【讨论】:

        • 您的示例不起作用:` 第 3 行:urldecode: command not found`
        • 希望有更多关于模式替换的解释。这个函数对我有用,但它会改变字符,使文件路径不能与解压缩函数一起使用。
        • @JustinPutney ${*//+/ } 将替换 all + 为空格,${_//%/\\x} 将替换 all %\x
        • 只想提一下这对我来说太慢了;对于 50k url,bash: 0m3.767s python: 0m0.200s(python 下一行:stackoverflow.com/a/21693459/1695680
        • @nhed – : is 在 bash 中是一个空操作,但是这段代码使用了 $_ 的值,它“扩展到之前的简单命令”(也就是说这是一个 perl 级别的混淆)。 urldecode() { local i="${*//+/ }"; echo -e "${i//%/\\x}"; } 会更易读(将每个 + 替换为空格,然后将每个 % 替换为 \x 以便 bash 知道正确解释转义序列)。
        【解决方案14】:

        使用 BASH,从标准输入中读取百分比编码的 URL 并进行解码:

        while read; do echo -e ${REPLY//%/\\x}; done
        

        CTRL-D 表示文件结束(EOF)并优雅退出。

        您可以通过将文件设置为标准来解码文件的内容:

        while read; do echo -e ${REPLY//%/\\x}; done < file
        

        您也可以对来自管道的输入进行解码,例如:

        echo 'a%21b' | while read; do echo -e ${REPLY//%/\\x}; done
        
        • 内置命令读取标准输入,直到看到换行符。它设置一个名为REPLY 的变量等于它刚刚读取的文本行。
        • ${REPLY//%/\\x} 将 '%' 的所有实例替换为 '\x'。
        • echo -e\xNN 解释为十六进制值为NN 的ASCII 字符。
        • while 重复此循环,直到读取命令失败,例如。已达到 EOF。

        以上内容不会将'+'更改为''。也将 '+' 更改为 ' ',例如来宾的 answer

        while read; do : "${REPLY//%/\\x}"; echo -e ${_//+/ }; done
        
        • : 是 BASH 内置命令。在这里,它只接受一个参数,不做任何事情。
        • 双引号将所有内容都包含在一个参数中。
        • _ 是一个特殊参数,在参数扩展之后等于上一个命令的最后一个参数。这是 REPLY 的值,所有 '%' 实例都替换为 '\x'。
        • ${_//+/ } 将所有 '+' 实例替换为 ' '。

        这仅使用 BASH,不会启动任何其他进程,类似于客人的回答。

        【讨论】:

        • + 到 SPACE 的解码应该发生在百分比解码之前。有关正确顺序的示例,请参见客人的回答。
        • : "${REPLY//%/\\x}"; echo -e ${_//+/ } 此处的顺序是将% 替换为\x,将+ 替换为' ',使用\xNN 符号解释字符。为什么你认为先替换 % 个字符还是 + 个字符 @RobinA.Meade 很重要?
        • 你是对的,对不起。我现在看到您的答案确实在评估 \xNN 之前将 + 替换为 SPACE。我的测试字符串是The time is 2013-12-31T14:00:00+00:00,我在meyerweb.com/eric/tools/dencoder 编码。您的答案正确地使用保留的时间戳中的+ 对其进行解码。
        【解决方案15】:

        扩展到 https://stackoverflow.com/a/37840948/8142470
        使用 HTML 实体

        $ htmldecode() { : "${*//+/ }"; echo -e "${_///\x}" | tr -d ';'; }
        $ html解码 “http://google.com/搜索&?q=urldecode+bash”http://google.com/search&?q=urldecode+bash

        (参数必须被引用)

        【讨论】:

          【解决方案16】:

          更新Jay's Python 3.5+ 的答案:
          echo "%31+%32%0A%33+%34" | python -c "import sys; from urllib.parse import unquote ; print(unquote(sys.stdin.read()))"

          不过,brendan's 带有解释的 bash 解决方案似乎更直接和优雅。

          【讨论】:

            【解决方案17】:

            在其他一些答案的基础上,但对于 POSIX 世界,可以使用以下函数:

            url_decode() {
                printf '%b\n' "$(sed -E -e 's/\+/ /g' -e 's/%([0-9a-fA-F]{2})/\\x\1/g')"
            }
            

            它使用printf '%b\n',因为没有echo -e,并中断了sed 调用以使其更易于阅读,从而强制-E 能够使用\1 的引用。它还强制% 后面的内容看起来像一些十六进制代码。

            【讨论】:

              【解决方案18】:

              使用zsh shell(而不是bash),唯一的shell 其变量可以保存任何字节值,包括NUL(编码为%00):

              set -o extendedglob +o multibyte
              string='Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en'
              decoded=${${string//+/ }//(#b)%([[:xdigit:]](#c2))/${(#):-0x$match[1]}}
              
              • ${var//pattern/replacement}:ksh 样式的参数扩展运算符,用于扩展为 $var 的值,并将每个匹配 pattern 的字符串替换为 replacement
              • (#b) 激活反向引用,因此模式中括号内的每个部分都可以作为替换中对应的 $match[n] 访问。
              • (#c2):相当于 ERE {2}
              • ${(#)param-expansion}:参数扩展,其中# 标志导致结果被解释为算术表达式并返回相应的字节值。
              • ${var:-value}:如果$var 为空,则扩展为value,此处根本不应用于任何变量,因此我们可以指定任意字符串作为参数扩展的主题。

              要使其成为就地解码变量内容的函数:

              uridecode_var() {
                emulate -L zsh
                set -o extendedglob +o multibyte
                eval $1='${${'$1'//+/ }//(#b)%([[:xdigit:]](#c2))/${(#):-0x$match[1]}}'
              }
              
              $ string='Mozilla%2F5.0%20%28Macintosh%3B%20U%3B%20Intel%20Mac%20OS%20X%2010.6%3B%20en'
              $ uridecode_var string
              $ print -r -- $string
              Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en
              

              【讨论】:

                【解决方案19】:

                使用 sed:

                #!/bin/bash
                URL_DECODE="$(echo "$1" | sed -E 's/%([0-9a-fA-F]{2})/\\x\1/g;s/\+/ /g'"
                echo -e "$URL_DECODE"
                
                • s/%([0-9a-fA-F]{2})/\\x\1/g 将 % 替换为 \x 以将 urlencoded 转换为十六进制
                • s/\+/ /g 将 + 替换为空格 ' ',以防在查询字符串中使用 +

                只需将其保存到decodeurl.sh 并使用chmod +x decodeurl.sh 使其可执行

                如果您也需要一种编码方式,此完整代码将有所帮助:

                #!/bin/bash
                #
                # Enconding e Decoding de URL com sed
                #
                # Por Daniel Cambría
                # daniel.cambria@bureau-it.com
                #
                # jul/2021
                
                function url_decode() {
                echo "$@" \
                    | sed -E 's/%([0-9a-fA-F]{2})/\\x\1/g;s/\+/ /g'
                }
                
                function url_encode() {
                    # Conforme RFC 3986
                    echo "$@" \
                    | sed \
                    -e 's/ /%20/g' \
                    -e 's/:/%3A/g' \
                    -e 's/,/%2C/g' \
                    -e 's/\?/%3F/g' \
                    -e 's/#/%23/g' \
                    -e 's/\[/%5B/g' \
                    -e 's/\]/%5D/g' \
                    -e 's/@/%40/g' \
                    -e 's/!/%41/g' \
                    -e 's/\$/%24/g' \
                    -e 's/&/%26/g' \
                    -e "s/'/%27/g" \
                    -e 's/(/%28/g' \
                    -e 's/)/%29/g' \
                    -e 's/\*/%2A/g' \
                    -e 's/\+/%2B/g' \
                    -e 's/,/%2C/g' \
                    -e 's/;/%3B/g' \
                    -e 's/=/%3D/g'
                }
                
                echo -e "URL decode: " $(url_decode "$1")
                echo -e "URL encode: " $(url_encode "$1")
                

                【讨论】:

                  【解决方案20】:

                  python,用于 zshrc

                  # Usage: decodeUrl %3A%2F%2F
                  function decodeUrl(){
                      echo "$1" | python3 -c "import sys; from urllib.parse import unquote; print(unquote(sys.stdin.read()));"    
                  }
                  
                  # Usage: encodeUrl https://google.com/search?q=urldecode+bash
                  #          return: https://google.com/search\?q\=urldecode+bash
                  function encodeUrl(){
                      echo "$1" | python3 -c "import sys; from urllib.parse import quote; print(quote(sys.stdin.read()));"
                  }
                  

                  【讨论】:

                    【解决方案21】:

                    用于 url 解码的 bash 成语

                    这是一个 bash 习惯用法,用于对变量 x 中保存的字符串进行 url 解码并将结果分配给变量 y

                    : "${x//+/ }"; printf -v y '%b' "${_//%/\\x}"
                    

                    与接受的答案不同,它在分配期间保留尾随换行符。 (尝试将 url 解码的结果 v%0A%0A%0A 分配给变量。)

                    它也很快。将 url 解码的结果分配给变量比接受的答案快 6700%

                    警告:bash 变量不可能包含 NUL。例如,任何尝试解码 %00 并将结果分配给变量的 bash 解决方案都将不起作用。

                    基准详情

                    函数.sh

                    #!/bin/bash
                    urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
                    x=%21%20
                    for (( i=0; i<5000; i++ )); do
                      y=$(urldecode "$x")
                    done
                    

                    idiom.sh

                    #!/bin/bash
                    x=%21%20
                    for (( i=0; i<5000; i++ )); do
                      : "${x//+/ }"; printf -v y '%b' "${_//%/\\x}"
                    done
                    
                    $ hyperfine --warmup 5 ./function.sh ./idiom.sh
                    Benchmark #1: ./function.sh
                      Time (mean ± σ):      2.844 s ±  0.036 s    [User: 1.728 s, System: 1.494 s]
                      Range (min … max):    2.801 s …  2.907 s    10 runs
                     
                    Benchmark #2: ./idiom.sh
                      Time (mean ± σ):      42.4 ms ±   1.0 ms    [User: 40.7 ms, System: 1.1 ms]
                      Range (min … max):    40.5 ms …  44.8 ms    64 runs
                     
                    Summary
                      './idiom.sh' ran
                       67.06 ± 1.76 times faster than './function.sh'
                    

                    如果你真的想要一个函数...

                    如果你真的想要一个函数,比如出于可读性的原因,我建议如下:

                    # urldecode [-v var ] argument
                    #
                    #   Urldecode the argument and print the result.
                    #   It replaces '+' with SPACE and then percent decodes.
                    #   The output is consistent with https://meyerweb.com/eric/tools/dencoder/
                    #
                    # Options:
                    #   -v var    assign the output to shell variable VAR rather than
                    #             print it to standard output
                    #
                    urldecode() {
                      local assign_to_var=
                      local OPTIND opt
                      while getopts ':v:' opt; do
                        case $opt in
                          v)
                            local var=$OPTARG
                            assign_to_var=Y
                            ;;
                          \?)
                            echo "$FUNCNAME: error: -$OPTARG: invalid option" >&2
                            exit 1
                            ;;
                          :)
                            echo "$FUNCNAME: error: -$OPTARG: this option requires an argument" >&2
                            exit 1
                            ;;
                          *)
                            echo "$FUNCNAME: error: an unexpected execution path has occurred." >&2
                            exit 1
                            ;;
                        esac
                      done
                      shift "$((OPTIND - 1))"
                      if [[ $assign_to_var ]]; then
                        : "${1//+/ }"; printf -v "$var" %b "${_//%/\\x}"
                      else
                        : "${1//+/ }"; printf %b "${_//%/\\x}"
                      fi
                    }
                    

                    将解码结果赋值给shell变量的例子:

                    x='v%0A%0A%0A'
                    urldecode -v y "$x"
                    echo -n "$y" | od -An -tx1
                    

                    结果:

                     76 0a 0a 0a
                    

                    这个函数虽然没有上面的习语那么快,但由于不涉及子shell,在做作业时仍然比接受的答案快 1300%。此外,如示例输出所示,由于不涉及命令替换,它保留了尾随换行符。

                    【讨论】:

                    • 不错!考虑urldecode() { local -n var=$1;shift;: "${*//+/ }"; printf -v var %b "${_//%/\\x}"; }
                    • @F.Hauri 您的函数完成了有效分配给 shell 变量的工作。好的!我在printf -v var ... 之后建模了我的函数,以提供打印到标准输出或分配给var 的灵活性,但确实通常不需要这种灵活性。
                    • 或者这个:urldecode() { local ret=($'\n');: "${1//+/ }";printf ${2+-v} $2 %b%s "${_//%/\\x}" "${ret[$#-1]}";}。如果您必须引用(或双引号)URL,那么 optional 第二个参数是 varname 如果提交。 (如果不是,解码后的 url 将被打印出来一个换行符。)
                    • @F.Hauri 这很聪明!是的,这是我提供的功能的一个很好的替代方案。两者都为用户提供了分配给变量或打印到标准输出的灵活性。
                    猜你喜欢
                    • 1970-01-01
                    • 2016-01-13
                    • 2011-03-14
                    • 2023-04-11
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-03-22
                    • 1970-01-01
                    相关资源
                    最近更新 更多