当前位置:   article > 正文

从零开始搭建Cydia软件源+制作deb安装包_cydia源搭建源码

cydia源搭建源码
Cydia中的软件源地址保存在 /etc/apt/sources.list.d/ 目录下,分为两种:
1. 以软件包形式安装的软件源,如Cydia默认的软件源,Modmyi、BigBoss等,该类软件源是以独立的.list文件记录软件源地址。
2. 由用户在Cydia里输入地址添加的软件源,该类软件源全部保存在 cydia.list中。

以上两种形式的软件源本质没有差别,但只软件源的文件存放位置上是有不同的。
以Saurik自己的软件源为例。打开 saurik.list文件, 可以看到有以下内容 (以#开头的行属于注释,没有实际用途)
引用
deb http://apt.saurik.com/ tangelo-3.7 main


那么,软件源的 Release 文件的地址是 http://apt.saurik.com/dists/tangelo-3.7/Release
Cydia就是通过或许Release文件进而检测软件源的存在,然后再下载记录软件包相关信息的 Packages 文件。

而对于在Cydia中输入软件源地址进行添加的这种源,方法有些不同。因为默认情况下,输入地址以后,Cydia会认为Release文件存放于输入的地址所在的目录下。在list文件中的记录信息为:
引用

并不会继续往子目录里检测Release文件。

因此,搭建Cydia软件源首先需要配置服务器上相关目录和文件的存放位置。

取决于软件源的添加方式,文件/目录的路径设置可以分为以下两种情况:

1.  只公布软件源的地址,让用户手动输入地址来添加。这种方式的文件/目录设置最为简单。
以威锋源为例,威锋源的地址为 http://app.weiphone.com/cydia
那么在郁闷app.weiphone.com下,存在目录cydia。目录cydia即使软件源所在的目录。
将文件Release放置在cydia目录下即完成了软件源的搭建。
要注意,搭建软件源,必须保证至少有Release和Packages两个文件。

2. 以软件包的形式安装,即直接在 /etc/apt/source.list.d/ 目录以文件的形式添加,那么这个就没有什么固定的位置了。
基本上仿照Saurik和BigBoss的list文件的格式即可。
list文件格式:
复制代码
  1. # do not edit this file to add your own custom sources
  2. # this file is subject to be upgraded as part of a package
  3. # either add your own .list file to /etc/apt/sources.list.d
  4. # or add your entry to the global /etc/apt/sources.list file

  5. deb 软件源地址 项目名 类型

文件名任意

其中,Release文件应放置于 软件源地址/项目名/ 这个目录下,Packages文件放置位置由Release文件来决定(详情见后文)。

之前提到过,搭建软件源必须要有Release和Packages两个文件。前者的作用是记录软件源本身的相关信息,而后者的作用则是记录具体软件包的存放位置和安装信息等数据。

以下是Release文件的格式:
引用
Origin: BigBoss
Label: BigBoss
Suite: stable
Version: 1.0
Codename: BigBoss
Support: http://cydia.saurik.com/support/*
Architectures: darwin-arm iphoneos-arm
Components: main
Description: Apps & Themes! We host your apps. Email me.
MD5Sum:
be8806290d5904cdf45b542706f6a3ad 165020 main/binary-darwin-arm/Packages
  03026ac993187b0eecae50466f64fb3c 35049 main/binary-darwin-arm/Packages.gz
  93091f5ca485e066d5fc32ca1327830c 3031061 main/binary-iphoneos-arm/Packages
  d7aec18dee5b627339b77a9d91e3f92f 368222 main/binary-iphoneos-arm/Packages.bz2

其中红字部分是必填内容,紫色部分是可选内容。

每项的作用:
引用

必须
Origin: 软件源名称,可以使用中文(Cydia的软件源列表中显示的标题)
Label:  同上,也可以使用中文
Suite: 软件源的类型,比如正式源,测试源等,可以分别用stable, beta, unstable等来表示,一般填 stable就可以了
Version: 版本号,这个其实不重要,随便填,一般都是写1.0
Codename: 代码代号,比如BigBoss的就写BigBoss,威锋的就写WeiPhone,也没什么限制,只能用英文
Architectures: 结构。iPhone平台统一写 iphoneos-arm
Components: main
Description: 软件介绍,可以使用中文和html代码,具体能使用哪些代码在下面会介绍。
可选
Support: 支持,没什么作用,除非特别需要,否则可以不要这个。
MD5Sum: 不是必须的,但如果Packages文件位置不与Release文件在同一目录下,则必须有此项。另外,如果需要签名Release文件,也必须有这个。关于MD5Sum的格式,在下文也会介绍。


Description格式
显示在Cydia中每个软件页面最下方。
不能直接换行,如果要实现显示换行显示,可以使用<br>代码。
要加粗显示,可以使用<strong></strong>代码
可以使用html代码设置字体颜色。
不能使用超链接代码。

代码: Description: WeiPhone-威锋网为您提供iPhone所需软件/补丁。<br><br>联系我们: <strong>weip.com@ gmail.com</strong>
实际显示效果如下:

MD5Sum格式
MD5Sum是用来记录Packages即相关文件的文件大小,存放路径和MD5值。

MD5Sum: 之后另起一行,开头要空一格(论坛里用quote或code代码之后都不显示开头的空格)

每行格式是:
空格+文件MD5值+空格+文件大小(以字节为单位)+文件路径 (全部没有+)

而文件路径的格式则有文件存放位置来决定。

如果是没有设置Release文件的路径,那么Release和Packages同在根目录,则路径为 Packages,直接就是文件名,没有其它路径。

如果在之前设置了Release文件的路径,如Saurik和BigBoss,那么Packages 的路径为 main/binary-iphoneos-arm/Packages,起始文件夹,即main,要与Release文件同在一个目录下。main和binary-iphoneos-arm要与Releases中的对应信息相匹配。

对于Packages.gz和Packages.bz2,格式相同,也记得要另起一行。

因此,Packages文件的保存位置就是 软件源地址/dists/main/Codename(与Release文件中一致)/main/binary-iphoneos-arm下。


Release文件的示例可以参看以下几个地址:
http://app.weiphone.com/cydia/Release
http://apt.saurik.com/dists/tangelo-3.7/Release
http://apt.bigboss.us.com/repofiles/cydia/dists/stable/Release




以下是生成Packages文件的方法:
Packages文件格式
复制代码
  1. Package: 3proxy
  2. Version: 0.5.3k-2
  3. Architecture: iphoneos-arm
  4. Maintainer: Jay Freeman (saurik) <>
  5. Installed-Size: 1208
  6. Filename: debs/3proxy_0.5.3k-2_iphoneos-arm.deb
  7. Size: 416318
  8. MD5sum: f84cb6764a9df30ab326c17f51de15fd
  9. Section: Networking
  10. Priority: optional
  11. Homepage: http://3proxy.ru/download/
  12. Description: tiny free proxy server
  13. Name: 3proxy
  14. Depiction: http://cydia.saurik.com/info/3proxy/
  15. Tag: purpose::daemon, role::hacker



Packages实质上是deb文件的control信息集合,另外多了deb文件本身的信息。(control文件是记录软件包本身的信息,但没有deb文件本身)

多出的deb文件信息为:
  • Filename(deb文件位置与文件名)
  • Size(deb文件大小,字节为单位)
  • MD5sum(deb文件MD5值)

要保证Cydia能正确获取deb的相关数据,除了以上3个deb文件信息以为,还必须保证至少有以下两项:
  • Package(软件标识符,相当于身份证号码,用于识别唯一的软件)
  • Version(软件版本号)


这里重点关注的是Filename。Filename项决定了在服务器上deb文件的存放位置。如果没有上级目录,即deb文件和Packages文件处于同一目录,那么只需要一个单独的文件名就可以了,不需要加上目录名,即xxxx.deb。但这样在软件数量多的时候会导致管理上的混乱。
假设deb文件存放在debs目录下,那么Filename就应该是 debs/xxx.deb 这样的格式。


其余项会在二楼deb制作教程中介绍。


一个软件包的全部信息在Packages文件中是以连续的一段存在,每一行是不同的信息。不同软件之间以空行做分隔。

如何生成Packages文件

方法一:
引用

环境:任何支持dpkg命令的unix系统

工具:dpkg及相关组件。
  • iPhone OS(已越狱):自带dpkg-deb命令,无dpkg-scanpackages命令
  • Debian/Ubuntu:自带dpkg-deb和dpkg-scanpackages命令
  • Fedora: 无dpkg相关命令
  • Mac OS X:无任何dpkg相关命令
  • Windows:非unix系统,无dpkg相关命令



以上系统中,Fedora不支持dpkg,也无法通过安装系统组件来支持dpkg,因此Fedora系统不能用于生成Packages文件。

而对于Mac OS X系统,本身虽然不支持dpkg,但可以通过安装一个叫 Fink 的软件来获得dpkg命令。
Fink 下载页面: http://www.finkproject.org/download/
如何安装请见官网说明。

对于Windows系统,可以通过安装 Cygwin + dpkg 来获取dpkg命令。
Cygwin下载地址: http://www.cygwin.com/setup.exe
dpkg命令可以直接在Cygwin中获取。
但个人不推荐在Windows下使用dpkg,因为Cygwin体积很大,与其安装这个,还不如直接安装个Ubuntu来的简单。


各个系统下生成Packages的方法基本一样。

最简单的方法是利用dpkg-scanpackages命令来制作Packages文件。

iPhone OS 不适用(因为没有这个命令)


  1. 将需要发布的deb文件放在一个目录,比如说debs下
  2. 命令行里进入到debs目录的上级目录
  3. 执行命令
    复制代码
    1. dpkg-scanpackages debs > Packages
    ,其中debs为deb存放目录。运行该命令可能需要root权限,可以使用root帐户登录,login root 或 su root 或使用sudo
  4. Packages存放于当前目录


如图所示

如果指定的文件夹不存在,则提示  dpkg-scanpackages: error: Binary dir ebs not found
如果在指定的文件夹内没有deb文件,则提示 Wrote 0 entries to output Packages file.

注意:Debian/Ubuntu系统下的dpkg-scanpackages命令不会输出Name,Author,Sponsor,Depiction等信息不会自动添加进去,所以需要手动加入这些数据。Mac OS X下无此问题。

以dpkg-scanpackages命令来生成Packages文件有一个很大的限制,就是必须保留全部要发布的和已经发布的deb文件,在deb数量多的情况下会浪费大量磁盘空间。

因此可以使用改进命令:
复制代码
  1. dpkg-scanpackages debs >> Packages
,这样不会每次都重新生成Packages文件,而是将debs目录下的deb信息添加到已有的Packages文件末尾。在新增软件的时候没什么问题,但如果是软件更新,那么就会出现重复条目的问题,这时候需要手动删除旧的软件包信息。

方法二
引用

上面的方法里也提到过,可以直接编辑Packages文件,因此用文本编辑器将相关数据写入Packages也是可以的,只是这样工作量会比较大,但这种方法没有系统的限制,任何系统下,不管有没有dpkg相关命令都可以使用。格式也是一样的,每项之间只要把Packages放在第一个就可以了,其余项没有顺序要求。

由于绝大部分数据可以从control里直接复制,需要自己获取的就只有Filename,Size和MD5sum。

在Unix系统下,包括Mac OS X和Linux,以及iPhone OS,获取文件大小可以使用命令 ls -l ;获取MD5值可以使用命令 md5sum

另外,在Windows下要解包deb文件可以使用7-zip,control 文件位于 control.tar.gz 下

方法三 (2010/03/23更新scandebs脚本)
引用

生成Packages和Release文件只是最基础的步骤,实际还需要压缩Packages文件,有时候还需要签名Release文件,为了简化操作,我自己写了一个脚本,具有以下功能:

  • 自动从服务器上获取 Packages 文件,不需要每次都事先准备
  • 自动生成Release文件
  • 自动生成Packages,Packages.bz2和Packages.gz
  • 在生成Packages文件之后无需保留deb文件
  • 保留control里的全部信息
  • 不会出现重复条目
  • 自动签名Release文件


http://app.weiphone.com/files/scandebs.tar.gz

更新记录 (8/11 v1.3):
        1. 修正grep命令精确匹配问题
        2. 若不存在debs目录或debs目录下无deb文件,退出
        3. 现在可以在Linux和BSD(iPhone和Mac)系统下使用了
        4. 其它优化

更新记录 (5/13 v1.2):
        1. 针对mac系统下无md5sum命令的问题,用openssl md5 FILE来获取文件MD5值
        2. 规范control文件格式(强制将Package项放在第一行)
        3. 完全自动模式,无需用户在签名Release时输入密码(需自行修改一下脚本,方法见下文)

更新记录 (3/23 v1.1):
        1. 修正了Release中Packages.gz项的拼写错误
        2. 增加参数功能,可以显示帮助,版本号,自选是否签名Release
        3. 每次生成Packages时会按Package标识排序


使用之前需要先修改下脚本(只需修改一次即可)【因为更新过,所以图片所示的行数已不匹配了,但是内容基本还是一样的。】
  1. 第46行,将wget后的地址改为自己源的Packages的地址
    另外,因为iPhone OS本身没有wget这个命令,可以去Cydia安装一个wget。使用此命令需要联网,否则请事先准备好Packages文件。
  2. 第132,136,140这三行,将Packages,Packages.bz2和Packages.gz根据需要自己修改(如果需要指定这几个文件的存放位置)
  3. 第151-158行,引号内的内容根据需要自己来修改(此部分用于生成Release文件)  
  4. 第166行,引号内的内容修改为自己的私匙的用户名和密码  
  5. Ubuntu 用户请注意Ubuntu下的 GPG 默认开启了use-agent功能,所以在签名Release的时候会弹出一个提示框,而这个提示框根本就没用,所以要禁用。
  6. 禁用方法:打开 ~/.gnupg/gpg.conf (~表示当前用户)或者直接用命令
    复制代码
    1. gedit ~/.gnupg/gpg.conf
    搜索 use-agent,将其注释掉(即修改为 #use-agent)



使用方法:
  1. 将scandebs文件放置在任意位置
  2. 准备debs文件夹,需在scandebs同级目录下
  3. 将要更新的deb文件放置在debs目录下
  4. 【可选】将Packages文件放置在scandebs同级目录下(如果需要修改Packages文件中的已有数据)
  5. 以命令 sh scandebs + 参数 来执行脚本;或 将文件属性设为0755,命令 chmod 0755 scandebs,之后可以直接使用命令 ./scandebs + 参数
  6. 【可选】如果提示要你输入签名Release文件的密码,输入之
  7. 得到Packages,Packages.bz2,Packages.gz,Release和Release.gpg【可选】这5或4个文件



显示帮助
复制代码
  1. ./scandebs -h
  2. ./scandebs --help


显示版本号
复制代码
  1. ./scandebs -v
  2. ./scandebs --version


不签名Release(无参数)
复制代码
  1. ./scandebs


使用签名Release功能
复制代码
  1. ./scandebs -s
  2. ./scandebs --sign



手动修改Packages注意事项
引用

前面说过,Packages文件可以手动编辑,有时候仅仅需要更改一些字段的内容,如果因为这个要重新打包deb,不一定合算,因此手动编辑Packages可以省下一些工作量。以下是一些注意事项:
  • 以下字段不可修改:Package,Version,Size,MD5Sum,Depends,Pre-Depends,Provides,Conflicts,Replaces
  • 其余字段可以任意修改,无需与deb里的control一致,因为Cydia本身不是读取的control的数据,而是从Packages中获取数据。
  • 修改字段以后,如果以dpkg-scanpackages重新生成Packages,那么修改过的部分会被还原成control里的原始数据。





签名Release的方法
引用

  1. 获取用于签名的GPG密匙(方法见下文)
  2. 运行命令
    复制代码
    1. gpg -abs -r "HuangRui" -o Release.gpg Release

    其中引号内的字符串为用于签名的密匙的用户名(用于区分不同的签名密匙)
  3. 输入密码
  4. 完成




为什么要签名Release
虽然不签名Release文件也没什么大的问题,但是签名Release有以下几个用途:
  • 解决Cydia刷新出现的  Wrong language code zh-Hans 或 Wrong language code zh-Hant  的问题(当然如果别的源有这个问题的话还是会报错)
  • 所有源内的数据均经过验证,确保安全(见图)

    上传至服务器
    引用


    1. 将Packages文件压缩为Packages.bz2(压缩格式 bzip2)和Packages.gz(压缩格式:gz) (如果是用的我写的脚本则可省略自己压缩的这一部)
    2. 修改Release文件(主要是MD5值和文件大小)
    3. 【可选】签名Release文件,生成Release.gpg
    4. 将Release,Release.gpg,Packages,Packages.bz2和Packages.gz以及要更新的deb文件上传到服务器指定位置。
    5. 以上所有文件的属性需设为0755(在ftp上设置)



    用于签名Release的密匙
    生成密匙
    可以看看这个页面 http://keyring.debian.org/creating-key.html

    生成密匙的操作是在命令行下完成,其中还需要有人机交互,所以WinSCP的命令行是不能用的,如果需要使用iPhone来生成密匙,请使用Putty或者其它SSH终端工具来连接。

    运行命令
    复制代码
    1. gpg --gen-key

    提示
    引用
    Please select what kind of key you want:
       (1) DSA and Elgamal (default)
       (2) DSA (sign only)
       (5) RSA (sign only)
    Your selection?

    一般就是1,默认

    回车后
    引用
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048)

    输入1024~4096之间的一个数值,数值越大,加密强度越高,但每次加密和解密需要的时间更多。

    我这里输入的是2048
    引用

    Requested keysize is 2048 bits

    Please specify how long the key should be valid.
             0 = key does not expire
            = key expires in n days
          w = key expires in n weeks
          m = key expires in n months
          y = key expires in n years
    Key is valid for? (0)
    Key does not expire at all
    Is this correct? (y/N) y


    密匙有效时间,一般选0,不会过期。

    问你确认,输入y+回车(小写y,如果要重新做则是大写N)

    Real name:

    输入该密匙所有者的名称,例如 WEIP Tech Team

    Email address:

    密匙所有者邮件地址,自己输入

    Comment:

    注释,怕分不清楚的话可以加点内容进去
    引用

    You are using the `utf-8′ character set.
    You selected this USER-ID:
        “WEIP Tech Team <weip.com@gmail,com>


    继续

    引用
    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?


    上面输错的话,名字错了就输入N,加上注释就输入C,邮件错误就输入E,不保存退出输入Q,确定输入O

    引用
    You need a Passphrase to protect your secret key.


    设置密码,该密码在每次使用加密时都要使用,必须牢记。输入时不会明文显示,回车后会要你再输一遍以匹配。

    设完密码之后就自动执行了。

    注意,在结果里面有一句
    引用

    gpg: key 0A02728F marked as ultimately trusted
    public and secret key created and signed.


    这串字符就是所谓的密匙标识了

    如果需要为这个密匙添加另外的使用者,可以用以下命令
    复制代码
    1. gpg --edit-key 0x0A02728F


    密匙前面要加上数字0和字母x

    command> 后输入
    复制代码
    1. adduid

    之后的操作跟前面的一样,不过在要输密码的时候只是要验证身份,不是创建密码。

    最后在command>后输入
    复制代码
    1. save


    假设创建了两个用户,A和B,原本是A拥有最高权限,要改为B拥有最高权限

    执行以下命令:
    复制代码
    1. gpg --edit-key 0x0A02728F


    command> 后输入
    复制代码
    1. uid 2


    然后输入
    复制代码
    1. Command> primary


    输入密码后在command>后输入
    复制代码
    1. save


    经过以上操作就成功生成了一个可以用于签名的密匙。

    导出公匙
    引用

    用于加密/签名的是刚刚申请到的私人密匙(Private Key),而要发布的是公匙(Public Key)
    运行命令
    复制代码
    1. gpg --export 0A02728F > weiphone-keyring.gpg
    文件名自己决定
    之后将生成的公匙发布就可以了。

    导入公匙
    引用

    需要导入公匙的是软件源的用户,下载公匙文件以后,让用户自己运行命令
    复制代码
    1. apt-key add weiphone-keyring.gpg


    导出私人密匙
    引用

    有时候软件源不是一个人在维护,如果是多个人维护的话可能需要导出私人密匙以共其他人加密/签名。
    运行命令
    复制代码
    1. gpg --export-secret-key -a "User Name" > private.key

    User Name是自己在生成密匙的时候输入的用户名,最后生成的文件,文件名随意,但 切记,这个密匙不要泄漏出去

    导入私人密匙
    引用

    得到私人密匙之后就是导入了,运行命令
    复制代码
    1. gpg --allow-secret-key-import --import private.key


    密匙管理
    引用

    查看公匙列表
    复制代码
    1. apt-key list

    复制代码
    1. gpg --list-keys


    当密匙不再使用时,可以删除密匙。
    删除公匙
    复制代码
    1. apt-key del 0A02728F

    复制代码
    1. gpg --delete-key "User Name"


    查看私人密匙列表
    复制代码
    1. gpg --list-secret-keys


    删除私人密匙
    复制代码
    1. gpg --delete-secret-key "User Name"



    关于GPG密匙的更多命令,可以看看这个网页(英文)http://irtfweb.ifa.hawaii.edu/~lockhart/gpg/gpg-cs.html

    关于公匙和私匙的介绍:http://www.hudong.com/wiki/%E5%85%AC%E5%8C%99

    关于源的搭建,也可以看看Saurik的文章 http://www.saurik.com/id/7


    最后再附送点其它东西。

    要在Cydia中显示源的图标或者分类图标,只要将图标文件放到Cydia的目录下即可。

    源的图标文件名为 域名.png,比如威锋源的地址为http://app.weiphone.com/cydia,那么图标文件名应为app.weiphone.com.png,该文件需位于 /Applications/Cydia.app/Sources/ 下,图标分辨率为60 × 60

    分类图标需位于 /Applications/Cydia.app/Ssctions/ 下,文件名有一定要求。一般来说文件名跟分类名一致就可以了,但也有例外。以威锋源为例,分类 [2.x] 所对应的图标文件名应为 2.x.png,没有方括号,但其它的就要有方括号。另外,一定要注意大小写的匹配,文件名编码须为UTF-8。


    制作软件源的安装包,这里就直接提供威锋源的安装包了。
    com.weiphone.source_1.2_iphoneos-arm.deb (78 K) 下载次数:664

    重点:
    1. list文件 /etc/apt/sources.list.d/weiphone.list
    复制代码
    1. # do not edit this file to add your own custom sources
    2. # this file is subject to be upgraded as part of a package
    3. # either add your own .list file to /etc/apt/sources.list.d
    4. # or add your entry to the global /etc/apt/sources.list file

    5. deb http://app.weiphone.com/cydia/ ./



    2. 公匙,其实放在哪里不重要,但Cydia的所有源的公匙都是放在 /usr/share/keyrings/ 下,所以尽量随主流吧

    3. 安装公匙的脚本 postinst或者extrainst_都行,只不过通常都用extrainst_
    复制代码
    1. #!/bin/sh
    2. if [[ $1 == install || $1 == upgrade ]]; then
    3.     /usr/bin/apt-key add /usr/share/keyrings/weiphone-keyring.gpg
    4. fi

    记得修改文件名

    4. 卸载时删除公匙的脚本,prerm或者postrm都行
    复制代码
    1. #!/bin/sh
    2. if [[ $1 == remove ]]; then
    3.     /usr/bin/apt-key del BB7EB3ED
    4. fi


    服务器上文件存放位置,最简单的
    cydia--
               |--debs--*.deb
               |--Packages
               |--Packages.bz2
               |--Packages.gz
               |--Release
               |--Release.gpg

    Cydia Wrong language code zh-Hans 或 Wrong language code zh-Hant 的解释
    引用

    其实这个不是错误,而是Cydia本身对中文的支持有问题。
    而且,这个提示并非是错误提示,实际是属于警告的性质,因为Cydia本身在中文支持上有些问题,但不影响使用,所以会出现警告。
    该警告的出现与Cydia软件源中是否存在中文无关,而是和系统语言设置有关,该问题只出现在简体中文和繁体中文系统下(不信把系统语言改成非中文的看还会不会出现错误)。

    何时会出现错误提示:
    很简单,Cydia刷新出了问题。
    一般有两种可能:
    1.  网络问题导致Cydia不能获取Packages或Release等文件
    2. Packages和Release文件本身有问题,比如说格式错误或者编码错误(BigBoss就闹过一次)

    如果网络通畅的话就不会出现这个错误提示了。


    deb安装包制作教程

    引用

    制作deb文件需要有dpkg-deb命令,Ubuntu/Debian 系统自带此命令,越狱过的 iPhone OS 也有此命令,Mac OS X 下需安装Fink,Windows 下需安装 Cygwin。

    Fink 下载页面: http://www.finkproject.org/download/
    Cygwin下载地址: http://www.cygwin.com/setup.exe

    以上系统中,iPhone OS最适合用来打包deb文件,因为iPhone OS上的用户/组设置与所需要的设置是完全一致的。但因为iPhone/iPod Touch毕竟是手持设备,处理性能比不上电脑,在打包体积较大的deb文件时需要很长时间,有可能会导致失去连接或者SpringBoard崩溃。而且在WinSCP中涉及文本修改的部分,如果文本含有中文的话,编码是个问题(不会保存为UTF-8)。
    Ubuntu/Debian 是 deb 文件系统的原生系统,在兼容性和处理性能上最好,但问题在于,Ubuntu/Debian 没有 iPhone OS 上的一些用户和组,最典型的就是wheel、mobile组和mobile用户。
    Mac OS X的问题跟 Ubuntu/Debian 差不多,没有mobile用户/组,而且需要装 Fink 才能支持 deb。
    Windows的问题最多,Cygwin体积超大不说,使用起来还很麻烦,加上 Windows 的文件系统和 Unix 标准完全不同,且 Windows 下会面临更严重的编码问题,所以不推荐用 Windows 来打包。

    不管是哪个系统,打包 deb 的方法是一样的,只是在某些地方对于某些系统需要特别注意。、

    一个 deb 安装包由两个部分组成,一个是安装控制/识别信息,另外一个就是实际的程序文件。

    用7-zip或Linux下的存档管理器打开 deb 文件,其中安装控制/识别信息储存在 control.tar.gz 里面,而 data.tar.xxx 则储存了程序数据。

    解包deb文件
    引用
    有时候不是需要制作一个全新的deb,而是需要修改现有的deb,那么第一步就是解包。假设deb的文件名是abc_1.0.deb

    那么解包命令是
    复制代码
    1. dpkg-deb -x abc_1.0.deb tmp
    复制代码
    1. dpkg-deb -e abc_1.0.deb tmp/DEBIAN

    第一个命令是用于解压出实际数据到tmp目录下,后一个命令是解压出安装控制脚本到tmp/DEBIAN目录下,此处必须是大写的DEBIAN。
    可以看到在tmp目录下出现了实际数据和DEBIAN目录。

    以dpkg-deb -x 和- e 命令解包deb会保留文件的属性/权限/用户/组等信息。

    关于dpkg-deb的命令,可以输入
    复制代码
    1. dpkg-deb --help


    进入DEBIAN目录,可以看到有一个control文件,无后缀名,这个文件就是用来记录deb的安装信息。有时候还可以看到postinst,preinst,prerm,postrm,extrainst_这些文件,这些文件是deb安装的时候执行的脚本(类似于Windows下的批处理文件)。

    另外一种解包deb的方法就是用7-zip或者存档管理器之类的软件直接解包到指定目录,但这样不会保留文件的属性/权限/用户/组等信息,因此除非这些信息不重要,或者这些信息是通过脚本来设置,否则不推荐使用该种方法。如果只是要提取某些文件的话倒是可以用,省事一些。


    准备打包deb的目录/文件
    引用

    如果是解包已有的deb,那么目录已经配置好了。如果是新建一个deb,需要有一个主目录,这里以tmp为例,在tmp目录下新建一个目录,DEBIAN。


    完成deb数据配置
    引用

    将程序文件放在tmp目录下。放置规则是,假如在iPhone OS上一个文件是 /Applications/ABC.app/ABC,那么就在 tmp 目录下依次新建目录Applications,ABC.app,然后把ABC放在ABC.app下。其余文件和目录也是一样的放置。

    这里要注意的是文件的属性/权限/用户/组的问题,当然前提是知道文件的属性和权限等信息。

    通常来说,可执行文件,比如应用程序的可执行文件,脚本等,属性需设为0755或更高(0775或0777),/var/mobile/下的绝大部分文件/文件夹的用户/组需设为mobile等。

    要设置文件/文件夹的权限/属性,使用命令
    复制代码
    1. chmod ABCD XXX
    这样的格式,ABCD为需要的属性/权限,比如0644,0755等,一般来说,可行性文件需要设为0755(0775和0777大部分情况下是用不上的,有些特殊的需要设为4755等),其它文件默认就是0644(不可执行),XXX是文件名,可以加上路径。

    要设置文件/文件夹的用户/组,使用命令
    复制代码
    1. chown user:group XXXX
    其中user是需要设置的用户,group是组。最常用的是root:wheel和mobile:mobile。
    注意:
    1. 如果当前用户是非root帐户,如果要将文件的用户/组设为root,需要使用sudo命令来提示权限。
    2. 如果要递归设置以上信息,可以使用 -R 参数。比如要将tmp目录下的所有子目录和文件设为0755及root:wheel,可以使用命令
    复制代码
    1. chmod -R 0755 tmp
    2. chown -R root:wheel tmp


    关于文件/文件夹的属性/权限/用户/组的更多说明:
    • 因为deb打包是先将所有的文件/文件夹归档为tar文件之后再压缩,因此文件/文件夹的属性/权限/用户/组这些信息会被保留下来,因此如果直接设置好了以后再打包deb的话就不需要通过postinst之类的控制脚本来设置权限等信息。
    • 如果无法直接设置属性/用户/组等信息,通常需要在postinst脚本里加入设置属性/权限/用户/组的命令
    • 如果deb中的目录是在iPhone OS本身就有的,那么不需要另外设置属性/权限/用户/组等,即使现有的和需要的不一样。因为deb安装不会替换原有文件夹的数据。比如/Applications目录是root:admin,而要打包的deb中该目录是ABC:DEF,那么不需要修改ABC:DEF
    • 尤其要注意的是mobile:mobile
    • Ubuntu/Debian上虽然没有wheel组,但是root:root在iPhone上会自动转为root:wheel,所以如果是准备将root:root变为root:wheel,那么可以保留root:root就可以了。
    • 理论上来说,在无安装脚本设置用户/组的前提下,如果不涉及mobile:mobile的用户/组,全部操作都可以直接在Ubuntu/Debian和Mac OS X上完成



    DEBIAN之control
    引用

    control记录了软件包标识,软件名,介绍,作者,冲突软件等信息,用来标识一个软件包。在某些软件中,如Icy,是区分大小写的,但在Cydia中是不区分大小写的。

    特别注意:
    • control文件必须是UTF-8,Unix编码,Unix/Linux换行符(LF),不符合规范的control会导致Cydia无法打开。
    • 文件末尾需有一个空行。


    Package:
    软件包标识符,类似于身份证,一个软件包必须要有一个唯一的标识符。通常是用com.xxx.abc这样的形式来命名。

    Architecture:
    架构,用于标识运行的系统,iPhone上为iphoneos-arm

    Version:
    版本号,不能用下划线和逗号和空格。格式有(以逗号分隔) 1.0,1.0f,0-1,1:1.0,其中1:1.0这种格式比较特殊,在Cydia中,1:1.0仍然会显示为1.0,但版本号实际是高于1.0的。


    以上3项是必须的,缺了任何一项deb打包就不能成功。

    以下均为可选项:

    Name:
    软件包在Cydia中的显示名称,中英文不限,也可以用空格,但不宜过长(长了显示不完全)。


    Author:
    软件作者。

    Maintainer:
    维护者,一般是软件源的拥有者。

    Sponsor:
    负责人,可以是个人也可以是网站。

    Author,Maintainer,Sponsor 的格式相同,均为 名称+空格+<邮件地址或网址>,经测试,如果名称为中文的话,即使写了邮件地址和网址,在Cydia中点击也不会跳转。
    示例: WEIP.Tech <weip.com@gmail,com> 或 WeiPhone.com < http://www.weiphone.com>
    如果没有邮件地址或网址,则不需要 <> 及<>中的内容。
    中文名或未提供邮件/网址,无 > 符号

    Icon:
    指定软件包的图标显示。当无Icon设定时,Cydia会显示该软件包所在的分类的图标。
    格式:
    • 在线地址,如 http://www.abc.com/abc.png
    • 本地地址:file://+路径,如file:///Applications/Cydia.app/Sources/app.weiphone.com.png
      注:在软件页面(非列表页面),自定义的图标是不会显示的,显示的是分类图标。

      Section:
      软件分类,中英文无限制,排列顺序是 英文->中文。

      另外,如果在分类加上[],比如 [工具],那么这个是排在最前面的。

      Installed-Size:
      解包后的文件大小,可以有小数位,以kb为单位,不需要注明kb,这个不需要很精确,而且小数位在Cydia里显示不出来(不是四舍五入,全部舍了)。至于文件大小是否包含DEBIAN目录中的内容就随意了。

      Priority:
      优先级,可填 Required,Important,Standard,Optional,Extra,依次为 必须,重要,一般,可选,次要。虽然没有什么实际作用,但优先级为Required和Important的软件包在卸载时会有警告,这样可以避免删除一些系统必须的软件。但Required和Important不要滥用,一般用Standard,Optional或Extra即可。
      优先级在Cydia中是不会显示的  

      Essential:
      是否必须软件包,可填 yes 和 no, 填yes则为必须软件包,卸载时Cydia会有警告。卸载Essential标记为yes的软件包可能会导致系统问题。当然此功能需慎用,不要因为不希望用户删除自己的软件而加入Essential: yes。如果没有Essential这项的话默认就是非必须的,相当于Essential: no。

      Depends:
      Depends 字段应该包含您的软件包正常工作绝对必需的任何软件包的名称。

      Pre-Depends:
      "Pre-Depends"是为特例而保留的。当某个软件包被作为"Pre-Depends"列出时,它强制系统在试图安装您的软件包之前完全安装所指定的软件包。

      Conflicts:
      冲突软件包。比如软件包A和B有冲突,不能同时安装。比如说A和B冲突,当系统已经安装了A的时候尝试安装B,则不能继续。

      Provides:
      提供的软件包,比如说软件包A包含B的全部功能,那么则是A provides B,因此可以在安装了A的前提下不安装B。但此功能在非Cydia的软件管理工具中可能会无法识别(实际是这些软件不合deb标准)

      Replaces:
      替换软件包,安装A会替换B。

      • 以上5项的格式相同,直接填软件包的Package标识即可,如果需要加入版本号,则为 软件表标识+空格+(判断符号 版本号)。
        比如 Depends: apt-key, firmware (>=3.0), 这表示依赖于apt-key,不限版本,firmware,且版本大于或等于3.0。
      • 判断符号:远远低于(<<)、低于(<)、低于或等于(<=)、仅等于(=)、等于或高于(>=)、大于(>)以及远远高于(>>)。
      • 表示多个软件包,以英文逗号分隔。
      • 表示“或”关系,用 | 分隔。比如软件包C依赖于A或B,可写Depends: A | B。 但“或”关系要慎用。原因是,当不存在“或”关系的时候,假设B依赖于A,且系统并未安装A,那么在Cydia中安装B的时候会自动下载安装A。而假如说C依赖于A或B,且A与B都未安装,那么在安装C的时候就会失败,因为系统无法判断是应该下载A还是B。除非系统已经安装了A或B,否则C不能安装。
      • 一个特殊的依赖:firmware。这个Package记录了固件版本,在对固件版本有要求的软件包上特别重要。
      • 假设B依赖于A,那么在卸载A的时候也会一起卸载B


      Description:
      软件描述,不能在control里直接换行,如果需要实现换行显示,可以使用<br>代码。当指定了Depiction时,在软件查看页面不会显示Description。

      Depiction:
      功能类似于软件描述,链接到一个网页,以网页的内容代替软件描述。只在软件查看页面显示,在软件包列表页面不显示。
      可以使用本地网页,格式同Icon。
      注意:此功能可能会消耗大量网络流量。

      Homepage:
      链接到页面,Cydia中显示为More Information。
      页面不会主动加载。

      Tag:
      标签,用于分类软件包信息。
      purpose:: 软件包类型,比如软件源,命令行,库等等。purpose::console表示该软件为命令行界面。可选项有 commercial, console, daemon, extension, library, uikit, x,对应图标文件在 /Applications/Cydia.app/Purposes 目录下。也可以自行添加 purpose 分类,并加入同名图标即可。
      role:: 软件包使用者归类。developer开发者,hacker骇客,enduser普通用户,该标签用于Cydia中软件包显示过滤。
      cydia::commercial Cydia Store软件。


      示例: control.txt (1 K) 下载次数:751去掉 .txt 后缀名



    DEBIAN之脚本preinst/postinst/prerm/postrm/extrainst_
    引用

    很多时候deb安装并不是把文件复制到iPhone里就可以了,还需要执行一些命令,比如设置权限,备份文件,加载启动进程等等,那么这时候就需要一些脚本来实现这些操作。

    标准的deb脚本有4个,preinst,postinst,prerm和postrm,pre是表示XX之前的前缀,post是表示XX之后的前缀,inst是install(安装)的缩写,rm是remove(移除)的缩写,所以这4个脚本的功能很明显:

    • preinst:在复制文件前执行的脚本
    • postinst:在复制文件之后执行的脚本
    • prerm:在卸载前执行的脚本
    • postrm:在卸载之后执行的脚本


    在Cydia中还存在一个独立的脚本,extrainst_,从字面上来讲就是额外的安装脚本。这个脚本是Cydia的作者Saurik为解决某些脚本只需要在安装时执行,在升级时不执行而专门引入的一个脚本,功能跟postinst差不多,和Installer时代的“ahhhh”比较相似。关于extrainst_的详情可以看看这个: http://www.telesphoreo.org/pipermail/cydia-packagers/2008-September/000252.html

    5个脚本的编写方法基本是一样的,但为了适应Cydia的安装,在某些情况下需要进行特定的配置。

    查看某些deb可能会发现这样的语句:
    复制代码
    1. if [[ $1 == install || $1 == upgrade ]]; then

    这种语句是为了区别安装/升级/卸载而准备的脚本。$1是一个外部变量,将这个外部变量传入脚本来执行,而这个外部变量是由Cydia软件自身生成的。
    简单来说,如果是安装,则是 $1 == install ;如果是升级,则是$1 == upgrade;如果是卸载则是 $1 == remove。

    if 是个判断语句,当满足if后[ ]中的指定条件时,if中的内容就会执行。那么这里就可以通过设定install/upgrade/remove来控制在不同操作时执行的命令。

    但要注意的是,这个功能只能在Cydia中使用,其它的apt软件管理工具,如Icy,Rock等,不能识别这个命令,因此无法执行if中的语句,所以在写脚本的时候到底需不需要用这种格式,就看自己的需要了。

    总体来说,Unix的脚本(Shell Script)有其固定的格式。

    文件顶头为
    复制代码
    1. #!/bin/bash

    表示调用bash这个shell

    之后就是运行的命令了。

    脚本中如果需要注释,可以使用 # 符号。 以 # 开头的行会被当作注释,里面的内容在执行过程中没有意义。

    通配符: *

    最常用的两个命令自然是设置属性/权限/用户/组

    设置属性/权限
    复制代码
    1. chmod 【-R】 属性 文件名

    由于deb的脚本执行都是在root用户下,因此不需要提升权限,即不需要使用sudo命令。
    -R参数:表示递归,加上此参数会将指定的目录及其子目录的全部目录和文件的属性改变。
    属性:有多种写法。具体可以看 http://baike.baidu.com/view/1229012.htm?fr=ala0_1
    比较常用的几种属性:

    • chmod +x XXXXX 为文件增加可执行权限
    • chmod 0644 XXXXX 不可执行文件最常使用的权限
    • chmod 0755 XXXXX 可执行文件最常使用的权限
      实例:
      复制代码
      1. chmod -R 0755 /Applications/Cydia.app


      设置用户/组
      复制代码
      1. chown 【-R】 用户:组 文件名

      同样不需要sudo来提示权限。-R也是表示递归。
      比如要将文件A设为root用户,wheel组,可以使用命令
      复制代码
      1. chown root:wheel A

      要将 /var/mobile/Documents 下所有文件夹和文件设为mobile用户和mobile组,可以使用命令
      复制代码
      1. chown -R mobile:mobile /var/mobile/Documents


      删除文件/文件夹
      复制代码
      1. rm 【参数】 文件名
      2. rmdir 文件夹名

      rm 是广义的删除命令,可以用于删除文件和文件夹。
      rm常用参数有 -f 和 -r
          参数 -f :强制删除,即使文件不存在。当无 -f 参数时,要删除一个不存在的文件就会报错,从而中断脚本的执行,因此在绝大部分情况下 -f 参数都是必要的。
          参数 -r :递归。要以rm命令删除文件夹,必须加上 -r 参数。该参数会删除目录下的全部子目录和文件,包括链接到的文件/文件夹。因此 -r 参数要慎用。比如有一个链接是指向根目录的,在   有 -r参数的情况下,删除这个链接会导致整个文件系统全部被删除。

      实例:
      删除 /var/mobile/abc文件
      复制代码
      1. rm -f /var/mobile/abc

      删除 /var/mobile/trash/下的全部文件/文件夹
      复制代码
      1. rm -rf /var/mobile/trash


      rmdir仅能用于删除空文件夹,也就是说,不能用于删除文件和非空的文件夹。

      实例:
      删除空目录 /var/mobile/trash
      复制代码
      1. rmdir /var/mobile/trash


      复制文件/文件夹
      复制代码
      1. cp 【参数】 原始文件 目的文件

      参数列表:

      • -l(小写字母L):创建硬链接,相当于一个镜像,而不是实际创建两个文件
        复制代码
        1. cp -l abc def

      • -f:强行复制,如果目的文件已存在,覆盖之且不提示
        复制代码
        1. cp -f abc def

      • -p:保留文件的属性、用户、组、时间戳等信息
        复制代码
        1. cp -p abc def

      • -r和-R:作用都是递归,将文件夹下的全部子文件和子文件夹一起复制
        复制代码
        1. cp -r abc/ def/

      • -s:创建符号链接而不是创建双份文件
        复制代码
        1. cp -s abc/ def/

      • -n:如果目的文件已存在,则不覆盖且不提示
        复制代码
        1. cp -n abc def

      • -a:相当与-dR,保留文件自身的属性等数据,一并复制子文件/文件夹
        复制代码
        1. cp -a abc/ def/



      移动文件/文件夹 & 重命名
      复制代码
      1. mv 【参数】 源文件 目的文件

      参数:
      -f:强行移动,如果目的文件已存在,覆盖之且不提示

      其实 mv  命令就是复制之后再删除,但 mv 命令会自动保留文件的属性等数据,移动文件夹时会自动移动子文件/子文件夹,因此都不需要另外的参数。

      重命名是由mv命令来实现的,mv 就是将 源文件 移动到 目标文件的位置并以目标文件的文件名保存。

      显示语句
      复制代码
      1. echo “语句"

      示例:显示语句“测试echo命令。”
      复制代码
      1. echo "test echo command"


      管理自启动服务
      复制代码
      1. launchctl load或unload  -w plist文件路径

      实例:
      让wefit3自启动
      复制代码
      1. launchctl load -w /System/Library/LaunchDaemons/com.weiphone.fitx.plist

      禁用iPhone日志记录syslogd
      复制代码
      1. launchctl unload -w /System/Library/LaunchDaemons/com.apple.syslogd.plist


      记录自启动进程的plist文件保存在以下两个目录:
      /System/Library/LaunchDaemons/ 和 /Library/LaunchDaemons/

      杀死进程
      复制代码
      1. killall 进程名

      示例:关闭Safari进程
      复制代码
      1. killall safari


      判断
      基本格式是
      复制代码
      1. if [ 判断条件一 ]; then
      2.     执行命令
      3. else
      4.    执行命令
      5. fi


      实例:
      如果文件abc存在,则备份为abc.bak,否则将文件def重命名为abc
      复制代码
      1. if [ -f abc]; then
      2.     mv -f abc abc.bak
      3. else
      4.     mv def abc
      5. fi

      其中[ -f abc ]可以由[ -e abc]取代
      如果目录abc不存在,则新建一个目录abc
      复制代码
      1. if [ ! -e abc ]; then
      2.     mkdir abc
      3. fi


      获取固件系统版本号
      复制代码
      1. sw_vers -productVersion


      获取设备型号
      复制代码
      1. uname -i
      2. uname -m

      -i 参数是显示设备代号,-m参数是显示设备型号(实质效果相同)
      比特说iPod Touch 1代,运行uname -i得到的结果是N45AP,而运行uname -m的结果是iPod1,1

      iPhone 2GiPhone1,1M68AP
      iPhone 3GiPhone1,2N82AP
      iPhone 3G[S]iPhone2,1N88AP
      iPhone 4iPhone3,1N90AP
      iPod Touch 1GiPod1,1N45AP
      iPod Touch 2GiPod2,1N72AP
      iPod Touch 3GiPod3,1N18AP
      iPadiPad1,1K48AP

      Cydia中安装完之后重新启动SpringBoard
      复制代码
      1. declare -a cydia
      2. cydia=($CYDIA)

      3. if [[ ${CYDIA+@} ]]; then
      4.     eval "echo 'finish:restart' >&${cydia[0]}"
      5. fi


      Cydia中安装完之后重新启动设备
      复制代码
      1. declare -a cydia
      2. cydia=($CYDIA)

      3. if [[ ${CYDIA+@} ]]; then
      4.     eval "echo 'finish:reboot' >&${cydia[0]}"
      5. fi

            
      几个比较有用的实例:
      备份
      preinst(安装之前就要把原始文件备份,不能等到安装完已经覆盖以后才备份)
      复制代码
      1. if [ ! -f 原始文件备份 ]; then
      2.     echo "原始文件的备份已存在,跳过备份"
      3. else
      4.     cp -p 原始文件 原始文件备份
      5.     echo "原始文件已备份"
      6. fi

      postrm(还原备份)
      复制代码
      1. echo "还原备份"
      2. mv -f 原始文件备份 原始文件

      备份操作在制作补丁的时候,尤其是替换类型的补丁时特别有用。

      判别具体固件版本
      在control里可以通过Depends来设置依赖的固件版本,但有时候需要在某个特定固件版本下进行操作
      比如说一个软件,要求固件版本大于或等于3.0,但在固件版本为3.1的时候必须删除某一个文件才能运行,那么脚本可以这样写:
      复制代码
      1. firmware=$(sw_vers -productVersion)
      2. if  [[ $firmware == 3.1 ]]; then
      3.     删除文件
      4. fi


      判别设备型号
      当设备型号为iPod Touch时删除某个文件
      复制代码
      1. platform=$(uname -i)
      2. if [[ $platform == "N45AP" || $platform == "N72AP" || $platform == "N18AP" ]]; then
      3.     删除文件
      4. fi
      复制代码
      1. platform=$(uname -m)
      2. if [ $platform == iPod* ]; then
      3.     删除文件
      4. fi


      更多关于Shell Script的信息请见 http://www.hack base.com/tech/2009-10-10/56808.html  (去掉空格)


    打包deb
    引用

    如果在DEBIAN中有脚本存在,则需要将整个DEBIAN文件夹及子文件属性设为0755
    复制代码
    1. chmod -R 0755 DEBIAN

    如果没有脚本的话保留0644属性即可,0755属性也没问题。

    打包命令
    复制代码
    1. dpkg-deb -b PATH FILENAME

    其中PATH是打包deb的工作目录,DEBIAN文件夹需位于PATH指定的目录下
    FILENAME是deb的文件名,这个可以自己决定。

    以上命令打包deb默认是采用gz格式压缩,压缩率有限,如果要获得更改的压缩率(更小的文件体积),可以使用bzip2和lzma格式。
    压缩为bzip2格式
    复制代码
    1. dpkg-deb -bZ bzip2 PATH FILENAME

    压缩为bzip2格式
    复制代码
    1. dpkg-deb -bZ lzma PATH FILENAME


    默认的gz格式压缩率最低,bzip2格式居中,lzma格式压缩率最高。(当然也会有例外)



    注意:
    • 压缩率越高,压缩时间越长,在iPhone上使用较高的压缩率有更大概率导致失去响应。
    • iPhone OS 2.x无lzma组件,因此无法安装lzma压缩的deb。iPhone OS 3.x可以解压lzma压缩。
    • 如果deb包含的文件文本量比较大,那么一般可以获得不错的压缩率。但如果是像铃声,jpg/png图片这样文件本身就是压缩格式的情况,继续压缩的可能性就不高了,这类情况很难获得比较好的压缩率



    【可选】deb文件规范命名
    引用

    命令
    复制代码
    1. dpkg-name abc_1.0.deb


    如果想指定文件名格式,可以使用
    复制代码
    1. dpkg-name --help

    来查看命令的使用帮助

    引用

    图形界面的deb制作工具 Debian Package Maker

    网址: http://code.google.com/p/debianpackagemaker/

    个人感觉不如直接在命令行里来的直观,有兴趣的朋友可以自己试试。



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/939382
推荐阅读
相关标签
  

闽ICP备14008679号