Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37570717
en ru br
Репозитории ALT
S:20180523-alt1.1
5.1: 20050629-alt1.1
www.altlinux.org/Changes

Группа :: Сети/WWW
Пакет: http_get

 Главная   Изменения   Спек   Патчи   Исходники   Загрузить   Gear   Bugs and FR  Repocop 

http_get-20100619/000075500000000000000000000000001215616273000135755ustar00rootroot00000000000000http_get-20100619/Makefile000064400000000000000000000021641215616273000152400ustar00rootroot00000000000000# Makefile for http_get

# CONFIGURE: If you are using a SystemV-based operating system, such as
# Solaris, you will need to uncomment this definition.
#SYSV_LIBS = -lnsl -lsocket

# CONFIGURE: If you want to compile in support for https, uncomment these
# definitions. You will need to have already built OpenSSL, available at
# http://www.openssl.org/ Make sure the SSL_TREE definition points to the
# tree with your OpenSSL installation - depending on how you installed it,
# it may be in /usr/local instead of /usr/local/ssl.
#SSL_TREE = /usr/local/ssl
#SSL_DEFS = -DUSE_SSL
#SSL_INC = -I$(SSL_TREE)/include
#SSL_LIBS = -L$(SSL_TREE)/lib -lssl -lcrypto


BINDIR = /usr/local/bin
MANDIR = /usr/local/man/man1
CC = gcc
CFLAGS = -Wall -O $(SSL_DEFS) $(SSL_INC)
#CFLAGS = -Wall -g $(SSL_DEFS) $(SSL_INC)
LDFLAGS = -s $(SSL_LIBS) $(SYSV_LIBS)
#LDFLAGS = -g $(SSL_LIBS) $(SYSV_LIBS)

all: http_get

http_get: http_get.c
$(CC) $(CFLAGS) http_get.c $(LDFLAGS) -o http_get

install: all
rm -f $(BINDIR)/http_get
cp http_get $(BINDIR)
rm -f $(MANDIR)/http_get.1
cp http_get.1 $(MANDIR)

clean:
rm -f http_get *.o core core.* *.core
http_get-20100619/README000064400000000000000000000014021215616273000144520ustar00rootroot00000000000000 http_get - get the contents of an http URL

http_get fetches an http URL and dumps the contents to stdout. It
does not do gopher, ftp, file, news, or any other type of URL, only http.
It can be configured to do https fetches as well.

Files in this distribution:

README this
Makefile guess
http_get.c source file
http_get.1 manual entry

To build: If you're on a SysV-like machine (which includes old Linux systems
but not new Linux systems), edit the Makefile and uncomment the SYSV_LIBS
line. If you're doing SSL, uncomment those lines too. Otherwise, just do
a make.

Feedback is welcome - send bug reports, enhancements, checks, money
orders, etc. to the addresses below.

