Browse Source

fixed su, added db interface

root/unroot method, ensures adb is running before gettting first device
master
Raphael Roberts 7 years ago
parent
commit
0a60004359
  1. 93
      adb.py
  2. 46
      android_db.py
  3. 1
      output
  4. 25
      sync_clip.py
  5. 6
      test.py

93
adb.py

@ -5,10 +5,11 @@ import re
import shutil
import subprocess
import time
import shlex
from android_db import AndroidSQLConn
from load_things import loaded
from decode_parcel import decode_parcel
debug = True
defaults = loaded.defaults
keycodes = loaded.keycodes
exe = defaults.exe
@ -23,6 +24,7 @@ exists = '''if [ -e "{file}" ]; then
else
echo "na"
fi'''
def merge(src, dst,log = False):
if not os.path.exists(dst):
return False
@ -46,17 +48,29 @@ def merge(src, dst,log = False):
os.rmdir(path)
return ok
def _adb(*args,out = False):
def _adb(*args,output = "shell"):
'''Output modes:
"out": return output
"shell": print to shell
"buffered": read line by line'''
args = [exe] + list(args)
if out:
if output == "out":
return subprocess.check_output(args,shell = False).decode().rstrip('\r\n')
else:
elif output == "shell":
ret = subprocess.call(args,shell = False)
if ret:
raise subprocess.CalledProcessError(ret,args)
elif output == "buffered":
p = subprocess.Popen(args,stdout = subprocess.PIPE)
return p.stdout
def kill_server():
_adb('kill-server')
def start_server():
_adb('start-server')
def get_info():
thing = _adb("devices","-l",out = True)
start_server()
thing = _adb("devices","-l",output="out")
formed = list(filter(bool,thing.split("\r\n")))[1:]
main = {}
for device in formed:
@ -65,12 +79,11 @@ def get_info():
"serial":categories[0],
"mode":categories[1]
}
device_dict.update(dict(category.split(":") for category in categories[2:]))
main[categories[0]] = device_dict
return main
class Device:
root_mode = False
def connect(ip,port=5555):
if not re.match(r'(\d{1,3}\.){3}\d{1,3}',ip):
raise TypeError("Invalid ip")
@ -87,8 +100,8 @@ class Device:
def disconnect(self):
if self.tcip:
_adb('disconnect',self.serial)
def db_connect(self,filepath):
return AndroidSQLConn(self,filepath)
def prim_device():
cont = True
while cont:
@ -108,37 +121,43 @@ class Device:
serial,info = list(get_info().items())[0]
self.__dict__.update(info)
def adb(self,*args,out = False):
def adb(self,*args,output="shell"):
args = ['-s',self.serial]+ list(args)
return _adb(*args,out = out)
def shell(self,*args,out=False):
args = ('shell',)+args
return self.adb(*args,out=out)
def sudo(self,*args,out = False):
if self.mode == 'recovery':
return self.shell(*args,out=out)
else:
args = '"{}"'.format(' '.join(args).replace('"','\\"'))
return self.shell('su','-c',args,out = out)
return _adb(*args,output = output)
def shell(self,*args,output="shell"):
args = ('shell',)+args
return self.adb(*args,output=output)
def sudo(self,*args,output="shell"):
if self.mode == 'recovery' or self.root_mode:
return self.shell(*args,output=output)
else:
return self.shell('su','--','--',*args,output=output)
@classmethod
def root(cls):
cls.root_mode = True
_adb('root')
@classmethod
def unroot(cls):
cls.root_mode = False
_adb('unroot')
def type(self,file):
e = exists.format(file = file)
res = self.sudo(e,out=True)
res = self.sudo(e,output="out")
return res
def exists(self,file):
return self.type(file) != "na"
def isfile(self,file):
return self.type(file) == 'file'
def isdir(self,file):
return self.type(file) == 'directory'
def delete(self,path):
return self.sudo("rm","-rf",path,out=True)
return self.sudo("rm","-rf",path,output="out")
def copy(self,remote,local,del_duplicates = True,ignore_error=True):
remote_type = self.type(remote)
@ -175,17 +194,14 @@ class Device:
def push(self,local,remote):
self.adb('push',local,remote)
def reboot(self,mode = None):
if mode:
if mode == "soft":
if self.mode != 'recovery':
pid = self.shell("pidof","zygote",out = True)
return self.sudo("kill",pid,out=False)
pid = self.shell("pidof","zygote",output="out")
return self.sudo("kill",pid,output="shell")
else:
return self.reboot()
else:
self.adb("reboot",mode)
else:
@ -206,15 +222,13 @@ class Device:
def unlock_phone(self,password):
if self.mode != 'recovery':
if not decode_parcel(self.shell('service','call', 'power','12',out=True),'int'):
if not decode_parcel(self.shell('service','call', 'power','12',output="out"),'int'):
self.send_keycode('power')
if decode_parcel(self.shell('service','call','trust','7',out=True),'int'):
if decode_parcel(self.shell('service','call','trust','7',output="out"),'int'):
self.send_keycode('space')
self.shell("input","text",str(password))
self.send_keycode('enter')
def backup(self,*partitions,name = None):
if self.mode != 'recovery':
self.reboot('recovery')
@ -231,10 +245,8 @@ class Device:
"as": "A"
}
options = "".join(options_dict[option] for option in partitions)
if not name:
name = "backup_"+datetime.datetime.today().strftime(defaults['date_format'])
filename = os.path.join(backupdir,name)
self.shell("twrp","backup",options,name)
phone_dir = "/data/media/0/TWRP/BACKUPS/{serial}/{name}".format(serial = self.serial,name = name)
@ -252,13 +264,12 @@ class Device:
local_name = name
name = os.path.split(name)[-1]
update_path = '{}/{}'.format(defaults['remote']['updates'],name)
if not self.exists(defaults['remote']['updates']):
self.sudo('mkdir',defaults['remote']['updates'])
if not self.exists(update_path):
self.push(local_name,defaults['remote']['updates'])
else:
update_path = '{}/{}'.format(defaults['remote']['updates'],name)
self.shell("twrp","install",update_path)
if __name__ == "__main__" and debug:
d = Device.prim_device()
d = Device.prim_device()

