Crypt-SecretBuffer

 view release on metacpan or  search on metacpan

SecretBuffer.xs  view on Meta::CPAN


void
new(...)
   ALIAS:
      Crypt::SecretBuffer::Exports::secret = 1
      Crypt::SecretBuffer::Exports::secret_buffer = 2
   INIT:
      SV *buf_ref= NULL;
      secret_buffer *buf= secret_buffer_new(0, &buf_ref);
      int i, next_arg= ix == 0? 1 : 0;
   PPCODE:
      if (items - next_arg == 1) {
         secret_buffer_splice_sv(buf, 0, 0, ST(next_arg));
      }
      else {
         if ((items - next_arg) & 1)
            croak("Odd number of arguments; expected (key => value) pairs");
         for (i= next_arg; i < items-1; i += 2) {
            SV *key= ST(i), *val= ST(i+1);
            {
               dSP;

SecretBuffer.xs  view on Meta::CPAN

      assign = 1
   INIT:
      int i;
      size_t from_ofs= (ix? 0 : buf->len), len_sum= 0;
      U8 *write_pos;
      secret_buffer_byte_range stack_ranges[16], *ranges= stack_ranges;
      if ((items-1) > 16) {
         Newx(ranges, (items-1), secret_buffer_byte_range);
         SAVEFREEPV(ranges);
      }
   PPCODE:
      for (i= 0; i < items-1; i++) {
         ranges[i].ptr= secret_buffer_SvPVbyte(ST(i+1), &ranges[i].len);
         len_sum += ranges[i].len;
      }
      secret_buffer_set_len(buf, from_ofs + len_sum);
      write_pos= buf->data + from_ofs;
      for (i= 0; i < items-1; i++) {
         memcpy(write_pos, ranges[i].ptr, ranges[i].len);
         write_pos += ranges[i].len;
      }
      XSRETURN(1); /* return self for chaining */

void
length(buf, val=NULL)
   auto_secret_buffer buf
   SV *val
   ALIAS:
      len = 1
   PPCODE:
      if (val) { /* writing */
         IV ival= SvIV(val);
         if (ival < 0) ival= 0;
         secret_buffer_set_len(buf, ival);
         /* return self, for chaining */
      }
      else /* reading */
         ST(0)= sv_2mortal(newSViv(buf->len));
      XSRETURN(1);

void
capacity(buf, val=NULL, flags= 0)
   auto_secret_buffer buf
   SV *val
   secret_buffer_alloc_flags flags
   PPCODE:
      if (val) { /* wiritng */
         IV ival= SvIV(val);
         if (ival < 0) ival= 0;
         if (flags & SECRET_BUFFER_AT_LEAST)
            secret_buffer_alloc_at_least(buf, ival);
         else
            secret_buffer_realloc(buf, ival);
         /* return self, for chaining */
      }
      else /* reading */
         ST(0)= sv_2mortal(newSViv(buf->capacity));
      XSRETURN(1);

void
clear(buf)
   auto_secret_buffer buf
   PPCODE:
      secret_buffer_realloc(buf, 0);
      XSRETURN(1); /* self, for chaining */

IV
index(buf, pattern, ofs_sv= &PL_sv_undef)
   secret_buffer *buf
   SV *pattern
   SV *ofs_sv
   ALIAS:
      rindex = 1

SecretBuffer.xs  view on Meta::CPAN

      secret_buffer_parse parse;
      // lim was captured as an SV so that undef can be used to indicate
      // end of the buffer.
      IV len= !SvOK(len_sv)? buf->len : SvIV(len_sv);
      ofs= normalize_offset(ofs, buf->len);
      if (!secret_buffer_parse_init(&parse, buf,
         ofs, ofs + normalize_offset(len, buf->len - ofs),
         (flags & SECRET_BUFFER_ENCODING_MASK)
      ))
         croak("%s", parse.error);
   PPCODE:
      if (secret_buffer_match(&parse, pattern, flags)) {
         PUSHs(sv_2mortal(newSViv(parse.pos - (U8*) buf->data)));
         PUSHs(sv_2mortal(newSViv(parse.lim - parse.pos)));
      }
      else if (parse.error)
         croak("%s", parse.error);

void
splice(buf, ofs, len, replacement)
   secret_buffer *buf
   IV ofs
   IV len
   SV *replacement
   PPCODE:
      /* normalize negative offset, and clamp to valid range */
      ofs= normalize_offset(ofs, buf->len);
      /* normalize negative count, and clamp to valid range */
      len= normalize_offset(len, buf->len - ofs);
      secret_buffer_splice_sv(buf, ofs, len, replacement);
      XSRETURN(1); /* return $self */

void
substr(buf, ofs, count_sv=NULL, replacement=NULL)
   secret_buffer *buf
   IV ofs
   SV *count_sv
   SV *replacement
   INIT:
      unsigned char *sub_start;
      secret_buffer *sub_buf= NULL;
      SV *sub_ref= NULL;
      IV count= count_sv? SvIV(count_sv) : buf->len;
   PPCODE:
      /* normalize negative offset, and clamp to valid range */
      ofs= normalize_offset(ofs, buf->len);
      /* normalize negative count, and clamp to valid range */
      count= normalize_offset(count, buf->len - ofs);
      sub_start= (unsigned char*) buf->data + ofs;
      /* If called in non-void context, construct new secret from this range */
      if (GIMME_V != G_VOID) {
         SV **el;
         sub_buf= secret_buffer_new(count, &sub_ref);
         if (count) {

SecretBuffer.xs  view on Meta::CPAN

         XSRETURN(0);
      else {
         ST(0)= sub_ref; /* already mortal */
         XSRETURN(1);
      }

void
append_asn1_der_length(buf, val)
   secret_buffer *buf
   UV val
   PPCODE:
      secret_buffer_append_uv_asn1_der_length(buf, val);

void
append_base128le(buf, val)
   secret_buffer *buf
   UV val
   PPCODE:
      secret_buffer_append_uv_base128le(buf, val);

void
append_base128be(buf, val)
   secret_buffer *buf
   UV val
   PPCODE:
      secret_buffer_append_uv_base128be(buf, val);

void
append_lenprefixed(buf, ...)
   secret_buffer *buf
   INIT:
      size_t bytes_needed= 0;
      IV i;
   PPCODE:
      /* Add up all the lengths and over-estimate 9 bytes for each length specifier */
      for (i= 1; i < items; i++) {
         STRLEN len;
         secret_buffer_SvPVbyte(ST(i), &len);
         bytes_needed += 9 + len;
      }
      /* ensure space with one reallocation */
      secret_buffer_alloc_at_least(buf, buf->len + bytes_needed);
      /* append each length and span to the buffer */
      for (i= 1; i < items; i++) {

SecretBuffer.xs  view on Meta::CPAN

   OUTPUT:
      RETVAL

void
append_sysread(buf, handle, count)
   auto_secret_buffer buf
   PerlIO *handle
   IV count
   INIT:
      IV got;
   PPCODE:
      got= secret_buffer_append_sysread(buf, handle, count);
      if (got < 0)
         XSRETURN_UNDEF;
      else
         PUSHs(sv_2mortal(newSViv(got)));

void
append_read(buf, handle, count)
   auto_secret_buffer buf
   PerlIO *handle
   IV count
   INIT:
      int got;
   PPCODE:
      got= secret_buffer_append_read(buf, handle, count);
      if (got < 0)
         XSRETURN_UNDEF;
      else
         PUSHs(sv_2mortal(newSViv(got)));

void
_append_console_line(buf, handle)
   auto_secret_buffer buf
   PerlIO *handle
   INIT:
      int got;
   PPCODE:
      got= secret_buffer_append_console_line(buf, handle);
      ST(0)= got == SECRET_BUFFER_GOTLINE? &PL_sv_yes
         : got == SECRET_BUFFER_EOF? &PL_sv_no
         : &PL_sv_undef;
      XSRETURN(1);

void
syswrite(buf, io, count=buf->len, ofs=0)
   secret_buffer *buf
   PerlIO *io
   IV ofs
   IV count
   INIT:
      IV wrote;
   PPCODE:
      wrote= secret_buffer_syswrite(buf, io, ofs, count);
      ST(0)= (wrote < 0)? &PL_sv_undef : sv_2mortal(newSViv(wrote));
      XSRETURN(1);

void
write_async(buf, io, count=buf->len, ofs=0)
   secret_buffer *buf
   PerlIO *io
   IV ofs
   IV count
   INIT:
      IV wrote;
      SV *ref_out= NULL;
   PPCODE:
      wrote= secret_buffer_write_async(buf, io, ofs, count, GIMME_V == G_VOID? NULL : &ref_out);
      /* wrote == 0 means that it supplied a result promise object, which is already mortal.
       * but avoid creating one when called in void context. */
      ST(0)= wrote? sv_2mortal(newSViv(wrote)) : ref_out? ref_out : &PL_sv_undef;
      XSRETURN(1);

void
stringify(buf, ...)
   auto_secret_buffer buf
   INIT:
      SV **field= hv_fetch((HV*)SvRV(ST(0)), "stringify_mask", 14, 0);
   PPCODE:
      if (!field || !*field) {
         ST(0)= sv_2mortal(newSVpvn("[REDACTED]", 10));
      } else if (SvOK(*field)) {
         ST(0)= *field;
      } else {
         ST(0)= secret_buffer_get_stringify_sv(buf);
      }
      XSRETURN(1);

void
unmask_to(buf, coderef)
   secret_buffer *buf
   SV *coderef
   INIT:
      int count= 0;
   PPCODE:
      PUSHMARK(SP);
      EXTEND(SP, 1);
      PUSHs(secret_buffer_get_stringify_sv(buf));
      PUTBACK;
      count= call_sv(coderef, GIMME_V);
      SPAGAIN;
      XSRETURN(count);

bool
_can_count_copies_in_process_memory()

SecretBuffer.xs  view on Meta::CPAN

      RETVAL

MODULE = Crypt::SecretBuffer           PACKAGE = Crypt::SecretBuffer::Exports

void
unmask_secrets_to(coderef, ...)
   SV *coderef
   INIT:
      int count= 0, i;
      secret_buffer *buf= NULL;
   PPCODE:
      PUSHMARK(SP);
      EXTEND(SP, items);
      for (i= 1; i < items; i++) {
         if (SvOK(ST(i)) && SvROK(ST(i)) && (buf= secret_buffer_from_magic(ST(i), 0)))
            PUSHs(secret_buffer_get_stringify_sv(buf));
         else
            PUSHs(ST(i));
      }
      PUTBACK;
      count= call_sv(coderef, GIMME_V);

SecretBuffer.xs  view on Meta::CPAN

   CODE:
      RETVAL= sb_wait_fh_readable(aTHX_ handle, timeout_sv);
   OUTPUT:
      RETVAL

void
_debug_charset(cset)
   secret_buffer_charset *cset
   INIT:
      HV *hv;
   PPCODE:
      PUSHs(sv_2mortal((SV*)newRV_noinc((SV*)(hv= newHV()))));
      hv_stores(hv, "bitmap", newSVpvn((char*)cset->bitmap, sizeof(cset->bitmap)));
      hv_stores(hv, "unicode_above_7F", newSViv(cset->unicode_above_7F));

MODULE = Crypt::SecretBuffer           PACKAGE = Crypt::SecretBuffer::AsyncResult

void
wait(result, timeout=-1)
   secret_buffer_async_result *result
   NV timeout
   INIT:
      IV os_err, bytes_written;
   PPCODE:
      if (secret_buffer_async_result_recv(result, (IV)(timeout*1000), &bytes_written, &os_err)) {
         EXTEND(sp, 2);
         ST(0)= sv_2mortal(newSViv(bytes_written));
         ST(1)= sv_2mortal(newSViv(os_err));
         XSRETURN(2);
      } else {
         XSRETURN(0);
      }

MODULE = Crypt::SecretBuffer           PACKAGE = Crypt::SecretBuffer::ConsoleState

SecretBuffer.xs  view on Meta::CPAN

            else if (len == 12 && memcmp(name, "auto_restore", 12) == 0) {
               if (SvOK(val)) auto_restore= val;
            }
            else {
               croak("Unknown option '%s'", name);
            }
         }
      }
      if (!handle)
         croak("'handle' is required");
   PPCODE:
      ST(0)= &PL_sv_undef;
      /* if it fails to initialize, return undef for 'maybe_new', else die */
      if (!sb_console_state_init(aTHX_ &cstate, handle)) {
         if (ix == 0)
            croak("Can't read console/tty state");
         XSRETURN(1);
      }
      if (auto_restore)
         cstate.auto_restore= SvTRUE(auto_restore);
      if (set_echo) {

SecretBuffer.xs  view on Meta::CPAN

         : NULL;
      secret_buffer *buf= secret_buffer_from_magic(
         buf_field? *buf_field : class_or_obj, SECRET_BUFFER_MAGIC_UNDEF_OK
      );
      bool subspan= span && ix >= 2;
      IV base_pos= subspan? span->pos : 0;
      IV pos=0, lim=0, len=0, base_lim=0;
      int encoding= span? span->encoding : 0, i;
      SV *encoding_sv= NULL;
      bool have_pos= false, have_lim= false, have_len= false;
   PPCODE:
      //warn("items=%d  span=%p  buf=%p  base_pos=%d", (int)items, span, buf, (int)base_pos);
      // 3-argument form, only usable when first arg is a buffer or refs a buffer
      if (buf && items >= 2 && looks_like_number(ST(1))) {
         pos= SvIV(ST(1));
         have_pos= true;
         if (items >= 3 && SvOK(ST(2))) {
            len= SvIV(ST(2));
            have_len= true;
            if (items >= 4) {
               encoding_sv= ST(3);

SecretBuffer.xs  view on Meta::CPAN

      RETVAL

void
encoding(span, newval_sv= NULL)
   secret_buffer_span *span
   SV *newval_sv
   INIT:
      SV *enc_const;
      AV *encodings= get_av("Crypt::SecretBuffer::_encodings", 0);
      if (!encodings) croak("BUG");
   PPCODE:
      if (newval_sv)
         if (!parse_encoding(aTHX_ newval_sv, &span->encoding))
            croak("Invalid encoding");
      enc_const= *av_fetch(encodings, span->encoding, 1);
      if (!enc_const || !SvOK(enc_const))
         croak("BUG");
      PUSHs(enc_const);

const char *
last_error(span)

SecretBuffer.xs  view on Meta::CPAN

set_up_us_the_bom(self)
   SV *self
   ALIAS:
      consume_bom = 1
   INIT:
      secret_buffer_span *span= secret_buffer_span_from_magic(self, SECRET_BUFFER_MAGIC_OR_DIE);
      secret_buffer_parse p;
      if (!secret_buffer_parse_init_from_sv(&p, self))
         croak("%s", p.error);
      PERL_UNUSED_VAR(ix);
   PPCODE:
      if (p.lim - p.pos >= 3 && p.pos[0] == 0xEF && p.pos[1] == 0xBB && p.pos[2] == 0xBF) {
         span->encoding= SECRET_BUFFER_ENCODING_UTF8;
         span->pos += 3;
      }
      else if (p.lim - p.pos >= 2 && p.pos[0] == 0xFF && p.pos[1] == 0xFE) {
         span->encoding= SECRET_BUFFER_ENCODING_UTF16LE;
         span->pos += 2;
      }
      else if (p.lim - p.pos >= 2 && p.pos[0] == 0xFE && p.pos[1] == 0xFF) {
         span->encoding= SECRET_BUFFER_ENCODING_UTF16BE;

SecretBuffer.xs  view on Meta::CPAN

      if (ret_type != 1 && parse.encoding == SECRET_BUFFER_ENCODING_BASE64)
         croak("Cannot perform parse, trim, or scan on base64 (pos / lim of result would not be whole bytes)");
      int op= (ix >> 8);
      bool matched;
      if (!pattern) {
         if (op == 3 || op == 4 || op == 5)
            pattern= get_sv("Crypt::SecretBuffer::Span::default_trim_regex", 0);
         if (!pattern)
            croak("pattern is required");
      }
   PPCODE:
      matched= secret_buffer_match(&parse, pattern, flags);
      if (parse.error)
         croak("%s", parse.error);
      switch (op) {
      case 1: // parse
         if (matched) span->pos= parse.lim - (U8*) buf->data;
         break;
      case 2: // rparse
         if (matched) span->lim= parse.pos - (U8*) buf->data;
         break;

SecretBuffer.xs  view on Meta::CPAN

   SV *self
   IV count
   INIT:
      secret_buffer_span *span= secret_buffer_span_from_magic(self, SECRET_BUFFER_MAGIC_OR_DIE);
      secret_buffer_parse p;
      UV len;
      size_t ofs;
      /* treat an invalid span as a bug, rather than returning it to the user in the err_out param */
      if (!secret_buffer_parse_init_from_sv(&p, self))
         croak("%s", p.error);
   PPCODE:
      while (count && p.pos < p.lim) {
         if (!secret_buffer_parse_uv_base128be(&p, &len)) {
            span->last_error= p.error;
            XSRETURN_EMPTY;
         }
         if (len > p.lim - p.pos) {
            span->last_error= "Length exceeds end of Span";
            XSRETURN_EMPTY;
         }
         ofs= p.pos - (U8*) p.sbuf->data;

SecretBuffer.xs  view on Meta::CPAN

   SV *self
   ALIAS:
      copy_to = 1
      append_to = 2
   INIT:
      SV *dst_sv= NULL;
      int next_arg, dst_encoding= -1;
      secret_buffer_parse src;
      if (!secret_buffer_parse_init_from_sv(&src, self))
         croak("%s", src.error);
   PPCODE:
      if (ix > 0) { /* called as 'copy_to' or 'append_to' */
         if (items < 2)
            croak("Missing copy/append destination");
         dst_sv= ST(1);
         next_arg= 2;
      }
      else { /* called as 'copy' */
         secret_buffer_new(0, &dst_sv);
         next_arg= 1;
      }



( run in 1.029 second using v1.01-cache-2.11-cpan-71847e10f99 )