Jef Poskanzer jef@mail.acme.com http://www.acme.com/jef/
http_get-20100619/http_get.1000064400000000000000000000040621215616273000154770ustar00rootroot00000000000000.TH http_get 1 "16 March 1999"
.SH NAME
http_get - get the contents of an http URL
.SH SYNOPSIS
.B http_get
.RB [ -t
.IR timeout ]
.RB [ -r
.IR referer ]
.RB [ -u
.IR user-agent ]
.RB [ -a
.IR username:password ]
.RB [ -c
.IR cookie ]
.RB [ -a
.I header value
.R ]
.RB [ -v ]
.I url
.SH DESCRIPTION
.PP
.I http_get
fetches an http URL and dumps the contents to stdout.
It does not do gopher, ftp, file, news, or any other type of URL, only http.
It can be configured to do https fetches as well.
.PP
The -t flag specifies a timeout in seconds.
If that much time passes with no activity, the fetch is aborted.
The default is 60 seconds.
.PP
The -r flag specifies a Referer header to send.
Some tightly-clenched web admins like to jigger their server to only
return files if the proper Referer is given.
.PP
The -u flag specifies a User-Agent header to send.
Some *really* tightly-clenched web admins like to jigger their server to only
return files if a well-known User-Agent is given.
.PP
The -a flag lets you do Basic Authentication.
.PP
The -c flag lets you pass in a cookie.
.PP
The -h flag lets you pass in one extra header.
.PP
The -v flag is for debugging; it tells http_get to show the HTTP headers
as well as the rest of the response.
.SH "EXIT STATUS"
.PP
If the fetch is successful (HTTP status 200), the command's exit status is 0.
Otherwise the exit status is the HTTP status code.
However, since a Unix command exit status is only one byte, the HTTP codes
show up mod 256.
Adding to the confusion, csh interprets the status byte as signed, while
in other shells it is unsigned.
Anyway, here is a table of some common status values:
.nf
HTTP sh csh
200 0 0
302 46 46
304 48 48
400 144 -112
401 145 -111
403 147 -109
404 148 -108
408 152 -104
500 244 -12
501 245 -11
503 247 -9
.fi
.SH AUTHOR
Originally based on a simple version by Al Globus <globus@nas.nasa.gov>.
Debugged, prettified, and extended by Jef Poskanzer <jef@mail.acme.com>.
http_get-20100619/http_get.c000064400000000000000000000433001215616273000155570ustar00rootroot00000000000000/* http_get - fetch the contents of an http URL
**
** Originally based on a simple version by Al Globus <globus@nas.nasa.gov>.
** Debugged and prettified by Jef Poskanzer <jef@mail.acme.com>. Also includes
** ifdefs to handle https via OpenSSL.
*/

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#ifdef USE_SSL
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif


/* Forwards. */
static void usage();
static int getURL( char* url, char* referer, char* user_agent, char* auth_token, int ncookies, char** cookies, char* header_name, char* header_value );
static int getURLbyParts( int protocol, char* host, unsigned short port, char* file, char* referer, char* user_agent, char* auth_token, int ncookies, char** cookies, char* header_name, char* header_value );
static int open_client_socket( char* hostname, unsigned short port );
static void show_error( char* cause );
static void sigcatch( int sig );
static int b64_encode( unsigned char* ptr, int len, char* space, int size );


/* Globals. */
static char* argv0;
static int verbose;
static int timeout;
static char* url;

/* Protocol symbols. */
#define PROTO_HTTP 0
#ifdef USE_SSL
#define PROTO_HTTPS 1
#endif

/* Header FSM states. */
#define HDST_LINE1_PROTOCOL 0
#define HDST_LINE1_WHITESPACE 1
#define HDST_LINE1_STATUS 2
#define HDST_BOL 10
#define HDST_TEXT 11
#define HDST_LF 12
#define HDST_CR 13
#define HDST_CRLF 14
#define HDST_CRLFCR 15

#define MAX_COOKIES 20


int
main( int argc, char** argv )
{
int argn;
char* referer;
char* user_agent;
char* auth_token;
int ncookies;
char* cookies[MAX_COOKIES];
char* header_name;
char* header_value;
int status;

argv0 = argv[0];
argn = 1;
timeout = 60;
referer = (char*) 0;
user_agent = "http_get";
auth_token = (char*) 0;
ncookies = 0;
header_name = (char*) 0;
header_value = (char*) 0;
verbose = 0;
while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
{
if ( strcmp( argv[argn], "-t" ) == 0 && argn + 1 < argc )
{
++argn;
timeout = atoi( argv[argn] );
}
else if ( strcmp( argv[argn], "-r" ) == 0 && argn + 1 < argc )
{
++argn;
referer = argv[argn];
}
else if ( strcmp( argv[argn], "-u" ) == 0 && argn + 1 < argc )
{
++argn;
user_agent = argv[argn];
}
else if ( strcmp( argv[argn], "-a" ) == 0 && argn + 1 < argc )
{
++argn;
auth_token = argv[argn];
}
else if ( strcmp( argv[argn], "-c" ) == 0 && argn + 1 < argc )
{
if ( ncookies >= MAX_COOKIES )
{
(void) fprintf( stderr, "%s: too many cookies\n", argv0 );
exit( 1 );
}
++argn;
cookies[ncookies++] = argv[argn];
}
else if ( strcmp( argv[argn], "-h" ) == 0 && argn + 2 < argc )
{
++argn;
header_name = argv[argn];
++argn;
header_value = argv[argn];
}
else if ( strcmp( argv[argn], "-v" ) == 0 )
verbose = 1;
else
usage();
++argn;
}
if ( argn >= argc )
usage();
url = argv[argn];
++argn;
if ( argn != argc )
usage();

(void) signal( SIGALRM, sigcatch );
status = getURL( url, referer, user_agent, auth_token, ncookies, cookies, header_name, header_value );

if ( status == 200 )
exit( 0 );
else if ( status == 0 )
exit( 1 );
else
exit( status );
}