46
android_db.py

@ -0,0 +1,46 @@
import shlex
import re
import csv
import sys
csv.field_size_limit(2**31-1)
param_str = re.compile(r'(?<=\()[ ,\?]+(?=\))')
validator = re.compile(r'^\?(?: *\, *\?)*$')
param_sep = re.compile(r' *\, *')
class AndroidSQLConn:
def __init__(self,device,filepath,use_root=True):
self.device = device
self.filepath = filepath
self.root = use_root
def _quote_param_(param):
if isinstance(param,str):
return "'{}'".format(param.replace("'","''"))
elif isinstance(param,bool):
return '1' if param else '0'
elif param is None:
return 'NULL'
else:
return str(param)
def _sub_params_(SQL,params):
p_string = param_str.search(SQL).group(0)
if not validator.match(p_string):
raise ValueError('Invalid substitution')
n_params = len(param_sep.split(p_string))
if len(params) < n_params:
raise ValueError('Not enough parameters supplied')
new_str = ','.join(map(
AndroidSQLConn._quote_param_,params[:n_params]
))
return param_str.sub(new_str,SQL,1)
def execute(self,SQL,params = None):
if params:
SQL = AndroidSQLConn._sub_params_(SQL,params)
SQL = shlex.quote(SQL)
if self.root:
shell = self.device.sudo
else:
shell = self.device.shell
out = shell('sqlite3','-header','-csv',shlex.quote(self.filepath),SQL,output="out")
if out:
return csv.DictReader(out.splitlines())

1
output

@ -0,0 +1 @@
'X:\\Users\\Ralphie\\Google Drive\\Python\\lib\\shlex.py'

25
sync_clip.py

@ -0,0 +1,25 @@
import pyperclip
import time
import re
def sync_clipboard(dev):
db_file = '/data/data/com.catchingnow.tinyclipboardmanager/databases/clippingnow.db'
try:
pid = dev.shell('pidof','com.catchingnow.tinyclipboardmanager',output="out")
dev.sudo('kill',pid,output='shell')
except:
pass
t = time.time()
text = pyperclip.paste()
conn = dev.db_connect(db_file)
# text = re.sub(r'([\{\}])',lambda match: match.group(1) * 2,text)
# sql = 'INSERT INTO cliphistory values ({},\'{}\',0)'.format(int(1000*t),text)
# sql = '"{}"'.format(sql)
# print(sql)
# dev.sudo('sqlite3','-csv',db_file,sql)
out = conn.execute("INSERT INTO cliphistory VALUES (?,?,?);",[int(1000*t),text,False])
# print(list(out))
dev.shell('am', 'start', '-n', 'com.catchingnow.tinyclipboardmanager/.activity.ActivityMain')
if __name__ == "__main__":
import adb
d = adb.Device.prim_device()
sync_clipboard(d)

6
test.py

@ -0,0 +1,6 @@
from adb import Device
d = Device.prim_device()
import time
d.root()
conn = d.db_connect('/data/data/com.catchingnow.tinyclipboardmanager/databases/clippingnow.db')
out = conn.execute('INSERT INTO cliphistory (date,history,star) values (?,?,?)',[int(time.time()*1000),"test_test",False])
Loading…
Cancel
Save