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 

Generated on Tue Mar 1 17:50:14 2011 for Barry by  doxygen 1.5.6