/*

                                   _JNJ`                        
                               .JNMH`                           
                              JMMF`       `;.                   
                            .NMM)          `MN.                 
                            MMM)            (MML                
                           (MMM`             MMML               
                     M  I  D  N  I  G  H  T    C  o  D  E       
                           (NMMF             MHNH               
                            NMML            .MMM                
                             NMML          .NMH                 
                              4MMNL       .#F                   
                               `4HNNL_   `                      
                                   `"""`                        

                          Copyright (C) 2004-2006
       "Ian (Larry) Latter" <ian dot latter at midnightcode dot org>

    Midnight Code is a registered trademark of Ian Latter.

    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, and mirrored at the Midnight Code web
    site; as at version 2 of the License only.
  
    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
    (version 2) along with this program; if not, write to the Free
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA, or see http://midnightcode.org/gplv2.txt

*/

/* htmlnx.c :: Midnight Code HTML test and example program		*/


#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <arpa/inet.h>

#include <libmidnightcode.h>


int
bin_to_std_err(char * value, int all_links,
               char * pro_url, char * abs_url, char * rel_url) {
  int url_len;
  int ret_i;


  url_len = 0;
  ret_i = 0;

  // printf("Debug URLs a: [%s]\n", value);

  url_len = strlen(value);
  if(!all_links) {
    if(!(midnightcode_parse_exttype(value, url_len,
                                    MIDNIGHTCODE_PARSE_EXT_TYPE_PICTURE) ||
         midnightcode_parse_exttype(value, url_len,
                                    MIDNIGHTCODE_PARSE_EXT_TYPE_VIDEO) ||
         midnightcode_parse_exttype(value, url_len,
                                    MIDNIGHTCODE_PARSE_EXT_TYPE_ARCHIVE)))
      return 0;
  }

  ret_i = midnightcode_html_urltype(value, url_len);

  switch(ret_i) {
    case MIDNIGHTCODE_HTML_URL_TYPE_ABSOLUTE:
      fprintf(stderr, "%s://%s%s\n", pro_url, abs_url, value);
      break;

    case MIDNIGHTCODE_HTML_URL_TYPE_RELATIVE:
      fprintf(stderr, "%s://%s/%s\n", pro_url, rel_url, value);
      break;

    case MIDNIGHTCODE_HTML_URL_TYPE_FULL:
      fprintf(stderr, "%s://%s\n", pro_url, value);
      break;

    case MIDNIGHTCODE_HTML_URL_TYPE_URI:
      fprintf(stderr, "%s\n", value);
      break;

    default:
      return 0;

  }

  return 1;
}


