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