/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc.  Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 *
 * 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; version 2
 * of the License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * END COPYRIGHT BLOCK **/
/*
 * statpingserv.c - determine the on/off status of any server.
 *
 * Takes a host and port, and the result can either be an
 * on or off icon, or text describing status.
 *
 * All blame to Adam Prishtina (adam@netscape.com)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <base/util.h>
#include "libadminutil/distadm.h"
#include "libadminutil/resource.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "libadmsslutil/certmgt.h"
#include "libadmsslutil/psetcssl.h"
#include "libadmsslutil/admsslutil.h"
#include "key.h"
#include "cert.h"
#include "secport.h"
#include "secmod.h"
#include "prnetdb.h"

#ifdef __cplusplus
}
#endif


int main(int argc, char *argv[])
{
  int _ai = ADMUTIL_Init();
  char *m;

  char *qs = getenv("QUERY_STRING");
  PRStatus    err;
  char        gifbuf[BUFSIZ];
  PRInt32     bytes;

  PRFileDesc *req_socket= NULL;
  int retcode = 0;
  PRNetAddr *netaddr = NULL;
  char *result;
  char *host;
  int port;

  PRFileDesc *gif;
  char *file;
  char *portstr;
  struct PRFileInfo64 prfileinfo;

  (void)_ai; /* get rid of unused variable warning */
  m = getenv("REQUEST_METHOD");

  if(!strcmp(m, "GET")) {
    if(qs)
      get_begin(qs);

    result = get_cgi_var("result", NULL, NULL);
    host = get_cgi_var("host", NULL, NULL);
    portstr = get_cgi_var("port", NULL, NULL);
    if (portstr) {
        port = atoi(portstr);
    } else {
        port = 0;
    }

    if(result && !strcmp(result, "text"))
      fprintf(stdout, "Content-type: text/html\n");
    else
      fprintf(stdout, "Content-type: image/gif\n");

    if (!host || !port) {
      rpt_err(APP_ERROR, "Invalid hostname and/or port number!", NULL, NULL);
      return -1;
    }
    netaddr = (PRNetAddr *)calloc(1, sizeof(PRNetAddr));
    if (NULL == netaddr) {
      rpt_err(APP_ERROR, "Failed to allocate PRNetAddr", NULL, NULL);
      return -1;
    }
    err = PR_StringToNetAddr(host, netaddr);
    if (PR_SUCCESS == err) {
      PR_InitializeNetAddr(PR_IpAddrNull, (PRUint16)port, netaddr);
    } else {
      PRAddrInfo *infop = PR_GetAddrInfoByName(host,
                            PR_AF_UNSPEC, (PR_AI_ADDRCONFIG|PR_AI_NOCANONNAME));
      if (infop) {
        void *iter = NULL;
        memset( netaddr, 0, sizeof( PRNetAddr ));
        /* need just one address */
        iter = PR_EnumerateAddrInfo(iter, infop, (PRUint16)port, netaddr);
        if (NULL == iter) {
           rpt_err(APP_ERROR, "Failed to enumerate addrinfo", NULL, NULL);
           retcode = -1;
        }
        PR_FreeAddrInfo(infop);
      } else {
        rpt_err(APP_ERROR, "Failed to get addrinfo", NULL, NULL);
        retcode = -1;
      }
    }

    if (retcode > -1) {
      req_socket = PR_NewTCPSocket();
      retcode = PR_Connect(req_socket, netaddr, 10000);
    }
    free(netaddr);

    if (retcode != 0) {
      /* SERVER IS DOWN - output the OFF button */
      if(result && !strcmp(result, "text")) {
        rpt_success("The server is DOWN.");
        return 1;
      }
      file = PR_smprintf("%s/togoff.gif", ICONDIR);
    }
    else {
      /* SERVER IS RUNNING - output of ON button */
      if(result && !strcmp(result, "text")) {
        rpt_success("The server is UP.");
        return 1;
      }
      file = PR_smprintf("%s/togon.gif", ICONDIR);
    }

    PR_Close(req_socket);

	if ((PR_FAILURE == PR_GetFileInfo64(file, &prfileinfo)) ||
		(prfileinfo.type != PR_FILE_FILE)) {
      rpt_err(APP_ERROR, "Cannot open gif file!", NULL, NULL);
	}

    fprintf(stdout, "Content-length: %ld\n\n", (size_t)prfileinfo.size);
	fflush(stdout);

	PR_Sync(PR_STDOUT);
    gif = PR_Open(file, PR_RDONLY, 0);
    PR_smprintf_free(file);
    if(!gif)
      rpt_err(APP_ERROR, "Cannot open gif file!", NULL, NULL);
	while (0 < (bytes = PR_Read(gif, gifbuf, sizeof(gifbuf)))) {
		PRInt32 remaining = bytes;
		PRInt32 byteswritten = 0;
		while (((byteswritten = PR_Write(PR_STDOUT, gifbuf+byteswritten, remaining)) != remaining) &&
			   (byteswritten > 0)) {
			remaining -= byteswritten;
		}
		if (byteswritten < 0) {
			rpt_err(APP_ERROR, "Cannot write gif to stdout!", NULL, NULL);
		}
	}
	if (bytes < 0) {
		rpt_err(APP_ERROR, "Cannot read gif to write to stdout!", NULL, NULL);
	}
	PR_Sync(PR_STDOUT);
	PR_Close(gif);
  }

  return 0;
}

