1 /*********************************************************************/ 2 // dar - disk archive - a backup/restoration program 3 // Copyright (C) 2002-2052 Denis Corbin 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 2 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 // 19 // to contact the author : http://dar.linux.free.fr/email.html 20 /*********************************************************************/ 21 22 /// \file user_interaction.hpp 23 /// \brief defines the interaction between libdar and the user. 24 /// \ingroup API 25 /// 26 /// Three classes are defined 27 /// - user_interaction is the root class that you can use to make your own classes 28 /// - user_interaction_callback is a specialized inherited class which is implements 29 /// user interaction thanks to callback functions 30 /// - user_interaction_blind provides fully usable objects that do not show anything 31 /// and always assume a negative answer from the user 32 /// . 33 34 /////////////////////////////////////////////////////////////////////// 35 // IMPORTANT : THIS FILE MUST ALWAYS BE INCLUDE AFTER infinint.hpp // 36 // (and infinint.hpp must be included too, always) // 37 /////////////////////////////////////////////////////////////////////// 38 #include "infinint.hpp" 39 /////////////////////////////////////////////////////////////////////// 40 41 42 43 #ifndef USER_INTERACTION_HPP 44 #define USER_INTERACTION_HPP 45 46 #include "../my_config.h" 47 48 #include <string> 49 #include "erreurs.hpp" 50 #include "integers.hpp" 51 #include "secu_string.hpp" 52 #include "on_pool.hpp" 53 54 namespace libdar 55 { 56 57 /// \addtogroup API 58 /// @{ 59 60 61 62 /// This is a pure virtual class that is used by libdar when interaction with the user is required. 63 64 //! You can base your own class on it using C++ inheritance 65 //! or use the class user_interaction_callback which implements 66 //! the interaction based on callback functions. 67 //! The user_interaction class is used by libdar in the following circumpstances: 68 //! - when is required a boolean answer to a question the pause() method is used 69 //! - when a warning needs to be displayed to the user the warning() method is used 70 //! - when a directory listing needs to be returned to the user the listing() method is used 71 //! . 72 //! the printf() method is built over the warning() methods to display a formated message 73 //! it has not to be redefined in any inherited class. 74 //! If you want to define you own class as inherited class of user_interaction 75 //! you need to overwrite: 76 //! - the clone() method. It is used to make local temporary copies of objets 77 //! in libdar. It acts like the constructor copy but is virtual. 78 //! - the pause() method 79 //! - the warning() method 80 //! - the listing() method (this is not mandatory). inherited classes *can* 81 //! overwrite the listing() method, which will be used if the use_listing 82 //! is set to true thanks to the set_use_listing() protected method. 83 //! In that case the listing of archive contents is done thanks to this listing() 84 //! method instead of the warning() method. 85 //! - get_string() method 86 //! - get_secu_string() method 87 //! . 88 //! WARNING ! 89 //! if your own class has specific fields, you will probably 90 //! need to redefine the copy constructor as well as operator = 91 //! if you don't understand this and why, don't play trying making your 92 //! own class, and/or read good C++ book about canonical form 93 //! of a C++ class, as well as how to properly make an inherited class. 94 //! And don't, complain if libdar segfault or core dumps. Libdar 95 //! *needs* to make local copies of these objects, if the copy constructor 96 //! is not properly defined in your inherited class this will crash the application. 97 //! \ingroup API 98 class user_interaction : public on_pool 99 { 100 public: 101 102 /// class constructor. 103 user_interaction(); ~user_interaction()104 virtual ~user_interaction() {}; 105 106 /// method used to ask a boolean question to the user. 107 108 //! \param[in] message is the message to be displayed, that is the question. 109 //! \exception Euser_abort If the user answer "false" or "no" to the question the method 110 //! must throw an exception of type "Euser_abort". pause(const std::string & message)111 virtual void pause(const std::string & message) 112 { 113 if(!pause2(message)) 114 throw Euser_abort(message); 115 }; 116 117 /// alternative method to the pause() method 118 119 //! \param[in] message The boolean question to ask to the user 120 //! \return the answer of the user (true/yes or no/false) 121 //! \note either pause2() or pause() *must* be overwritten, but not both. 122 //! libdar always calls pause() which default implementation relies on pause2() where it converts negative 123 //! return from pause2() by throwing the appropriated exception. As soon as you overwrite pause(), 124 //! pause2() is no more used. pause2(const std::string & message)125 virtual bool pause2(const std::string & message) 126 { throw Elibcall("user_interaction::pause2", "user_interaction::pause() or pause2() must be overwritten !"); }; 127 128 129 /// \brief method used to display a warning or a message to the user. 130 /// 131 /// \param[in] message is the message to display. 132 /// \note since API 3.1.x this method must no more be ovewritten, instead 133 /// the protected method inherited_warning() must be used. 134 void warning(const std::string & message); 135 136 /// method used to ask a question that needs an arbitrary answer. 137 138 //! \param[in] message is the question to display to the user. 139 //! \param[in] echo is set to false is the answer must not be shown while the user answers. 140 //! \return the user's answer. 141 virtual std::string get_string(const std::string & message, bool echo) = 0; 142 143 /// same a get_string() but uses secu_string instead 144 145 //! \param[in] message is the question to display to the user. 146 //! \param[in] echo is set to false is the answer must not be shown while the user answers. 147 //! \return the user's answer. 148 virtual secu_string get_secu_string(const std::string & message, bool echo) = 0; 149 150 151 /// optional method to use if you want file listing splitted in several fields. 152 /// If you need to use this feature, you have then to supply an implementation for this method, 153 /// in your inherited class which will be called by libdar in place of the warning method 154 /// You then also have to call the set_use_listing() method with true as parameter 155 /// from the constructor of your inherited class (for example) to tell libdar that the listing() method is 156 /// to be used in place of the warning() method for archive listing. 157 158 //! \param[in] flag is the given information about the EA, compression, presence of saved data. 159 //! \param[in] perm is the access permission of the file. 160 //! \param[in] uid User ID of the file. 161 //! \param[in] gid Group ID of the file. 162 //! \param[in] size file size. 163 //! \param[in] date file modification date. 164 //! \param[in] filename file name. 165 //! \param[in] is_dir true if file is a directory. 166 //! \param[in] has_children true if file is a directory which is not empty. 167 //! \note This is not a pure virtual method, this is normal, 168 //! so your inherited class is not obliged to overwrite it. 169 virtual void listing(const std::string & flag, 170 const std::string & perm, 171 const std::string & uid, 172 const std::string & gid, 173 const std::string & size, 174 const std::string & date, 175 const std::string & filename, 176 bool is_dir, 177 bool has_children); 178 179 180 181 /// optional method to use if you want dar_manager database contents listing split in several fields. 182 /// if you want to use this feature, you have then to supply an implementation for this method 183 /// in your inherited class, method that will be called by libdar in place of the warning method. 184 /// You will also have to call the set_use_dar_manager_show_files() protected method with true as argument 185 /// from the constructor of your inherited class to tell libdar to use the dar_manager_show_files() 186 /// method in place of the warning() method. 187 188 /// \param[in] filename name of the file 189 /// \param[in] data_change whether the backup owns the most recent data for the file 190 /// \param[in] ea_change whether the backup owns the most recent Extended Attributes for the file 191 /// \note this method can be set for database::show_files() method to call it 192 virtual void dar_manager_show_files(const std::string & filename, 193 bool data_change, 194 bool ea_change); 195 196 197 /// optional method to use if you want dar_manager database archive listing split in several fields 198 /// if you want to use this feature, you have then to supply an implementation for this method 199 /// in your inherited class, method that will be called by libdar in place of the warning method. 200 /// You will also have to call the set_use_dar_manager_contents() protected method with true as argument 201 /// from the constructor of your inherited class to tell libdar to use the dar_manager_contents() 202 /// method in place of the warning() method. 203 204 /// \param[in] number is the number of the archive in the database 205 /// \param[in] chemin recorded path where to find this archive 206 /// \param[in] archive_name basename of this archive 207 /// \note this method can be set for database::show_contents() to call it 208 virtual void dar_manager_contents(U_I number, 209 const std::string & chemin, 210 const std::string & archive_name); 211 212 /// optional method to use if you want dar_manager statistics listing split in several fields 213 /// if you want to use this feature, you have then to supply an implementation for this method 214 /// in your inherited class, method that will be called by libdar in place of the warning method. 215 /// You will also have to call the set_use_dar_manager_statistics() protected method with true as argument 216 /// from the constructor of your inherited class to tell libdar to use the dar_manager_statistics() 217 /// method in place of the warning() method. 218 219 /// \param[in] number archive number 220 /// \param[in] data_count amount of file which last version is located in this archive 221 /// \param[in] total_data total number of file covered in this database 222 /// \param[in] ea_count amount of EA which last version is located in this archive 223 /// \param[in] total_ea total number of file that have EA covered by this database 224 /// \note this method can be set for database::show_most_recent_stats() method to call it 225 virtual void dar_manager_statistics(U_I number, 226 const infinint & data_count, 227 const infinint & total_data, 228 const infinint & ea_count, 229 const infinint & total_ea); 230 231 /// optional method to use if you want dar_manager statistics listing split in several fields 232 /// if you want to use this feature, you have then to supply an implementation for this method 233 /// in your inherited class, method that will be called by libdar in place of the warning method. 234 /// You will also have to call the set_use_dar_manager_show_version() protected method with true as argument 235 /// from the constructor of your inherited class to tell libdar to use the dar_manager_show_version() 236 /// method in place of the warning() method. 237 238 /// \param[in] number archive number 239 /// \param[in] data_date is the last modification date of the requested file in thie archive whose number is "number" 240 /// \param[in] data_presence is the nature of this modification, true if the data was saved, false if it was deleted 241 /// \param[in] ea_date is the date of the EA for the requested file in the archive whose number is "number" 242 /// \param[in] ea_presence is the nature of this modification, true if the EAs were saved, false if they were deleted 243 /// \note this method can be set for database::show_version() method to call it 244 virtual void dar_manager_show_version(U_I number, 245 const std::string & data_date, 246 const std::string & data_presence, 247 const std::string & ea_date, 248 const std::string & ea_presence); 249 250 /// libdar uses this call to format output before send to warning() method. 251 252 //! This is not a virtual method, it has not to be overwritten, it is 253 //! just a sublayer over warning() 254 //! Supported masks for the format string are: 255 //! - \%s \%c \%d \%\% (normal behavior) 256 //! - \%i (matches infinint *) 257 //! - \%S (matches std::string *) 258 //! . 259 void printf(const char *format, ...); 260 261 /// for libdar to know if it is interesting to use listing(), dar_manager_show_files(), 262 /// dar_manager_contents(), dar_manager_statistics() or to keep reporting listing thanks 263 /// to the warning() method, 264 265 //! this is not a virtual method, it has not to be overwritten in inherited classes. get_use_listing() const266 bool get_use_listing() const { return use_listing; }; 267 //! this is not a virtual method, it has not to be overwritten in inherited classes. get_use_dar_manager_show_files() const268 bool get_use_dar_manager_show_files() const { return use_dar_manager_show_files; }; 269 //! this is not a virtual method, it has not to be overwritten in inherited classes. get_use_dar_manager_contents() const270 bool get_use_dar_manager_contents() const { return use_dar_manager_contents; }; 271 //! this is not a virtual method, it has not to be overwritten in inherited classes. get_use_dar_manager_statistics() const272 bool get_use_dar_manager_statistics() const { return use_dar_manager_statistics; }; 273 //! this is not a virtual method, it has not to be overwritten in inherited classes. get_use_dar_manager_show_version() const274 bool get_use_dar_manager_show_version() const { return use_dar_manager_show_version; }; 275 276 277 /// make a newly allocated object which has the same properties as "this". 278 279 //! This *is* a virtual method, it *must* be overwritten in any inherited class 280 //! copy constructor and = operator may have to be overwritten too if necessary 281 //! Warning ! 282 //! clone() must throw exception if necessary (Ememory), but never 283 //! return a nullptr pointer ! 284 virtual user_interaction *clone() const = 0; 285 286 /// make a pause each N line of output when calling the warning method 287 288 //! \param[in] num is the number of line to display at once, zero for unlimited display 289 //! \note. Since API 3.1, the warning method is no more a pure virtual function 290 //! you need to call the parent warning method in your method for this warning_with_more 291 //! method works as expected. warning_with_more(U_I num)292 void warning_with_more(U_I num) { at_once = num; count = 0; }; 293 294 protected: 295 296 /// method to be called with true as argument if you have defined a listing() method. 297 298 //! in the constructor of any inherited class that define a listing() method 299 //! it is advisable to call set_use_listing() with true as argument for libdar 300 //! knows that the listing() call has to be used in place of the warning() call 301 //! for file listing. set_use_listing(bool val)302 void set_use_listing(bool val) { use_listing = val; }; 303 304 /// method to be called with true as argument if you have defined a dar_manager_show_files() method. set_use_dar_manager_show_files(bool val)305 void set_use_dar_manager_show_files(bool val) { use_dar_manager_show_files = val; }; 306 307 /// method to be called with true as argument if you have defined a dar_manager_contents() method. set_use_dar_manager_contents(bool val)308 void set_use_dar_manager_contents(bool val) { use_dar_manager_contents = val; }; 309 310 /// method to be called with true as argument if you have defined a dar_manager_statistics() method. set_use_dar_manager_statistics(bool val)311 void set_use_dar_manager_statistics(bool val) { use_dar_manager_statistics = val; }; 312 313 /// method to be called with true as argument if you have defined a dar_manager_show_version() method. set_use_dar_manager_show_version(bool val)314 void set_use_dar_manager_show_version(bool val) { use_dar_manager_show_version = val; }; 315 316 /// need to be overwritten in place of the warning() method since API 3.1.x 317 318 /// \param[in] message message to display 319 /// 320 virtual void inherited_warning(const std::string & message) = 0; 321 322 private: 323 bool use_listing; 324 bool use_dar_manager_show_files; 325 bool use_dar_manager_contents; 326 bool use_dar_manager_statistics; 327 bool use_dar_manager_show_version; 328 U_I at_once, count; 329 330 }; 331 332 333 /// full implemented class for user_interaction based on callback functions. 334 335 //! this class is an inherited class of user_interaction it is used by 336 //! dar command line programs, but you can use it if you wish. 337 //! \ingroup API 338 class user_interaction_callback : public user_interaction 339 { 340 public: 341 342 /// constructor which receive the callback functions. 343 344 //! \param[in] x_warning_callback is used by warning() method 345 //! \param[in] x_answer_callback is used by the pause() method 346 //! \param[in] x_string_callback is used by get_string() method 347 //! \param[in] x_secu_string_callback is used by get_secu_string() method 348 //! \param[in] context_value will be passed as last argument of callbacks when 349 //! called from this object. 350 //! \note The context argument of each callback is set with the context_value given 351 //! in the user_interaction_callback object constructor. The value can 352 //! can be any arbitrary value (nullptr is valid), and can be used as you wish. 353 //! Note that the listing callback is not defined here, but thanks to a specific method 354 user_interaction_callback(void (*x_warning_callback)(const std::string &x, void *context), 355 bool (*x_answer_callback)(const std::string &x, void *context), 356 std::string (*x_string_callback)(const std::string &x, bool echo, void *context), 357 secu_string (*x_secu_string_callback)(const std::string &x, bool echo, void *context), 358 void *context_value); 359 360 /// overwritting method from parent class. 361 void pause(const std::string & message); 362 /// overwritting method from parent class. 363 std::string get_string(const std::string & message, bool echo); 364 /// overwritting method from parent class. 365 secu_string get_secu_string(const std::string & message, bool echo); 366 /// overwritting method from parent class. 367 void listing(const std::string & flag, 368 const std::string & perm, 369 const std::string & uid, 370 const std::string & gid, 371 const std::string & size, 372 const std::string & date, 373 const std::string & filename, 374 bool is_dir, 375 bool has_children); 376 377 /// overwritting method from parent class 378 void dar_manager_show_files(const std::string & filename, 379 bool available_data, 380 bool available_ea); 381 382 /// overwritting method from parent class 383 void dar_manager_contents(U_I number, 384 const std::string & chemin, 385 const std::string & archive_name); 386 387 /// overwritting method from parent class 388 void dar_manager_statistics(U_I number, 389 const infinint & data_count, 390 const infinint & total_data, 391 const infinint & ea_count, 392 const infinint & total_ea); 393 394 /// overwritting method from parent class 395 void dar_manager_show_version(U_I number, 396 const std::string & data_date, 397 const std::string & data_presence, 398 const std::string & ea_date, 399 const std::string & ea_presence); 400 401 /// You can set a listing callback thanks to this method. 402 403 //! If set, when file listing will this callback function will 404 //! be used instead of the x_warning_callback given as argument 405 //! of the constructor. set_listing_callback(void (* callback)(const std::string & flag,const std::string & perm,const std::string & uid,const std::string & gid,const std::string & size,const std::string & date,const std::string & filename,bool is_dir,bool has_children,void * context))406 void set_listing_callback(void (*callback)(const std::string & flag, 407 const std::string & perm, 408 const std::string & uid, 409 const std::string & gid, 410 const std::string & size, 411 const std::string & date, 412 const std::string & filename, 413 bool is_dir, 414 bool has_children, 415 void *context)) 416 { 417 tar_listing_callback = callback; 418 set_use_listing(true); // this is to inform libdar to use listing() 419 }; 420 421 // You can set a dar_manager_show_files callback thanks to this method 422 set_dar_manager_show_files_callback(void (* callback)(const std::string & filename,bool available_data,bool available_ea,void * context))423 void set_dar_manager_show_files_callback(void (*callback)(const std::string & filename, 424 bool available_data, 425 bool available_ea, 426 void *context)) 427 { 428 dar_manager_show_files_callback = callback; 429 set_use_dar_manager_show_files(true); // this is to inform libdar to use the dar_manager_show_files() method 430 }; 431 set_dar_manager_contents_callback(void (* callback)(U_I number,const std::string & chemin,const std::string & archive_name,void * context))432 void set_dar_manager_contents_callback(void (*callback)(U_I number, 433 const std::string & chemin, 434 const std::string & archive_name, 435 void *context)) 436 { 437 dar_manager_contents_callback = callback; 438 set_use_dar_manager_contents(true); // this is to inform libdar to use the dar_manager_contents() method 439 }; 440 set_dar_manager_statistics_callback(void (* callback)(U_I number,const infinint & data_count,const infinint & total_data,const infinint & ea_count,const infinint & total_ea,void * context))441 void set_dar_manager_statistics_callback(void (*callback)(U_I number, 442 const infinint & data_count, 443 const infinint & total_data, 444 const infinint & ea_count, 445 const infinint & total_ea, 446 void *context)) 447 { 448 dar_manager_statistics_callback = callback; 449 set_use_dar_manager_statistics(true); // this is to inform libdar to use the dar_manager_statistics() method 450 }; 451 set_dar_manager_show_version_callback(void (* callback)(U_I number,const std::string & data_date,const std::string & data_presence,const std::string & ea_date,const std::string & ea_presence,void * context))452 void set_dar_manager_show_version_callback(void (*callback)(U_I number, 453 const std::string & data_date, 454 const std::string & data_presence, 455 const std::string & ea_date, 456 const std::string & ea_presence, 457 void *context)) 458 { 459 dar_manager_show_version_callback = callback; 460 set_use_dar_manager_show_version(true); // this is to inform libdar to use the dar_manager_show_version() method 461 }; 462 463 464 /// overwritting method from parent class. 465 virtual user_interaction *clone() const; 466 467 protected: 468 /// change the context value of the object that will be given to callback functions change_context_value(void * new_value)469 void change_context_value(void *new_value) { context_val = new_value; }; 470 471 /// overwritting method from parent class. 472 void inherited_warning(const std::string & message); 473 474 private: 475 void (*warning_callback)(const std::string & x, void *context); // pointer to function 476 bool (*answer_callback)(const std::string & x, void *context); // pointer to function 477 std::string (*string_callback)(const std::string & x, bool echo, void *context); // pointer to function 478 secu_string (*secu_string_callback)(const std::string & x, bool echo, void *context); // pointer to function 479 void (*tar_listing_callback)(const std::string & flags, 480 const std::string & perm, 481 const std::string & uid, 482 const std::string & gid, 483 const std::string & size, 484 const std::string & date, 485 const std::string & filename, 486 bool is_dir, 487 bool has_children, 488 void *context); 489 void (*dar_manager_show_files_callback)(const std::string & filename, 490 bool available_data, 491 bool available_ea, 492 void *context); 493 void (*dar_manager_contents_callback)(U_I number, 494 const std::string & chemin, 495 const std::string & archive_name, 496 void *context); 497 void (*dar_manager_statistics_callback)(U_I number, 498 const infinint & data_count, 499 const infinint & total_data, 500 const infinint & ea_count, 501 const infinint & total_ea, 502 void *context); 503 void (*dar_manager_show_version_callback)(U_I number, 504 const std::string & data_date, 505 const std::string & data_presence, 506 const std::string & ea_date, 507 const std::string & ea_presence, 508 void *context); 509 510 void *context_val; 511 }; 512 513 514 /// full implementation class for user_interaction, which shows nothing and assumes answer "no" to any question 515 516 class user_interaction_blind : public user_interaction 517 { 518 public: pause2(const std::string & message)519 bool pause2(const std::string & message) { return false; }; 520 get_string(const std::string & message,bool echo)521 std::string get_string(const std::string & message, bool echo) { return "user_interaction_blind, is blindly answering no"; }; get_secu_string(const std::string & message,bool echo)522 secu_string get_secu_string(const std::string & message, bool echo) { return secu_string(); }; 523 clone() const524 user_interaction *clone() const { user_interaction *ret = new (get_pool()) user_interaction_blind(); if(ret == nullptr) throw Ememory("user_interaction_blind::clone"); return ret; }; 525 526 protected: inherited_warning(const std::string & message)527 void inherited_warning(const std::string & message) {}; // do not display any warning, this is "bind user_interaction" ! 528 529 }; 530 531 /// @} 532 533 } // end of namespace 534 535 #endif 536