2 /// \file bjavaloader.cc
7 Copyright (C) 2008-2009, Nicolas VIVIEN
8 Copyright (C) 2005-2012, 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 #include "barrygetopt.h"
39 // supported javaloader commands
40 #define CMD_LIST "dir"
41 #define CMD_ERASE "erase"
42 #define CMD_LOAD "load"
43 #define CMD_SCREENSHOT "screenshot"
44 #define CMD_SETTIME "settime"
45 #define CMD_EVENTLOG "eventlog"
46 #define CMD_CLEAR_LOG "cleareventlog"
47 #define CMD_SAVE "save"
48 #define CMD_DEVICEINFO "deviceinfo"
49 #define CMD_WIPE "wipe"
50 #define CMD_LOGSTRACES "logstacktraces"
51 #define CMD_RESETFACTORY "resettofactory"
53 // time string format specifier and user friendly description
54 #define TIME_FMT "%Y-%m-%d %H:%M:%S"
55 #define TIME_FMT_EXAMPLE "yyyy-mm-dd HH:MM:SS"
58 using namespace Barry
;
62 int logical
, major
, minor
;
63 const char *Version
= Barry::Version(logical
, major
, minor
);
65 cerr
<< string_vprintf(
66 _("bjavaloader - Command line USB Blackberry Java Loader\n"
67 " Copyright 2008-2009, Nicolas VIVIEN.\n"
68 " Copyright 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)\n"
71 " -A Save all modules found\n"
72 " -a Wipe applications only\n"
73 " -i Wipe filesystem only\n"
74 " -f Force erase, if module is in use\n"
76 " -s List sibling in module list\n"
77 " -p pin PIN of device to talk with\n"
78 " If only one device is plugged in, this flag is optional\n"
79 " -P pass Simplistic method to specify device password\n"
80 " -v Dump protocol data during operation\n"
85 " Lists modules on the handheld\n"
88 " Provides information on the handheld\n"
90 " %s <.cod file> ...\n"
91 " Loads modules onto the handheld\n"
93 " %s [-A] <module name> ...\n"
94 " Retrieves modules from the handheld and writes to .cod file\n"
95 " Note: will overwrite existing files!\n"
98 " Wipes the handheld\n"
99 " Use Caution: Wiping filesystem will remove all data\n"
100 " such as messages, contacts, etc.\n"
101 " Wiping applications will remove all .cod files\n"
102 " on the device, including OS .cod files.\n"
105 " Reset IT policy to factory defaults\n"
106 " Use Caution: Resetting IT policy to factory defaults will\n"
107 " also perform a filesystem wipe which will remove\n"
108 " all data such as messages, contacts, etc.\n"
110 " %s [-f] <module name> ...\n"
111 " Erase module from handheld\n"
114 " Retrieves the handheld event log\n"
117 " Clears the handheld event log\n"
120 " Dump the stack traces for all threads to the event log\n"
123 " Make a screenshot of handheld\n"
126 " Sets the time on the handheld to the current time\n"
127 " Or the time specified as an argument to %s\n"
128 " If given as argument, current system timezone is assumed\n"),
141 CMD_SETTIME
, TIME_FMT_EXAMPLE
, CMD_SETTIME
)
151 AutoClose(FILE *fh
) : fp(fh
) {}
158 void SetTime(Barry::Mode::JavaLoader
*javaloader
, const char *timestr
)
164 memset(&timeinfo
, 0, sizeof(timeinfo
));
167 char *p
= strptime(timestr
, TIME_FMT
, &timeinfo
);
169 // NULL is return when strptime fails to match all of the format
170 // string, and returns a pointer to the NULL byte at the end of
171 // the input string on success
172 if( p
== NULL
|| p
!= (timestr
+ strlen(timestr
)) ) {
173 throw runtime_error(string(_("Unable to parse time string: ")) + timestr
);
176 when
= mktime(&timeinfo
);
177 } else { // time string is NULL, get current time
181 javaloader
->SetTime(when
);
184 void SendAppFile(Barry::Mode::JavaLoader
*javaloader
, const char *filename
)
186 ifstream
file(filename
);
187 javaloader
->LoadApp(file
);
190 void GetScreenshot(Barry::Mode::JavaLoader
*javaloader
, const char *filename
)
194 // - info object contains the screenshot properties (width, height...)
195 // - image will be filled with the raw pixel screenshot data
198 javaloader
->GetScreenshot(info
, image
);
201 // Convert to BMP format
202 Data
bitmap(-1, GetTotalBitmapSize(info
));
203 ScreenshotToBitmap(info
, image
, bitmap
);
206 FILE *fp
= fopen(filename
, "wb");
208 throw runtime_error(string(_("Can't open: ")) + filename
);
212 fwrite(bitmap
.GetData(), bitmap
.GetSize(), 1, fp
);
215 void SaveModule(Barry::Mode::JavaLoader
*javaloader
, const char *filename
)
217 string
fname(filename
), module
;
219 size_t ext_index
= fname
.rfind(".cod");
220 if( ext_index
!= string::npos
) {
221 // filename contains .cod extension, strip it for module name
222 module
= fname
.substr(0, ext_index
);
225 // filename does not contain .cod extension, use it as module name
227 // append extension to file name
228 fname
.append(".cod");
231 ofstream
file(fname
.c_str(), ios::binary
| ios::trunc
);
232 javaloader
->Save(module
.c_str(), file
);
236 int main(int argc
, char *argv
[])
240 cout
.sync_with_stdio(true); // leave this on, since libusb uses
241 // stdio for debug messages
246 bool list_siblings
= false,
253 vector
<string
> params
;
257 Usb::EndpointPair epOverride
;
259 // process command line options
261 int cmd
= getopt(argc
, argv
, "Aaifhsp:P:v");
267 case 'p': // Blackberry PIN
268 pin
= strtoul(optarg
, NULL
, 16);
271 case 'P': // Device password
275 case 'f': // turn on 'force' mode for erase
279 case 's': // turn on listing of sibling modules
280 list_siblings
= true;
283 case 'v': // data dump on
287 case 'A': // save all modules
291 case 'a': // wipe apps only
295 case 'i': // wipe filesystem
310 cerr
<< _("missing command") << endl
;
315 // Fetch command from remaining arguments
316 string cmd
= argv
[0];
320 // Put the remaining arguments into an array
321 for (; argc
> 0; argc
--, argv
++) {
322 params
.push_back(string(argv
[0]));
325 // Initialize the barry library. Must be called before
327 Barry::Init(data_dump
);
329 // Probe the USB bus for Blackberry devices and display.
330 // If user has specified a PIN, search for it in the
331 // available device list here as well
333 int activeDevice
= probe
.FindActive(pin
);
334 if( activeDevice
== -1 ) {
335 cerr
<< _("No device selected, or PIN not found")
340 // Create our controller object
341 Barry::Controller
con(probe
.Get(activeDevice
));
342 Barry::Mode::JavaLoader
javaloader(con
);
345 // execute each mode that was turned on
347 javaloader
.Open(password
.c_str());
348 javaloader
.StartStream();
350 if( cmd
== CMD_LIST
) {
352 javaloader
.GetDirectory(dir
, list_siblings
);
355 else if( cmd
== CMD_LOAD
) {
356 if( params
.size() == 0 ) {
357 cerr
<< _("specify at least one .cod file to load") << endl
;
362 vector
<string
>::iterator i
= params
.begin(), end
= params
.end();
363 for( ; i
!= end
; ++i
) {
364 cout
<< _("loading: ") << (*i
) << "... ";
365 SendAppFile(&javaloader
, (*i
).c_str());
366 cout
<< _("done.") << endl
;
369 else if( cmd
== CMD_ERASE
) {
370 if( params
.size() == 0 ) {
371 cerr
<< _("specify at least one module to erase") << endl
;
376 vector
<string
>::iterator i
= params
.begin(), end
= params
.end();
377 for( ; i
!= end
; ++i
) {
378 cout
<< _("erasing: ") << (*i
) << "... ";
380 javaloader
.ForceErase((*i
));
382 javaloader
.Erase((*i
));
383 cout
<< _("done.") << endl
;
386 else if( cmd
== CMD_SCREENSHOT
) {
387 if( params
.size() == 0 ) {
388 cerr
<< _("specify a .bmp filename") << endl
;
393 GetScreenshot(&javaloader
, params
[0].c_str());
395 else if( cmd
== CMD_SETTIME
) {
396 if( params
.size() > 0 ) {
397 SetTime(&javaloader
, params
[0].c_str());
399 SetTime(&javaloader
, NULL
);
402 else if( cmd
== CMD_EVENTLOG
) {
404 javaloader
.GetEventlog(log
);
407 else if( cmd
== CMD_CLEAR_LOG
) {
408 javaloader
.ClearEventlog();
410 else if( cmd
== CMD_LOGSTRACES
) {
411 javaloader
.LogStackTraces();
413 else if( cmd
== CMD_SAVE
) {
416 javaloader
.GetDirectory(dir
, false);
417 JLDirectory::BaseIterator i
= dir
.begin();
418 for( ; i
!= dir
.end(); ++i
) {
419 cout
<< _("saving: ") << i
->Name
<< "... ";
420 SaveModule(&javaloader
,i
->Name
.c_str());
421 cout
<< _("done.") << endl
;
424 else if( params
.size() == 0 ) {
425 cerr
<< _("specify at least one module to save") << endl
;
430 vector
<string
>::iterator i
= params
.begin(), end
= params
.end();
431 for( ; i
!= end
; ++i
) {
432 cout
<< _("saving: ") << (*i
) << "... ";
433 SaveModule(&javaloader
, (*i
).c_str());
434 cout
<< _("done.") << endl
;
438 else if( cmd
== CMD_DEVICEINFO
) {
440 javaloader
.DeviceInfo(info
);
443 else if( cmd
== CMD_WIPE
) {
444 cout
<< string_vprintf(
445 // TRANSLATORS: you may translate yes/no as long as you also
446 // translate "yes" to match.
447 _("Use Caution: Wiping filesystem will remove all data\n"
448 " such as messages, contacts, etc.\n"
449 " Wiping applications will remove all .cod files\n"
450 " on the device, including OS .cod files.\n\n"
451 "You have selected to wipe the filesystem of device '%s'\n"
452 "Continue with wipe? (yes/no) "), probe
.Get(activeDevice
).m_pin
.Str().c_str());
454 getline(cin
, confirm
);
455 if( confirm
== _("yes") ) {
456 javaloader
.Wipe(wipe_apps
, wipe_fs
);
459 cout
<< _("Response of 'yes' not received, aborting.") << endl
;
462 else if( cmd
== CMD_RESETFACTORY
) {
463 cout
<< string_vprintf(
464 _("Use Caution: Resetting IT policy to factory defaults will\n"
465 " also perform a filesystem wipe which will remove\n"
466 " all data such as messages, contacts, etc.\n\n"
467 "You have selected to reset device '%s' to factory defaults\n"
468 "Continue with wipe? (yes/no) "), probe
.Get(activeDevice
).m_pin
.Str().c_str());
470 getline(cin
, confirm
);
471 if( confirm
== _("yes") ) {
472 javaloader
.ResetToFactory();
475 cout
<< _("Response of 'yes' not received, aborting.") << endl
;
479 cerr
<< _("invalid command: ") << cmd
<< endl
;
485 javaloader
.StopStream();
488 catch( Usb::Error
&ue
) {
489 std::cout
<< endl
; // flush any normal output first
490 std::cerr
<< _("Usb::Error caught: ") << ue
.what() << endl
;
493 catch( Barry::Error
&se
) {
495 std::cerr
<< _("Barry::Error caught: ") << se
.what() << endl
;
498 catch( std::exception
&e
) {
500 std::cerr
<< _("std::exception caught: ") << e
.what() << endl
;