/*******************************************\
| * Ce programme est sous license GNU GPL  * |
| * This software is under GNU/GPL license  * |
| * * * * * * * * * * * * * * * * * * * * * * |
| * http://www.gnu.org/copyleft/gpl.html    * |
 \*******************************************/

/*
 * http://ed.zehome.com/                    
 * Made by Laurent Coustet <ed@zehome.com>
 */

#include <stdio.h>
#include <stdlib.h>
#include <cgi.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/types.h>
#include <dirent.h>
#include <mysql/mysql.h>

#include "debug.h"
#include "edblog.h"
#include "templates.h"
#include "mysql.h"
#include "news.h"
#include "guestbook.h"
#include "blog2.h"


/* avec un / */
#define SITEPATH "/home/ed/www2/"
#define LOGPATH "/home/ed/www2/log"
#define VISITFILE "/home/ed/www2/visites.txt"

#define BLOGFILE "/home/ed/www/blog.txt"

#define URL "http://ed.zehome.com/"
#define BUF_SIZE 1024
#define NOMBRE_DE_VISITEURS_MAX 200
#define VERSION "3.0"
#define PHOTO_REP "/home/ed/www/photos"
#define SCREENSHOT_REP "/home/ed/www/screenshots"
#define PHOTOS_PAR_LIGNE 4-1
#define BASEDIR "./html/"
#define NEWSPASSWORD "*******"


struct timeval start_time;
struct timezone start_timezone;
struct timeval stop_time;
struct timezone stop_timezone;

s_cgi *cgi;

char *extension = ".html";
float gentime=0.0;

char *__client_ip;

void printhtml (char *string);
void check_sh (char *string);
int include_file (char *filepath,int html);
void addvisit ();
void checkvisit (char *ip);
void html_generated();
void html_stats();
void photo_print_index();
void include_html (char *filename);
void get_connected();

void html_print_credits ()
{
  printf("\n"
         "<!-- Version: %s -->", VERSION);
}

void html_print_headers ()
{
  cgiHeader ();
  html_print_credits ();
  include_file ("./includes/headershead",0);
  html_stats();
  include_file ("./includes/headerstail",0);
}

void html_print_footer ()
{
  include_file ("./includes/footerhead",0);
  html_generated();
  include_file ("./includes/footertail",0);
  html_print_credits ();
}

int main (int argc, char *argv[])
{
  char *path_info = NULL;
  cgiDebug (0, 0);
  cgi = cgiInit ();
  path_info = getenv ("PATH_INFO");
  gettimeofday(&start_time, &start_timezone);

  if(getenv("REMOTE_ADDR")!=NULL)
    __client_ip = strdup(getenv ("REMOTE_ADDR"));
  else
    __client_ip = strdup("127.0.0.1");

  checkvisit(__client_ip);

  if (! path_info)
  {
    html_print_headers ();
    if ((cgiGetValue(cgi, "page") == NULL))
      include_html ("accueil");
    else if (strstr(cgiGetValue(cgi, "page"), "photos"))
    {
      if (strstr("album", cgiGetValue(cgi, "page")))
        fprintf(stdout,"Album %s\n", cgiGetValue(cgi, "Album"));
      else
        photo_print_index (PHOTO_REP, "photos");
    }
    else if (strstr(cgiGetValue(cgi, "page"), "blog"))
    {
      init_blog ("templates/head.tpl", "templates/body.tpl", "templates/tail.tpl");
      draw_head (stdout);
      draw_blog (stdout,"blog.txt");
      draw_tail (stdout);
    }
    else if (strstr(cgiGetValue(cgi, "page"), "guestbook"))
      GetGB ();

    else if (strstr(cgiGetValue(cgi, "page"), "screenshots"))
      photo_print_index (SCREENSHOT_REP, "screenshots");

    else if (strstr(cgiGetValue(cgi, "page"), "news2"))
      GetNews ();

    else if (strstr(cgiGetValue(cgi, "page"), "addgb"))
    {
      if (AddGB(cgiGetValue(cgi, "texte"), cgiGetValue(cgi, "auteur"), __client_ip, getenv("HTTP_USER_AGENT")) == 0)
        printf("Commentaire ajouté<br />\n");
      else
        printf("Erreur d'ajout. Informations manquantes ou érronées.\n");

      GetGB ();
    }
    else if (strstr(cgiGetValue(cgi, "page"), "addnewsconfirm"))
    {
      if (strcmp(cgiGetValue(cgi, "password"), NEWSPASSWORD)==0)
      {
        AddNews(cgiGetValue(cgi, "titre"), cgiGetValue(cgi, "texte"));
        printf("News ajoutée!<br /><a href=\"./?page=news2\"<< Retour</a>\n");
      }
      else
        printf("Mauvais password!\n");
    }

    else if (cgiGetValue(cgi, "page") != NULL)
      include_html (cgiGetValue(cgi, "page"));

    html_print_footer ();
  }

  return 0;
}

