Crypt-SecretBuffer

 view release on metacpan or  search on metacpan

secret_buffer_console.c  view on Meta::CPAN

      state->hdl= tmp;
      state->own_fd= true;
   }
   return true;
}

static bool sb_console_state_get_echo(sb_console_state *state) {
   return state->mode & ENABLE_ECHO_INPUT;
}

static bool sb_console_state_set_echo(sb_console_state *state, bool enable) {
   DWORD mode= enable? (state->mode | ENABLE_ECHO_INPUT)
                     : (state->mode & ~ENABLE_ECHO_INPUT);
   if (SetConsoleMode(state->hdl, mode)) {
      state->mode= mode;
      return true;
   }
   return false;
}

static bool sb_console_state_get_line_input(sb_console_state *state) {
   return state->mode & ENABLE_LINE_INPUT;
}

static bool sb_console_state_set_line_input(sb_console_state *state, bool enable) {
   DWORD mode= enable? (state->mode | ENABLE_LINE_INPUT)
                     : (state->mode & ~ENABLE_LINE_INPUT);
   if (SetConsoleMode(state->hdl, mode)) {
      state->mode= mode;
      return true;
   }
   return false;
}

static bool sb_console_state_restore(sb_console_state *state) {
   if (SetConsoleMode(state->hdl, state->orig_mode)) {
      state->mode= state->orig_mode;
      return true;
   }
   return false;
}

static void sb_console_state_destroy(pTHX_ sb_console_state *state) {
   if (state->hdl != INVALID_HANDLE_VALUE) {
      if (state->auto_restore)
         if (!sb_console_state_restore(state))
            warn("failed to restore console state");
      if (state->own_fd)
         if (!CloseHandle(state->hdl))
            warn("BUG: CloseHandle failed");
      state->hdl= INVALID_HANDLE_VALUE;
   }
   state->pending_high_surrogate= 0;
}

static bool
sb_console_state_wait_char_readable(pTHX_ sb_console_state *state, SV *timeout_sv) {
   return sb_wait_win32_handle_readable(aTHX_ state->hdl, timeout_sv);
}

/* Windows API provides unicode key characters when you use ReadConsoleInputW.
 * SecretBuffer is UTF-8 by default, so this function translates them.
 * Returns true if it added a character, and false if no character is available yet,
 * and croaks on OS errors or invalid surrogate pairs.
 * It only appends whole characters (encoded as UTF-8) and may store half a
 * surrogate pair into `state` to be combined with a subsequent call.
 */
static bool
sb_append_console_char(pTHX_ sb_console_state *state, secret_buffer *dest) {
   INPUT_RECORD in_rec[16];
   const char *error= NULL;
   DWORD err_code= 0;
   int cp= -1;
   /* Inspect pending console events until we find a real character-producing key event,
    * including looking for surrogate pair if half a character is received.
    * Discard non-character events.
    */
   while (cp < 0 && !error) {
      DWORD i, nread;
      if (!PeekConsoleInputW(state->hdl, in_rec, sizeof(in_rec)/sizeof(*in_rec), &nread)) {
         error= "PeekConsoleInputW failed";
         err_code= GetLastError();
         translate_to_errno();
         break;
      }
      if (!nread)
         break;
      for (i = 0; i < nread && cp < 0 && !error; i++) {
         if (in_rec[i].EventType == KEY_EVENT
             && in_rec[i].Event.KeyEvent.bKeyDown
             && in_rec[i].Event.KeyEvent.uChar.UnicodeChar != 0
         ) {
            cp= (int) in_rec[i].Event.KeyEvent.uChar.UnicodeChar;
            if (state->pending_high_surrogate) {
               /* this needs to be the low surrogate, or die */
               if (cp >= 0xDC00 && cp <= 0xDFFF) {
                  /* combine them */
                  cp = 0x10000 + ((state->pending_high_surrogate - 0xD800) << 10) + (cp - 0xDC00);
                  state->pending_high_surrogate= 0;
               } else {
                  /* croak, but also clear the surrogate so the next read can succeed */
                  state->pending_high_surrogate= 0;
                  error= "received unpaired high UTF-16 surrogate";
                  break; /* stop before i++ so that this event is available later */
               }
            }
            /* new high surrogate? */
            else if (cp >= 0xD800 && cp <= 0xDBFF) {
               state->pending_high_surrogate= cp;
               cp= -1; /* keep looping since the low surrogate is probably in a following event */
            }
            /* low surrogate without high surrogate */
            else if (cp >= 0xDC00 && cp <= 0xDFFF) {
               error= "received unpaired low UTF-16 surrogate";
            }
         }
      }
      /* discard consumed events */
      if (i > 0) {
         DWORD nread2;
         if (!ReadConsoleInputW(state->hdl, in_rec, i, &nread2)) {



( run in 1.109 second using v1.01-cache-2.11-cpan-d8267643d1d )