/* PIPServer - A deamon for finger protocol v2
 *
 * Copyright (C) 1999 Michael Baumer <baumi@vis.ethz.ch>
 *
 * This program 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 2 of the License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <config.h>

#ifdef HAVE_PATHS_H
#include <paths.h>
#endif /* HAVE_PATHS_H */
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <string.h>

#include "finger.h"
#include "parser.h"
#include "local_user.h"
#include "readutmp.h"
#include "file.h"
#include "conn.h"
#include "log.h"
#include "acl.h"

/* answer to a online request 
 *
 * subpackets: <user> ~ only report that user
 *
 * todo: check permission of requesting party
 */

/* not fancy yet: only returns logged in poeple w/o any info */

void online_handler(Node *node)
{
  Node *subnode;
  char *username;
  char *tmp;
  login_info *linfo, *current;

  /* todo: make the sorting an option */
  linfo = read_utmp(1);

  fprintf(stdout, "<online_reply>\n");

  if (!node->child) {

    /* report all users, if we are allowed to */

    if (config.acl->options & ACL_USERLIST)
    
      while(linfo) {
	printf("<user>\n");
	printf("<login>%s</login>\n", linfo->login_user);
	printf("<time>%s</time>\n", ctime(&linfo->login_time));
	printf("<utctime>%d</utctime>\n", linfo->login_time);
	printf("<status>%s</status>\n", linfo->status);
	if (config.acl->options & ACL_IDLETIME)
	  printf("<idle>%d</idle>\n", linfo->idle_time);
	if (config.acl->options & ACL_FROMHOST)
	  printf("<from>%s</from>\n", linfo->fromhost);
	printf("<realname>%s</realname>\n", linfo->realname);
	printf("<host>%s</host>\n", linfo->hostname);
	printf("</user>\n");
	linfo = linfo->next;
      }
    else {
      printf("<error>Permission denied</error>\n");
    }

  }
  else {
    subnode = node->child;
    while(subnode) {
      if (!strcmp(subnode->id, "user")) {
	
	username = subnode->value;
	/* entspace it */
	while (*username && isspace(*username))
	  username++;
	tmp = username + strlen(username) - 1;
	while((tmp >= username) && (isspace(*tmp))) {
	  *tmp = '\0';
	  tmp--;
	}

	/* search for that login */
	current = linfo;
	while(current) {
	  if (!strncmp(username, current->login_user, UT_NAMESIZE-1)) {
	    printf("<user>\n");
	    printf("<login>%s</login>\n", current->login_user);
	    printf("<time>%s</time>",  ctime(&current->login_time));
	    printf("<status>%s</status>", current->status);
	    printf("</user>\n");
	  }
	  current = current->next;
	}

      }
      subnode = subnode->next;
    }
  }
  
  /* free linfo */

  fprintf(stdout, "</online_reply>\n");
}

/* online_forwarder
 *
 * Called for <online> on client nodes
 * 
 * Forwards the online request to the sitemaster
 */
void online_forwarder(Node *node)
{
  int s;
  char *pip = "<pip>\r\n";
  char *online = "<online></online></pip>\r\n";
  char inbuf[256];
  int nread;
  int fwd = 0;
  int pos = 0;
  int i;
  int taglen = strlen("<online_reply>");

  s = make_conn(config.sitehost, NULL);

  if (s >= 0) {
      write(s, pip, strlen(pip));
      
      while (pos<5) {
	nread = read(s, &inbuf[pos], sizeof(inbuf) - 1);
	if (nread <= 0)
	  exit(0);
	pos += nread;
      }
      if (strncmp(inbuf, "<pip>", 5))
	exit(0);

      write(s, online, strlen(online));
      
      while ((nread = read(s, &inbuf[pos], sizeof(inbuf)-1 - pos))) {
	if (nread == -1) {
	  log(LOG_ERR, "While reading from master: %m");
	  break;
	}
	pos += nread;
	inbuf[pos] = '\0';
	
	/* search for '<' */
	for (i=0 ; i < pos ; i++)
	  if (inbuf[i] == '<') {
	    /* have we read enough data ? */
	    if (i + taglen + fwd > pos)
	      break;

	    if (!fwd) {
	      /* we are waiting for begin of reply */
	      if (!strncmp(&inbuf[i], "<online_reply>", taglen)) {
		/* move '<o...y>' to begin of buffer */
		memmove(inbuf, &inbuf[i], sizeof(inbuf) - i);
		pos -= i;
		fwd = 1;
		/* restart loop after '<o...y>' */
		i = taglen-1;
	      }
	    }
	    else {
	      /* we are waiting for end of reply */
	      if (!strncmp(&inbuf[i], "</online_reply>", taglen+1)) {
		fwd = 2;
		i += taglen+1;
		break;
	      }
	    }
	  }
	
	if (fwd && i) {
	  fwrite(inbuf, 1, i, stdout);
	  memmove(inbuf, &inbuf[i], sizeof(inbuf) - i);
	  pos -= i;
	  if (fwd==2)
	    fwd = 0;
	}
      }
      fflush(stdout);
  }
}



syntax highlighted by Code2HTML, v. 0.9.1