void check_sh (char *string)
{
  if ((strstr((const char *) string,".."))!=NULL)
  {
    fprintf(stdout, "Erreur: Requete invalide. (contiend '../')\n");
    html_print_footer ();
    exit (1);
  }

  while (*string != '\0')
  {
    switch (*string)
    {
      case ' ':
      case '\\':
      case '`':
      case '~':
      case '|':
        printf("Requete invalide.\n");
        html_print_footer ();
        exit(1);
        break;
    }

    string++;
  }
}

void printhtml (char *string)    /* replace < and > by &lt; and &gt; */
{
  while (*string)
  {
    switch (*string)
    {
      case '\n':
        fprintf (stdout,"<br>\n");
        break;
      case '&':
        fprintf (stdout,"&amp;");
        break;
      default:
        fprintf (stdout,"%c", *string);
        break;
    }

    string++;
  }
}

void include_html (char *filename)
{
  char *newfilename;
  int s;

  s = strlen(BASEDIR)+strlen(filename);
  newfilename = (char *)calloc(s+2, 1);
  snprintf(newfilename, s+2, "%s%s", BASEDIR, filename);

  include_file(newfilename, 0);
  free(newfilename);
}

int include_file (char *filepath, int html)
{
  char *new_filepath;
  FILE *fichier;
  char *buffer;
  int size=0;

  check_sh (filepath);
  new_filepath = calloc(strlen(filepath)+strlen(extension)+1, 1);

  sprintf(new_filepath, "%s%s", filepath, extension);
  //strncpy(new_filepath, filepath, strlen(filepath));
  //strncat(new_filepath, extension, strlen(extension));
  /* fprintf(stdout, "filepath: %s\n",new_filepath); */
  if ((fichier = fopen (new_filepath,"r"))==NULL)
  {
    fprintf(stdout, "Ouverture du fichier %s impossible\n",new_filepath);
    return (-1);
  }
  else
  {
    fseek(fichier, 0, SEEK_END);
    size = ftell(fichier);
    fseek(fichier, 0, SEEK_SET);
    buffer = (char *) calloc(size+1, 1);

    while (fread(buffer, sizeof(char), size, fichier))
    {
      if(html==0)
          fprintf(stdout,"%s",buffer);
      else
          printhtml (buffer);
    }
    fclose(fichier);
    memset(buffer, 0, size+1);
  }

  free(new_filepath);
  free(buffer);
  return (0);
}

void html_generated()
{
  gettimeofday(&stop_time, &stop_timezone);
  gentime = ((stop_time.tv_usec - start_time.tv_usec) / 1000000.0);
  fprintf(stdout, "%fs\n", gentime);
}

void checkvisit (char *ip)
{
  FILE *logfile;
  char *ligne;
  int i, j=0, add=1;

  struct
  {
    char *lignecomplete;
    int date;
    char *ip;
  } visiteur[NOMBRE_DE_VISITEURS_MAX];

  int timeout = 1200;
  int date = time (NULL);
  ligne = calloc(31, 1);

  if (ip == NULL)
    return;

  printf("Votre ip: %s\n", ip);

  if ((logfile = fopen (LOGPATH,"r"))==NULL)
  {
    fprintf(stdout, "Ouverture du fichier de logs %s impossible\n",LOGPATH);
    exit(1);
  } else {
    for (j=0;(fgets(ligne,30,logfile)!=NULL) && (j < NOMBRE_DE_VISITEURS_MAX);++j)
    {
      visiteur[j].lignecomplete = calloc(strlen(ligne)+1, 1);
      strcpy(visiteur[j].lignecomplete, ligne);

      visiteur[j].ip = strtok(ligne, " ");
      visiteur[j].date = strtol(strtok(NULL, " "), NULL, 10);

      if ((strstr(ip,visiteur[j].ip)) != NULL) add=0;
    }
    fclose(logfile);
    if ((logfile = fopen (LOGPATH,"w"))==NULL)
    {
      fprintf(stdout, "Ouverture du fichier de logs %s impossible\n",LOGPATH);
      exit(1);
    }

    for (i=0; i<j;i++) {
      if ( (date - visiteur[i].date) <= timeout )
        fprintf(logfile,"%s",visiteur[i].lignecomplete);
    }

    if (add == 1)
    {
      if (strstr(ip, ".") != NULL)
      {
        fprintf(logfile,"%s %d\n",ip,date);
        addvisit();
      }
    }

    fclose(logfile);
  }

  bzero(ip, strlen(ip));
}