static void
usage()
{
(void) fprintf( stderr, "usage: %s [-c cookie] [-t timeout] [-r referer] [-u user-agent] [-a username:password] [-h header value] [-v] url\n", argv0 );
exit( 1 );
}


/* URL must be of the form http://host-name[:port]/file-name */
static int
getURL( char* url, char* referer, char* user_agent, char* auth_token, int ncookies, char** cookies, char* header_name, char* header_value )
{
char* s;
int protocol;
char host[2000];
int host_len;
unsigned short port;
char* file = (char*) 0;
char* http = "http://";
int http_len = strlen( http );
#ifdef USE_SSL
char* https = "https://";
int https_len = strlen( https );
#endif /* USE_SSL */
int proto_len;

if ( url == (char*) 0 )
{
(void) fprintf( stderr, "%s: null URL\n", argv0 );
exit( 1 );
}
if ( strncmp( http, url, http_len ) == 0 )
{
proto_len = http_len;
protocol = PROTO_HTTP;
}
#ifdef USE_SSL
else if ( strncmp( https, url, https_len ) == 0 )
{
proto_len = https_len;
protocol = PROTO_HTTPS;
}
#endif /* USE_SSL */
else
{
(void) fprintf( stderr, "%s: non-http URL\n", argv0 );
exit( 1 );
}

/* Get the host name. */
for ( s = url + proto_len; *s != '\0' && *s != ':' && *s != '/'; ++s )
;
host_len = s - url;
host_len -= proto_len;
strncpy( host, url + proto_len, host_len );
host[host_len] = '\0';

/* Get port number. */
if ( *s == ':' )
{
port = (unsigned short) atoi( ++s );
while ( *s != '\0' && *s != '/' )
++s;
}
else
{
#ifdef USE_SSL
if ( protocol == PROTO_HTTPS )
port = 443;
else
#endif
port = 80;
}

/* Get the file name. */
if ( *s == '\0' )
file = "/";
else
file = s;

return getURLbyParts( protocol, host, port, file, referer, user_agent, auth_token, ncookies, cookies, header_name, header_value );
}


