Select Git revision
prot-a-parse.c
-
Linus Tolke authoredLinus Tolke authored
prot-a-parse.c 7.32 KiB
/*
* $Id: prot-a-parse.c,v 0.7 1991/09/15 10:30:12 linus Exp $
* Copyright (C) 1991 Lysator Academic Computer Association.
*
* This file is part of the LysKOM server.
*
* LysKOM is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 1, or (at your option)
* any later version.
*
* LysKOM is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with LysKOM; see the file COPYING. If not, write to
* Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
* or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
* MA 02139, USA.
*
* Please mail bug reports to bug-lyskom@lysator.liu.se.
*/
/*
* prot-a-parse.c - parse protocol-A messages.
*
* BUG: Not all functions are used, I think. /ceder
*/
static char *rcsid = "$Id: prot-a-parse.c,v 0.7 1991/09/15 10:30:12 linus Exp $";
#include <setjmp.h>
#include <string.h>
#include "s-string.h"
#include <kom-types.h>
#include "lyskomd.h"
#include "com.h"
#include "connections.h"
#include "prot-a-parse.h"
#include "isc-parse.h"
#include <server/smalloc.h>
#include "minmax.h"
#include "prot-a.h"
#include "config.h"
#include "log.h"
long
prot_a_parse_long(Connection *client)
{
String token;
String_size end;
long res;
token = prot_a_get_token(client);
res = s_strtol(token, &end, PROTOCOL_NUMBER_BASE);
if (end != s_strlen(token))
longjmp(parse_env, ISC_PROTOCOL_ERR);
return res;
}
void
prot_a_parse_priv_bits(Connection *client,
Priv_bits *res)
{
String token;
token = prot_a_get_token(client);
if ( s_strlen(token) != 16 )
longjmp(parse_env, ISC_PROTOCOL_ERR);
res->wheel = token.string[ 0 ] != '0';
res->admin = token.string[ 1 ] != '0';
res->statistic = token.string[ 2 ] != '0';
res->create_pers = token.string[ 3 ] != '0';
res->create_conf = token.string[ 4 ] != '0';
res->change_name = token.string[ 5 ] != '0';
res->flg7 = token.string[ 6 ] != '0';
res->flg8 = token.string[ 7 ] != '0';
res->flg9 = token.string[ 8 ] != '0';
res->flg10 = token.string[ 9 ] != '0';
res->flg11 = token.string[ 10 ] != '0';
res->flg12 = token.string[ 11 ] != '0';
res->flg13 = token.string[ 12 ] != '0';
res->flg14 = token.string[ 13 ] != '0';
res->flg15 = token.string[ 14 ] != '0';
res->flg16 = token.string[ 15 ] != '0';
}
void
prot_a_parse_conf_type(Connection *client,
Conf_type *res)
{
String token;
token = prot_a_get_token(client);
if ( s_strlen(token) != 4 )
longjmp(parse_env, ISC_PROTOCOL_ERR);
res->rd_prot = token.string[ 0 ] != '0';
res->original = token.string[ 1 ] != '0';
res->secret = token.string[ 2 ] != '0';
res->letter_box = token.string[ 3 ] != '0';
}
/*
* Parse a string. At most 'maxlen' characters are allowed. If the
* client sends a longer string only the first 'maxlen+1' characters
* are read. Any remaining characters are discarded.
*/
/*
* +++ This needs cleaning up. See comments in and above mux_parse_string.
*/
void
prot_a_parse_string(Connection *client,
String *result,
int maxlen)
{
String_size hptr; /* Pointer to 'H' */
String_size client_len; /* The len the client is sending. */
String_size truncated_len; /* How much the server will receive. */
String_size to_skip;
static u_long err_cnt = 0;
switch ( client->string_parse_pos )
{
case 0:
if ( (result->len != 0 || result->string != NULL) && err_cnt++ < 20 )
{
log ("prot_a_parse_string(): result->len == %lu, "
"result->string == %lu. This memory will not be free()'d.\n",
(u_long)result->len, (u_long)result->string);
*result = EMPTY_STRING;
if ( err_cnt == 20 )
log("Won't log the above warning no more.");
}
/* Get number and discard trailing 'H' */
client_len = s_strtol(s_fsubstr(client->unparsed,
client->first_to_parse,
END_OF_STRING),
&hptr, PROTOCOL_NUMBER_BASE);
if ( hptr == -1
|| client->first_to_parse + hptr
>= s_strlen(client->unparsed) )
{
longjmp(parse_env, ISC_MSG_INCOMPLETE);
}
/* Check that
a) there is a trailing H
b) there was at least one digit before the H */
if ( client->unparsed.string[ client->first_to_parse
+ hptr ] != 'H'
|| hptr <= 0 )
{
longjmp(parse_env, ISC_PROTOCOL_ERR);
}
client->first_to_parse += 1 + hptr;
client->string_parse_pos = 1;
result->len = client_len; /* +++ Transfer */
/* Fall through */
case 1:
client_len = result->len;
/* Check that the entire string is transmitted. */
/* (Don't care about the trailing part that will be skipped if the
* string is longer than maxlen) */
truncated_len = min(maxlen + 1, client_len);
if ( client->first_to_parse + truncated_len
> s_strlen(client->unparsed) )
{
longjmp(parse_env, ISC_MSG_INCOMPLETE);
}
*result = EMPTY_STRING;
s_mem_crea_str(result,
client->unparsed.string + client->first_to_parse,
truncated_len);
result->len = client_len; /* Ugly! +++ */
client->first_to_parse += truncated_len;
client->string_parse_pos = 2;
/* Fall through */
case 2:
/* Was the string too long? If so, skip the truncated data. */
client_len = result->len;
truncated_len = min(maxlen+1, client_len);
if ( client_len > truncated_len )
{
to_skip = min(client_len - truncated_len,
client->unparsed.len - client->first_to_parse);
client_len -= to_skip;
client->first_to_parse += to_skip;
}
result->len = client_len;
if ( client_len > truncated_len )
longjmp(parse_env, ISC_MSG_INCOMPLETE);
/* Fall through */
default:
client->string_parse_pos = 0;
}
}
extern void
prot_a_parse_misc_info(Connection *client,
Misc_info *result)
{
switch ( client->struct_parse_pos )
{
case 0:
result->type = prot_a_parse_long(client);
client->struct_parse_pos = 1;
/* Fall through */
case 1:
switch( result->type )
{
case recpt:
result->datum.recipient = prot_a_parse_long(client);
break;
case cc_recpt:
result->datum.cc_recipient = prot_a_parse_long(client);
break;
case loc_no:
result->datum.local_no = prot_a_parse_long(client);
break;
case comm_to:
result->datum.comment_to = prot_a_parse_long(client);
break;
case footn_to:
result->datum.footnote_to = prot_a_parse_long(client);
break;
case comm_in:
case footn_in:
case rec_time:
case sent_by:
case sent_at:
/* Fall through */
#ifndef COMPILE_CHECKS
default:
#endif
longjmp(parse_env, ISC_PROTOCOL_ERR);
}
default:
client->struct_parse_pos = 0;
}
}
String
prot_a_get_token(Connection *client)
{
String result;
String_size old_first;
old_first = client->first_to_parse;
result = s_strtok(client->unparsed, &client->first_to_parse,
s_fcrea_str(WHITESPACE));
/* Check that there was at least one trailing blank. */
if ( client->first_to_parse >= s_strlen(client->unparsed) )
{
client->first_to_parse = old_first;
longjmp(parse_env, ISC_MSG_INCOMPLETE);
}
return result;
}