void addvisit ()
{
  FILE *visitfile;
  long long visites=0;
  char *line;
  line = calloc(20, 1);

  if ((visitfile = fopen (VISITFILE,"r"))==NULL)
  {
    fprintf(stdout, "Ouverture du fichier de logs %s impossible\n",LOGPATH);
    exit(1);
  }

  fgets(line, 20, visitfile);
  visites = strtoll(line, NULL, 10);
  free(line);
  // fprintf(stderr,"visites: %d\n",visites);
  fclose(visitfile);

  if ((visitfile = fopen (VISITFILE, "w")) == NULL)
  {
    fprintf(stdout, "Ouverture du fichier de logs %s impossible\n",LOGPATH);
    exit(1);
  }
  fprintf(visitfile,"%lld\n",visites+1);
  // fprintf(stdout,"%d\n",visites+1);
  fclose(visitfile);
}

void get_connected()
{
  FILE *logfile;
  char *line;
  int i;
  line = calloc(31, 1);
  if ((logfile = fopen (LOGPATH,"r"))==NULL)
  {
    fprintf(stdout, "Ouverture du fichier de logs %s impossible\n",LOGPATH);
    exit(1);
  }

  for (i=0;(fgets(line,30,logfile) != NULL);i++);

  free(line);
  fclose(logfile);

  printf("%d connectés", i);
}

void html_stats()
{
  FILE *visitfile;
  int visites;
  char *line;
  line = calloc(11, 1);
  if ((visitfile = fopen (VISITFILE,"r"))==NULL)
  {
    fprintf(stderr, "Ouverture du fichier de logs %s impossible\n",LOGPATH);
    //exit(1);
    return;
  }
  fgets(line,10,visitfile);
  visites = strtol(line,NULL,10);
  free(line);
  printf("<span><b>Stats:</b><br />");
  printf("%d visites\n",visites);
  printf("<br />");
  get_connected ();
  printf("</span>\n");
  fclose(visitfile);

}

void photo_print_index(char *dir,char *rep)
{
  DIR *directory;
  struct dirent *st_directory;
  int i=0;
  int tr=1;
  st_directory = calloc(201, 1);

  if ((directory = opendir(dir))==NULL)
    {
      fprintf(stdout, "Ouverture du répertoire d'images: %s impossible.\n",dir);
      exit(1);
    }
  fprintf(stdout, "<h1 align=\"center\">Photos / screenshots</h1>");
  fprintf(stdout, "<table border=\"0\" class=\"photos\" cellspacing=\"15\" cellpadding=\"15\" align=\"center\">\n<tr>\n");
  while ( (i<=PHOTOS_PAR_LIGNE) && ((st_directory = readdir(directory))!=NULL) )
    {
      if ( (strncmp(&(st_directory->d_name[0]),(const char *)".",1)!=0) && (strncmp(&(st_directory->d_name[1]),(const char *)"..",2)!=0) && (strstr(&(st_directory->d_name[0]),"thumb")==NULL) )
    {
      // fprintf(stdout, "Readdir %s filename: %s\n<br>",PHOTO_REP,&(st_directory->d_name[0]));
      fprintf(stdout, "<td><a href=\"%s/%s\"><img border=\"0\" src=\"%s/thumb/%s\" alt=\"%s\"></a></td>\n",rep,&(st_directory->d_name[0]),rep,&(st_directory->d_name[0]),&(st_directory->d_name[0]));

      if (i == PHOTOS_PAR_LIGNE)
        {
          i=0;
          fprintf(stdout,"</tr>\n<tr>\n");
          tr++;
        }
      else
        {
          i++;
        }
    }
    }

  if (tr > 0)
    {
      fprintf(stdout,"<td>&nbsp;</td></tr>\n");
    }
  fprintf(stdout,"</table>\n");
  closedir(directory);
}