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

Generated on Tue Jun 30 16:08:13 2009 for Barry by  doxygen 1.5.8