]> lifelog.hopto.org Git - PerlCNFWEBServer.git/commitdiff
init
authorWill Budic <redacted>
Thu, 15 May 2025 08:23:11 +0000 (18:23 +1000)
committerWill Budic <redacted>
Thu, 15 May 2025 10:47:15 +0000 (20:47 +1000)
index.cgi [new file with mode: 0755]
install_cpan_modules_required.pl [new file with mode: 0755]

diff --git a/index.cgi b/index.cgi
new file mode 100755 (executable)
index 0000000..46a1fa7
--- /dev/null
+++ b/index.cgi
@@ -0,0 +1,116 @@
+#!/usr/bin/env perl
+# A delegated CNFParser processed rendering of the Document Index Web page, a Model-View-Controller Pattern approuch.
+# The index.cnf script contains the structure and page skeleton,
+# all configuration as well as the HTMLIndexProcessorPlugin converting the CNF to final HTML.
+# It is very convienient, as both style and script for the page is separated and developed in the index.cnf.
+# Which then can be moved to a respective include file over there.
+# This controller binds and provides to the parser to do its magic thing.
+#
+use v5.30;
+use strict;
+use warnings;
+use Exception::Class ('LifeLogException');
+use Syntax::Keyword::Try;
+##
+# We use dynamic perl compilations. The following ONLY HERE required to carp to browser on
+# system requirments or/and unexpected perl compiler errors.
+##
+use CGI::Carp qw(fatalsToBrowser set_message);
+
+BEGIN {
+   sub handle_errors {
+      my $err = shift;
+      say "<html><body><h2>Server Error</h2><pre>Error: $err</pre></body></html>";
+  }
+  set_message(\&handle_errors);
+}
+
+use lib "system/modules";
+require CNFParser;
+require CNFNode;
+
+our $GLOB_HTML_SERVE = "'{}/*.cgi' '{}/*.htm' '{}/*.html' '{}/*.md' '{}/*.txt'";
+our $script_path = $0; $script_path =~ s/\w+.cgi$//;
+
+exit &HTMLPageBuilderFromCNF;
+
+sub HTMLPageBuilderFromCNF {
+    my $html = obtainDirListingHTML('docs');
+    my $cnf  = CNFParser -> new (
+                            $script_path."index.cnf",{
+                             DO_ENABLED => 1, HAS_EXTENSIONS=>1,
+                             ANONS_ARE_PUBLIC => 1,
+                                PAGE_HEAD     => "<h1 id=\"index_head\">Index Page of Docs Directory</h1>",
+                                PAGE_CONTENT  => $html,
+                                PAGE_FOOT     => "<!--Not Defined-->"
+                            }
+                );
+    my $ptr = $cnf->data();
+    $ptr = $ptr->{'PAGE'};
+    say $$ptr if $ptr;
+    return 0
+}
+
+sub obtainDirListingHTML {
+    my ($dir, $ret) = (shift,"");
+    my $html = listFiles($dir,$script_path,"");
+    if($html){
+       $ret .="<ul><b>$dir &#8594;</b>\n";
+       $ret .= $html;
+        opendir (my $handle, $script_path.$dir) or die "Couldn't open directory, $!";
+        while (my $node = readdir $handle) {
+            my $file_full_path = "$script_path$dir/$node";
+            if($node !~ /^\./ && -d $file_full_path){
+               $html = obtainDirListingHTML($dir.'/'.$node);
+               $ret .= $html if $html
+            }
+        }
+        closedir $handle;
+       $ret .= "</ul>";
+    }
+    return $ret;
+}
+
+sub listFiles ($){
+    my ($dir, $script_path, $ret) = @_;
+    my $path = $script_path.$dir;
+    my $spec = $GLOB_HTML_SERVE; $spec =~ s/{}/$path/gp;
+    my @files = glob ($spec);
+       @files =  sort {
+            ( $a=~m/\w+[_-]*/ eq $b=~m/\w+[_-]*/ && length $a > length $b) ||
+              $a <=> $b
+    }  @files;
+    foreach my $file(@files){
+            ($file =~ m/(\w+\.\w*)$/g);
+            my $name = $1;
+            if($file =~ /\.md$/){
+                my @title = getDocTitle($file);
+                $ret .= qq(\t\t\t<li><a href="$dir/$title[0]">$title[1]</a> &dash; $name</li>\n);
+            }else{
+                $ret .= qq(\t\t\t<li><a href="$dir/$name">$name</a></li>\n);
+            }
+    }
+
+    return $ret;
+}
+
+sub getDocTitle($){
+    my ($file,$ret) = shift;
+    open(my $fh, '<', $file) or LifeLogException->throw("Can't open $file: $!");
+    while (my $line = <$fh>) {
+        if($line =~ /^#+\s*(.*)/){
+           $ret = $1;
+           last;
+        }
+    }
+    close $fh;
+    ($file =~ m/(\w+\.\w*)$/g);
+    return ($1,$ret)
+}
+1;
+=begin copyright
+Programed by  : Will Budić
+EContactHash  : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source        : https://github.com/wbudic/LifeLog
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright
diff --git a/install_cpan_modules_required.pl b/install_cpan_modules_required.pl
new file mode 100755 (executable)
index 0000000..c573912
--- /dev/null
@@ -0,0 +1,220 @@
+#!/usr/bin/env perl
+##
+# Module installer for projects.
+# Run this script from any Project directory containing perl modules or scripts.
+##
+use warnings; use strict;
+###
+# Prerequisites for this script itself. Run first:
+# cpan Term::ReadKey;
+# cpan Term::ANSIColor;
+## no critic (ProhibitStringyEval)  
+use Term::ReadKey;
+use Term::ANSIColor qw(:constants);
+
+use constant PERL_FILES_GLOB => "*local/*.pl local/*.pm system/modules/*.pm tests/*.pm tests/*.pl *.pl *.pm *.cgi";
+
+my $project = `pwd`."/".$0; $project =~ s/\/.*.pl$//g;  $project =~ s/\s$//g;
+my @user_glob;
+our $PERL_VERSION = $^V->{'original'}; my $ERR = 0; my $key;
+
+print WHITE "\n *** Project Perl Module Installer coded by ",BRIGHT_RED, "https://github.com/wbudic", WHITE,"***", qq(
+         \nRunning scan on project path:$project 
+         \nYou have Perl on $^O [$^X] version: $PERL_VERSION\n
+);
+print BLUE "<<@<\@INC<\n# Your default module package paths:\n", YELLOW; 
+local $. = 0; foreach(@INC){  
+  print $.++.".: $_\n"; 
+}
+print BLUE ">>\n", RESET;
+if($> > 0){
+  print "You are NOT installing system wide, which is required for webservers CGI.\nAre you sure about this?\n"
+}else{
+  print "You are INSTALLING modules SYSTEM WIDE, are you sure about this?\n"
+}
+if(@ARGV==0){
+  print qq(\nThis program will try to figure out now all the modules 
+  required for this project, and install them if missing.
+  This can take some time.
+  ); 
+  print RED "Do you want to proceed (press either the 'Y'es or 'N'o key)?", RESET;
+
+do{
+  ReadMode('cbreak');  
+  $key = ReadKey(0); print "\n";
+  ReadMode('normal');
+    exit 1 if(uc $key eq 'N');
+    $key = "[ENTER]" if $key =~ /\n/;
+    print "You have pressed the '$key' key, that is nice, but why?\nOnly the CTRL+C/Y/N keys do something normal." if uc $key ne 'Y';
+  }while(uc $key ne 'Y');
+}
+else{
+  foreach(@ARGV){
+    if(-d $_){
+      $_ =~ s/\s$//g;
+      print "\nGlobing for perl files in $project/$_";
+      my @located = glob("$_/*.pl $_/*.pm");
+      print " ... found ".@located." files.";
+      push @user_glob, @located;
+      
+    }else{
+      warn "Argument: $_ is not a local directory."
+    }
+  }
+}
+
+my @locals=(); 
+print "\nGlobing for perl modules in project $project";
+my @perl_files = glob(PERL_FILES_GLOB); 
+print " ... found ".@perl_files." files.\n";
+push @perl_files, @user_glob;
+my %modules; my %localPackages;
+foreach my $file(@perl_files){
+   next if $0 =~ /$file$/;
+   if($file =~ /(\w*)\.pm$/){
+      $localPackages{$1}=$file;
+   }
+   print "\nExamining:$file\n";      
+   my $res  =  `perl -ne '/\\s*(^use\\s([a-zA-Z:]*))\\W/ and print "\$2;"' $file`;
+   my @list = split(/;+/,$res);
+   foreach(@list){
+     if($_=~ /^\w\d\.\d+.*/){
+      print "\tA specified 'use $_' found in ->$file\n";
+      if($PERL_VERSION ne $_){         
+         $_ =~s/^v//g;
+         my @fv = split(/\./, $_);
+         $PERL_VERSION =~s/^v//g;
+         my @pv = split(/\./, $PERL_VERSION);
+         push @fv, 0 if @fv < 3;
+         for my$i(0..$#fv){
+           if( $pv[$i] < $fv[$i] ){
+              $ERR++; print "\n\t\033[31mERROR -> Perl required version has been found not matching.\033[0m\n";
+              last
+           }
+         }
+      }
+     }
+   }
+   foreach(@list){    
+    $_ =~ s/^\s*|\s*use\s*//g;
+    $_ =~ s/[\'\"].*[\'\"]$//g;    
+    next if !$_ or $_ =~ /^[a-z]|\d*\.\d*$|^\W/;
+    $_ =~ s/\(\)|\(.*\)|qw\(.*\)//g;
+    $modules{$_}=$file if $_;
+    print "$_\n";
+   }
+   if($file=~/\.pm$/){# it is presumed local package module.  
+      $locals[@locals] = `perl -ne '/\\s*(^package\\s(\\w+))/ and print "\$2" and exit' $file`;
+   }
+}
+
+print WHITE "\nList of Modules required for thie project:\n";
+my @missing=(); 
+foreach my $mod (sort keys %modules){
+    my $missing;
+    eval "use $mod";
+    if ($@){
+      $missing[@missing] = $mod;
+      print MAGENTA "\t$mod \t in ", $modules{$mod}," is suspicious?\n";
+    }else{
+      print BLUE "\t$mod\n" 
+    }
+}foreach(@missing){
+  if(exists $localPackages{$_}){
+      delete $modules{$_}
+  }else{
+      print BRIGHT_RED $_, MAGENTA, " is missing!\n"
+  }
+}
+my %skip_candidates;
+my $missing_count = @missing;
+if($missing_count>0){
+  foreach my $candidate(@missing){
+    foreach(@locals){
+      if($_ eq $candidate && not exists $skip_candidates{$_}){
+        $missing_count--;        
+        $skip_candidates{$_} = 1;
+        print GREEN, "Found the missing $candidate module in locals.\n"
+      }
+    }
+  }
+}
+my $perls = `whereis perl`;
+print GREEN, "Following is all of ",$perls;
+print YELLOW, "Reminder -> Make sure you switched to the right brew release.\n" if $perls =~ /perlbrew/; 
+print RESET, "Number of local modules:",scalar(@locals),"\n";
+print RESET, "Number of external modules:",scalar(keys %modules),"\n";
+print RESET, "Number of cpan modules about to be tried to install:",$missing_count,"\n";
+
+print GREEN, qq(
+Do you still want to continue to compile/test/install or check further modules?
+Only the first run is the depest and can take a long time, i.e. if you have to install over 5 modules.
+At other times this will only check further your current status.
+
+Now (press either the 'Y'es or 'N'o key) please?), RESET;
+do{
+ReadMode('cbreak');  
+$key = ReadKey(0); print "\n";
+ReadMode('normal');
+  exit 1 if(uc $key eq 'N');
+  $key = "[ENTER]" if $key =~ /\n/;
+  print "You have pressed the '$key' key, that is nice, but why?\nOnly the CTRL+C/Y/N keys do something normal.\n" if uc $key ne 'Y';
+}while(uc $key ne 'Y');
+
+my ($mcnt,$mins) = (0,0);
+my @kangaroos = sort keys %skip_candidates;
+
+##
+# Some modules if found to be needed to be forcefeed. can be hardcoded here my friends, why not?
+##
+foreach ((                
+                'LWP::Simple',
+                'LWP::Protocol::https',
+                'XML::LibXML::SAX'
+)){
+  $modules{$_}=1; print "Forcefeed: $_\n"
+}
+
+MODULES_LOOP: 
+foreach my $mod (sort keys %modules){
+
+  foreach(@kangaroos){
+      if($_ eq $mod){
+        next MODULES_LOOP
+      }
+  }
+  $mcnt++;
+  ## no critic (ProhibitStringyEval)
+  eval "use $mod";
+  if ($@) {
+      system(qq(perl -MCPAN -e 'install $mod'));     
+      if ($? == -1) {
+        print "failed to install: $mod\n";
+      }else{  
+        my $v = eval "\$$mod\::VERSION";
+           $v = $v ? "(v$v)" : "";
+        print "Installed module $mod $v!\n";
+        $mins++
+      }    
+  }else{       
+   $mod =~ s/\s*$//;   
+   my $v = eval "\$$mod\::VERSION";
+      $v = $v ? "(v$v)" : "";
+      print "Skipping module $mod $v, already installed!\n";
+  }
+}
+print "\nProject $project\nRequires $mcnt modules.\nInstalled New: $mins\n";
+print "WARNING! - This project requires in ($ERR) parts code that might not be compatible yet with your installed/running version of perl (v$PERL_VERSION).\n" 
+if $ERR;
+
+
+=begin copyright
+Programed by  : Will Budic
+EContactHash  : 990MWWLWM8C2MI8K (https://github.com/wbudic/EContactHash.md)
+Source        : https://github.com/wbudic/PerlCNF.git
+Documentation : Specifications_For_CNF_ReadMe.md
+    This source file is copied and usually placed in a local directory, outside of its repository project.
+    So it could not be the actual or current version, can vary or has been modiefied for what ever purpose in another project.
+    Please leave source of origin in this file for future references.
+Open Source Code License -> https://github.com/wbudic/PerlCNF/blob/master/ISC_License.md
+=cut copyright