#!/usr/bin/perl
print "Content-type: text/html"."\n\n";

######################################
#                                    #
# ReadCSVPlus v1.3                   #
# Copyright 2000 by Mutasem Abudahab #
# mutasem@abudahab.com               #
# http://ezscripting.com             #
#                                    #
# Last modified on Aug. 28, 2000     #
#                                    #
######################################
#
# Copyright Notice:
# Copyright 2000 Mutasem R. Abudahab.  All Rights Reserved.
#
# This code may be used and modified by anyone so long as this header and
# copyright information remains intact.  By using this code you agree to 
# indemnify Mutasem R. Abudahab from any liability that might arise from its 
# use.  You must obtain written consent before selling or redistributing 
# this code.

#------------------- Start working on the script --------------------#

# Replace "data.csv" with the full path to your csv database file

    $csv_file_path="linksdata.csv";

# Replace "template.html" with the full path to your HTML template.

    $html_template_path="links_tempnf.html";

# Replace "http://www.domain.com/images/new.gif" with the URL to the graphic
# image that will be displayed next to a record, when ReadCSVPlus marks it as
# new.

    $new_image_file="http://www.domain.com/images/new.gif";

# Replace this value with the number of days related to <<date_local>> after
# which the script will stop displaying the 'new' image graphic.

    $new_compare_dat="10";

# Replace this value with the number of random records the script will display
# when you query for a random display (display=random).

    $num_random=1;

# Replace this value with the message the script will display, when it finds
# no matches to a query

    $no_matches_found="sorry, no results found";

#-------------- DO NOT CHANGE ANYTHING UNDER THIS LINE --------------#

$nv=0;
$qs=$ENV{'QUERY_STRING'};
if($sort_field=&pick_up("sort_a",$qs)){
        $sort_a="yes";
        }
if($s_field=&pick_up("sort_d",$qs)){
        $sort_d="yes";
        }
if($sort_d eq "yes"){
        $sort_field=$s_field;
        }
@csv_lines=&modify_CSV($csv_file_path);
$lcl=@csv_lines;
@headers=split(";",$csv_lines[0]);
foreach $one (@headers){
        $one=&search_prepare($one);
        }
$l_headers=@headers;
for($l=0;$l<=($l_headers-1);$l=$l+1){
        if($headers[$l]=~/^$sort_field$/){
                $sort_location=$l+1;
                $s_flag=999;
                }
        if(($headers[$l]=~/^date_local$/)||($headers[$l]=~/^date_local$/)){
                $date_location=$l+1;
                }
        }
if(($s_flag !=999)&&($sort_field=~/\W/i)){
        &produce_error(
                "The field name that you are trying to sort by can not be found in your CSV database file."
                );
        }
if($rec_range=&pick_up("rec_range",$qs)){
        if($rec_range=~/^\((\d+)\)\((\d+)-(\d+)\)(.+)/){
                $page=$1;
                $rec_start=$2;
                $rec_end=$3;
                $recs=$4;
                @matched_lines=split(" ",$recs);
                foreach $match (@matched_lines){
                        if($match=~/\D/){
                                &produce_error(
                                        "unpropper form found in rec_range in URL."
                                        );
                                }
                        }
                goto PARTIAL;
                }
                else{
                        &produce_error(
                                "unpropper form found in rec_range in URL."
                                );
                        }
        }
if($display=&pick_up("display",$qs)){
        if($display eq "random"){
                $display="random";
                goto PREPARE;
                }
        elsif($display eq "all"){
                $display="all";
                goto PREPARE;
                }
                else{
                        &produce_error(
                                "undefined display mode requested."
                                );
                        }
        }
@conditions=split("&",$qs);
$l_conditions=@conditions;
$absolute=$l_conditions;
foreach $one (@conditions){
        $one=~s/%([\dA-Fa-f][\dA-Fa-f])/pack("C",hex($1))/eg;
        $one=~tr/+/ /;
        }
