java_file.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import os
  2. import typing
  3. import java_literals
  4. import java_types
  5. import smali_literals
  6. from typing import List, Tuple
  7. def get_class_name(jvm_name :str) -> str:
  8. split_jvm_name = jvm_name.split('/')
  9. class_name = split_jvm_name[len(split_jvm_name) - 1]
  10. if len(class_name) == 1:
  11. if class_name == 'I': return java_types.integer
  12. elif class_name == 'Z': return java_types.boolean
  13. elif class_name == 'J': return java_types.long
  14. elif class_name == 'F': return java_types.float
  15. elif class_name == 'D': return java_types.double
  16. elif class_name == 'V': return java_types.void
  17. else: return java_types.object
  18. else:
  19. # if starts with array, drop it
  20. if split_jvm_name[0][0] == '[':
  21. split_jvm_name[0] = split_jvm_name[0][1:]
  22. joined_name = '.'.join(split_jvm_name)
  23. # if ends with semicolon, drop it
  24. if joined_name[len(joined_name) - 1] == ';':
  25. joined_name = joined_name[:len(joined_name) - 1]
  26. if joined_name[0] == 'L':
  27. joined_name = joined_name[1:]
  28. return joined_name
  29. def get_method_name(method_and_type: str) -> str:
  30. type_index = method_and_type.index(':')
  31. return method_and_type[:type_index]
  32. class Line(List[str]):
  33. def string(self) -> str:
  34. join = ' '.join(self)
  35. replace = join.replace(' ', ' ', -1)
  36. trim_space = replace.rstrip()
  37. no_space_after_dot = trim_space.replace('. ', ' ', -1)
  38. no_space_before_semicolon = no_space_after_dot.replace(' ;', ';', -1)
  39. return no_space_before_semicolon
  40. class JavaFile:
  41. def __init__(self) -> None:
  42. self.lines :list[Line] = []
  43. self.imports :List[str] = []
  44. self.extends :str = ''
  45. self.implements : List[str] = []
  46. self.class_name : str = ''
  47. self.indent :int = 0
  48. self.smali_lines :int = 0
  49. def indentate(self, line :str) -> str:
  50. if self.indent < 1: return line
  51. line = '\t' * self.indent + line
  52. return line
  53. def add_line(self, line :list[str]) -> None:
  54. converted_line = Line()
  55. for word in line: converted_line.append(word)
  56. self.lines.append(self.indentate(converted_line))
  57. def first(self) -> Line:
  58. return self.lines[0]
  59. def last(self) -> Line:
  60. return self.lines[len(self.lines) - 1]
  61. def last_class_declaration(self) -> Tuple[Line, int]:
  62. for i in range(len(self.lines) - 1, -1, -1):
  63. line = self.lines[i]
  64. for word in line:
  65. if word == java_literals._class:
  66. return line, i
  67. return None, -1
  68. def replace_last(self, line :Line) -> None:
  69. self.lines[len(self.lines) - 1] = self.indentate(line)
  70. def replace(self, index :int, line :Line) -> None:
  71. self.lines[index] = line
  72. def print(self) -> None:
  73. for line in self.lines: print(line)
  74. def save(self, directory :str) -> None:
  75. class_name_parts = self.class_name.split('.')
  76. class_name = class_name_parts[len(class_name_parts) - 1]
  77. with open(os.path.join(directory, class_name + '.java'), 'w+') as file:
  78. file.writelines(self.lines)
  79. def parse_line(self, line :str) -> typing.Any:
  80. split_line = line.split()
  81. self.smali_lines += 1
  82. if len(split_line) != 0:
  83. opcode = split_line[0]
  84. if opcode == smali_literals._class:
  85. pass