Skip to content

Commit

Permalink
iOS私有api检查工具,目前已经完成了document api和framework header的相关内容
Browse files Browse the repository at this point in the history
  • Loading branch information
hustcc committed Oct 27, 2015
0 parents commit c2b14cc
Show file tree
Hide file tree
Showing 21 changed files with 842 additions and 0 deletions.
65 changes: 65 additions & 0 deletions .gitignore
@@ -0,0 +1,65 @@
# Created by https://www.gitignore.io/api/python

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover

# Translations
*.mo
*.pot

# Django stuff:
*.log

# Sphinx documentation
docs/_build/

# PyBuilder
target/


# custom
tmp/
17 changes: 17 additions & 0 deletions .project
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>iOS-private-api-checker</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
9 changes: 9 additions & 0 deletions .pydevproject
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?><pydev_project>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/${PROJECT_DIR_NAME}</path>
<path>/${PROJECT_DIR_NAME}/tmp</path>
</pydev_pathproperty>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
</pydev_project>
11 changes: 11 additions & 0 deletions .settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,11 @@
eclipse.preferences.version=1
encoding//api/api_utils.py=utf-8
encoding//db/api_dbs.py=utf-8
encoding//db/dsidx_dbs.py=utf-8
encoding//db/mysql_utils.py=utf-8
encoding//db/other_dbs.py=utf-8
encoding//db/sqlite_utils.py=utf-8
encoding//dump/class_dump_utils.py=utf-8
encoding/batch.py=utf-8
encoding/config.py=utf-8
encoding/iOS_private.py=utf-8
10 changes: 10 additions & 0 deletions README.md
@@ -0,0 +1,10 @@
## iOS私有API检查工具 ##

参考

