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 " << 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
<< 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)));
170 // unknown database, use null parser
171 return auto_ptr
<Parser
>( new Parser
);
175 auto_ptr
<Builder
> GetBuilder(const string
&name
, const string
&filename
)
177 // check for recognized database names
178 if( name
== "Address Book" ) {
179 return auto_ptr
<Builder
>(
180 new RecordBuilder
<Contact
, Store
<Contact
> > (
181 new Store
<Contact
>(filename
, true)));
184 else if( name == "Messages" ) {
185 return auto_ptr<Parser>(
186 new RecordParser<Message, Store<Message> > (
187 new Store<Message>(filename, true)));
189 else if( name == "Calendar" ) {
190 return auto_ptr<Parser>(
191 new RecordParser<Calendar, Store<Calendar> > (
192 new Store<Calendar>(filename, true)));
196 throw std::runtime_error("No Builder available for database");
200 int main(int argc
, char *argv
[])
202 cout
.sync_with_stdio(true); // leave this on, since libusb uses
203 // stdio for debug messages
208 bool list_only
= false,
210 ldif_contacts
= false,
214 vector
<string
> dbNames
, saveDbNames
;
216 // process command line options
218 int cmd
= getopt(argc
, argv
, "c:d:f:hlp:s:tv");
224 case 'c': // contacts to ldap ldif
225 ldif_contacts
= true;
229 case 'd': // show dbname
230 dbNames
.push_back(string(optarg
));
233 case 'f': // filename
234 #ifdef __BOOST_MODE__
237 cerr
<< "-f option not supported - no Boost "
238 "serialization support available";
241 case 'l': // list only
245 case 'p': // Blackberry PIN
246 pin
= strtoul(optarg
, NULL
, 16);
249 case 's': // save dbname
250 saveDbNames
.push_back(string(optarg
));
253 case 't': // display database database
257 case 'v': // data dump on
268 // Initialize the barry library. Must be called before
270 Barry::Init(data_dump
);
272 // Probe the USB bus for Blackberry devices and display.
273 // If user has specified a PIN, search for it in the
274 // available device list here as well
276 int activeDevice
= -1;
277 cout
<< "Blackberry devices found:" << endl
;
278 for( int i
= 0; i
< probe
.GetCount(); i
++ ) {
279 cout
<< probe
.Get(i
) << endl
;
280 if( probe
.Get(i
).m_pin
== pin
)
287 if( activeDevice
== -1 ) {
289 // can we default to single device?
290 if( probe
.GetCount() == 1 )
293 cerr
<< "No device selected" << endl
;
298 cerr
<< "PIN " << setbase(16) << pin
299 << " not found" << endl
;
304 // Create our controller object
305 Barry::Controller
con(probe
.Get(activeDevice
));
308 // execute each mode that was turned on
312 // Dump list of all databases to stdout
314 // open desktop mode socket
315 con
.OpenMode(Controller::Desktop
);
316 cout
<< con
.GetDBDB() << endl
;
319 // Dump list of contacts to an LDAP LDIF file
320 // This uses the Controller convenience templates
321 if( ldif_contacts
) {
322 // make sure we're in desktop mode
323 con
.OpenMode(Controller::Desktop
);
325 // create a storage functor object that accepts
326 // Barry::Contact objects as input
327 Contact2Ldif
storage(ldifBaseDN
);
329 // load all the Contact records into storage
330 con
.LoadDatabaseByType
<Barry::Contact
>(storage
);
333 // Dump contents of selected databases to stdout, or
334 // to file if specified.
335 // This is retrieving data from the Blackberry.
336 if( dbNames
.size() ) {
337 vector
<string
>::iterator b
= dbNames
.begin();
339 for( ; b
!= dbNames
.end(); b
++ ) {
340 con
.OpenMode(Controller::Desktop
);
341 auto_ptr
<Parser
> parse
= GetParser(*b
,filename
);
342 unsigned int id
= con
.GetDBID(*b
);
343 con
.LoadDatabase(id
, *parse
.get());
347 // Save contents of file to specified databases
348 // This is writing data to the Blackberry.
349 if( saveDbNames
.size() ) {
350 vector
<string
>::iterator b
= saveDbNames
.begin();
352 for( ; b
!= saveDbNames
.end(); b
++ ) {
353 con
.OpenMode(Controller::Desktop
);
354 auto_ptr
<Builder
> build
=
355 GetBuilder(*b
, filename
);
356 unsigned int id
= con
.GetDBID(*b
);
357 con
.SaveDatabase(id
, *build
);
362 catch( Barry::BError
&se
) {
363 std::cerr
<< "BError caught: " << se
.what() << endl
;
365 catch( Usb::UsbError
&ue
) {
366 std::cerr
<< "UsbError caught: " << ue
.what() << endl
;
368 catch( std::runtime_error
&re
) {
369 std::cerr
<< "std::runtime_error caught: " << re
.what() << endl
;
372 catch( std::exception
&e
) {
373 std::cerr
<< "std::exception caught: " << e
.what() << endl
;