2 /// \file bjavaloader.cc
7 Copyright (C) 2008-2009, Nicolas VIVIEN
8 Copyright (C) 2005-2010, Net Direct Inc. (http://www.netdirect.ca/)
10 Some parts are inspired from btool.cc
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 See the GNU General Public License in the COPYING file at the
22 root directory of this project for more details.
26 #include <barry/barry.h>
37 // supported javaloader commands
38 #define CMD_LIST "dir"
39 #define CMD_ERASE "erase"
40 #define CMD_LOAD "load"
41 #define CMD_SCREENSHOT "screenshot"
42 #define CMD_SETTIME "settime"
43 #define CMD_EVENTLOG "eventlog"
44 #define CMD_CLEAR_LOG "cleareventlog"
45 #define CMD_SAVE "save"
46 #define CMD_DEVICEINFO "deviceinfo"
47 #define CMD_WIPE "wipe"
48 #define CMD_LOGSTRACES "logstacktraces"
49 #define CMD_RESETFACTORY "resettofactory"
51 // time string format specifier and user friendly description
52 #define TIME_FMT "%Y-%m-%d %H:%M:%S"
53 #define TIME_FMT_EXAMPLE "yyyy-mm-dd HH:MM:SS"
56 using namespace Barry
;
61 const char *Version
= Barry::Version(major
, minor
);
64 << "bjavaloader - Command line USB Blackberry Java Loader\n"
65 << " Copyright 2008-2009, Nicolas VIVIEN.\n"
66 << " Copyright 2005-2010, Net Direct Inc. (http://www.netdirect.ca/)\n"
67 << " Using: " << Version
<< "\n"
69 << " -A Save all modules found\n"
70 << " -a Wipe applications only\n"
71 << " -i Wipe filesystem only\n"
72 << " -f Force erase, if module is in use\n"
74 << " -s List sibling in module list\n"
75 << " -p pin PIN of device to talk with\n"
76 << " If only one device is plugged in, this flag is optional\n"
77 << " -P pass Simplistic method to specify device password\n"
78 << " -v Dump protocol data during operation\n"
82 << " " << CMD_LIST
<< " [-s]\n"
83 << " Lists modules on the handheld\n"
85 << " " << CMD_DEVICEINFO
<< "\n"
86 << " Provides information on the handheld\n"
88 << " " << CMD_LOAD
<< " <.cod file> ...\n"
89 << " Loads modules onto the handheld\n"
91 << " " << CMD_SAVE
<< " [-A] <module name> ...\n"
92 << " Retrieves modules from the handheld and writes to .cod file\n"
93 << " Note: will overwrite existing files!\n"
95 << " " << CMD_WIPE
<< " [-a | -i]\n"
96 << " Wipes the handheld\n"
97 << " Use Caution: Wiping filesystem will remove all data\n"
98 << " such as messages, contacts, etc.\n"
99 << " Wiping applications will remove all .cod files\n"
100 << " on the device, including OS .cod files.\n"
102 << " " << CMD_RESETFACTORY
<< "\n"
103 << " Reset IT policy to factory defaults\n"
104 << " Use Caution: Resetting IT policy to factory defaults will\n"
105 << " also perform a filesystem wipe which will remove\n"
106 << " all data such as messages, contacts, etc.\n"
108 << " " << CMD_ERASE
<< " [-f] <module name> ...\n"
109 << " Erase module from handheld\n"
111 << " " << CMD_EVENTLOG
<< "\n"
112 << " Retrieves the handheld event log\n"
114 << " " << CMD_CLEAR_LOG
<< "\n"
115 << " Clears the handheld event log\n"
117 << " " << CMD_LOGSTRACES
<< "\n"
118 << " Dump the stack traces for all threads to the event log\n"
120 << " " << CMD_SCREENSHOT
<< " <.bmp file>\n"
121 << " Make a screenshot of handheld\n"
123 << " " << CMD_SETTIME
<< " [" << TIME_FMT_EXAMPLE
<< "]\n"
124 << " Sets the time on the handheld to the current time\n"
125 << " Or the time specified as an argument to " << CMD_SETTIME
<< "\n"
126 << " If given as argument, current system timezone is assumed\n"
136 AutoClose(FILE *fh
) : fp(fh
) {}
143 void SetTime(Barry::Mode::JavaLoader
*javaloader
, const char *timestr
)
149 memset(&timeinfo
, 0, sizeof(timeinfo
));
152 char *p
= strptime(timestr
, TIME_FMT
, &timeinfo
);
154 // NULL is return when strptime fails to match all of the format
155 // string, and returns a pointer to the NULL byte at the end of
156 // the input string on success
157 if( p
== NULL
|| p
!= (timestr
+ strlen(timestr
)) ) {
158 throw runtime_error(string("Unable to parse time string: ") + timestr
);
161 when
= mktime(&timeinfo
);
162 } else { // time string is NULL, get current time
166 javaloader
->SetTime(when
);
169 void SendAppFile(Barry::Mode::JavaLoader
*javaloader
, const char *filename
)
171 ifstream
file(filename
);
172 javaloader
->LoadApp(file
);
175 void GetScreenshot(Barry::Mode::JavaLoader
*javaloader
, const char *filename
)
179 // - info object contains the screenshot properties (width, height...)
180 // - image will be filled with the raw pixel screenshot data
183 javaloader
->GetScreenshot(info
, image
);
186 // Convert to BMP format
187 Data
bitmap(-1, GetTotalBitmapSize(info
));
188 ScreenshotToBitmap(info
, image
, bitmap
);
191 FILE *fp
= fopen(filename
, "wb");
193 throw runtime_error(string("Can't open: ") + filename
);
197 fwrite(bitmap
.GetData(), bitmap
.GetSize(), 1, fp
);
200 void SaveModule(Barry::Mode::JavaLoader
*javaloader
, const char *filename
)
202 string
fname(filename
), module
;
204 size_t ext_index
= fname
.rfind(".cod");
205 if( ext_index
!= string::npos
) {
206 // filename contains .cod extension, strip it for module name
207 module
= fname
.substr(0, ext_index
);
210 // filename does not contain .cod extension, use it as module name
212 // append extension to file name
213 fname
.append(".cod");
216 ofstream
file(fname
.c_str(), ios::binary
| ios::trunc
);
217 javaloader
->Save(module
.c_str(), file
);
221 int main(int argc
, char *argv
[])
225 cout
.sync_with_stdio(true); // leave this on, since libusb uses
226 // stdio for debug messages
231 bool list_siblings
= false,
238 vector
<string
> params
;
242 Usb::EndpointPair epOverride
;
244 // process command line options
246 int cmd
= getopt(argc
, argv
, "Aaifhsp:P:v");
252 case 'p': // Blackberry PIN
253 pin
= strtoul(optarg
, NULL
, 16);
256 case 'P': // Device password
260 case 'f': // turn on 'force' mode for erase
264 case 's': // turn on listing of sibling modules
265 list_siblings
= true;
268 case 'v': // data dump on
272 case 'A': // save all modules
276 case 'a': // wipe apps only
280 case 'i': // wipe filesystem
295 cerr
<< "missing command" << endl
;
300 // Fetch command from remaining arguments
301 string cmd
= argv
[0];
305 // Put the remaining arguments into an array
306 for (; argc
> 0; argc
--, argv
++) {
307 params
.push_back(string(argv
[0]));
310 // Initialize the barry library. Must be called before
312 Barry::Init(data_dump
);
314 // Probe the USB bus for Blackberry devices and display.
315 // If user has specified a PIN, search for it in the
316 // available device list here as well
318 int activeDevice
= probe
.FindActive(pin
);
319 if( activeDevice
== -1 ) {
320 cerr
<< "No device selected, or PIN not found" << endl
;
324 // Create our controller object
325 Barry::Controller
con(probe
.Get(activeDevice
));
326 Barry::Mode::JavaLoader
javaloader(con
);
329 // execute each mode that was turned on
331 javaloader
.Open(password
.c_str());
332 javaloader
.StartStream();
334 if( cmd
== CMD_LIST
) {
336 javaloader
.GetDirectory(dir
, list_siblings
);
339 else if( cmd
== CMD_LOAD
) {
340 if( params
.size() == 0 ) {
341 cerr
<< "specify at least one .cod file to load" << endl
;
346 vector
<string
>::iterator i
= params
.begin(), end
= params
.end();
347 for( ; i
!= end
; ++i
) {
348 cout
<< "loading " << (*i
) << "... ";
349 SendAppFile(&javaloader
, (*i
).c_str());
350 cout
<< "done." << endl
;
353 else if( cmd
== CMD_ERASE
) {
354 if( params
.size() == 0 ) {
355 cerr
<< "specify at least one module to erase" << endl
;
360 vector
<string
>::iterator i
= params
.begin(), end
= params
.end();
361 for( ; i
!= end
; ++i
) {
362 cout
<< "erasing: " << (*i
) << "... ";
364 javaloader
.ForceErase((*i
));
366 javaloader
.Erase((*i
));
367 cout
<< "done." << endl
;
370 else if( cmd
== CMD_SCREENSHOT
) {
371 if( params
.size() == 0 ) {
372 cerr
<< "specify a .bmp filename" << endl
;
377 GetScreenshot(&javaloader
, params
[0].c_str());
379 else if( cmd
== CMD_SETTIME
) {
380 if( params
.size() > 0 ) {
381 SetTime(&javaloader
, params
[0].c_str());
383 SetTime(&javaloader
, NULL
);
386 else if( cmd
== CMD_EVENTLOG
) {
388 javaloader
.GetEventlog(log
);
391 else if( cmd
== CMD_CLEAR_LOG
) {
392 javaloader
.ClearEventlog();
394 else if( cmd
== CMD_LOGSTRACES
) {
395 javaloader
.LogStackTraces();
397 else if( cmd
== CMD_SAVE
) {
400 javaloader
.GetDirectory(dir
, false);
401 JLDirectory::BaseIterator i
= dir
.begin();
402 for( ; i
!= dir
.end(); ++i
) {
403 cout
<< "saving: " << i
->Name
<< "... ";
404 SaveModule(&javaloader
,i
->Name
.c_str());
405 cout
<< "done." << endl
;
408 else if( params
.size() == 0 ) {
409 cerr
<< "specify at least one module to save" << endl
;
414 vector
<string
>::iterator i
= params
.begin(), end
= params
.end();
415 for( ; i
!= end
; ++i
) {
416 cout
<< "saving: " << (*i
) << "... ";
417 SaveModule(&javaloader
, (*i
).c_str());
418 cout
<< "done." << endl
;
422 else if( cmd
== CMD_DEVICEINFO
) {
424 javaloader
.DeviceInfo(info
);
427 else if( cmd
== CMD_WIPE
) {
429 << "Use Caution: Wiping filesystem will remove all data\n"
430 << " such as messages, contacts, etc.\n"
431 << " Wiping applications will remove all .cod files\n"
432 << " on the device, including OS .cod files.\n\n"
433 << "Continue with wipe? (yes/no) ";
435 getline(cin
, confirm
);
436 if( confirm
== "yes" ) {
437 javaloader
.Wipe(wipe_apps
, wipe_fs
);
440 cout
<< "Response of 'yes' not received, aborting." << endl
;
443 else if( cmd
== CMD_RESETFACTORY
) {
445 << "Use Caution: Resetting IT policy to factory defaults will\n"
446 << " also perform a filesystem wipe which will remove\n"
447 << " all data such as messages, contacts, etc.\n\n"
448 << "Continue with wipe? (yes/no) ";
450 getline(cin
, confirm
);
451 if( confirm
== "yes" ) {
452 javaloader
.ResetToFactory();
455 cout
<< "Response of 'yes' not received, aborting." << endl
;
459 cerr
<< "invalid command \"" << cmd
<< "\"" << endl
;
465 javaloader
.StopStream();
468 catch( Usb::Error
&ue
) {
469 std::cout
<< endl
; // flush any normal output first
470 std::cerr
<< "Usb::Error caught: " << ue
.what() << endl
;
473 catch( Barry::Error
&se
) {
475 std::cerr
<< "Barry::Error caught: " << se
.what() << endl
;
478 catch( std::exception
&e
) {
480 std::cerr
<< "std::exception caught: " << e
.what() << endl
;