- [RuntimeBrowser](https://github.com/nst/RuntimeBrowser/tree/master/tools/ios_headers_history)

- [iOS-private-api-scanner](https://github.com/mrmign/iOS-private-api-scanner)

1. `私有的api = (class-dump Framework下的库生成的头文件中的api - (Framework下的头文件里的api = 有文档的api + 没有文档的api)) + PrivateFramework下的api`
2. 私有的api在公开的Framework及私有的PrivateFramework都有。
Empty file added api/__init__.py
Empty file.
92 changes: 92 additions & 0 deletions api/api_utils.py
@@ -0,0 +1,92 @@
#coding=utf-8
'''
Created on 2015年10月27日
Framework下的头文件里的api = 有文档的api + 没有文档的api
@author: hzwangzhiwei
'''
from db import dsidx_dbs
import os

def framework_dump_header_apis(sdk, framework_folder):
'''
class-dump Framework下的库生成的头文件中的api
sdk: sdk version
info: 用class-dump对所有的公开库(/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk/System/Library/Frameworks)进行逆向工程得到所有的头文件内容。提取每个.h文件中的api得到api集合set_A。
'''
pass

def framework_header_apis(sdk, framework_folder):
'''
get all public frameworks' header files(documented)
'''
def iterate_dir(framework, prefix, path):
files = []
for f in os.listdir(path):
if os.path.isfile(os.path.join(path, f)):
files.append((framework, prefix + f, os.path.join(path, f)))
elif os.path.isdir(os.path.join(path, f)):
files += iterate_dir(framework, prefix + f + "/", os.path.join(path, f))
return files
all_headers = []

for framework in os.listdir(framework_folder):
if framework.endswith(".framework"):
header_path = framework_folder + framework +"/Headers/"
if os.path.exists(header_path):
#for header in os.listdir(header_path):
# file_path = header_path + header
# allpaths.append((framework, header, file_path))
all_headers += iterate_dir(framework, "", os.path.join(framework_folder, header_path))

return all_headers

#没有文档的api
def undocument_apis(sdk):
'''
info:不在文档中的api方法
'''
framework_header_apis(sdk) - document_apis(sdk)

#有文档的api
def document_apis(sdk, db_path):
'''
has document apis
info:获得带文档的api。(/Users/sngTest/Library/Developer/Shared/Documentation/DocSets/com.apple.adc.documentation.AppleiOS7.0.iOSLibrary.docset/Contents/Resources),在里面有个docSet.dsidx的文件,这就是Xcode针对api做的数据库,从这里可以获得带文档的api的各种信息了,从而有了带文档的api集合set_B。
'''
doc_apis = []
#从dsidx 数据库中获得初始数据
apiset = dsidx_dbs.get_dsidx_apis(db_path)
#过滤初始数据获得有文档的api集合
for api in apiset:
Z_PK = api['Z_PK']
ZDECLAREDIN = api['ZDECLAREDIN']
# get containername from ZCONTAINER table
container_name = ''
if Z_PK:
container_name = dsidx_dbs.get_container_name(Z_PK, db_path) or ''
# get frameworkname and headerpath from ZHEADER table

framework_name = ''
header_path = ''
if ZDECLAREDIN:
frame_header = dsidx_dbs.get_framework_and_header(ZDECLAREDIN, db_path)
if frame_header:
framework_name = frame_header.get('ZFRAMEWORKNAME', '')
header_path = frame_header.get('ZHEADERPATH', '')

doc_apis.append({'api_name': api['ZTOKENNAME'], 'class_name': container_name, 'type': api['ZTOKENTYPE'], 'header_file': header_path, 'framework': framework_name, 'sdk': sdk})
return doc_apis

def private_framework_apis(sdk):
'''
PrivateFramework下的api
'''
pass

def all_private_apis(sdk):
pub_private_apis = framework_dump_header_apis(sdk) - document_apis(sdk) - undocument_apis(sdk)

pri_private_apis = private_framework_apis(sdk)

return pub_private_apis + pri_private_apis
26 changes: 26 additions & 0 deletions batch.py
@@ -0,0 +1,26 @@
#coding=utf-8
'''
Created on 2015年10月27日
一些预处理脚本
@author: hzwangzhiwei
'''
from db import api_dbs
from api import api_utils

#重建document api数据库
def rebuild_document_api(sdk, docset):
#先删除对应的sdk document api数据
api_dbs.delete_document_by_sdk(sdk)

document_apis = api_utils.document_apis(sdk, docset)
for api in document_apis:
print api

return api_dbs.insert_document_dbs(document_apis)


if __name__ == '__main__':
#重建sdk=7.0的有文档api
print rebuild_document_api('7.0', 'docSet.dsidx')


19 changes: 19 additions & 0 deletions config.py
@@ -0,0 +1,19 @@
#coding=utf-8
'''
Created on 2015年10月27日
@author: hzwangzhiwei
'''

mysql_info = {
'HOST': '127.0.0.1',
'PORT': 3306,
'USERNAME': 'root',
'PASSWORD': 'root',
'CHARTSET': 'UTF8',
'DB': 'ios_private',
}

sqlite_info = {
'DB': 'ios_private.db',
}
Empty file added db/__init__.py
Empty file.
19 changes: 19 additions & 0 deletions db/api_dbs.py
@@ -0,0 +1,19 @@
#coding=utf-8
'''
Created on 2015年10月27日
@author: hzwangzhiwei
'''
from db.sqlite_utils import SqliteHandler

#批量插入有文档的api
def insert_document_dbs(datas):
sql = "insert into document_apis(api_name, class_name, type, header_file, sdk, framework) values(:api_name, :class_name, :type, :header_file, :sdk, :framework)"
return SqliteHandler().exec_insert_many(sql, datas)


def delete_document_by_sdk(sdk):
sql = "delete from document_apis where sdk = ?;"
return SqliteHandler().exec_update(sql, (sdk, ))


30 changes: 30 additions & 0 deletions db/dsidx_dbs.py
@@ -0,0 +1,30 @@
#coding=utf-8
'''
Created on 2015年10月27日
.dsidx 文件解读
@author: hzwangzhiwei
'''
from db.sqlite_utils import SqliteHandler
def get_dsidx_apis(db_path):
'''
has document apis
info:获得带文档的api。(/Users/sngTest/Library/Developer/Shared/Documentation/DocSets/com.apple.adc.documentation.AppleiOS7.0.iOSLibrary.docset/Contents/Resources),在里面有个docSet.dsidx的文件,这就是Xcode针对api做的数据库,从这里可以获得带文档的api的各种信息了,从而有了带文档的api集合set_B。
'''
sql = "SELECT T.Z_PK, T.ZTOKENNAME, T.ZTOKENTYPE, T.ZCONTAINER, M.ZDECLAREDIN FROM ZTOKEN AS T, ZTOKENMETAINFORMATION AS M WHERE ZTOKENTYPE IN (3,9,12,13,16) AND T.Z_PK = M.ZTOKEN"
apiset = SqliteHandler(db = db_path).exec_select(sql)
return apiset


def get_container_name(Z_PK, db_path):
sql = "SELECT ZCONTAINERNAME FROM ZCONTAINER WHERE Z_PK = ?;"
container = SqliteHandler(db = db_path).exec_select_one(sql, (Z_PK, ))
if container:
return container['ZCONTAINERNAME']
return None


def get_framework_and_header(Z_PK, db_path):
sql = "SELECT ZFRAMEWORKNAME, ZHEADERPATH FROM ZHEADER WHERE Z_PK = ?;"
rst = SqliteHandler(db = db_path).exec_select_one(sql, (Z_PK, ))
return rst
6 changes: 6 additions & 0 deletions db/mysql_utils.py
@@ -0,0 +1,6 @@
#coding=utf-8
'''
Created on 2015年10月27日
@author: hzwangzhiwei
'''
58 changes: 58 additions & 0 deletions db/other_dbs.py
@@ -0,0 +1,58 @@
#coding=utf-8
'''
Created on 2015年10月27日
@author: hzwangzhiwei
'''
from db.sqlite_utils import SqliteHandler
def create_some_table():
#创建framework_header_apis
sql1 = ("create table framework_dump_header_apis("
"api_name varchar,"
"class_name varchar,"
"type varchar,"
"header_file varchar,"
"sdk varchar,"
"framework varchar)")


sql2 = ("create table framework_header_apis("
"api_name varchar,"
"class_name varchar,"
"type varchar,"
"header_file varchar,"
"sdk varchar,"
"framework varchar)")


sql3 = ("create table document_apis("
"api_name varchar,"
"class_name varchar,"
"type varchar,"
"header_file varchar,"
"sdk varchar,"
"framework varchar)")


sql4 = ("create table undocument_apis("
"api_name varchar,"
"class_name varchar,"
"type varchar,"
"header_file varchar,"
"sdk varchar,"
"framework varchar)")


sql5 = ("create table private_apis("
"api_name varchar,"
"class_name varchar,"
"type varchar,"
"header_file varchar,"
"sdk varchar,"
"framework varchar)")

SqliteHandler().exec_sql(sql1, ())
SqliteHandler().exec_sql(sql2, ())
SqliteHandler().exec_sql(sql3, ())
SqliteHandler().exec_sql(sql4, ())
SqliteHandler().exec_sql(sql5, ())

0 comments on commit c2b14cc

Please sign in to comment.