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

Generated on 29 Mar 2010 for Barry by  doxygen 1.6.1