Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/libsvn_subr/quoprint.c  view on Meta::CPAN



/* Close handler for svn_quoprint_encode().  */
static svn_error_t *
finish_encoding_data(void *baton)
{
  struct encode_baton *eb = baton;
  svn_error_t *err = SVN_NO_ERROR;
  apr_size_t len;

  /* Terminate the current output line if it's not empty.  */
  if (eb->linelen > 0)
    {
      len = 2;
      err = svn_stream_write(eb->output, "=\n", &len);
    }

  /* Pass on the close request and clean up the baton.  */
  if (err == SVN_NO_ERROR)
    err = svn_stream_close(eb->output);
  svn_pool_destroy(eb->pool);
  return err;
}


svn_stream_t *
svn_quoprint_encode(svn_stream_t *output, apr_pool_t *pool)
{
  apr_pool_t *subpool = svn_pool_create(pool);
  struct encode_baton *eb = apr_palloc(subpool, sizeof(*eb));
  svn_stream_t *stream;

  eb->output = output;
  eb->linelen = 0;
  eb->pool = subpool;
  stream = svn_stream_create(eb, pool);
  svn_stream_set_write(stream, encode_data);
  svn_stream_set_close(stream, finish_encoding_data);
  return stream;
}


svn_stringbuf_t *
svn_quoprint_encode_string(const svn_stringbuf_t *str, apr_pool_t *pool)
{
  svn_stringbuf_t *encoded = svn_stringbuf_create_empty(pool);
  int linelen = 0;

  encode_bytes(encoded, str->data, str->len, &linelen);
  if (linelen > 0)
    svn_stringbuf_appendcstr(encoded, "=\n");
  return encoded;
}



/* Quoted-printable-encoded input --> binary output */

struct decode_baton {
  svn_stream_t *output;
  char buf[3];                  /* Bytes waiting to be decoded */
  int buflen;                   /* Number of bytes waiting */
  apr_pool_t *pool;
};


/* Decode a byte string which may or may not be the total amount of
   data being decoded.  INBUF and *INBUFLEN carry the leftover bytes
   from call to call.  Have room for four bytes in INBUF and
   initialize *INBUFLEN to 0 and *DONE to FALSE.  Output will be
   appended to STR.  */
static void
decode_bytes(svn_stringbuf_t *str, const char *data, apr_size_t len,
             char *inbuf, int *inbuflen)
{
  const char *p, *find1, *find2;
  char c;

  for (p = data; p <= data + len; p++)
    {
      /* Append this byte to the buffer and see what we have.  */
      inbuf[(*inbuflen)++] = *p;
      if (*inbuf != '=')
        {
          /* Literal character; append it if it's valid as such.  */
          if (VALID_LITERAL(*inbuf))
            svn_stringbuf_appendbyte(str, *inbuf);
          *inbuflen = 0;
        }
      else if (*inbuf == '=' && *inbuflen == 2 && inbuf[1] == '\n')
        {
          /* Soft newline; ignore.  */
          *inbuflen = 0;
        }
      else if (*inbuf == '=' && *inbuflen == 3)
        {
          /* Encoded character; decode it and append.  */
          find1 = strchr(hextab, inbuf[1]);
          find2 = strchr(hextab, inbuf[2]);
          if (find1 != NULL && find2 != NULL)
            {
              c = (char)(((find1 - hextab) << 4) | (find2 - hextab));
              svn_stringbuf_appendbyte(str, c);
            }
          *inbuflen = 0;
        }
    }
}


/* Write handler for svn_quoprint_decode.  */
static svn_error_t *
decode_data(void *baton, const char *data, apr_size_t *len)
{
  struct decode_baton *db = baton;
  apr_pool_t *subpool;
  svn_stringbuf_t *decoded;
  apr_size_t declen;
  svn_error_t *err = SVN_NO_ERROR;

  /* Decode this block of data.  */
  subpool = svn_pool_create(db->pool);
  decoded = svn_stringbuf_create_empty(subpool);
  decode_bytes(decoded, data, *len, db->buf, &db->buflen);

  /* Write the output, clean up, go home.  */
  declen = decoded->len;
  if (declen != 0)
    err = svn_stream_write(db->output, decoded->data, &declen);
  svn_pool_destroy(subpool);
  return err;
}


/* Close handler for svn_quoprint_decode().  */
static svn_error_t *
finish_decoding_data(void *baton)
{
  struct decode_baton *db = baton;
  svn_error_t *err;

  /* Pass on the close request and clean up the baton.  */
  err = svn_stream_close(db->output);
  svn_pool_destroy(db->pool);
  return err;
}


svn_stream_t *
svn_quoprint_decode(svn_stream_t *output, apr_pool_t *pool)
{
  apr_pool_t *subpool = svn_pool_create(pool);
  struct decode_baton *db = apr_palloc(subpool, sizeof(*db));
  svn_stream_t *stream;

  db->output = output;
  db->buflen = 0;
  db->pool = subpool;
  stream = svn_stream_create(db, pool);
  svn_stream_set_write(stream, decode_data);
  svn_stream_set_close(stream, finish_decoding_data);
  return stream;
}


svn_stringbuf_t *
svn_quoprint_decode_string(const svn_stringbuf_t *str, apr_pool_t *pool)
{
  svn_stringbuf_t *decoded = svn_stringbuf_create_empty(pool);
  char ingroup[4];
  int ingrouplen = 0;

  decode_bytes(decoded, str->data, str->len, ingroup, &ingrouplen);
  return decoded;
}



( run in 1.919 second using v1.01-cache-2.11-cpan-677af5a14d3 )