static int
getURLbyParts( int protocol, char* host, unsigned short port, char* file, char* referer, char* user_agent, char* auth_token, int ncookies, char** cookies, char* header_name, char* header_value )
{
int sockfd;
#ifdef USE_SSL
SSL_CTX* ssl_ctx = (SSL_CTX*) 0;
SSL* ssl = (SSL*) 0;
#endif
char buf[20000];
int i, bytes, b, header_state, status;

(void) alarm( timeout );
sockfd = open_client_socket( host, port );

#ifdef USE_SSL
if ( protocol == PROTO_HTTPS )
{
/* Make SSL connection. */
int r;
SSL_load_error_strings();
SSLeay_add_ssl_algorithms();
ssl_ctx = SSL_CTX_new( SSLv23_client_method() );
ssl = SSL_new( ssl_ctx );
SSL_set_fd( ssl, sockfd );
r = SSL_connect( ssl );
if ( r <= 0 )
{
(void) fprintf(
stderr, "%s: %s - SSL connection failed - %d\n",
argv0, url, r );
ERR_print_errors_fp( stderr );
exit( 1 );
}
}
#endif

/* Build request buffer, starting with the GET. */
(void) alarm( timeout );
bytes = snprintf( buf, sizeof(buf), "GET %s HTTP/1.0\r\n", file );
/* HTTP/1.1 host header - some servers want it even in HTTP/1.0. */
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "Host: %s\r\n", host );
if ( referer != (char*) 0 )
/* Referer. */
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "Referer: %s\r\n", referer );
/* User-agent. */
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "User-Agent: %s\r\n", user_agent );
/* Fixed headers. */
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "Accept: */*\r\n" );
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "Accept-Language: en\r\n" );
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "Accept-Charset: iso-8859-1,*,utf-8\r\n" );
if ( auth_token != (char*) 0 )
{
/* Basic Auth info. */
char token_buf[1000];
token_buf[b64_encode( (unsigned char*) auth_token, strlen( auth_token ), token_buf, sizeof(token_buf) )] = '\0';
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "Authorization: Basic %s\r\n", token_buf );
}
/* Cookies. */
for ( i = 0; i < ncookies; ++i )
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "Cookie: %s\r\n", cookies[i] );
/* Optional extra header. */
if ( header_name != (char*) 0 )
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "%s: %s\r\n", header_name, header_value );
/* Blank line. */
bytes += snprintf( &buf[bytes], sizeof(buf) - bytes, "\r\n" );
/* Now actually send it. */
#ifdef USE_SSL
if ( protocol == PROTO_HTTPS )
(void) SSL_write( ssl, buf, bytes );
else
#endif
(void) write( sockfd, buf, bytes );

/* Get lines until a blank one. */
(void) alarm( timeout );
header_state = HDST_LINE1_PROTOCOL;
status = 0;
for (;;)
{
#ifdef USE_SSL
if ( protocol == PROTO_HTTPS )
bytes = SSL_read( ssl, buf, sizeof(buf) );
else
#endif
bytes = read( sockfd, buf, sizeof(buf) );
if ( bytes <= 0 )
break;
for ( b = 0; b < bytes; ++b )
{
if ( verbose )
(void) write( 1, &buf[b], 1 );
switch ( header_state )
{
case HDST_LINE1_PROTOCOL:
switch ( buf[b] )
{
case ' ': case '\t':
header_state = HDST_LINE1_WHITESPACE; ; break;
case '\n': header_state = HDST_LF ; break;
case '\r': header_state = HDST_CR; break;
}
break;
case HDST_LINE1_WHITESPACE:
switch ( buf[b] )
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
status = buf[b] - '0';
header_state = HDST_LINE1_STATUS;
break;
case '\n': header_state = HDST_LF ; break;
case '\r': header_state = HDST_CR; break;
default: header_state = HDST_TEXT; break;
}
break;
case HDST_LINE1_STATUS:
switch ( buf[b] )
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
status = status * 10 + buf[b] - '0';
break;
case '\n': header_state = HDST_LF ; break;
case '\r': header_state = HDST_CR; break;
default: header_state = HDST_TEXT; break;
}
break;
case HDST_BOL:
switch ( buf[b] )
{
case '\n': header_state = HDST_LF; break;
case '\r': header_state = HDST_CR; break;
default: header_state = HDST_TEXT; break;
}
break;
case HDST_TEXT:
switch ( buf[b] )
{
case '\n': header_state = HDST_LF; break;
case '\r': header_state = HDST_CR; break;
}
break;

case HDST_LF:
switch ( buf[b] )
{
case '\n': goto end_of_headers;
case '\r': header_state = HDST_CR; break;
default: header_state = HDST_TEXT; break;
}
break;

case HDST_CR:
switch ( buf[b] )
{
case '\n': header_state = HDST_CRLF; break;
case '\r': goto end_of_headers;
default: header_state = HDST_TEXT; break;
}
break;

case HDST_CRLF:
switch ( buf[b] )
{
case '\n': goto end_of_headers;
case '\r': header_state = HDST_CRLFCR; break;
default: header_state = HDST_TEXT; break;
}
break;

case HDST_CRLFCR:
switch ( buf[b] )
{
case '\n': case '\r': goto end_of_headers;
default: header_state = HDST_TEXT; break;
}
break;
}
}
}
end_of_headers:
/* Dump out the rest of the headers buffer. */
if ( bytes > 0 )
{
++b;
(void) write( 1, &buf[b], bytes - b );
}

