# bjavaloader.cc

Go to the documentation of this file.

    00001 ///
    00002 /// \file       bjavaloader.cc
    00003 ///
    00004 ///
    00005
    00006 /*
    00007     Copyright (C) 2008-2009, Nicolas VIVIEN
    00008     Copyright (C) 2005-2011, Net Direct Inc. (http://www.netdirect.ca/)
    00009
    00010         Some parts are inspired from btool.cc
    00011
    00012     This program is free software; you can redistribute it and/or modify
    00013     it under the terms of the GNU General Public License as published by
    00014     the Free Software Foundation; either version 2 of the License, or
    00015     (at your option) any later version.
    00016
    00017     This program is distributed in the hope that it will be useful,
    00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00020
    00021     See the GNU General Public License in the COPYING file at the
    00022     root directory of this project for more details.
    00023 */
    00024
    00025
    00026 #include <barry/barry.h>
    00027 #include <iostream>
    00028 #include <vector>
    00029 #include <string>
    00030 #include <cstring>
    00031 #include <algorithm>
    00032 #include <getopt.h>
    00033 #include <fstream>
    00034 #include <string.h>
    00035 #include <time.h>
    00036 #include "i18n.h"
    00037
    00038 // supported javaloader commands
    00039 #define CMD_LIST                "dir"
    00040 #define CMD_ERASE               "erase"
    00041 #define CMD_LOAD                "load"
    00042 #define CMD_SCREENSHOT          "screenshot"
    00043 #define CMD_SETTIME             "settime"
    00044 #define CMD_EVENTLOG            "eventlog"
    00045 #define CMD_CLEAR_LOG           "cleareventlog"
    00046 #define CMD_SAVE                "save"
    00047 #define CMD_DEVICEINFO          "deviceinfo"
    00048 #define CMD_WIPE                "wipe"
    00049 #define CMD_LOGSTRACES          "logstacktraces"
    00050 #define CMD_RESETFACTORY        "resettofactory"
    00051
    00052 // time string format specifier and user friendly description
    00053 #define TIME_FMT         "%Y-%m-%d %H:%M:%S"
    00054 #define TIME_FMT_EXAMPLE "yyyy-mm-dd HH:MM:SS"
    00055
    00056 using namespace std;
    00057 using namespace Barry;
    00058
    00059 void Usage()
    00060 {
    00061    int major, minor;
    00062    const char *Version = Barry::Version(major, minor);
    00063
    00064    cerr
    00065    << "bjavaloader - Command line USB Blackberry Java Loader\n"
    00066    << "        Copyright 2008-2009, Nicolas VIVIEN.\n"
    00067    << "        Copyright 2005-2011, Net Direct Inc. (http://www.netdirect.ca/)\n"
    00068    << "        Using: " << Version << "\n"
    00069    << "\n"
    00070    << "   -A        Save all modules found\n"
    00071    << "   -a        Wipe applications only\n"
    00072    << "   -i        Wipe filesystem only\n"
    00073    << "   -f        Force erase, if module is in use\n"
    00074    << "   -h        This help\n"
    00075    << "   -s        List sibling in module list\n"
    00076    << "   -p pin    PIN of device to talk with\n"
    00077    << "             If only one device is plugged in, this flag is optional\n"
    00078    << "   -P pass   Simplistic method to specify device password\n"
    00079    << "   -v        Dump protocol data during operation\n"
    00080    << "\n"
    00081    << "commands\n"
    00082    << "\n"
    00083    << "   " << CMD_LIST << " [-s]\n"
    00084    << "      Lists modules on the handheld\n"
    00085    << "\n"
    00086    << "   " << CMD_DEVICEINFO << "\n"
    00087    << "      Provides information on the handheld\n"
    00088    << "\n"
    00089    << "   " << CMD_LOAD << " <.cod file> ...\n"
    00090    << "      Loads modules onto the handheld\n"
    00091    << "\n"
    00092    << "   " << CMD_SAVE << " [-A] <module name> ...\n"
    00093    << "      Retrieves modules from the handheld and writes to .cod file\n"
    00094    << "      Note: will overwrite existing files!\n"
    00095    << "\n"
    00096    << "   " << CMD_WIPE << " [-a | -i]\n"
    00097    << "      Wipes the handheld\n"
    00098    << "      Use Caution: Wiping filesystem will remove all data\n"
    00099    << "                   such as messages, contacts, etc.\n"
    00100    << "                   Wiping applications will remove all .cod files\n"
    00101    << "                   on the device, including OS .cod files.\n"
    00102    << "\n"
    00103    << "   " << CMD_RESETFACTORY << "\n"
    00104    << "      Reset IT policy to factory defaults\n"
    00105    << "      Use Caution: Resetting IT policy to factory defaults will\n"
    00106    << "                   also perform a filesystem wipe which will remove\n"
    00107    << "                   all data such as messages, contacts, etc.\n"
    00108    << "\n"
    00109    << "   " << CMD_ERASE << " [-f] <module name> ...\n"
    00110    << "      Erase module from handheld\n"
    00111    << "\n"
    00112    << "   " << CMD_EVENTLOG << "\n"
    00113    << "      Retrieves the handheld event log\n"
    00114    << "\n"
    00115    << "   " << CMD_CLEAR_LOG << "\n"
    00116    << "      Clears the handheld event log\n"
    00117    << "\n"
    00118    << "   " << CMD_LOGSTRACES << "\n"
    00119    << "      Dump the stack traces for all threads to the event log\n"
    00120    << "\n"
    00121    << "   " << CMD_SCREENSHOT << " <.bmp file>\n"
    00122    << "      Make a screenshot of handheld\n"
    00123    << "\n"
    00124    << "   " << CMD_SETTIME << " [" << TIME_FMT_EXAMPLE << "]\n"
    00125    << "      Sets the time on the handheld to the current time\n"
    00126    << "      Or the time specified as an argument to " << CMD_SETTIME << "\n"
    00127    << "      If given as argument, current system timezone is assumed\n"
    00128    << endl;
    00129 }
    00130
    00131
    00132 class AutoClose
    00133 {
    00134         FILE *fp;
    00135
    00136 public:
    00137         AutoClose(FILE *fh) : fp(fh) {}
    00138         ~AutoClose()
    00139         {
    00140                 fclose(fp);
    00141         }
    00142 };
    00143
    00144 void SetTime(Barry::Mode::JavaLoader *javaloader, const char *timestr)
    00145 {
    00146         time_t when;
    00147
    00148         if( timestr ) {
    00149                 struct tm timeinfo;
    00150                 memset(&timeinfo, 0, sizeof(timeinfo));
    00151
    00152                 // parse time string
    00153                 char *p = strptime(timestr, TIME_FMT, &timeinfo);
    00154
    00155                 // NULL is return when strptime fails to match all of the format
    00156                 // string, and returns a pointer to the NULL byte at the end of
    00157                 // the input string on success
    00158                 if( p == NULL || p != (timestr + strlen(timestr)) ) {
    00159                         throw runtime_error(string("Unable to parse time string: ") + timestr);
    00160                 }
    00161
    00162                 when = mktime(&timeinfo);
    00163         } else { // time string is NULL, get current time
    00164                 time(&when);
    00165         }
    00166
    00167         javaloader->SetTime(when);
    00168 }
    00169
    00170 void SendAppFile(Barry::Mode::JavaLoader *javaloader, const char *filename)
    00171 {
    00172         ifstream file(filename);
    00173         javaloader->LoadApp(file);
    00174 }
    00175
    00176 void GetScreenshot(Barry::Mode::JavaLoader *javaloader, const char *filename)
    00177 {
    00178
    00179         // Take a screenshot
    00180         //   - info object contains the screenshot properties (width, height...)
    00181         //   - image will be filled with the raw pixel screenshot data
    00182         JLScreenInfo info;
    00183         Data image;
    00184         javaloader->GetScreenshot(info, image);
    00185
    00186
    00187         // Convert to BMP format
    00188         Data bitmap(-1, GetTotalBitmapSize(info));
    00189         ScreenshotToBitmap(info, image, bitmap);
    00190
    00191         // Write BMP file
    00192         FILE *fp = fopen(filename, "wb");
    00193         if (fp == NULL) {
    00194                 throw runtime_error(string("Can't open: ") + filename);
    00195         }
    00196         AutoClose ac(fp);
    00197
    00198         fwrite(bitmap.GetData(), bitmap.GetSize(), 1, fp);
    00199 }
    00200
    00201 void SaveModule(Barry::Mode::JavaLoader *javaloader, const char *filename)
    00202 {
    00203         string fname(filename), module;
    00204
    00205         size_t ext_index = fname.rfind(".cod");
    00206         if( ext_index != string::npos ) {
    00207                 // filename contains .cod extension, strip it for module name
    00208                 module = fname.substr(0, ext_index);
    00209         }
    00210         else {
    00211                 // filename does not contain .cod extension, use it as module name
    00212                 module = fname;
    00213                 // append extension to file name
    00214                 fname.append(".cod");
    00215         }
    00216
    00217         ofstream file(fname.c_str(), ios::binary | ios::trunc);
    00218         javaloader->Save(module.c_str(), file);
    00219 }
    00220
    00221
    00222 int main(int argc, char *argv[])
    00223 {
    00224         INIT_I18N(PACKAGE);
    00225
    00226         cout.sync_with_stdio(true);     // leave this on, since libusb uses
    00227                                         // stdio for debug messages
    00228
    00229         try {
    00230
    00231                 uint32_t pin = 0;
    00232                 bool list_siblings = false,
    00233                         force_erase = false,
    00234                         data_dump = false,
    00235                         all_modules = false,
    00236                         wipe_apps = true,
    00237                         wipe_fs = true;
    00238                 string password;
    00239                 vector<string> params;
    00240                 string busname;
    00241                 string devname;
    00242                 string iconvCharset;
    00243                 Usb::EndpointPair epOverride;
    00244
    00245                 // process command line options
    00246                 for(;;) {
    00247                         int cmd = getopt(argc, argv, "Aaifhsp:P:v");
    00248                         if( cmd == -1 )
    00249                                 break;
    00250
    00251                         switch( cmd )
    00252                         {
    00253                         case 'p':       // Blackberry PIN
    00254                                 pin = strtoul(optarg, NULL, 16);
    00255                                 break;
    00256
    00257                         case 'P':       // Device password
    00258                                 password = optarg;
    00259                                 break;
    00260
    00261                         case 'f':       // turn on 'force' mode for erase
    00262                                 force_erase = true;
    00263                                 break;
    00264
    00265                         case 's':       // turn on listing of sibling modules
    00266                                 list_siblings = true;
    00267                                 break;
    00268
    00269                         case 'v':       // data dump on
    00270                                 data_dump = true;
    00271                                 break;
    00272
    00273                         case 'A':       // save all modules
    00274                                 all_modules = true;
    00275                                 break;
    00276
    00277                         case 'a':       // wipe apps only
    00278                                 wipe_fs = false;
    00279                                 break;
    00280
    00281                         case 'i':       // wipe filesystem
    00282                                 wipe_apps = false;
    00283                                 break;
    00284
    00285                         case 'h':       // help
    00286                         default:
    00287                                 Usage();
    00288                                 return 0;
    00289                         }
    00290                 }
    00291
    00292                 argc -= optind;
    00293                 argv += optind;
    00294
    00295                 if( argc < 1 ) {
    00296                         cerr << "missing command" << endl;
    00297                         Usage();
    00298                         return 1;
    00299                 }
    00300
    00301                 // Fetch command from remaining arguments
    00302                 string cmd = argv[0];
    00303                 argc --;
    00304                 argv ++;
    00305
    00306                 // Put the remaining arguments into an array
    00307                 for (; argc > 0; argc --, argv ++) {
    00308                         params.push_back(string(argv[0]));
    00309                 }
    00310
    00311                 // Initialize the barry library.  Must be called before
    00312                 // anything else.
    00313                 Barry::Init(data_dump);
    00314
    00315                 // Probe the USB bus for Blackberry devices and display.
    00316                 // If user has specified a PIN, search for it in the
    00317                 // available device list here as well
    00318                 Barry::Probe probe;
    00319                 int activeDevice = probe.FindActive(pin);
    00320                 if( activeDevice == -1 ) {
    00321                         cerr << "No device selected, or PIN not found" << endl;
    00322                         return 1;
    00323                 }
    00324
    00325                 // Create our controller object
    00326                 Barry::Controller con(probe.Get(activeDevice));
    00327                 Barry::Mode::JavaLoader javaloader(con);
    00328
    00329                 //
    00330                 // execute each mode that was turned on
    00331                 //
    00332                 javaloader.Open(password.c_str());
    00333                 javaloader.StartStream();
    00334
    00335                 if( cmd == CMD_LIST ) {
    00336                         JLDirectory dir;
    00337                         javaloader.GetDirectory(dir, list_siblings);
    00338                         cout << dir;
    00339                 }
    00340                 else if( cmd == CMD_LOAD ) {
    00341                         if( params.size() == 0 ) {
    00342                                 cerr << "specify at least one .cod file to load" << endl;
    00343                                 Usage();
    00344                                 return 1;
    00345                         }
    00346
    00347                         vector<string>::iterator i = params.begin(), end = params.end();
    00348                         for( ; i != end; ++i ) {
    00349                                 cout << "loading " << (*i) << "... ";
    00350                                 SendAppFile(&javaloader, (*i).c_str());
    00351                                 cout << "done." << endl;
    00352                         }
    00353                 }
    00354                 else if( cmd == CMD_ERASE ) {
    00355                         if( params.size() == 0 ) {
    00356                                 cerr << "specify at least one module to erase" << endl;
    00357                                 Usage();
    00358                                 return 1;
    00359                         }
    00360
    00361                         vector<string>::iterator i = params.begin(), end = params.end();
    00362                         for( ; i != end; ++i ) {
    00363                                 cout << "erasing: " << (*i) << "... ";
    00364                                 if( force_erase )
    00365                                         javaloader.ForceErase((*i));
    00366                                 else
    00367                                         javaloader.Erase((*i));
    00368                                 cout << "done." << endl;
    00369                         }
    00370                 }
    00371                 else if( cmd == CMD_SCREENSHOT ) {
    00372                         if( params.size() == 0 ) {
    00373                                 cerr << "specify a .bmp filename" << endl;
    00374                                 Usage();
    00375                                 return 1;
    00376                         }
    00377
    00378                         GetScreenshot(&javaloader, params[0].c_str());
    00379                 }
    00380                 else if( cmd == CMD_SETTIME ) {
    00381                         if( params.size() > 0 ) {
    00382                                 SetTime(&javaloader, params[0].c_str());
    00383                         } else {
    00384                                 SetTime(&javaloader, NULL);
    00385                         }
    00386                 }
    00387                 else if( cmd == CMD_EVENTLOG ) {
    00388                         JLEventlog log;
    00389                         javaloader.GetEventlog(log);
    00390                         cout << log;
    00391                 }
    00392                 else if( cmd == CMD_CLEAR_LOG ) {
    00393                         javaloader.ClearEventlog();
    00394                 }
    00395                 else if( cmd == CMD_LOGSTRACES ) {
    00396                         javaloader.LogStackTraces();
    00397                 }
    00398                 else if( cmd == CMD_SAVE ) {
    00399                         if( all_modules ) {
    00400                                 JLDirectory dir;
    00401                                 javaloader.GetDirectory(dir, false);
    00402                                 JLDirectory::BaseIterator i = dir.begin();
    00403                                 for( ; i != dir.end(); ++i ) {
    00404                                         cout << "saving: " << i->Name << "... ";
    00405                                         SaveModule(&javaloader,i->Name.c_str());
    00406                                         cout << "done." << endl;
    00407                                 }
    00408                         }
    00409                         else if( params.size() == 0 ) {
    00410                                 cerr << "specify at least one module to save" << endl;
    00411                                 Usage();
    00412                                 return 1;
    00413                         }
    00414                         else {
    00415                                 vector<string>::iterator i = params.begin(), end = params.end();
    00416                                 for( ; i != end; ++i ) {
    00417                                         cout << "saving: " << (*i) << "... ";
    00418                                         SaveModule(&javaloader, (*i).c_str());
    00419                                         cout << "done." << endl;
    00420                                 }
    00421                         }
    00422                 }
    00423                 else if( cmd == CMD_DEVICEINFO ) {
    00424                         JLDeviceInfo info;
    00425                         javaloader.DeviceInfo(info);
    00426                         cout << info;
    00427                 }
    00428                 else if( cmd == CMD_WIPE ) {
    00429                         cout
    00430                                 << "Use Caution: Wiping filesystem will remove all data\n"
    00431                                 << "             such as messages, contacts, etc.\n"
    00432                                 << "             Wiping applications will remove all .cod files\n"
    00433                                 << "             on the device, including OS .cod files.\n\n"
    00434                                 << "Continue with wipe? (yes/no) ";
    00435                         string confirm;
    00436                         getline(cin, confirm);
    00437                         if( confirm == "yes" ) {
    00438                                 javaloader.Wipe(wipe_apps, wipe_fs);
    00439                         }
    00440                         else {
    00441                                 cout << "Response of 'yes' not received, aborting." << endl;
    00442                         }
    00443                 }
    00444                 else if( cmd == CMD_RESETFACTORY ) {
    00445                         cout
    00446                                 << "Use Caution: Resetting IT policy to factory defaults will\n"
    00447                                 << "             also perform a filesystem wipe which will remove\n"
    00448                                 << "             all data such as messages, contacts, etc.\n\n"
    00449                                 << "Continue with wipe? (yes/no) ";
    00450                         string confirm;
    00451                         getline(cin, confirm);
    00452                         if( confirm == "yes" ) {
    00453                                 javaloader.ResetToFactory();
    00454                         }
    00455                         else {
    00456                                 cout << "Response of 'yes' not received, aborting." << endl;
    00457                         }
    00458                 }
    00459                 else {
    00460                         cerr << "invalid command \"" << cmd << "\"" << endl;
    00461                         Usage();
    00462                         return 1;
    00463                 }
    00464
    00465                 // Stop
    00466                 javaloader.StopStream();
    00467
    00468         }
    00469         catch( Usb::Error &ue) {
    00470                 std::cout << endl;      // flush any normal output first
    00471                 std::cerr << "Usb::Error caught: " << ue.what() << endl;
    00472                 return 1;
    00473         }
    00474         catch( Barry::Error &se ) {
    00475                 std::cout << endl;
    00476                 std::cerr << "Barry::Error caught: " << se.what() << endl;
    00477                 return 1;
    00478         }
    00479         catch( std::exception &e ) {
    00480                 std::cout << endl;
    00481                 std::cerr << "std::exception caught: " << e.what() << endl;
    00482                 return 1;
    00483         }
    00484
    00485         return 0;
    00486 }
    00487