3 /// Barry library tester
7 Copyright (C) 2005-2006, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
32 using namespace Barry
;
37 << "btool - Command line USB Blackberry Test Tool\n"
38 << " Copyright 2005-2006, Net Direct Inc. (http://www.netdirect.ca/)\n\n"
39 << " -c dn Convert address book database to LDIF format, using the\n"
40 << " specified baseDN\n"
41 << " -d db Load database 'db' and dump to screen\n"
42 << " Can be used multiple times to fetch more than one DB\n"
43 << " -f file Filename to save or load handheld data to/from\n"
45 << " -l List devices\n"
46 << " -p pin PIN of device to talk with\n"
47 << " If only one device plugged in, this flag is optional\n"
48 << " -s db Save database 'db' from data loaded from -f file\n"
49 << " -t Show database database table\n"
50 << " -v Dump protocol data during operation\n"
58 Contact2Ldif(const std::string
&baseDN
) : m_baseDN(baseDN
) {}
59 void operator()(const Contact
&rec
)
61 rec
.DumpLdif(cout
, m_baseDN
);
65 template <class Record
>
68 std::vector
<Record
> records
;
69 mutable typename
std::vector
<Record
>::const_iterator rec_it
;
74 Store(const string
&filename
, bool load
)
75 : rec_it(records
.end()),
83 if( load
&& filename
.size() ) {
84 // filename is available, attempt to load
85 cout
<< "Loading: " << filename
<< endl
;
86 ifstream
ifs(filename
.c_str());
87 boost::archive::text_iarchive
ia(ifs
);
89 cout
<< records
.size()
90 << " records loaded from '"
91 << filename
<< "'" << endl
;
92 sort(records
.begin(), records
.end());
93 rec_it
= records
.begin();
96 typename
std::vector
<Record
>::const_iterator beg
= records
.begin(), end
= records
.end();
97 for( ; beg
!= end
; beg
++ ) {
102 } catch( boost::archive::archive_exception
&ae
) {
103 cerr
<< "Archive exception in ~Store(): "
104 << ae
.what() << endl
;
110 cout
<< "Store counted " << dec
<< count
<< " records." << endl
;
111 #ifdef __BOOST_MODE__
114 if( !load
&& filename
.size() ) {
115 // filename is available, attempt to save
116 cout
<< "Saving: " << filename
<< endl
;
117 const std::vector
<Record
> &r
= records
;
118 ofstream
ofs(filename
.c_str());
119 boost::archive::text_oarchive
oa(ofs
);
121 cout
<< dec
<< r
.size() << " records saved to '"
122 << filename
<< "'" << endl
;
125 } catch( boost::archive::archive_exception
&ae
) {
126 cerr
<< "Archive exception in ~Store(): "
127 << ae
.what() << endl
;
133 void operator()(const Record
&rec
)
136 std::cout
<< rec
<< std::endl
;
137 records
.push_back(rec
);
140 // retrieval operator
141 bool operator()(Record
&rec
, unsigned int databaseId
) const
143 if( rec_it
== records
.end() )
151 auto_ptr
<Parser
> GetParser(const string
&name
, const string
&filename
)
153 // check for recognized database names
154 if( name
== "Address Book" ) {
155 return auto_ptr
<Parser
>(
156 new RecordParser
<Contact
, Store
<Contact
> > (
157 new Store
<Contact
>(filename
, false)));
159 else if( name
== "Messages" ) {
160 return auto_ptr
<Parser
>(
161 new RecordParser
<Message
, Store
<Message
> > (
162 new Store
<Message
>(filename
, false)));
164 else if( name
== "Calendar" ) {
165 return auto_ptr
<Parser
>(
166 new RecordParser
<Calendar
, Store
<Calendar
> > (
167 new Store
<Calendar
>(filename
, false)));
169 else if( name
== "Service Book" ) {
170 return auto_ptr
<Parser
>(
171 new RecordParser
<ServiceBook
, Store
<ServiceBook
> > (
172 new Store
<ServiceBook
>(filename
, false)));
175 // unknown database, use null parser
176 return auto_ptr
<Parser
>( new Parser
);
180 auto_ptr
<Builder
> GetBuilder(const string
&name
, const string
&filename
)
182 // check for recognized database names
183 if( name
== "Address Book" ) {
184 return auto_ptr
<Builder
>(
185 new RecordBuilder
<Contact
, Store
<Contact
> > (
186 new Store
<Contact
>(filename
, true)));
189 else if( name == "Messages" ) {
190 return auto_ptr<Parser>(
191 new RecordParser<Message, Store<Message> > (
192 new Store<Message>(filename, true)));
194 else if( name == "Calendar" ) {
195 return auto_ptr<Parser>(
196 new RecordParser<Calendar, Store<Calendar> > (
197 new Store<Calendar>(filename, true)));
199 else if( name == "Service Book" ) {
200 return auto_ptr<Parser>(
201 new RecordParser<ServiceBook, Store<ServiceBook> > (
202 new Store<ServiceBook>(filename, true)));
206 throw std::runtime_error("No Builder available for database");
210 int main(int argc
, char *argv
[])
212 cout
.sync_with_stdio(true); // leave this on, since libusb uses
213 // stdio for debug messages
218 bool list_only
= false,
220 ldif_contacts
= false,
224 vector
<string
> dbNames
, saveDbNames
;
226 // process command line options
228 int cmd
= getopt(argc
, argv
, "c:d:f:hlp:s:tv");
234 case 'c': // contacts to ldap ldif
235 ldif_contacts
= true;
239 case 'd': // show dbname
240 dbNames
.push_back(string(optarg
));
243 case 'f': // filename
244 #ifdef __BOOST_MODE__
247 cerr
<< "-f option not supported - no Boost "
248 "serialization support available";
251 case 'l': // list only
255 case 'p': // Blackberry PIN
256 pin
= strtoul(optarg
, NULL
, 16);
259 case 's': // save dbname
260 saveDbNames
.push_back(string(optarg
));
263 case 't': // display database database
267 case 'v': // data dump on
278 // Initialize the barry library. Must be called before
280 Barry::Init(data_dump
);
282 // Probe the USB bus for Blackberry devices and display.
283 // If user has specified a PIN, search for it in the
284 // available device list here as well
286 int activeDevice
= -1;
287 cout
<< "Blackberry devices found:" << endl
;
288 for( int i
= 0; i
< probe
.GetCount(); i
++ ) {
289 cout
<< probe
.Get(i
) << endl
;
290 if( probe
.Get(i
).m_pin
== pin
)
297 if( activeDevice
== -1 ) {
299 // can we default to single device?
300 if( probe
.GetCount() == 1 )
303 cerr
<< "No device selected" << endl
;
308 cerr
<< "PIN " << setbase(16) << pin
309 << " not found" << endl
;
314 // Create our controller object
315 Barry::Controller
con(probe
.Get(activeDevice
));
318 // execute each mode that was turned on
322 // Dump list of all databases to stdout
324 // open desktop mode socket
325 con
.OpenMode(Controller::Desktop
);
326 cout
<< con
.GetDBDB() << endl
;
329 // Dump list of contacts to an LDAP LDIF file
330 // This uses the Controller convenience templates
331 if( ldif_contacts
) {
332 // make sure we're in desktop mode
333 con
.OpenMode(Controller::Desktop
);
335 // create a storage functor object that accepts
336 // Barry::Contact objects as input
337 Contact2Ldif
storage(ldifBaseDN
);
339 // load all the Contact records into storage
340 con
.LoadDatabaseByType
<Barry::Contact
>(storage
);
343 // Dump contents of selected databases to stdout, or
344 // to file if specified.
345 // This is retrieving data from the Blackberry.
346 if( dbNames
.size() ) {
347 vector
<string
>::iterator b
= dbNames
.begin();
349 for( ; b
!= dbNames
.end(); b
++ ) {
350 con
.OpenMode(Controller::Desktop
);
351 auto_ptr
<Parser
> parse
= GetParser(*b
,filename
);
352 unsigned int id
= con
.GetDBID(*b
);
353 con
.LoadDatabase(id
, *parse
.get());
357 // Save contents of file to specified databases
358 // This is writing data to the Blackberry.
359 if( saveDbNames
.size() ) {
360 vector
<string
>::iterator b
= saveDbNames
.begin();
362 for( ; b
!= saveDbNames
.end(); b
++ ) {
363 con
.OpenMode(Controller::Desktop
);
364 auto_ptr
<Builder
> build
=
365 GetBuilder(*b
, filename
);
366 unsigned int id
= con
.GetDBID(*b
);
367 con
.SaveDatabase(id
, *build
);
372 catch( Barry::BError
&se
) {
373 std::cerr
<< "BError caught: " << se
.what() << endl
;
375 catch( Usb::UsbError
&ue
) {
376 std::cerr
<< "UsbError caught: " << ue
.what() << endl
;
378 catch( std::runtime_error
&re
) {
379 std::cerr
<< "std::runtime_error caught: " << re
.what() << endl
;
382 catch( std::exception
&e
) {
383 std::cerr
<< "std::exception caught: " << e
.what() << endl
;