/* Copy the data. */
for (;;)
{
(void) alarm( timeout );
#ifdef USE_SSL
if ( protocol == PROTO_HTTPS )
bytes = SSL_read( ssl, buf, sizeof(buf) );
else
#endif
bytes = read( sockfd, buf, sizeof(buf) );
if ( bytes == 0 )
break;
if ( bytes < 0 )
show_error( "read" );
(void) write( 1, buf, bytes );
}
#ifdef USE_SSL
if ( protocol == PROTO_HTTPS )
{
SSL_free( ssl );
SSL_CTX_free( ssl_ctx );
}
#endif
(void) close( sockfd );
return status;
}


#if defined(AF_INET6) && defined(IN6_IS_ADDR_V4MAPPED)
#define USE_IPV6
#endif

static int
open_client_socket( char* hostname, unsigned short port )
{
#ifdef USE_IPV6
struct addrinfo hints;
char portstr[10];
int gaierr;
struct addrinfo* ai;
struct addrinfo* ai2;
struct addrinfo* aiv4;
struct addrinfo* aiv6;
struct sockaddr_in6 sa;
#else /* USE_IPV6 */
struct hostent *he;
struct sockaddr_in sa;
#endif /* USE_IPV6 */
int sa_len, sock_family, sock_type, sock_protocol;
int sockfd;

(void) memset( (void*) &sa, 0, sizeof(sa) );

#ifdef USE_IPV6

(void) memset( &hints, 0, sizeof(hints) );
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
(void) snprintf( portstr, sizeof(portstr), "%d", (int) port );
if ( (gaierr = getaddrinfo( hostname, portstr, &hints, &ai )) != 0 )
{
(void) fprintf(
stderr, "%s: getaddrinfo %s - %s\n", argv0, hostname,
gai_strerror( gaierr ) );
exit( 1 );
}

/* Find the first IPv4 and IPv6 entries. */
aiv4 = (struct addrinfo*) 0;
aiv6 = (struct addrinfo*) 0;
for ( ai2 = ai; ai2 != (struct addrinfo*) 0; ai2 = ai2->ai_next )
{
switch ( ai2->ai_family )
{
case AF_INET:
if ( aiv4 == (struct addrinfo*) 0 )
aiv4 = ai2;
break;
case AF_INET6:
if ( aiv6 == (struct addrinfo*) 0 )
aiv6 = ai2;
break;
}
}

/* If there's an IPv4 address, use that, otherwise try IPv6. */
if ( aiv4 != (struct addrinfo*) 0 )
{
if ( sizeof(sa) < aiv4->ai_addrlen )
{
(void) fprintf(
stderr, "%s - sockaddr too small (%lu < %lu)\n",
hostname, (unsigned long) sizeof(sa),
(unsigned long) aiv4->ai_addrlen );
exit( 1 );
}
sock_family = aiv4->ai_family;
sock_type = aiv4->ai_socktype;
sock_protocol = aiv4->ai_protocol;
sa_len = aiv4->ai_addrlen;
(void) memmove( &sa, aiv4->ai_addr, sa_len );
goto ok;
}
if ( aiv6 != (struct addrinfo*) 0 )
{
if ( sizeof(sa) < aiv6->ai_addrlen )
{
(void) fprintf(
stderr, "%s - sockaddr too small (%lu < %lu)\n",
hostname, (unsigned long) sizeof(sa),
(unsigned long) aiv6->ai_addrlen );
exit( 1 );
}
sock_family = aiv6->ai_family;
sock_type = aiv6->ai_socktype;
sock_protocol = aiv6->ai_protocol;
sa_len = aiv6->ai_addrlen;
(void) memmove( &sa, aiv6->ai_addr, sa_len );
goto ok;
}

(void) fprintf(
stderr, "%s: no valid address found for host %s\n", argv0, hostname );
exit( 1 );

ok:
freeaddrinfo( ai );

#else /* USE_IPV6 */

he = gethostbyname( hostname );
if ( he == (struct hostent*) 0 )
{
(void) fprintf( stderr, "%s: unknown host - %s\n", argv0, hostname );
exit( 1 );
}
sock_family = sa.sin_family = he->h_addrtype;
sock_type = SOCK_STREAM;
sock_protocol = 0;
sa_len = sizeof(sa);
(void) memmove( &sa.sin_addr, he->h_addr, he->h_length );
sa.sin_port = htons( port );

#endif /* USE_IPV6 */

sockfd = socket( sock_family, sock_type, sock_protocol );
if ( sockfd < 0 )
show_error( "socket" );

if ( connect( sockfd, (struct sockaddr*) &sa, sa_len ) < 0 )
show_error( "connect" );

return sockfd;
}