for($l=1;$l<=(@csv_lines-1);$l=$l+1){
        @line_entries=split(";",$csv_lines[$l]);
        foreach $entry (@line_entries){
                $entry=&search_prepare($entry);
                $entry=&sweep_spaces($entry);
                }
        CHECK_CONDITIONS:
        foreach $rule (@conditions){
                if($rule=~/[^=<>!]<[^=<>!]/){
                        ($var,$val)=split("<",$rule);
                        &error_if_nonnumiric;
                        $var=&sweep_spaces($var);
                        $val=&sweep_spaces($val);
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] < $val){
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                        }
                elsif($rule=~/[^=<>!]>[^=<>!]/){
                        ($var,$val)=split(">",$rule);
                        &error_if_nonnumiric;
                        $var=&sweep_spaces($var);
                        $val=&sweep_spaces($val);
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] > $val){
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                        }
                elsif($rule=~/[^=<>!]>[^=<>!]/){
                        ($var,$val)=split(">",$rule);
                        &error_if_nonnumiric;
                        $var=&sweep_spaces($var);
                        $val=&sweep_spaces($val);
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] > $val){
                                                print $line_entries[$p]."<BR>";
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                        }
                elsif(($rule=~/[^=<>!](>=)[^=<>!]/)||($rule=~/[^=<>!](=>)[^=<>!]/)){
                        ($var,$val)=split($+,$rule);
                        &error_if_nonnumiric;
                        $var=&sweep_spaces($var);
                        $val=&sweep_spaces($val);
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] >= $val){
                                                print $line_entries[$p]."<BR>";
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                        }
                elsif(($rule=~/[^=<>!](<=)[^=<>!]/)||($rule=~/[^=<>!](=<)[^=<>!]/)){
                        ($var,$val)=split($+,$rule);
                        &error_if_nonnumiric;
                        $var=&sweep_spaces($var);
                        $val=&sweep_spaces($val);
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] <= $val){
                                                print $line_entries[$p]."<BR>";
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                        }
                elsif($rule=~/[^=<>!]!![^=<>!]/){
                        ($var,$val)=split("!!",$rule);
                        &error_if_nonnumiric;
                        $var=&sweep_spaces($var);
                        $val=&sweep_spaces($val);
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] != $val){
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                        }
               elsif(($rule=~/[^=<>!](!=)[^=<>!]/)||($rule=~/[^=<>!](=!)[^=<>!]/)){
                        ($var,$val)=split($+,$rule);
                        $var=&sweep_spaces($var);
                        $val=&sweep_spaces($val);
                        if($val=~/^".+"$/){
                        $val=~s/^"//;
                        $val=~s/"$//;
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] !~ /^$val$/i){
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                                } #end of the new if exact
                        else{
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] !~ /$val/i){
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }

                                }
                        }
               elsif(($rule=~/[^=<>!]=[^=<>!]/)||($rule=~/[^=<>!]=$/)){
                        ($var,$val)=split("=",$rule);
                        if($val !~/\S/){
                                $c_match=$c_match+1;
                                next CHECK_CONDITIONS;
                                }
                        $var=&sweep_spaces($var);
                        $val=&sweep_spaces($val);
                        if($val=~/^".+"$/){
                                $val=~s/^"//;
                                $val=~s/"$//;
                                for($p=0;$p<=($l_headers-1);$p=$p+1){
                                        if($var=~/^$headers[$p]$/){
                                                if($line_entries[$p] =~ /^$val$/i){
                                                        $c_match=$c_match+1;
                                                        next CHECK_CONDITIONS;
                                                        }
                                                }
                                }

                                }
                        elsif($var=~/^search$/i){
                                foreach $lin_ent (@line_entries){
                                        if($lin_ent=~/$val/i){
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                                else{
                        for($p=0;$p<=($l_headers-1);$p=$p+1){
                                if($var=~/^$headers[$p]$/){
                                        if($line_entries[$p] =~ /$val/i){
                                                $c_match=$c_match+1;
                                                next CHECK_CONDITIONS;
                                                }
                                        }
                                }
                                }
                        }
               else{
                        &produce_error(
                                "Unreadable request found in your query.",
                                "Please check the syntax of your query and try again."
                                );
                        }
                }
        if($c_match == $absolute){
                $matched_lines[$num]=$l;
                if($sort_location != 0){
                        $sort_values[$num]=$line_entries[$sort_location-1];
                        }
                if($date_location != 0){
                        $date_values[$num]=$line_entries[$date_location-1];
                        $date_values[$num]=&sweep_spaces($date_values[$num]);
                        if($date_values[$num]!~/\d{1,2}[,-\/\\]\d{1,2}[,-\/\\]\d{4}/){
                                $date_values[$num]="not dated";
                                }
                        }
                $num=$num+1;
                }
        $c_match=0;
        }
PREPARE:
$lcsv=@csv_lines-1;
if($display eq "all"){
        @matched_lines=(1..$lcsv);
        }
if($display eq "random"){
        srand;
        if($num_random < 1){
                &produce_error(
                        "cannot display less than 1 random records. Set $num_random to a value greater than 1." 
                        );
                }
        if($num_random > $lcsv){
                $num_random=$lcsv;
                }
        @matched_lines=();
        $num=0;
        $l=1;
        REDO:
        for($l;$l<=$num_random;$l=$l+1){
                $record_n=int(rand($lcsv))+1;
                $matched_lines[$num]=$record_n;
                for($u=0;$u<=($num-1);$u=$u+1){
                        if($matched_lines[$num] == $matched_lines[$u]){
                                goto REDO;
                                }
                        }
                $num=$num+1;
                }
        }
$lml=@matched_lines;
if(($sort_a eq "yes")||($sort_d eq "yes")){
        &sort_results;
        }
SHOW:
if(open(HTML,$html_template_path)){
        @html_lines=<HTML>;
        close(HTML);
        $html=join("",@html_lines);
        unless($html=~/(.*)<template>(.*)<\/template>(.*)/is){
                &produce_error(
                        "Your HTML template file does not contain template tags necessary to display records."
                        );
                }
        $upper=$1;
        $html_temp=$2;
        $footer=$3;
        foreach $part ($upper,$html_temp,$footer){
                $part=&translate_special_variables($part,($lml-$nv),($lcl-1));
                }
        if(($lml-$nv) == 0){
                print $upper;
                print $no_matches_found."<BR>\n";
                print $footer;
                exit(0);
                }
        print $upper."\n";
        for($w=0;$w<=(@matched_lines-1);$w=$w+1){
                @m_e=split(";",$csv_lines[$matched_lines[$w]]);
                $out=$html_temp;
                foreach $m_entry (@m_e){
                        $m_entry=&search_prepare($m_entry);
                        }
                for($lh=0;$lh<=($l_headers-1);$lh=$lh+1){
                        $out=~s/!!$headers[$lh]!!/$m_e[$lh]/isg;
                        }
                if($out=~/!!NEW_IMAGE!!/i){
                        $new_img=&check_if_new($new_compare_dat,$new_image_file,$date_values[$w]);
                        $out=~s/!!NEW_IMAGE!!/$new_img/isg;
                        }
                $out=~s/!!\#_LINE!!/$csv_file_path&line_$matched_lines[$w]/ig;
                $out=~s/!!.*!!//g;
                print $out;
                }
        print $footer."\n";
        }
        else{
                &produce_error(
                        "could not open HTML template file. Please check that you have provided",
                        "the script with the correct path in \$html_template_path variable."
                        );
                }
exit;
sub modify_CSV
{
if(open(CSV,$_[0])){
    }
    else{
                &produce_error(
                        "Can't open CSV database file.",
                        "Please, check that you have provided the cgi script with correct path to your CSV database file.",
                        ); 
    }
$ccc=0;
while($in_lin=<CSV>){
        if($in_lin!~/\S/){
                next;
                }
        $lines[$ccc]=$in_lin;
        $ccc=$ccc+1;
        }
$lines_length=@lines;
$lines_length=$lines_length-1;
for($l=0;$l<=$lines_length;$l=$l+1){
        $lines[$l]=~s/""/%01/g;
        while($lines[$l]=~/("[^"]+")/){
                $match=$1;
                $match=~s/"//g;
                $match=~s/,/%02/g;
                $lines[$l]=~s/("[^"]+")/$match/;
                }
        }
close(CSV);
chomp(@lines);
return @lines;
}  
sub search_prepare{
        $_[0]=~s/%01/"/g;
        $_[0]=~s/%02/,/g;
        return $_[0];
        }
sub produce_error
{
print "<HTML><HEAD><TITLE>Error message</TITLE><BODY>\n";
print "<img border=\"0\" src=\"http://www.ezscripting.com/images/title01.gif\"><HR>";
print "<CENTER><IFRAME SRC=\"http://www.ezscripting.com/banners/ads.pl?iframe\" MARGINWIDTH=0 MARGINHEIGHT=0 HSPACE=0 VSPACE=0 FRAMEBORDER=0 SCROLLING=NO WIDTH=468 HEIGHT=60></IFRAME></CENTER>";
print "<BR><font face=\"Arial\"><B>ERROR MESSAGE:</B></FONT><BR><BR>";
print "<font face=\"Arial\">";
foreach $line (@_){
        print "$line<BR>\n";
        }

print "<BR>For more information go to <a href=\"http://www.ezscripting.com\">WWW.EZSCRIPTING.COM</a>";
print "</FONT>";
print "<p align=\"center\"><font size=\"1\" face=\"Arial\"><a href=\"http://www.ezscripting.com/admin/add_bug.shtml\">Report Bug</a> - <a href=\"http://www.ezscripting.com/faq.shtml\">FAQ</a> - <a href=\"http://www.ezscripting.com/forums.shtml\">Discussion Forums</a></font></p><hr>";
print "<p align=\"right\"><b><font size=\"2\" face=\"Arial\">ReadCSV<font color=\"#FF0000\">Plus </font></font></b><font face=\"Arial\" size=\"1\">by <a href=\"mailto:mutasem\@abudahab.com\">Mutasem Abudahab</a>, <a href=\"http://www.ezscripting.com\">EZScripting.com</a></font></p>";
print "</BODY></HTML>";
exit(0);
return (1);
}
sub error_if_nonnumiric
{
if($val =~ /\D/){
        &produce_error(
                "You cannot use non-numiric values as right arguments of:",
                "1- Greater than.",
                "2- Less than.",
                "3- Equal or greater than.",
                "4- Equal or less than.",
                "Operators."
                );
        }
return (1);
}
sub sweep_spaces{
        $_[0]=~s/^ +//;
        $_[0]=~s/ +$//;
        return $_[0];
        }
sub translate_special_variables{
        ($secs,$mins,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=gmtime(time);
        $b_time="$secs".":"."$mins".":"."$hour"." GMT";
        $b_date="$mday".",".($mon+1).",".(1900+$year);
        $_[0]=~s/!!#_matches!!/$_[1]/isg;
        $_[0]=~s/!!#_total!!/$_[2]/isg;
        $_[0]=~s/!!#_date!!/$b_date/isg;
        $_[0]=~s/!!#_time!!/$b_time/isg;
        return $_[0];
        }
sub pick_up{
        if(($_[1]=~/^$_[0]=([^&\b]+)/i)||($_[1]=~/&$_[0]=([^&\b]+)/i)){
                $pick=$+;
                $pick=~s/%([\dA-Fa-f][\dA-Fa-f])/pack("C",hex($1))/eg;
                $pick=~tr/+/ /;
                $_[1]=~s/$_[0]=[^&\b]+//i;
                $_[1]=~s/&&/&/g;
                $_[1]=~s/^&//g;
                $_[1]=~s/&$//g;
                }
                else{
                        return 0;
                        }
        return $pick;
        }
sub check_if_new{
        if($_[0] < 1){
                &produce_error(
                        "You need to provide \$new_compare_dat with a value",
                        "in order to display an image presenting new records."
                        );
                }
        if($_[1] eq ""){
                &produce_error(
                        "you need to provide \$new_image_file with a path to an image file",
                        "in order to display an image presenting new records."
                        );
                }
        if($_[2] eq "not dated"){
                return "!!NEW_IMAGE!!";
                }
        ($dd,$mm,$yy)=split(",",$_[2]);
        $days=$dd+($mm*30)+($yy*364);
        ($secs,$mins,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=gmtime(time);
        $ndays=$mday+(($mon+1)*30)+((1900+$year)*364);
        $def=$ndays-$days;
        if($def <= $new_compare_dat){        
                return "<IMG SRC=\"$_[1]\" ALT=\"new record\">";
                }
        return "!!NEW_IMAGE!!";
        }
sub sort_results{
        local $l;
        for($l=0;$l<=(@matched_lines-1);$l=$l+1){
                $new_len=length $matched_lines[$l];
                if($new_len>=$dig_len){
                        $dig_len=$new_len;
                        }
                                              
                }
        for($l=0;$l<=(@matched_lines-1);$l=$l+1){
                $new_m_val=$dig_len-(length $matched_lines[$l]);
                $sort_values[$l]=$sort_values[$l]."|||||".("0"x$new_m_val).$matched_lines[$l];
                }
        @sort_values=sort(@sort_values);
        foreach $s_value (@sort_values){
                ($dummy,$matched_lines[$ghg])=split(/\|\|\|\|\|/,$s_value);
                $matched_lines[$ghg]=~s/^0//;
                $ghg=$ghg+1;
                }
        if($sort_d eq "yes"){
                @matched_lines=reverse(@matched_lines);
                }
        }
sub error_if_meta{
        if(($var=~/\/\$\^<>\|\\\[\]\(\)\{\}&=\?/)||($val=~/\/\?\$\^<>\|\\\[\]\(\)\{\}&=\?/)){
                &produce_error(
                        "\?\$\^<>\|\\\[\]\(\)\{\}&=/ are meta charechters forbidden and reserved by servers for security purposes."
                        );
                }
        }
