// $Id: Finger.cc,v 1.26 2003/08/31 00:38:11 vern Exp $
//
// Copyright (c) 1996, 1997, 1998, 1999, 2001, 2002
//      The Regents of the University of California.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that: (1) source code distributions
// retain the above copyright notice and this paragraph in its entirety, (2)
// distributions including binary code include the above copyright notice and
// this paragraph in its entirety in the documentation or other materials
// provided with the distribution, and (3) all advertising materials mentioning
// features or use of this software display the following acknowledgement:
// ``This product includes software developed by the University of California,
// Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
// the University nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#include "config.h"

#include <ctype.h>

#include "NetVar.h"
#include "Finger.h"
#include "Event.h"
#include "TCP_Rewriter.h"

FingerConn::FingerConn(NetSessions* s, HashKey* k, double t, const ConnID* id,
		const struct tcphdr* tp)
: TCP_Connection(s, k, t, id, tp)
	{
	did_deliver = 0;
	}

void FingerConn::BuildEndpoints()
	{
	orig = new TCP_EndpointLine(this, 1, 0, 1);

	if ( finger_reply )
		resp = new TCP_EndpointLine(this, 0, 0, 1);
	else
		resp = new TCP_Endpoint(this, 0);
	}

void FingerConn::Done()
	{
	if ( (! did_deliver || orig->AsEndpointLine()->HasPartialLine()) &&
	     (orig->state == TCP_CLOSED || orig->prev_state == TCP_CLOSED) )
		// ### should include the partial text
		Weird("partial_finger_request");

	TCP_Connection::Done();
	}

void FingerConn::NewLine(TCP_Endpoint* s, int length, const char* line, int /* is_const */)
	{
	const char* end_of_line = line + length;

	if ( s == orig )
		{
		
		if ( ! finger_request && ! rule_matcher )
			return;

		line = skip_whitespace(line, end_of_line);

		// Check for /W.
		int long_cnt = (line + 2 <= end_of_line && line[0] == '/' && toupper(line[1]) == 'W');
		if ( long_cnt )
			line = skip_whitespace(line+2, end_of_line);

		const char* at = strchr_n(line, end_of_line, '@');
		const char* host = 0;
		if ( ! at )
			at = host = end_of_line;
		else
			host = at + 1;

		val_list* vl = new val_list;
		vl->append(BuildConnVal());
		vl->append(new Val(long_cnt, TYPE_BOOL));
		vl->append(new StringVal(at - line, line));
		vl->append(new StringVal(end_of_line - host, host));

		if ( finger_request )
			ConnectionEvent(finger_request, vl);

		if ( rule_matcher )
			Match(Rule::FINGER, (const u_char *) line,
				end_of_line - line, true, true, 1);

		did_deliver = 1;
		}

	else
		{
		if ( ! finger_reply )
			return;

		val_list* vl = new val_list;
		vl->append(BuildConnVal());
		vl->append(new StringVal(end_of_line - line, line));

		ConnectionEvent(finger_reply, vl);
		}
	}

#include "finger-rw.bif.func_def"