static void
show_error( char* cause )
{
char buf[5000];
(void) sprintf( buf, "%s: %s - %s", argv0, url, cause );
perror( buf );
exit( 1 );
}


static void
sigcatch( int sig )
{
(void) fprintf( stderr, "%s: %s - timed out\n", argv0, url );
exit( 1 );
}


/* Base-64 encoding. This encodes binary data as printable ASCII characters.
** Three 8-bit binary bytes are turned into four 6-bit values, like so:
**
** [11111111] [22222222] [33333333]
**
** [111111] [112222] [222233] [333333]
**
** Then the 6-bit values are represented using the characters "A-Za-z0-9+/".
*/

static char b64_encode_table[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 0-7 */
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 8-15 */
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 16-23 */
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 24-31 */
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 32-39 */
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 40-47 */
'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 48-55 */
'4', '5', '6', '7', '8', '9', '+', '/' /* 56-63 */
};

static int b64_decode_table[256] = {
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */
52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */
15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */
-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */
41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */
};

/* Do base-64 encoding on a hunk of bytes. Return the actual number of
** bytes generated. Base-64 encoding takes up 4/3 the space of the original,
** plus a bit for end-padding. 3/2+5 gives a safe margin.
*/
static int
b64_encode( unsigned char* ptr, int len, char* space, int size )
{
int ptr_idx, space_idx, phase;
char c;

space_idx = 0;
phase = 0;
for ( ptr_idx = 0; ptr_idx < len; ++ptr_idx )
{
switch ( phase )
{
case 0:
c = b64_encode_table[ptr[ptr_idx] >> 2];
if ( space_idx < size )
space[space_idx++] = c;
c = b64_encode_table[( ptr[ptr_idx] & 0x3 ) << 4];
if ( space_idx < size )
space[space_idx++] = c;
++phase;
break;
case 1:
space[space_idx - 1] =
b64_encode_table[
b64_decode_table[(int) ((unsigned char) space[space_idx - 1])] |
( ptr[ptr_idx] >> 4 ) ];
c = b64_encode_table[( ptr[ptr_idx] & 0xf ) << 2];
if ( space_idx < size )
space[space_idx++] = c;
++phase;
break;
case 2:
space[space_idx - 1] =
b64_encode_table[
b64_decode_table[(int) ((unsigned char) space[space_idx - 1])] |
( ptr[ptr_idx] >> 6 ) ];
c = b64_encode_table[ptr[ptr_idx] & 0x3f];
if ( space_idx < size )
space[space_idx++] = c;
phase = 0;
break;
}
}
/* Pad with ='s. */
while ( phase++ < 3 )
if ( space_idx < size )
space[space_idx++] = '=';
return space_idx;
}
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin