/** 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 **/
/*
 * viewdata.c:  View generic server parameters in HTML Admin Interface.
 * 
 * Initial version: 3/11/99 by Adam Prishtina
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <prtypes.h>

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

#include <base/util.h>
#include "libadminutil/distadm.h"
#include "libadminutil/admutil.h"
#include "libadminutil/resource.h"
#include "libadmsslutil/admsslutil.h"
#include "libadmin/libadmin.h"
#include "libadmin/cluster.h"

#define MY_PAGE "viewdata.html"

#define NBUF_SIZE 1024

/*
 * i18n conversions defines and function;
 * properties file  = "viewdata.properties"
 */
#define RESOURCE_FILE "viewdata"
#define resource_key(a,b)   a b

#define DBT_INV_NUMBER 			resource_key(RESOURCE_FILE, "1")
#define DBT_INV_NUMBER_DESC 		resource_key(RESOURCE_FILE, "2")
#define DBT_SUBTITLE 		        resource_key(RESOURCE_FILE, "3")
#define DBT_WITH   		        resource_key(RESOURCE_FILE, "4")

/* html resource */
#define DBT_OUTPUT_DATA_SERVER_PRODUCT_NAME	resource_key(RESOURCE_FILE, "20")
#define DBT_OUTPUT_DATA_DATE 		        resource_key(RESOURCE_FILE, "21")
#define DBT_OUTPUT_DATA_SERVER_ROOT 		resource_key(RESOURCE_FILE, "22")
#define DBT_OUTPUT_DATA_SERVER_PORT 		resource_key(RESOURCE_FILE, "23")
#define DBT_OUTPUT_DATA_PRODUCT_NAME 		resource_key(RESOURCE_FILE, "24")
#define DBT_OUTPUT_DATA_VENDOR 		        resource_key(RESOURCE_FILE, "25")
#define DBT_OUTPUT_DATA_PRODUCT_VERSION 	resource_key(RESOURCE_FILE, "26")
#define DBT_OUTPUT_DATA_BUILD_NUMBER 		resource_key(RESOURCE_FILE, "27")
#define DBT_OUTPUT_DATA_BUILD_SECURITY 		resource_key(RESOURCE_FILE, "28")
#define DBT_OUTPUT_DATA_REVISION_NUMBER 	resource_key(RESOURCE_FILE, "29")
#define DBT_OUTPUT_DATA_DESCRIPTION 		resource_key(RESOURCE_FILE, "30")
#define DBT_MAIN_TABLE_HEADER 		        resource_key(RESOURCE_FILE, "31")
#define DBT_MAIN_TABLE_FOOTER 		        resource_key(RESOURCE_FILE, "32")
#define DBT_MAIN_SERVER_ID 		        resource_key(RESOURCE_FILE, "33")
#define DBT_MAIN_PRODUCT_VERSION 		resource_key(RESOURCE_FILE, "34")
#define DBT_MAIN_UPGRADE_AVAILABLE 		resource_key(RESOURCE_FILE, "35")
#define DBT_MAIN_PRODUCT_URL 		        resource_key(RESOURCE_FILE, "36")


static  char *acceptLanguage = (char*)"en";
static  Resource *i18nResource = NULL;

char*
getResourceString(char *key) {
  static char msgbuf[BUFSIZ]; /* ok - not threaded code */
  return (char *)(res_getstring(i18nResource, key, acceptLanguage, msgbuf, sizeof(msgbuf), NULL));
}

static void i18nInit() {
	i18nResource = res_find_and_init_resource(PROPERTYDIR, RESOURCE_FILE);
	if (getenv("HTTP_ACCEPT_LANGUAGE")) {
		acceptLanguage = getenv("HTTP_ACCEPT_LANGUAGE");
	}
}


/*
 * Get the AdmldapInfo struct for ldap SDK API.
 */

AdmldapInfo get_adm_ldapinfo(const char *configdir, const char *securitydir) {

  AdmldapInfo ldapInfo = NULL;
  int rv;
  
  ldapInfo = admldapBuildInfo((char *)configdir, &rv);
  if(!ldapInfo)
    exit(0);
  
  rv = ADMSSL_InitSimple((char *)configdir, (char *)securitydir, 1);
  if(rv)
    exit(0);
  
  return(ldapInfo);
}



/* 
 * Get bind DN and bind PW info. 
 */

int get_bindinfo(char **binddn, char **bindpw) {

  int rv;
  int err;
  char *username = 0;
  char *localAdmin = 0;

  rv = ADM_GetUserDNString(&err, binddn); /* & of (*binddn) */
  if (rv < 0 || !*binddn || !**binddn) {
    rv = ADM_GetCurrentUsername(&err, &username);
    if (rv < 0 || !username || !*username)
      exit(0);
    else {
      /* No DN, maybe it is local super */
      localAdmin = admGetLocalAdmin(NULL, &rv);
      if (localAdmin) {
	if (strcmp(username, localAdmin))
	  exit(0);
	else {
	  *binddn = NULL;
	  *bindpw = NULL;
	}
      }
      else
	exit(0);
    }
  }
  
  if (*binddn) rv = ADM_GetCurrentPassword(&err, bindpw);
  return 1;
}


LDAP *server_bind(const char *securitydir, char *host, int port, int security, char *binddn, char *bindpw) {

  int ldapError;

  LDAP *server;


  if(!(server = util_ldap_init(securitydir, NULL, host, port, security, 0, NULL))) {
      return NULL;
  }

  if ((ldapError = util_ldap_bind(server, binddn, bindpw, LDAP_SASL_SIMPLE, NULL, NULL, NULL, NULL))
      != LDAP_SUCCESS ) {
    switch (ldapError) {
    case LDAP_INAPPROPRIATE_AUTH:
    case LDAP_INVALID_CREDENTIALS:
    case LDAP_INSUFFICIENT_ACCESS:
      /* authenticate failed: Should not continue */
#ifdef LDAP_DEBUG
      util_ldap_perror( ld, "util_ldap_bind:" );
#endif
      ldap_unbind_ext(server, NULL, NULL);
      return NULL;
    case LDAP_NO_SUCH_OBJECT:
    case LDAP_ALIAS_PROBLEM:
    case LDAP_INVALID_DN_SYNTAX:
#ifdef LDAP_DEBUG
      util_ldap_perror( ld, "util_ldap_bind:" );
#endif
      /* Not a good DN */
      ldap_unbind_ext(server, NULL, NULL);
      return NULL;
    default:
      ldap_unbind_ext(server, NULL, NULL);
      return NULL;
    }
  }

  return server;
}


int get_product_url(LDAP *server, char *sie, char **text, char **url) {

  char *dn;
  char *domain;
  char *tmp, *tmp2;
  char *base = NULL;

  LDAPMessage *entry;
  int ldapError;
  char **vals;

  *url = NULL;
  *text = NULL;

  /* Get the domain */
  tmp = strdup(sie);
  if (!(tmp2 = strrchr(tmp, ','))) {
      free(tmp);
      return 1;
  }
  tmp2[0] = '\0';
  if (!(domain = strrchr(tmp, ','))) {
      free(tmp);
      return 1;
  }
  domain++;
  tmp2[0] = ',';

  while(*domain == ' ')
    domain++;

  /* form the rest of the url */

  if(strstr(sie, "Administration")) {
    base = "ou=Admin, ou=Global Preferences";
  }
  else if(strstr(sie, "Directory")) {
    base = "ou=Directory, ou=Global Preferences";
  }
  else if(strstr(sie, "Enterprise")) {
    base = "ou=Enterprise, ou=Global Preferences";
  }
  else if(strstr(sie, "Certificate")) {
    base = "ou=Certificate, ou=Global Preferences";
  }

  dn = PR_smprintf("%s, %s", base, domain);

  if((ldapError = ldap_search_ext_s(server, dn, LDAP_SCOPE_BASE,
									"(objectclass=*)", NULL, 0,
									NULL, NULL, NULL, -1, &entry)) != LDAP_SUCCESS) {
    PR_smprintf_free(dn);
    return 1;
  }

  PR_smprintf_free(dn);
  if((vals = util_ldap_get_values(server, entry, "nshtmladminproducturl"))) {
    *url = strdup(vals[0]);
    util_ldap_value_free(vals);
  }
  if((vals = util_ldap_get_values(server, entry, "nshtmladminproducttext"))) {
    *text = strdup(vals[0]);
    util_ldap_value_free(vals);
  }

  if(*url && *text)
    return 0;
  return 1;
}


void output_data(LDAP *server, char *sie) {

  LDAPMessage *entry;
  char **vals;
  int ldapError;

  char *tmp = strdup(sie);
  char *isie;

  /* SIE has some data... */

  if((ldapError = ldap_search_ext_s(server, sie, LDAP_SCOPE_BASE,
                                    "(objectclass=*)", NULL, 0,
                                    NULL, NULL, NULL, -1, &entry)) != LDAP_SUCCESS)
    return;


  if((vals = util_ldap_get_values(server, entry, "serverproductname"))) {
    fprintf(stdout,(const char*)getResourceString(DBT_OUTPUT_DATA_SERVER_PRODUCT_NAME), vals[0]);
    util_ldap_value_free(vals);
  }


  if((vals = util_ldap_get_values(server, entry, "installationtimestamp"))) {
    struct tm tm = {0};
    char buf[BIG_LINE];
    int rc;

    /* only PARSE YYYYmmddHHMMSS */
    rc = sscanf(vals[0], "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, 
                &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);

    if (rc < 6) {
        PR_snprintf(buf, sizeof(buf), "Error: date [%s] not in YYYYmmddHHMMSS format", vals[0]);
    } else {
        tm.tm_year -= 1900;  /* the number of years since 1900 */
        tm.tm_mon  -= 1;     /* The number of month since January, in the range 0 to 11 */

#ifdef LINUX
        strftime(buf, BIG_LINE, "%b %d, %Y %T %p", &tm);
        tzset();
        PR_snprintf(buf, sizeof(buf), "%s %s", buf, daylight ? tzname[1] : tzname[0]);
#else
        strftime(buf, sizeof(buf), "%b %d, %Y %T %p %Z", &tm);
#endif
    }

    util_ldap_value_free(vals);
    vals = NULL;
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_DATE), buf);
  }


  if((vals = util_ldap_get_values(server, entry, "serverroot"))) {
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_SERVER_ROOT), vals[0]);
    util_ldap_value_free(vals);
  }

  if(!(vals = util_ldap_get_values(server, entry, "nsserverport"))) {
    /* argh, port can be in the configuration object */

    char *config_buf = PR_smprintf("cn=configuration, %s", sie);

    if((ldapError = ldap_search_ext_s(server, config_buf, LDAP_SCOPE_BASE,
                                      "(objectclass=*)", NULL, 0,
                                      NULL, NULL, NULL, -1, &entry)) != LDAP_SUCCESS) {
      PR_smprintf_free(config_buf);
      return;
    }

    PR_smprintf_free(config_buf);
    vals = util_ldap_get_values(server, entry, "nsserverport");
  }
  if(vals) {
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_SERVER_PORT), vals[0]);
    util_ldap_value_free(vals);
  }

  /* ... and ISIE has the rest. */

  isie = strtok(tmp, ",");
  isie = strtok(NULL, "\0");
  while(*isie == ' ')
    isie++; /* eliminate spaces */

  if((ldapError = ldap_search_ext_s(server, isie, LDAP_SCOPE_BASE,
                                    "(objectclass=*)", NULL, 0,
                                    NULL, NULL, NULL, -1, &entry)) != LDAP_SUCCESS)
    return;

  if((vals = util_ldap_get_values(server, entry, "nsproductname"))) {
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_PRODUCT_NAME), vals[0]);
    util_ldap_value_free(vals);
  }

  if((vals = util_ldap_get_values(server, entry, "nsvendor"))) {
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_VENDOR), vals[0]);
    util_ldap_value_free(vals);
  }

  if((vals = util_ldap_get_values(server, entry, "nsproductversion"))) {
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_PRODUCT_VERSION), vals[0]);
    util_ldap_value_free(vals);
  }

  if((vals = util_ldap_get_values(server, entry, "nsbuildnumber"))) {
    fprintf(stdout,(const char*)getResourceString(DBT_OUTPUT_DATA_BUILD_NUMBER), vals[0]);
    util_ldap_value_free(vals);
  }

  if((vals = util_ldap_get_values(server, entry, "nsbuildsecurity"))) {
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_BUILD_SECURITY), vals[0]);
    util_ldap_value_free(vals);
  }

  if((vals = util_ldap_get_values(server, entry, "nsrevisionnumber"))) {
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_REVISION_NUMBER), vals[0]);
    util_ldap_value_free(vals);
  }

  if((vals = util_ldap_get_values(server, entry, "description"))) {
    fprintf(stdout, (const char*)getResourceString(DBT_OUTPUT_DATA_DESCRIPTION), vals[0]);
    util_ldap_value_free(vals);
  }

}

int main(int argc, char *argv[])
{

    int _ai = ADMUTIL_Init();
    char *qs = getenv("QUERY_STRING");
    char line[BIG_LINE];
    FILE *html = open_html_file(MY_PAGE);
    char *sie = NULL;
    char *binddn, *bindpw;
    LDAP *server;
    LDAPMessage *entry;
    int ldapError;
    const char *configdir = util_get_conf_dir();
    const char *secdir = util_get_security_dir();
    char *securitydir = NULL;

    AdmldapInfo ldapInfo = get_adm_ldapinfo(configdir, secdir);

    (void)_ai; /* get rid of unused variable warning */
    i18nInit();

    if(!get_bindinfo(&binddn, &bindpw))
      exit(0);
    
    securitydir = admldapGetSecurityDir(ldapInfo);
    server = server_bind(securitydir,
			 admldapGetHost(ldapInfo),
			 admldapGetPort(ldapInfo),
			 admldapGetSecurity(ldapInfo),
			 binddn,
			 bindpw);
    
    fprintf(stdout, "Content-type: text/html;charset=utf-8\n\n");

    if (!server) {
      char buf[BUFSIZ];
      PR_snprintf(buf, sizeof(buf), "Error: could not open connection to [%s:%d]\n",
		  admldapGetHost(ldapInfo), admldapGetPort(ldapInfo));
      rpt_err(NETWORK_ERROR, buf, NULL, NULL);
    }

    if(qs)  {
       get_begin(qs);
       sie=get_cgi_var("sie", NULL, NULL);
    }

    if (!sie) { /* error - incorrect usage */
      rpt_err(INCORRECT_USAGE, "This program must be called as a GET CGI with the sie parameter", NULL, NULL);
    }

    while(next_html_line(html, line))  {
        if(parse_line(line, NULL))  {
            if(directive_is(line, "SHOW_DATA"))  {
	      fprintf(stdout, "%s", getResourceString(DBT_MAIN_TABLE_HEADER));
	      output_data(server, sie);
	      fprintf(stdout, "%s", getResourceString(DBT_MAIN_TABLE_FOOTER));
            } 
            else if(directive_is(line, "ID_TITLE"))  {
	      char **vals;
	      if((ldapError = ldap_search_ext_s(server, sie, LDAP_SCOPE_BASE,
                                            "(objectclass=*)", NULL, 0, NULL,
                                            NULL, NULL, -1, &entry)) != LDAP_SUCCESS)
		continue;
	      
	      if((vals = util_ldap_get_values(server, entry, "nsserverid"))) {
		fprintf(stdout, (const char*)getResourceString(DBT_MAIN_SERVER_ID), vals[0]);
		util_ldap_value_free(vals);
	      }
	    }
            else if(directive_is(line, "SHOW_URL"))  {
	      char *text;
	      char *url;

	      if(get_product_url(server, sie, &text, &url) == 0) {
		/* success - output link */
		fprintf(stdout, (const char*)getResourceString(DBT_MAIN_PRODUCT_URL), url, text);
	      }
	    }
	    else
	      fputs(line, stdout);
	}
    }

    return 0;	
}
