idb 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +19 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +65 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +2 -0
  9. data/bin/idb +5 -0
  10. data/idb.gemspec +41 -0
  11. data/lib/LICENSE +20 -0
  12. data/lib/README.md +54 -0
  13. data/lib/config/.dummy +0 -0
  14. data/lib/config/settings.yml +8 -0
  15. data/lib/gui/app_binary_tab_widget.rb +45 -0
  16. data/lib/gui/app_details_group_box.rb +213 -0
  17. data/lib/gui/app_list_dialog.rb +67 -0
  18. data/lib/gui/app_list_widget_item.rb +9 -0
  19. data/lib/gui/binary_strings_widget.rb +33 -0
  20. data/lib/gui/browse_filesystem_widget.rb +4 -0
  21. data/lib/gui/ca_manager_dialog.rb +137 -0
  22. data/lib/gui/cache_db_widget.rb +61 -0
  23. data/lib/gui/certificate_item.rb +5 -0
  24. data/lib/gui/console_widget.rb +163 -0
  25. data/lib/gui/cycript_console_widget.rb +68 -0
  26. data/lib/gui/cycript_thread.rb +81 -0
  27. data/lib/gui/device_info_group_box.rb +55 -0
  28. data/lib/gui/device_status_dialog.rb +351 -0
  29. data/lib/gui/file_system_events_widget.rb +4 -0
  30. data/lib/gui/fs_viewer_tab_widget.rb +245 -0
  31. data/lib/gui/i_device_syslog_thread.rb +47 -0
  32. data/lib/gui/images/check.png +0 -0
  33. data/lib/gui/images/folder.ico +0 -0
  34. data/lib/gui/images/iphone.ico +0 -0
  35. data/lib/gui/images/screenshot.png +0 -0
  36. data/lib/gui/key_chain_widget.rb +86 -0
  37. data/lib/gui/local_storage_tab_widget.rb +37 -0
  38. data/lib/gui/log_plain_text_edit.rb +18 -0
  39. data/lib/gui/log_widget.rb +71 -0
  40. data/lib/gui/main_tab_widget.rb +179 -0
  41. data/lib/gui/pasteboard_monitor_widget.rb +116 -0
  42. data/lib/gui/path_list_widget_item.rb +5 -0
  43. data/lib/gui/pb_watcher_thread.rb +63 -0
  44. data/lib/gui/plist_file_widget.rb +66 -0
  45. data/lib/gui/qt_ruby_variant.rb +16 -0
  46. data/lib/gui/screenshot_wizard.rb +169 -0
  47. data/lib/gui/settings_dialog.rb +69 -0
  48. data/lib/gui/settings_tab_widget.rb +149 -0
  49. data/lib/gui/shared_libraries_widget.rb +47 -0
  50. data/lib/gui/snoop_it_fs_events_widget.rb +150 -0
  51. data/lib/gui/snoop_it_keychain_widget.rb +172 -0
  52. data/lib/gui/snoop_it_sensitive_api_widget.rb +128 -0
  53. data/lib/gui/snoop_it_tab_widget.rb +27 -0
  54. data/lib/gui/snoop_it_update_thread.rb +48 -0
  55. data/lib/gui/sqlite_widget.rb +73 -0
  56. data/lib/gui/ssh_port_forward_tab_widget.rb +209 -0
  57. data/lib/gui/tool_widget.rb +94 -0
  58. data/lib/gui/url_handler_widget.rb +26 -0
  59. data/lib/gui/url_scheme_fuzz_widget.rb +103 -0
  60. data/lib/gui/url_scheme_widget.rb +60 -0
  61. data/lib/gui/weak_class_dump_widget.rb +89 -0
  62. data/lib/helper/ssh_port_forwarder.rb +72 -0
  63. data/lib/idb.rb +295 -0
  64. data/lib/idb/version.rb +3 -0
  65. data/lib/lib/CgBI.rb +153 -0
  66. data/lib/lib/abstract_device.rb +31 -0
  67. data/lib/lib/app.rb +286 -0
  68. data/lib/lib/app_binary.rb +57 -0
  69. data/lib/lib/ca_interface.rb +151 -0
  70. data/lib/lib/configuration.rb +0 -0
  71. data/lib/lib/console_launcher.rb +24 -0
  72. data/lib/lib/device.rb +438 -0
  73. data/lib/lib/device_ca_interface.rb +36 -0
  74. data/lib/lib/host_file_wrapper.rb +27 -0
  75. data/lib/lib/i_device_diagnostics_wrapper.rb +90 -0
  76. data/lib/lib/keychain_plist_parser.rb +15 -0
  77. data/lib/lib/local_operations.rb +67 -0
  78. data/lib/lib/otool_wrapper.rb +116 -0
  79. data/lib/lib/plist_util.rb +72 -0
  80. data/lib/lib/qt_thread_fix.rb +29 -0
  81. data/lib/lib/rsync_git_manager.rb +81 -0
  82. data/lib/lib/screen_shot_util.rb +59 -0
  83. data/lib/lib/settings.rb +67 -0
  84. data/lib/lib/simulator.rb +60 -0
  85. data/lib/lib/simulator_ca_interface.rb +16 -0
  86. data/lib/lib/snoop_it_wrapper.rb +80 -0
  87. data/lib/lib/ssh_operations.rb +136 -0
  88. data/lib/lib/ssh_port_forwarder.rb +43 -0
  89. data/lib/lib/tools.rb +11 -0
  90. data/lib/lib/url_scheme_fuzzer.rb +98 -0
  91. data/lib/lib/usb_muxd_wrapper.rb +32 -0
  92. data/lib/lib/weak_class_dump_wrapper.rb +62 -0
  93. data/lib/utils/dumpdecrypted/README +4 -0
  94. data/lib/utils/dumpdecrypted/dumpdecrypted_armv6.dylib +0 -0
  95. data/lib/utils/dumpdecrypted/dumpdecrypted_armv7.dylib +0 -0
  96. data/lib/utils/ios-ssl-kill-switch/com.isecpartners.nabla.sslkillswitch_v0.5-iOS_6.1.deb +0 -0
  97. data/lib/utils/keychain_dump/README +2 -0
  98. data/lib/utils/keychain_dump/keychain_dump +0 -0
  99. data/lib/utils/pbwatcher/pbwatcher +0 -0
  100. data/lib/utils/pcviewer/protectionclassviewer +0 -0
  101. data/lib/utils/weak_class_dump/README +5 -0
  102. data/lib/utils/weak_class_dump/weak_classdump.cy +726 -0
  103. metadata +412 -0
