1 /* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */ 2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL 3 * project 2001. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * openssl-core@openssl.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59 #include <string.h> 60 #include "cryptlib.h" 61 #include <openssl/e_os2.h> 62 #include <openssl/buffer.h> 63 #include <openssl/ui.h> 64 #include <openssl/err.h> 65 #include "ui_locl.h" 66 67 IMPLEMENT_STACK_OF(UI_STRING_ST) 68 69 static const UI_METHOD *default_UI_meth=NULL; 70 71 UI *UI_new(void) 72 { 73 return(UI_new_method(NULL)); 74 } 75 76 UI *UI_new_method(const UI_METHOD *method) 77 { 78 UI *ret; 79 80 ret=(UI *)OPENSSL_malloc(sizeof(UI)); 81 if (ret == NULL) 82 { 83 UIerr(UI_F_UI_NEW_METHOD,ERR_R_MALLOC_FAILURE); 84 return NULL; 85 } 86 if (method == NULL) 87 ret->meth=UI_get_default_method(); 88 else 89 ret->meth=method; 90 91 ret->strings=NULL; 92 ret->user_data=NULL; 93 ret->flags=0; 94 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data); 95 return ret; 96 } 97 98 static void free_string(UI_STRING *uis) 99 { 100 if (uis->flags & OUT_STRING_FREEABLE) 101 { 102 OPENSSL_free((char *)uis->out_string); 103 switch(uis->type) 104 { 105 case UIT_BOOLEAN: 106 OPENSSL_free((char *)uis->_.boolean_data.action_desc); 107 OPENSSL_free((char *)uis->_.boolean_data.ok_chars); 108 OPENSSL_free((char *)uis->_.boolean_data.cancel_chars); 109 break; 110 default: 111 break; 112 } 113 } 114 OPENSSL_free(uis); 115 } 116 117 void UI_free(UI *ui) 118 { 119 if (ui == NULL) 120 return; 121 sk_UI_STRING_pop_free(ui->strings,free_string); 122 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data); 123 OPENSSL_free(ui); 124 } 125 126 static int allocate_string_stack(UI *ui) 127 { 128 if (ui->strings == NULL) 129 { 130 ui->strings=sk_UI_STRING_new_null(); 131 if (ui->strings == NULL) 132 { 133 return -1; 134 } 135 } 136 return 0; 137 } 138 139 static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt, 140 int prompt_freeable, enum UI_string_types type, int input_flags, 141 char *result_buf) 142 { 143 UI_STRING *ret = NULL; 144 145 if (prompt == NULL) 146 { 147 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,ERR_R_PASSED_NULL_PARAMETER); 148 } 149 else if ((type == UIT_PROMPT || type == UIT_VERIFY 150 || type == UIT_BOOLEAN) && result_buf == NULL) 151 { 152 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,UI_R_NO_RESULT_BUFFER); 153 } 154 else if ((ret = (UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING)))) 155 { 156 ret->out_string=prompt; 157 ret->flags=prompt_freeable ? OUT_STRING_FREEABLE : 0; 158 ret->input_flags=input_flags; 159 ret->type=type; 160 ret->result_buf=result_buf; 161 } 162 return ret; 163 } 164 165 static int general_allocate_string(UI *ui, const char *prompt, 166 int prompt_freeable, enum UI_string_types type, int input_flags, 167 char *result_buf, int minsize, int maxsize, const char *test_buf) 168 { 169 int ret = -1; 170 UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable, 171 type, input_flags, result_buf); 172 173 if (s) 174 { 175 if (allocate_string_stack(ui) >= 0) 176 { 177 s->_.string_data.result_minsize=minsize; 178 s->_.string_data.result_maxsize=maxsize; 179 s->_.string_data.test_buf=test_buf; 180 ret=sk_UI_STRING_push(ui->strings, s); 181 /* sk_push() returns 0 on error. Let's addapt that */ 182 if (ret <= 0) ret--; 183 } 184 else 185 free_string(s); 186 } 187 return ret; 188 } 189 190 static int general_allocate_boolean(UI *ui, 191 const char *prompt, const char *action_desc, 192 const char *ok_chars, const char *cancel_chars, 193 int prompt_freeable, enum UI_string_types type, int input_flags, 194 char *result_buf) 195 { 196 int ret = -1; 197 UI_STRING *s; 198 const char *p; 199 200 if (ok_chars == NULL) 201 { 202 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER); 203 } 204 else if (cancel_chars == NULL) 205 { 206 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER); 207 } 208 else 209 { 210 for(p = ok_chars; *p; p++) 211 { 212 if (strchr(cancel_chars, *p)) 213 { 214 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, 215 UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); 216 } 217 } 218 219 s = general_allocate_prompt(ui, prompt, prompt_freeable, 220 type, input_flags, result_buf); 221 222 if (s) 223 { 224 if (allocate_string_stack(ui) >= 0) 225 { 226 s->_.boolean_data.action_desc = action_desc; 227 s->_.boolean_data.ok_chars = ok_chars; 228 s->_.boolean_data.cancel_chars = cancel_chars; 229 ret=sk_UI_STRING_push(ui->strings, s); 230 /* sk_push() returns 0 on error. 231 Let's addapt that */ 232 if (ret <= 0) ret--; 233 } 234 else 235 free_string(s); 236 } 237 } 238 return ret; 239 } 240 241 /* Returns the index to the place in the stack or -1 for error. Uses a 242 direct reference to the prompt. */ 243 int UI_add_input_string(UI *ui, const char *prompt, int flags, 244 char *result_buf, int minsize, int maxsize) 245 { 246 return general_allocate_string(ui, prompt, 0, 247 UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL); 248 } 249 250 /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ 251 int UI_dup_input_string(UI *ui, const char *prompt, int flags, 252 char *result_buf, int minsize, int maxsize) 253 { 254 char *prompt_copy=NULL; 255 256 if (prompt) 257 { 258 prompt_copy=BUF_strdup(prompt); 259 if (prompt_copy == NULL) 260 { 261 UIerr(UI_F_UI_DUP_INPUT_STRING,ERR_R_MALLOC_FAILURE); 262 return 0; 263 } 264 } 265 266 return general_allocate_string(ui, prompt_copy, 1, 267 UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL); 268 } 269 270 int UI_add_verify_string(UI *ui, const char *prompt, int flags, 271 char *result_buf, int minsize, int maxsize, const char *test_buf) 272 { 273 return general_allocate_string(ui, prompt, 0, 274 UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf); 275 } 276 277 int UI_dup_verify_string(UI *ui, const char *prompt, int flags, 278 char *result_buf, int minsize, int maxsize, const char *test_buf) 279 { 280 char *prompt_copy=NULL; 281 282 if (prompt) 283 { 284 prompt_copy=BUF_strdup(prompt); 285 if (prompt_copy == NULL) 286 { 287 UIerr(UI_F_UI_DUP_VERIFY_STRING,ERR_R_MALLOC_FAILURE); 288 return -1; 289 } 290 } 291 292 return general_allocate_string(ui, prompt_copy, 1, 293 UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf); 294 } 295 296 int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, 297 const char *ok_chars, const char *cancel_chars, 298 int flags, char *result_buf) 299 { 300 return general_allocate_boolean(ui, prompt, action_desc, 301 ok_chars, cancel_chars, 0, UIT_BOOLEAN, flags, result_buf); 302 } 303 304 int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, 305 const char *ok_chars, const char *cancel_chars, 306 int flags, char *result_buf) 307 { 308 char *prompt_copy = NULL; 309 char *action_desc_copy = NULL; 310 char *ok_chars_copy = NULL; 311 char *cancel_chars_copy = NULL; 312 313 if (prompt) 314 { 315 prompt_copy=BUF_strdup(prompt); 316 if (prompt_copy == NULL) 317 { 318 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); 319 goto err; 320 } 321 } 322 323 if (action_desc) 324 { 325 action_desc_copy=BUF_strdup(action_desc); 326 if (action_desc_copy == NULL) 327 { 328 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); 329 goto err; 330 } 331 } 332 333 if (ok_chars) 334 { 335 ok_chars_copy=BUF_strdup(ok_chars); 336 if (ok_chars_copy == NULL) 337 { 338 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); 339 goto err; 340 } 341 } 342 343 if (cancel_chars) 344 { 345 cancel_chars_copy=BUF_strdup(cancel_chars); 346 if (cancel_chars_copy == NULL) 347 { 348 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE); 349 goto err; 350 } 351 } 352 353 return general_allocate_boolean(ui, prompt_copy, action_desc_copy, 354 ok_chars_copy, cancel_chars_copy, 1, UIT_BOOLEAN, flags, 355 result_buf); 356 err: 357 if (prompt_copy) OPENSSL_free(prompt_copy); 358 if (action_desc_copy) OPENSSL_free(action_desc_copy); 359 if (ok_chars_copy) OPENSSL_free(ok_chars_copy); 360 if (cancel_chars_copy) OPENSSL_free(cancel_chars_copy); 361 return -1; 362 } 363 364 int UI_add_info_string(UI *ui, const char *text) 365 { 366 return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, 367 NULL); 368 } 369 370 int UI_dup_info_string(UI *ui, const char *text) 371 { 372 char *text_copy=NULL; 373 374 if (text) 375 { 376 text_copy=BUF_strdup(text); 377 if (text_copy == NULL) 378 { 379 UIerr(UI_F_UI_DUP_INFO_STRING,ERR_R_MALLOC_FAILURE); 380 return -1; 381 } 382 } 383 384 return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, 385 0, 0, NULL); 386 } 387 388 int UI_add_error_string(UI *ui, const char *text) 389 { 390 return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, 391 NULL); 392 } 393 394 int UI_dup_error_string(UI *ui, const char *text) 395 { 396 char *text_copy=NULL; 397 398 if (text) 399 { 400 text_copy=BUF_strdup(text); 401 if (text_copy == NULL) 402 { 403 UIerr(UI_F_UI_DUP_ERROR_STRING,ERR_R_MALLOC_FAILURE); 404 return -1; 405 } 406 } 407 return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, 408 0, 0, NULL); 409 } 410 411 char *UI_construct_prompt(UI *ui, const char *object_desc, 412 const char *object_name) 413 { 414 char *prompt = NULL; 415 416 if (ui->meth->ui_construct_prompt) 417 prompt = ui->meth->ui_construct_prompt(ui, 418 object_desc, object_name); 419 else 420 { 421 char prompt1[] = "Enter "; 422 char prompt2[] = " for "; 423 char prompt3[] = ":"; 424 int len = 0; 425 426 if (object_desc == NULL) 427 return NULL; 428 len = sizeof(prompt1) - 1 + strlen(object_desc); 429 if (object_name) 430 len += sizeof(prompt2) - 1 + strlen(object_name); 431 len += sizeof(prompt3) - 1; 432 433 prompt = (char *)OPENSSL_malloc(len + 1); 434 BUF_strlcpy(prompt, prompt1, len + 1); 435 BUF_strlcat(prompt, object_desc, len + 1); 436 if (object_name) 437 { 438 BUF_strlcat(prompt, prompt2, len + 1); 439 BUF_strlcat(prompt, object_name, len + 1); 440 } 441 BUF_strlcat(prompt, prompt3, len + 1); 442 } 443 return prompt; 444 } 445 446 void *UI_add_user_data(UI *ui, void *user_data) 447 { 448 void *old_data = ui->user_data; 449 ui->user_data = user_data; 450 return old_data; 451 } 452 453 void *UI_get0_user_data(UI *ui) 454 { 455 return ui->user_data; 456 } 457 458 const char *UI_get0_result(UI *ui, int i) 459 { 460 if (i < 0) 461 { 462 UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_SMALL); 463 return NULL; 464 } 465 if (i >= sk_UI_STRING_num(ui->strings)) 466 { 467 UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_LARGE); 468 return NULL; 469 } 470 return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); 471 } 472 473 static int print_error(const char *str, size_t len, UI *ui) 474 { 475 UI_STRING uis; 476 477 memset(&uis, 0, sizeof(uis)); 478 uis.type = UIT_ERROR; 479 uis.out_string = str; 480 481 if (ui->meth->ui_write_string 482 && !ui->meth->ui_write_string(ui, &uis)) 483 return -1; 484 return 0; 485 } 486 487 int UI_process(UI *ui) 488 { 489 int i, ok=0; 490 491 if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui)) 492 return -1; 493 494 if (ui->flags & UI_FLAG_PRINT_ERRORS) 495 ERR_print_errors_cb( 496 (int (*)(const char *, size_t, void *))print_error, 497 (void *)ui); 498 499 for(i=0; i<sk_UI_STRING_num(ui->strings); i++) 500 { 501 if (ui->meth->ui_write_string 502 && !ui->meth->ui_write_string(ui, 503 sk_UI_STRING_value(ui->strings, i))) 504 { 505 ok=-1; 506 goto err; 507 } 508 } 509 510 if (ui->meth->ui_flush) 511 switch(ui->meth->ui_flush(ui)) 512 { 513 case -1: /* Interrupt/Cancel/something... */ 514 ok = -2; 515 goto err; 516 case 0: /* Errors */ 517 ok = -1; 518 goto err; 519 default: /* Success */ 520 ok = 0; 521 break; 522 } 523 524 for(i=0; i<sk_UI_STRING_num(ui->strings); i++) 525 { 526 if (ui->meth->ui_read_string) 527 { 528 switch(ui->meth->ui_read_string(ui, 529 sk_UI_STRING_value(ui->strings, i))) 530 { 531 case -1: /* Interrupt/Cancel/something... */ 532 ok = -2; 533 goto err; 534 case 0: /* Errors */ 535 ok = -1; 536 goto err; 537 default: /* Success */ 538 ok = 0; 539 break; 540 } 541 } 542 } 543 err: 544 if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui)) 545 return -1; 546 return ok; 547 } 548 549 int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)(void)) 550 { 551 if (ui == NULL) 552 { 553 UIerr(UI_F_UI_CTRL,ERR_R_PASSED_NULL_PARAMETER); 554 return -1; 555 } 556 switch(cmd) 557 { 558 case UI_CTRL_PRINT_ERRORS: 559 { 560 int save_flag = !!(ui->flags & UI_FLAG_PRINT_ERRORS); 561 if (i) 562 ui->flags |= UI_FLAG_PRINT_ERRORS; 563 else 564 ui->flags &= ~UI_FLAG_PRINT_ERRORS; 565 return save_flag; 566 } 567 case UI_CTRL_IS_REDOABLE: 568 return !!(ui->flags & UI_FLAG_REDOABLE); 569 default: 570 break; 571 } 572 UIerr(UI_F_UI_CTRL,UI_R_UNKNOWN_CONTROL_COMMAND); 573 return -1; 574 } 575 576 int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 577 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 578 { 579 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp, 580 new_func, dup_func, free_func); 581 } 582 583 int UI_set_ex_data(UI *r, int idx, void *arg) 584 { 585 return(CRYPTO_set_ex_data(&r->ex_data,idx,arg)); 586 } 587 588 void *UI_get_ex_data(UI *r, int idx) 589 { 590 return(CRYPTO_get_ex_data(&r->ex_data,idx)); 591 } 592 593 void UI_set_default_method(const UI_METHOD *meth) 594 { 595 default_UI_meth=meth; 596 } 597 598 const UI_METHOD *UI_get_default_method(void) 599 { 600 if (default_UI_meth == NULL) 601 { 602 default_UI_meth=UI_OpenSSL(); 603 } 604 return default_UI_meth; 605 } 606 607 const UI_METHOD *UI_get_method(UI *ui) 608 { 609 return ui->meth; 610 } 611 612 const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) 613 { 614 ui->meth=meth; 615 return ui->meth; 616 } 617 618 619 UI_METHOD *UI_create_method(char *name) 620 { 621 UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD)); 622 623 if (ui_method) 624 { 625 memset(ui_method, 0, sizeof(*ui_method)); 626 ui_method->name = BUF_strdup(name); 627 } 628 return ui_method; 629 } 630 631 /* BIG FSCKING WARNING!!!! If you use this on a statically allocated method 632 (that is, it hasn't been allocated using UI_create_method(), you deserve 633 anything Murphy can throw at you and more! You have been warned. */ 634 void UI_destroy_method(UI_METHOD *ui_method) 635 { 636 OPENSSL_free(ui_method->name); 637 ui_method->name = NULL; 638 OPENSSL_free(ui_method); 639 } 640 641 int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui)) 642 { 643 if (method) 644 { 645 method->ui_open_session = opener; 646 return 0; 647 } 648 else 649 return -1; 650 } 651 652 int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis)) 653 { 654 if (method) 655 { 656 method->ui_write_string = writer; 657 return 0; 658 } 659 else 660 return -1; 661 } 662 663 int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui)) 664 { 665 if (method) 666 { 667 method->ui_flush = flusher; 668 return 0; 669 } 670 else 671 return -1; 672 } 673 674 int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis)) 675 { 676 if (method) 677 { 678 method->ui_read_string = reader; 679 return 0; 680 } 681 else 682 return -1; 683 } 684 685 int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui)) 686 { 687 if (method) 688 { 689 method->ui_close_session = closer; 690 return 0; 691 } 692 else 693 return -1; 694 } 695 696 int UI_method_set_prompt_constructor(UI_METHOD *method, char *(*prompt_constructor)(UI* ui, const char* object_desc, const char* object_name)) 697 { 698 if (method) 699 { 700 method->ui_construct_prompt = prompt_constructor; 701 return 0; 702 } 703 else 704 return -1; 705 } 706 707 int (*UI_method_get_opener(UI_METHOD *method))(UI*) 708 { 709 if (method) 710 return method->ui_open_session; 711 else 712 return NULL; 713 } 714 715 int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*) 716 { 717 if (method) 718 return method->ui_write_string; 719 else 720 return NULL; 721 } 722 723 int (*UI_method_get_flusher(UI_METHOD *method))(UI*) 724 { 725 if (method) 726 return method->ui_flush; 727 else 728 return NULL; 729 } 730 731 int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*) 732 { 733 if (method) 734 return method->ui_read_string; 735 else 736 return NULL; 737 } 738 739 int (*UI_method_get_closer(UI_METHOD *method))(UI*) 740 { 741 if (method) 742 return method->ui_close_session; 743 else 744 return NULL; 745 } 746 747 char* (*UI_method_get_prompt_constructor(UI_METHOD *method))(UI*, const char*, const char*) 748 { 749 if (method) 750 return method->ui_construct_prompt; 751 else 752 return NULL; 753 } 754 755 enum UI_string_types UI_get_string_type(UI_STRING *uis) 756 { 757 if (!uis) 758 return UIT_NONE; 759 return uis->type; 760 } 761 762 int UI_get_input_flags(UI_STRING *uis) 763 { 764 if (!uis) 765 return 0; 766 return uis->input_flags; 767 } 768 769 const char *UI_get0_output_string(UI_STRING *uis) 770 { 771 if (!uis) 772 return NULL; 773 return uis->out_string; 774 } 775 776 const char *UI_get0_action_string(UI_STRING *uis) 777 { 778 if (!uis) 779 return NULL; 780 switch(uis->type) 781 { 782 case UIT_PROMPT: 783 case UIT_BOOLEAN: 784 return uis->_.boolean_data.action_desc; 785 default: 786 return NULL; 787 } 788 } 789 790 const char *UI_get0_result_string(UI_STRING *uis) 791 { 792 if (!uis) 793 return NULL; 794 switch(uis->type) 795 { 796 case UIT_PROMPT: 797 case UIT_VERIFY: 798 return uis->result_buf; 799 default: 800 return NULL; 801 } 802 } 803 804 const char *UI_get0_test_string(UI_STRING *uis) 805 { 806 if (!uis) 807 return NULL; 808 switch(uis->type) 809 { 810 case UIT_VERIFY: 811 return uis->_.string_data.test_buf; 812 default: 813 return NULL; 814 } 815 } 816 817 int UI_get_result_minsize(UI_STRING *uis) 818 { 819 if (!uis) 820 return -1; 821 switch(uis->type) 822 { 823 case UIT_PROMPT: 824 case UIT_VERIFY: 825 return uis->_.string_data.result_minsize; 826 default: 827 return -1; 828 } 829 } 830 831 int UI_get_result_maxsize(UI_STRING *uis) 832 { 833 if (!uis) 834 return -1; 835 switch(uis->type) 836 { 837 case UIT_PROMPT: 838 case UIT_VERIFY: 839 return uis->_.string_data.result_maxsize; 840 default: 841 return -1; 842 } 843 } 844 845 int UI_set_result(UI *ui, UI_STRING *uis, const char *result) 846 { 847 int l = strlen(result); 848 849 ui->flags &= ~UI_FLAG_REDOABLE; 850 851 if (!uis) 852 return -1; 853 switch (uis->type) 854 { 855 case UIT_PROMPT: 856 case UIT_VERIFY: 857 { 858 char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize)+1]; 859 char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize)+1]; 860 861 BIO_snprintf(number1, sizeof(number1), "%d", 862 uis->_.string_data.result_minsize); 863 BIO_snprintf(number2, sizeof(number2), "%d", 864 uis->_.string_data.result_maxsize); 865 866 if (l < uis->_.string_data.result_minsize) 867 { 868 ui->flags |= UI_FLAG_REDOABLE; 869 UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_SMALL); 870 ERR_add_error_data(5,"You must type in ", 871 number1," to ",number2," characters"); 872 return -1; 873 } 874 if (l > uis->_.string_data.result_maxsize) 875 { 876 ui->flags |= UI_FLAG_REDOABLE; 877 UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_LARGE); 878 ERR_add_error_data(5,"You must type in ", 879 number1," to ",number2," characters"); 880 return -1; 881 } 882 } 883 884 if (!uis->result_buf) 885 { 886 UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER); 887 return -1; 888 } 889 890 BUF_strlcpy(uis->result_buf, result, 891 uis->_.string_data.result_maxsize + 1); 892 break; 893 case UIT_BOOLEAN: 894 { 895 const char *p; 896 897 if (!uis->result_buf) 898 { 899 UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER); 900 return -1; 901 } 902 903 uis->result_buf[0] = '\0'; 904 for(p = result; *p; p++) 905 { 906 if (strchr(uis->_.boolean_data.ok_chars, *p)) 907 { 908 uis->result_buf[0] = 909 uis->_.boolean_data.ok_chars[0]; 910 break; 911 } 912 if (strchr(uis->_.boolean_data.cancel_chars, *p)) 913 { 914 uis->result_buf[0] = 915 uis->_.boolean_data.cancel_chars[0]; 916 break; 917 } 918 } 919 } 920 default: 921 break; 922 } 923 return 0; 924 }