int
main(int argc, char **argv) {
  int ret_i;
  char input_file_name[64] = "\0";
  char original_url[256] = "\0";
  char absolute_url[256] = "\0";
  char relative_url[256] = "\0";
  char protocol_url[256] = "\0";
  int all_links = 0;
  int help = 0;
  void * tmp_void_p;
  struct midnightcode_html_document_head_t * html_list_head_p;
  struct midnightcode_html_document_element_t * now_document;
  struct midnightcode_html_tag_element_t * now_tag;
  int list_num;
  int fp;
  char *buffer;
  int buffer_size = 1024000;
  int found_a;

  // Prepare switches
  struct midnightcode_switch_t switches[] = {
    { "if", "input_file", "HTML file for parsing",
      MIDNIGHTCODE_PARSE_TYPE_STRING, 64, 0, &input_file_name },
    { "ou", "orig_url", "Original URL",
      MIDNIGHTCODE_PARSE_TYPE_STRING, 256, 0, &original_url },
    { "al", "all_links", "Dump all links",
      MIDNIGHTCODE_PARSE_TYPE_NONE, 0, 0, &all_links },
    { "h", "help", "Display this help/usage screen",
      MIDNIGHTCODE_PARSE_TYPE_NONE, 0, 0, &help },
    { 0 }
  };

  // Prepare HTML
  midnightcode_list_init(html_struct_head,
                         midnightcode_html_document_element_t);
  tmp_void_p = (void *)&html_struct_head;
  html_list_head_p = tmp_void_p;

  // Process switches
  if((ret_i = midnightcode_switch_process(argc, argv, switches)) != 0) {
    fprintf(stdout, "\n");
    midnightcode_logo(0,
      MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON);
    midnightcode_license(0,
      MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON, 
      MIDNIGHTCODE_LICENSE_TEXT_COPYRIGHT);
    fprintf(stdout, "    Error in switches, switch \"%s\" is unkown"
            " at parameter number %d.\n\n", argv[ret_i], ret_i);
    midnightcode_switch_usage(MIDNIGHTCODE_SWITCH_STYLE_SOFT,
                              argv[0], switches);
    exit(1);
  }
  if(help) {
    midnightcode_logo(0, MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON);
  midnightcode_license(0,
    MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON, 
    MIDNIGHTCODE_LICENSE_TEXT_COPYRIGHT);
    midnightcode_switch_usage(MIDNIGHTCODE_SWITCH_STYLE_SOFT,
                              argv[0], switches);
    exit(1);
  }

  fflush(stdout);

  // Process license and logo
  midnightcode_logo(0,
    MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON);
  midnightcode_license(0,
    MIDNIGHTCODE_COLOUR_STYLE_BLOOD_MOON, 
    MIDNIGHTCODE_LICENSE_TEXT_ALL);


  // Program title
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_H1,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "HTML File Parser: %s", argv[0]);


  // Reserving buffer memory
  buffer = malloc(buffer_size);
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Reserving buffer memory");
  if(!buffer) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    fprintf(stdout, "\n");
    exit(1);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }
  memset(buffer, 0, buffer_size);


  // Section :: Validation
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_H2,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Perform input validation");

  // Validate input file
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Validating input file");
  if(!strlen(input_file_name) ||
     (access(input_file_name, F_OK) != 0)) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    fprintf(stdout, "\n");
    exit(1);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }

  // Section :: Acquisition
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_H2,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Acquire source HTML data");

  // Opening input file
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Opening input file");
  if(!(fp = open(input_file_name, O_RDONLY))) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    fprintf(stdout, "\n");
    exit(1);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }

  // Reading input file
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Reading input file");
  if(read(fp, buffer, buffer_size - 1) < 1) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    fprintf(stdout, "\n");
    exit(1);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }

  // Closing input file
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Closing input file");
  if(close(fp)) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    fprintf(stdout, "\n");
    exit(1);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }

  // Section :: Processing
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_H2,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Process HTML data");

  // Process HTML links
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Parsing HTML content");
  if((ret_i = midnightcode_html_parse(buffer, strlen(buffer),
                           html_list_head_p)) != 0) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    exit(1);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }


  // Section :: Deconstruct
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_H2,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Deconstruct HTML data");

  // Checking URL Protocol
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Validating URL protocol");
  if(!strlen(original_url) ||
     midnightcode_html_urlproto(protocol_url, original_url,
       strlen(original_url)) < 1) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    exit(1);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }


  // Checking URL Base
  midnightcode_status_text(MIDNIGHTCODE_STATUS_TYPE_TEXT,
                           MIDNIGHTCODE_STATUS_STYLE_NORMAL,
                           "Validating URL base");
  if(!strlen(original_url) || 
     midnightcode_html_urlbase(absolute_url, original_url,
       strlen(original_url), MIDNIGHTCODE_HTML_URL_TYPE_ABSOLUTE) < 1 ||
     midnightcode_html_urlbase(relative_url, original_url,
       strlen(original_url), MIDNIGHTCODE_HTML_URL_TYPE_RELATIVE) < 1) {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_FAIL);
    exit(1);
  } else {
    midnightcode_status_flag(MIDNIGHTCODE_STATUS_FLAG_OKAY);
  }

  fprintf(stdout, "\n");
  found_a = 0;
  midnightcode_list_for_each(now_document, html_list_head_p) {
    if(now_document) {
      if(now_document->tag) {
        list_num = 0;
        found_a = 0;
        midnightcode_list_for_each(now_tag, now_document->tag) {
          list_num++;
          if(list_num == 1) {
            if(now_tag->option) {
              if(strcasecmp(now_tag->option, "a") == 0) {
                found_a = 1;
                continue;
              }
            }
          }
          if(found_a && now_tag->option) {
            if(strcasecmp(now_tag->option, "href") == 0) {
              if(now_tag->value) {
                ret_i = bin_to_std_err(now_tag->value, all_links,
                          protocol_url, absolute_url, relative_url);
              }
            }
          }
        }
      }
    }
  }

  exit(0);
}