@@ -0,0 +1,68 @@
1
+ require_relative 'console_widget'
2
+ require_relative 'cycript_thread'
3
+ require 'open3'
4
+
5
+ module Idb
6
+ class CycriptConsoleWidget < Qt::Widget
7
+
8
+ def initialize *args
9
+ super *args
10
+ @to_send = nil
11
+ @console = ConsoleWidget.new
12
+ @console.connect(SIGNAL('command(QString)')) {|cmd|
13
+ puts cmd.inspect
14
+ @cycript_thread.send_data cmd + "\n"
15
+ # @cycript_thread.send_data "testtest\n"
16
+ }
17
+
18
+ @start = Qt::PushButton.new "Start"
19
+ @start.connect(SIGNAL :released) {
20
+ # @start.setEnabled(false)
21
+ # @stop.setEnabled(true)
22
+ start
23
+
24
+ #@console.result data
25
+
26
+ }
27
+
28
+ @stop = Qt::PushButton.new "Stop"
29
+ @stop.connect(SIGNAL :released) {
30
+ Thread.list.each {|t| p t}
31
+ @cycript_thread.send_data "testtest\n"
32
+ Thread.pass
33
+
34
+ }
35
+
36
+ layout = Qt::VBoxLayout.new do |v|
37
+ v.add_widget(@console)
38
+ v.add_widget(@start)
39
+ v.add_widget(@stop)
40
+ end
41
+ setLayout(layout)
42
+
43
+
44
+ end
45
+ def pure_string s
46
+ x = loop{ s[/\033\[\d+m/] = "" }
47
+ rescue IndexError
48
+ return s
49
+ x
50
+ end
51
+
52
+ def start
53
+ @cycript_thread = CycriptThread.new
54
+ @cycript_thread.connect(SIGNAL('new_entry(QString)')) {|line|
55
+ @console.result line
56
+ }
57
+ @cycript_thread.launch_process
58
+ end
59
+
60
+ def stop
61
+ @cycript_thread.stop
62
+ end
63
+
64
+
65
+
66
+
67
+ end
68
+ end
@@ -0,0 +1,81 @@
1
+ require 'net/ssh'
2
+
3
+ module Idb
4
+ class CycriptThread < Qt::Object
5
+ signals "new_entry(QString)"
6
+
7
+ attr_accessor :channel
8
+
9
+ def initialize *args
10
+ super *args
11
+ $terminate_cycript_thread = false
12
+ @queue = Queue.new
13
+
14
+
15
+
16
+ end
17
+
18
+ def send_data data
19
+ puts "sending data"
20
+ # @queue << data
21
+ @channel.send_data data
22
+ # @channel.send_data "testtest\n"
23
+ end
24
+
25
+
26
+ def stop
27
+ $terminate_cycript_thread = true
28
+ end
29
+
30
+ def launch_process
31
+
32
+ @channel = $device.ssh.open_channel do |ch|
33
+ channel.request_pty do |ch, success|
34
+ raise "Error requesting pty" unless success
35
+ ch.exec("export TERM=vt220; stty -echo -icanon; cycript -p SpringBoard") do |ch, success|
36
+ raise "Error opening shell" unless success
37
+
38
+ ch.on_extended_data do |ch, type, data|
39
+ STDOUT.print "Error: #{data}\n"
40
+ end
41
+
42
+ ch.on_data do |ch, data|
43
+ puts "emitting"
44
+ emit new_entry(data)
45
+ puts "done"
46
+ end
47
+
48
+ ch.on_close { |ch|
49
+ $log.info "cycript terminated"
50
+ }
51
+
52
+
53
+ end
54
+ end
55
+ end
56
+
57
+
58
+ puts "thred"
59
+ @abc = Thread.new do
60
+ loop do
61
+ #TODO mutex to protect device?
62
+ #even better: make one central thread that calls process.
63
+ # and all functions using it call it to ensure its running. or auto start it.
64
+ sleep 0.5
65
+ puts "loop"
66
+ $device.ssh.loop 0.1
67
+ puts "done"
68
+ if $terminate_cycript_thread
69
+ $log.info "Terminating cycript"
70
+ channel.close
71
+ break
72
+ end
73
+ end
74
+ $log.info "Terminating thread"
75
+ end
76
+
77
+
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,55 @@
1
+ require_relative 'device_status_dialog'
2
+
3
+ module Idb
4
+ class DeviceInfoGroupBox < Qt::GroupBox
5
+ signals "disconnect()"
6
+
7
+ def initialize *args
8
+ super *args
9
+
10
+ # details on selected app
11
+ @layout = Qt::GridLayout.new
12
+ setLayout(@layout)
13
+ setTitle "Selected Device"
14
+
15
+ @device = Qt::Label.new "<b><font color='red'>Please select a device from the 'Devices' menu.</font></b>", self, 0
16
+ @layout.addWidget @device, 0, 0, 2, 1
17
+ end
18
+
19
+ def update_device
20
+ if $device.device?
21
+ uname = $device.ops.execute("/bin/uname -a")
22
+ ssh_connection_info = ""
23
+ if $device.mode == "usb"
24
+ ssh_connection_info = " "
25
+ @device.setText "<b>USB device:</b> <b><font color='red'>Manually connect via SSH as #{$settings.ssh_username}@localhost:#{$device.usb_ssh_port}</font></b><br>#{uname}"
26
+ else
27
+ @device.setText "<b>USB device:</b> ssh://#{$settings.ssh_username}:[redacted]@#{$settings.ssh_host}:#{$settings.ssh_port}<br>#{uname}"
28
+ end
29
+
30
+ @status = Qt::PushButton.new "Status"
31
+ @status.connect(SIGNAL(:released)) {
32
+ @device_status = DeviceStatusDialog.new
33
+ @device_status.exec
34
+ }
35
+ @layout.addWidget @status, 0, 1
36
+
37
+ @disconnect = Qt::PushButton.new "Disconnect"
38
+ @disconnect.connect(SIGNAL(:released)) {
39
+ $device.close unless $device.nil?
40
+ $device = nil
41
+ emit disconnect()
42
+ @disconnect.setEnabled(false)
43
+ @status.setEnabled(false)
44
+ @device.setText("<b><font color='red'>Please select a device from the 'Devices' menu.</font></b>")
45
+ }
46
+ @layout.addWidget @disconnect, 1, 1
47
+
48
+ else
49
+ @device.setText "<b>Simulator:</b> #{$device.sim_dir}"
50
+ end
51
+ end
52
+
53
+
54
+ end
55
+ end
@@ -0,0 +1,351 @@
1
+ module Idb
2
+ class DeviceStatusDialog < Qt::Dialog
3
+
4
+
5
+ def installed_check_mark
6
+ installed_check_mark = Qt::Label.new
7
+ pixmap = Qt::Pixmap.new File.join(File.dirname(File.expand_path(__FILE__)), '/images/check.png')
8
+ installed_check_mark.setPixmap pixmap
9
+ installed_check_mark
10
+ end
11
+
12
+ def mark_rsync_installed
13
+ @rsync_label.text = @rsync_label.text + "<br>found: #{$device.rsync_path}"
14
+ @layout.addWidget installed_check_mark, 7, 1
15
+ setFixedHeight(sizeHint().height());
16
+ end
17
+
18
+ def mark_clutch_installed
19
+ @clutch_label.text = @clutch_label.text + "<br>found: #{$device.clutch_path}"
20
+ @layout.addWidget installed_check_mark, 8, 1
21
+ setFixedHeight(sizeHint().height());
22
+ end
23
+
24
+ def mark_keychain_dump_installed
25
+ @keychain_dump_label.text = @keychain_dump_label.text + "<br>found: #{$device.keychain_dump_path}"
26
+ @layout.addWidget installed_check_mark, 6, 1
27
+ setFixedHeight(sizeHint().height());
28
+ end
29
+
30
+ def mark_pcviewer_installed
31
+ @pcviewer_label.text = @pcviewer_label.text + "<br>found: #{$device.pcviewer_path}"
32
+ @layout.addWidget installed_check_mark, 5, 1
33
+ setFixedHeight(sizeHint().height());
34
+ end
35
+
36
+ def mark_pbwatcher_installed
37
+ @pbwatcher_label.text = @pbwatcher_label.text + "<br>found: #{$device.pbwatcher_path}"
38
+ @layout.addWidget installed_check_mark, 4, 1
39
+ setFixedHeight(sizeHint().height());
40
+ end
41
+
42
+ def mark_dumpdecrypted_installed
43
+ @dumpdecrypted_label.text = @dumpdecrypted_label.text + "<br>Found: #{$device.dumpdecrypted_path}"
44
+ @layout.addWidget installed_check_mark, 3, 1
45
+ setFixedHeight(sizeHint().height());
46
+ end
47
+
48
+
49
+ def mark_apt_get_installed
50
+ @aptget_label.text = @aptget_label.text + "<br>Found: #{$device.apt_get_path}"
51
+ @layout.addWidget installed_check_mark, 0, 1
52
+ setFixedHeight(sizeHint().height());
53
+ end
54
+
55
+ def mark_open_installed
56
+ @open_label.text = @open_label.text + "<br>Found: #{$device.open_path}"
57
+ @layout.addWidget installed_check_mark, 1, 1
58
+ setFixedHeight(sizeHint().height());
59
+ end
60
+
61
+ def mark_openurl_installed
62
+ @openurl_label.text = @openurl_label.text + "<br>Found: #{$device.openurl_path}"
63
+ @layout.addWidget installed_check_mark, 2, 1
64
+ setFixedHeight(sizeHint().height());
65
+ end
66
+
67
+ def mark_cycript_installed
68
+ @cycript_label.text = @cycript_label.text + "<br>Found: #{$device.cycript_path}"
69
+ @layout.addWidget installed_check_mark, 8, 1
70
+ setFixedHeight(sizeHint().height());
71
+ end
72
+
73
+
74
+ def initialize *args
75
+ super *args
76
+ @layout = Qt::GridLayout.new
77
+ setLayout(@layout)
78
+ setWindowTitle "Device Status"
79
+
80
+ @close_button = Qt::PushButton.new "Close"
81
+ @close_button.connect(SIGNAL(:released)) {|x|
82
+ reject()
83
+ }
84
+ #TODO: prevent closing
85
+ @layout.addWidget @close_button, 9, 2
86
+
87
+
88
+ #######################
89
+ ### APT-GET
90
+ #######################
91
+
92
+
93
+ @aptget_label = Qt::Label.new "<b>apt-get / aptitude</b><br>(Install additional software packages)"
94
+ @layout.addWidget @aptget_label, 0, 0
95
+
96
+
97
+ if $device.apt_get_installed?
98
+ mark_apt_get_installed
99
+ else
100
+ @install_aptget = Qt::PushButton.new "Install"
101
+ @install_aptget.connect(SIGNAL(:released)) {
102
+ $device.install_apt_get
103
+ if $device.apt_get_installed?
104
+ @install_aptget.hide
105
+ mark_apt_get_installed
106
+ end
107
+ }
108
+ @layout.addWidget @install_aptget, 0, 1
109
+ end
110
+ #######################
111
+ ### OPEN
112
+ #######################
113
+
114
+ @open_label = Qt::Label.new "<b>open</b><br>(Open apps on the device)"
115
+ @layout.addWidget @open_label, 1, 0
116
+
117
+ if $device.open_installed?
118
+ mark_open_installed
119
+ else
120
+ @install_open = Qt::PushButton.new "Install"
121
+ @install_open.connect(SIGNAL(:released)) {
122
+ $device.install_open
123
+ if $device.open_installed?
124
+ @install_open.hide
125
+ mark_open_installed
126
+ else
127
+ error = Qt::MessageBox.new
128
+ error.setInformativeText("open could not be installed. Please make sure Cydia has finished all tasks and is closed on the device.")
129
+ error.setIcon(Qt::MessageBox::Critical)
130
+ error.exec
131
+ end
132
+ }
133
+ @layout.addWidget @install_open, 1, 1
134
+ end
135
+
136
+ #######################
137
+ ### OPEN URL
138
+ #######################
139
+
140
+
141
+ @openurl_label = Qt::Label.new "<b>openURL</b><br>(Open URL on the device)"
142
+ @layout.addWidget @openurl_label, 2, 0
143
+
144
+
145
+ if $device.openurl_installed?
146
+ mark_openurl_installed
147
+ else
148
+ # @install_openurl = Qt::PushButton.new "Install"
149
+ # @install_openurl.connect(SIGNAL(:released)) {
150
+ # $device.install_openurl
151
+ # if $device.open_installed?
152
+ # @install_open.hide
153
+ # mark_open_installed
154
+ # end
155
+ # }
156
+ # @layout.addWidget @install_openurl, 2, 1
157
+ end
158
+
159
+
160
+ #######################
161
+ ### DUMPDECRYPTED
162
+ #######################
163
+
164
+ @dumpdecrypted_label = Qt::Label.new "<b>dumpdecrypted</b><br>(Decrypt app binaries on the device).<br>Developed and maintained by Stefan Esser https://github.com/stefanesser/dumpdecrypted"
165
+ @layout.addWidget @dumpdecrypted_label, 3, 0
166
+
167
+ if $device.dumpdecrypted_installed?
168
+ mark_dumpdecrypted_installed
169
+ else
170
+ @install_dumpdecrypted = Qt::PushButton.new "Install"
171
+ @install_dumpdecrypted.connect(SIGNAL(:released)) {
172
+ $device.install_dumpdecrypted
173
+ if $device.dumpdecrypted_installed?
174
+ @install_dumpdecrypted.hide
175
+ mark_dumpdecrypted_installed
176
+ else
177
+ error = Qt::MessageBox.new
178
+ error.setInformativeText("No compiled version of dumpdecrypted was found in utils/dumpdecrypted. It cannot be shipped with idb due to licensing issues. Compilation failed likely due to XCode 5 not shipping the right version of gcc anymore. Try manually copying dumpdecrypted.dylib into /var/root on the device.")
179
+ error.setIcon(Qt::MessageBox::Critical)
180
+ error.exec
181
+ end
182
+
183
+ }
184
+ @layout.addWidget @install_dumpdecrypted, 3, 1
185
+ end
186
+
187
+
188
+ #######################
189
+ ### PBWATCHER
190
+ #######################
191
+
192
+
193
+ @pbwatcher_label = Qt::Label.new "<b>pbwatcher</b><br>(idb pasteboard monitor helper)"
194
+ @layout.addWidget @pbwatcher_label, 4, 0
195
+
196
+ if $device.pbwatcher_installed?
197
+ mark_pbwatcher_installed
198
+ else
199
+ @install_pbwatcher = Qt::PushButton.new "Install"
200
+ @install_pbwatcher.connect(SIGNAL(:released)) {
201
+ $device.install_pbwatcher
202
+ if $device.pbwatcher_installed?
203
+ @install_pbwatcher.hide
204
+ mark_pbwatcher_installed
205
+ end
206
+ }
207
+
208
+
209
+ @layout.addWidget @install_pbwatcher, 4, 1
210
+ end
211
+
212
+
213
+ #######################
214
+ ### PCVIEWER
215
+ #######################
216
+
217
+
218
+ @pcviewer_label = Qt::Label.new "<b>pcviewer</b><br>(idb file protection class helper)"
219
+ @layout.addWidget @pcviewer_label, 5, 0
220
+
221
+ if $device.pcviewer_installed?
222
+ mark_pcviewer_installed
223
+ else
224
+ @install_pcviewer = Qt::PushButton.new "Install"
225
+ @install_pcviewer.connect(SIGNAL(:released)) {
226
+ $device.install_pcviewer
227
+ if $device.pcviewer_installed?
228
+ @install_pcviewer.hide
229
+ mark_pcviewer_installed
230
+ end
231
+ }
232
+
233
+
234
+ @layout.addWidget @install_pcviewer, 5, 1
235
+ end
236
+
237
+ #######################
238
+ ### KEYCHAIN_DUMPER
239
+ #######################
240
+
241
+
242
+ @keychain_dump_label = Qt::Label.new "<b>keychain_dump</b><br>(dumps the keychain into a plist file.<br>https://code.google.com/p/iphone-dataprotection/)"
243
+ @layout.addWidget @keychain_dump_label, 6, 0
244
+
245
+ if $device.keychain_dump_installed?
246
+ mark_keychain_dump_installed
247
+ else
248
+ @install_keychain_dump = Qt::PushButton.new "Install"
249
+ @install_keychain_dump.connect(SIGNAL(:released)) {
250
+ $device.install_keychain_dump
251
+ if $device.keychain_dump_installed?
252
+ @install_keychain_dump.hide
253
+ mark_keychain_dump_installed
254
+ end
255
+ }
256
+
257
+
258
+ @layout.addWidget @install_keychain_dump, 6, 1
259
+
260
+ end
261
+
262
+
263
+ #######################
264
+ ### rsync
265
+ #######################
266
+
267
+
268
+ @rsync_label = Qt::Label.new "<b>rsync</b><br>(folder synchronization)"
269
+ @layout.addWidget @rsync_label, 7, 0
270
+
271
+ if $device.rsync_installed?
272
+ mark_rsync_installed
273
+ else
274
+ @install_rsync = Qt::PushButton.new "Install"
275
+ @install_rsync.connect(SIGNAL(:released)) {
276
+ $device.install_rsync
277
+ if $device.rsync_installed?
278
+ @install_rsync.hide
279
+ mark_rsync_installed
280
+ else
281
+ error = Qt::MessageBox.new
282
+ error.setInformativeText("rsync could not be installed. Please make sure Cydia has finished all tasks and is closed on the device.")
283
+ error.setIcon(Qt::MessageBox::Critical)
284
+ error.exec
285
+ end
286
+ }
287
+
288
+
289
+ @layout.addWidget @install_rsync, 7, 1
290
+
291
+ end
292
+
293
+
294
+ #######################
295
+ ### CYCRIPT
296
+ #######################
297
+
298
+ @cycript_label = Qt::Label.new "<b>cycript</b><br>(explore and modify running applications using a hybrid of Objective-C++ and JavaScript. http://www.cycript.org/ )"
299
+ @layout.addWidget @cycript_label, 8, 0
300
+
301
+ if $device.cycript_installed?
302
+ mark_cycript_installed
303
+ else
304
+ @install_cycript = Qt::PushButton.new "Install"
305
+ @install_cycript.connect(SIGNAL(:released)) {
306
+ $device.install_cycript
307
+ if $device.cycript_installed?
308
+ @install_cycript.hide
309
+ mark_cycript_installed
310
+ else
311
+ error = Qt::MessageBox.new
312
+ error.setInformativeText("cycript could not be installed. Please make sure Cydia has finished all tasks and is closed on the device.")
313
+ error.setIcon(Qt::MessageBox::Critical)
314
+ error.exec
315
+ end
316
+ }
317
+ @layout.addWidget @install_cycript, 8, 1
318
+ end
319
+
320
+ #######################
321
+ ### clutch
322
+ #######################
323
+
324
+
325
+ # @clutch_label = Qt::Label.new "<b>Clutch (not used by idb)</b><br>(App cracking tool that also performs decryption. Installation from cydia.iphonecake.com.)"
326
+ # @layout.addWidget @clutch_label, 8, 0
327
+ #
328
+ # if $device.clutch_installed?
329
+ # mark_clutch_installed
330
+ # else
331
+ # @install_clutch = Qt::PushButton.new "Install"
332
+ # @install_clutch.connect(SIGNAL(:released)) {
333
+ # $device.setup_clutch_source
334
+ # $device.install_clutch
335
+ # if $device.clutch_installed?
336
+ # @install_clutch.hide
337
+ # mark_clutch_installed
338
+ # end
339
+ # }
340
+ #
341
+ #
342
+ # @layout.addWidget @install_clutch, 8, 1
343
+ #
344
+ # end
345
+
346
+ setFixedHeight(sizeHint().height());
347
+ end
348
+
349
+
350
+ end
351
+ end