You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

58 lines
1.8 KiB

  1. import shlex
  2. import re
  3. import csv
  4. import sys
  5. csv.field_size_limit(2**31-1)
  6. dict_params = re.compile(r':([^\ \,\.\\\(\)\=]+)')
  7. list_params = re.compile(r'\?')
  8. class AndroidSQLConn:
  9. def __init__(self, device, filepath, use_root=True):
  10. self.device = device
  11. self.filepath = filepath
  12. self.root = use_root
  13. def _quote_param_(param):
  14. if isinstance(param, str):
  15. return "'{}'".format(param.replace("'", "''"))
  16. elif isinstance(param, bool):
  17. return '1' if param else '0'
  18. elif param is None:
  19. return 'NULL'
  20. else:
  21. return str(param)
  22. def _sub_params_(SQL, params):
  23. params = iter(params)
  24. try:
  25. return list_params.sub(lambda match: AndroidSQLConn._quote_param_(next(params)), SQL)
  26. except StopIteration:
  27. raise TypeError("Not enough parameters")
  28. def _sub_params_dict_(SQL, params):
  29. try:
  30. return dict_params.sub(lambda match: AndroidSQLConn._quote_param_(params[match.group(1)]), SQL)
  31. except KeyError:
  32. raise TypeError("Parameter specified but not in mapping")
  33. def execute(self, SQL, params=None):
  34. if params:
  35. if isinstance(params, dict):
  36. SQL = AndroidSQLConn._sub_params_dict_(SQL, params)
  37. else:
  38. SQL = AndroidSQLConn._sub_params_(SQL, params)
  39. SQL = shlex.quote(SQL)
  40. if self.root:
  41. shell = self.device.sudo
  42. else:
  43. shell = self.device.shell
  44. out = shell('sqlite3', '-header', '-csv',
  45. shlex.quote(self.filepath), SQL, output="out")
  46. if out:
  47. return csv.DictReader(out.splitlines())
  48. if __name__ == "__main__":
  49. print(AndroidSQLConn._sub_params_(
  50. "SELECT * FROM table WHERE name=?,age=?;", ["boby;DROP TABLE table", 1]))