@c -*-texinfo-*-

@node misc
@section Various utilities

@menu
* base64::                Base64 encoder/decoder
* bit-strings::           Bit-string data type
* bytevectors::           Bytevector utilities
* password::              Password hashing
* tcp::                   Basic TCP client connections
@end menu


@node base64
@subsection Base 64 encoding and decoding
The @code{(industria base64)} library provides procedures for
dealing with the standard Base 64 encoding from RFC 4648 and some
variations thereof. The Base 64 encoding can be used to represent
arbitrary bytevectors purely in printable ASCII.

One variation of Base 64 is in the alphabet used. The standard encoding
uses an alphabet that ends with @code{#\+} and @code{#\/}, but these
characters are reserved in some applications. One such application is
HTTP URLs, so there is a special encoding called base64url that simply
uses a different alphabet.

The line length can also vary. Some applications will need Base 64
encoded strings that have no line endings at all, while other
applications have 64 or 76 characters per line. For these uses the
line length must be a multiple of four characters. Sometimes there is
not enough input to get a multiple of four, but then the padding
character @code{#\=} is used. Some applications don't use padding.

Some applications have their own ``Base 64'' encodings that encode bits
in a different order. Such will be deemed magic and shall not work
with this library.

@deffn Procedure base64-encode bv [start end line-length no-padding alphabet port]
Encodes the bytevector @var{bv} in Base 64 encoding. Optionally a range
of bytes can be specified with @var{start} and @var{end}.

If a maximum line length is required, set @var{line-length} to an
integer multiple of four (the default is @code{#f}). To omit padding
at the end of the data, set @var{no-padding} or a non-false value. The
@var{alphabet} is a string of length 64 (by default
@code{base64-alphabet}).

The @var{port} is either a textual output port or @code{#f}, in which
case this procedure returns a string.
@end deffn

@deffn Procedure base64-decode str [alphabet port strict? strict-padding?]
Decodes the Base 64 data in @var{str}. The result is written to the
binary output @var{port} or returned as a bytevector if @var{port} is
@code{#f} or omitted.

If @var{strict?} is true or omitted then the string has to contain
pure Base 64 data and no whitespace or other extra characters.
Otherwise non-alphabet characters are ignored.

If @var{strict-padding?} is true or omitted then the string has to
be padded to a multiple of four characters.

The default alphabet is @var{base64-alphabet}.
@end deffn

@deffn Procedure put-delimited-base64 port type bv [line-length]
Write the Base 64 encoding of @var{bv} to the @var{port}. The output is
delimited by BEGIN/END lines that include the @var{type}.
@cindex ASCII Armor

@example
(import (industria base64))
(put-delimited-base64 (current-output-port) "EXAMPLE"
                      (string->utf8 "POKEY THE PENGUIN"))
@print{} -----BEGIN EXAMPLE-----
@print{} UE9LRVkgVEhFIFBFTkdVSU4=
@print{} -----END EXAMPLE-----
@end example
@end deffn

@deffn Procedure get-delimited-base64 port [strict?]
Reads a delimited Base 64 encoded bytevector and returns two values:
@var{type} (a string) and @var{data} (a bytevector). The @var{data}
value is the end-of-file object if @code{port-eof?} would return
@code{#t}.

@emph{Note}: This procedure ignores MIME headers. Some delimited
Base 64 formats have headers on the line after BEGIN, followed by an
empty line.

@emph{Note}: This procedure ignores the Radix-64 checksum. The
Radix-64 format (RFC 4880) is based on Base 64, but appends a CRC-24
(prefixed by @code{#\=}) at the end of the data.

The rationale for ignoring headers and checksums is that it follows
the Principle of Robustness: ``Be conservative in what you send; be
liberal in what you accept from others.'' Lines before the BEGIN line
are also ignored, because some applications (like OpenSSL) like to
prepend a human readable version of the data.

You should probably use special parsers if you are reading data with
headers or checksums. For some applications, e.g.@: MIME, you would
also set @var{strict?} to @code{#f}.

@example
(get-delimited-base64
 (open-string-input-port
  "-----BEGIN EXAMPLE-----\n\
AAECAwQFBg==\n\
-----END EXAMPLE-----\n"))
@result{} "EXAMPLE"
@result{} #vu8(0 1 2 3 4 5 6)
@end example
@end deffn

@deffn Constant base64-alphabet
The alphabet used by the standard Base 64 encoding. The alphabet is
@code{#\A}--@code{#\Z}, @code{#\a}--@code{#\z},
@code{#\0}--@code{#\9}, @code{#\+}, @code{#\/}.
@end deffn

@deffn Constant base64url-alphabet
The alphabet used by the base64url encoding. The alphabet is
@code{#\A}--@code{#\Z}, @code{#\a}--@code{#\z},
@code{#\0}--@code{#\9}, @code{#\-}, @code{#\_}.
@end deffn

@noindent
Version history:
@itemize
@item
@code{Industria 1.5} -- The decoder was optimized and the
@var{strict?} argument was introduced.
@end itemize


@node bit-strings
@subsection Bit-string data type
The @code{(industria bit-strings)} library provides a data type for
representing strings of bits.

@deffn Procedure make-bit-string length bytevector
Returns a new bit-string of @var{length} bits, which are aligned to
the start of the @var{bytevector} (with zero padding bits at the end).
@end deffn

@deffn Procedure bit-string-unused bit-string
Return the number of unused bits at the end of the bytevector
representation of @var{bit-string}.
@end deffn

@deffn Procedure bit-string->integer bit-string
Return the integer representation of @var{bit-string} (a non-negative
exact integer).
@end deffn

@deffn Procedure bit-string-bit-set? bit-string idx
True if bit @var{idx} of @var{bit-string} is set.
@end deffn

@deffn Procedure bytevector->bit-string bytevector length
Same as @code{make-bit-string}.
@end deffn

@deffn Procedure integer->bit-string int length
Return a new bit-string of @var{length} bits which represents the
integer @var{int}.
@end deffn

@deffn Procedure bit-string=? bit-string0 bit-string1
True if @var{bit-string0} equals @var{bit-string1} (same length and
bit values) and false otherwise.
@end deffn


@node bytevectors
@subsection Bytevector utilities
The @code{(industria bytevectors)} library contains utilities for
working with R6RS bytevectors.

@deffn Procedure bytevector-append [bytevector ...]
Appends the given bytevectors.
@end deffn

@deffn Procedure bytevector-concatenate list
@var{list} is a list of bytevectors. The bytevectors are appended.
@end deffn

@deffn Procedure subbytevector bytevector start [end]
Analogous to @code{substring}. Returns a new bytevector containing the
bytes of @var{bytevector} from index @code{start} to @var{end}
(exclusive).
@end deffn

@deffn Procedure bytevector-for-each proc bytevector
Apply @var{proc} to each byte in @var{bytevector}, in left-to-right
order.
@end deffn

@deffn Procedure bytevector-u8-index bytevector byte [start end]
Searches @var{bytevector} for @var{byte}, from left to right. The
optional arguments @var{start} and @var{end} give the range to search.
By default the whole bytevector is searched. Returns @code{#f} is no
match is found.
@end deffn

@deffn Procedure bytevector-u8-index-right bytevector byte [start end]
Analogous to @code{bytevector-u8-index-right}, except this procedure
searches right-to-left.
@end deffn

@deffn Procedure bytevector->uint bytevector [endian]
@var{bytevector} is interpreted as an unsigned integer in (by default)
big endian byte order and is converted to an integer. The empty
bytevector is treated as zero.
@end deffn

@deffn Procedure bytevector->sint bytevector [endian]
@var{bytevector} is interpreted as a signed integer in (by default)
big endian byte order and is converted to an integer. The empty
bytevector is treated as zero.
@end deffn

@deffn Procedure uint->bytevector integer [endian length]
@var{integer} is converted to an unsigned integer in (by default) big
endian byte order. The returned bytevector has the minimum possible
length, unless @var{length} is specified. Zero is converted to the
empty bytevector.

@example
(import (industria bytevectors))
(uint->bytevector 256)
@result{} #vu8(1 0)
(uint->bytevector 255)
@result{} #vu8(255)
@end example
@end deffn

@deffn Procedure sint->bytevector integer [endian length]
@var{integer} is converted to an signed integer in (by default) big
endian byte order. The returned bytevector has the minimum possible
length, unless @var{length} is specified (it needs one more bit than
@code{uint->bytevector}). Zero is converted to the empty bytevector.
@end deffn

@deffn Procedure bytevector=?/constant-time bytevector1 bytevector2
True if @var{bytevector1} and @var{bytevector2} are of equal length
and have the same contents.

This is a drop-in replacement for @code{bytevector=?} that does not
leak information about the outcome of the comparison by how much time
the comparison takes to perform. It works by accumulating the
differences between the bytevectors. This kind of operation is most
often needed when comparing fixed-length message digests, so the
length comparison is done in the obvious (fast) way.
@end deffn


@node password
@subsection Password hashing
The procedure provided by @code{(industria crypto password)} is the
same type of procedure that is called @code{crypt} in the standard C
library. It is used for password hashing, i.e.@: it scrambles
passwords. This is a method often used when passwords need to be
stored in databases.

The scrambling algorithms are based on cryptographic primitives but
have been modified so that they take more time to compute. They also
happen to be quite annoying to implement.

Only DES and MD5 based hashes are currently supported.

@deffn Procedure crypt password salt
Scrambles a @var{password} using the given @var{salt}. The @var{salt}
can also be a hash. The returned hash will be prefixed by the salt.

A fresh random salt should be used when hashing a new password. The
purpose of the salt is to make it infeasible to reverse the hash
using lookup tables.

To verify that a password matches a hash, you can do something like
@code{(string=? hash (crypt password hash))}.

@example
(import (industria crypto password))
(crypt "test" "..")
@result{} "..9sjyf8zL76k"
@end example

@example
(crypt "test" "$1$RQ3YWMJd$")
@result{} "$1$RQ3YWMJd$oIomUD5DCxenAs2icezcn."
@end example

@example
(string=? "$1$ggKHY.Dz$fNBcmNFTa1BFGXoLsRDkS."
          (crypt "test" "$1$ggKHY.Dz$fNBcmNFTa1BFGXoLsRDkS."))
@result{} #t
@end example
@end deffn

@c TODO: there ought be a simple way to generate a fresh salt

@c ======================================================================
@node tcp
@subsection Basic TCP client connections
The @code{(industria tcp)} provides a simple TCP client. This
library needs implementation-specific code, so the author is not eager
to provide more than the bare minimum.

This library should work with Ikarus Scheme, GNU Guile, Larceny (not
tested with Petit Larceny and Common Larceny), Mosh Scheme, Petite
Chez Scheme (as long as the nc command is installed), Vicare Scheme,
and Ypsilon Scheme. Once upon a time it also worked with PLT Scheme,
but it has not been tested with Racket.

Some newer alternatives to this library are SRFI-106 and
@url{https://github.com/ktakashi/r6rs-usocket}.

@deffn Procedure tcp-connect hostname portname
Initiates a TCP connection to the given @var{hostname} and
@var{portname} (both of which are strings).

Returns an input-port and an output-port. They are not guaranteed to
be distinct.
@end deffn
