package Net::FullAuto::ISets::Local::FullAutoAPI_is; ### OPEN SOURCE LICENSE - GNU AFFERO PUBLIC LICENSE Version 3.0 ####### # # Net::FullAuto - Powerful Network Process Automation Software # Copyright © 2000-2034 Brian M. Kelly # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or any later version. # # 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public # License along with this program. If not, see: # <http://www.gnu.org/licenses/agpl.html>. # ####################################################################### our $VERSION='0.01'; our $DISPLAY='FullAuto RESTful API Server'; our $CONNECT='secure'; our $defaultInstanceType='t2.small'; use 5.005; use strict; use warnings; my $service_and_cert_password='Full@ut0O1'; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw($select_fullautoapi_setup); use Net::FullAuto::Cloud::fa_amazon; use Net::FullAuto::FA_Core qw[$localhost cleanup fetch clean_filehandle]; use Time::Local; use File::HomeDir; my $home_dir=File::HomeDir->my_home; $home_dir||=$ENV{'HOME'}||''; $home_dir.='/'; my $username=getlogin || getpwuid($<); my $do;my $ad;my $prompt;my $public_ip=''; my $builddir='';my @ls_tmp=(); my $avail_port=''; my $configure_fullautoapi=sub { my $selection=$_[0]||''; my $service_and_cert_password=$_[1]||''; my $domain_url=$_[2]||''; my ($stdout,$stderr)=('',''); my $handle=connect_shell();my $connect_error=''; $handle->cwd('~'); my $userhome=$handle->cmd('pwd'); my $sudo=($^O eq 'cygwin')?'':'sudo '; my $security_group='FullAutoAPISecurityGroup'; ($stdout,$stderr)=setup_aws_security( $security_group,'FullAutoAPI Security Group'); my $c='aws ec2 describe-security-groups '. "--group-names $security_group"; my ($hash,$output,$error)=('','',''); ($hash,$output,$error)=run_aws_cmd($c); my $cidr=$hash->{SecurityGroups}->[0]->{IpPermissions} ->[0]->{IpRanges}->[0]->{CidrIp}; $c='aws ec2 authorize-security-group-ingress '. "--group-name $security_group --protocol ". 'tcp --port 80 --cidr '.$cidr." 2>&1"; ($hash,$output,$error)=run_aws_cmd($c); $c='aws ec2 authorize-security-group-ingress '. "--group-name $security_group --protocol ". 'tcp --port 443 --cidr '.$cidr." 2>&1"; $c='aws ec2 authorize-security-group-ingress '. "--group-name $security_group --protocol ". 'tcp --port 11211 --cidr '.$cidr." 2>&1"; ($hash,$output,$error)=run_aws_cmd($c); $c='aws ec2 authorize-security-group-ingress '. "--group-name $security_group --protocol ". 'tcp --port 3000 --cidr '.$cidr." 2>&1"; ($hash,$output,$error)=run_aws_cmd($c); ($stdout,$stderr)=$handle->cmd($sudo."perl -e \'use CPAN;". "CPAN::HandleConfig-\>load;print \$CPAN::Config-\>{build_dir}\'"); $builddir=$stdout; my $fa_ver=$Net::FullAuto::VERSION; ($stdout,$stderr)=$handle->cmd($sudo. "ls -1t $builddir | grep Net-FullAuto-$fa_ver"); my @lstmp=split /\n/,$stdout; foreach my $line (@lstmp) { unshift @ls_tmp, $line if $line!~/\.yml$/; } $do=1; if ($do==1) { unless ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd($sudo. "chmod -v 755 ~",'__display__'); ($stdout,$stderr)=$handle->cmd("sudo yum clean all"); ($stdout,$stderr)=$handle->cmd("sudo yum grouplist hidden"); ($stdout,$stderr)=$handle->cmd("sudo yum groups mark convert"); ($stdout,$stderr)=$handle->cmd( "sudo yum -y groupinstall 'Development tools'",'__display__'); ($stdout,$stderr)=$handle->cmd( 'sudo yum -y install openssl-devel icu cyrus-sasl'. ' libicu cyrus-sasl-devel libtool-ltdl-devel libxml2-devel'. ' freetype-devel libpng-devel java-1.7.0-openjdk-devel'. ' unixODBC unixODBC-devel libtool-ltdl libtool-ltdl-devel'. ' ncurses-devel xmlto git-all autoconf','__display__'); } else { my $cygcheck=`/bin/cygcheck -c` || die $!; my $uname=`/bin/uname` || die $!; my $uname_all=`/bin/uname -a` || die $!; $uname_all.=$uname; my %need_packages=(); my $srvout=''; ($srvout,$stderr)=$handle->cmd("cygrunsrv -L",'__display__'); if ($srvout=~/exim/) { ($stdout,$stderr)=$handle->cmd("cygrunsrv --stop exim",'__display__'); ($stdout,$stderr)=$handle->cmd("cygrunsrv -R exim"); } if ($srvout=~/nginx_first_time/) { ($stdout,$stderr)=$handle->cmd( "cygrunsrv --stop nginx_first_time",'__display__'); ($stdout,$stderr)=$handle->cmd("cygrunsrv -R nginx_first_time"); ($stdout,$stderr)=$handle->cmd( "rm -rvf ${home_dir}FullAutoAPI/deps/nginx*", '__display__'); } if ($srvout=~/fullautoapi/) { ($stdout,$stderr)=$handle->cmd("cygrunsrv --stop fullautoapi", '__display__'); ($stdout,$stderr)=$handle->cmd("cygrunsrv -R fullautoapi"); ($stdout,$stderr)=$handle->cmd("rm -rvf ${home_dir}FullAutoAPI/lib", '__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf ${home_dir}FullAutoAPI/script", '__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf ${home_dir}FullAutoAPI/root", '__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf ${home_dir}FullAutoAPI/db*", '__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf ${home_dir}FullAutoAPI/inc", '__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf ${home_dir}FullAutoAPI/full*", '__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf ${home_dir}FullAutoAPI/blib", '__display__'); } if ($srvout=~/memcached/) { ($stdout,$stderr)=$handle->cmd("cygrunsrv --stop memcached", '__display__'); ($stdout,$stderr)=$handle->cmd("cygrunsrv -R memcached"); ($stdout,$stderr)=$handle->cmd( "rm -rvf ${home_dir}FullAutoAPI/deps/memcached*", '__display__'); } if ($uname_all=~/x86_64/) { foreach my $package ('libxml2','libxml2-devel','libtool', 'autoconf','autobuild','automake','pkg-config', 'libuuid-devel','wget','git','httpd', 'httpd-mod_ssl','httpd-tools','exim','zip') { unless (-1<index $cygcheck, "$package ") { $need_packages{$package}=''; } } } else { foreach my $package ('libxml2','libxml2-devel','libtool', 'autoconf','autobuild','automake','pkg-config', 'libuuid-devel','wget','git','httpd','httpd-mod_ssl', 'httpd-tools','exim','zip') { unless (-1<index $cygcheck, "$package ") { $need_packages{$package}=''; } } } # http://www.fjakkarin.com/2015/11/cygwin-cygserver-and-apache-httpd/ ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "https://github.com/transcode-open/apt-cyg/archive/master.zip", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'chown -v $username:$username master.zip','__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd("unzip -o master.zip",'__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf master.zip",'__display__'); ($stdout,$stderr)=$handle->cmd("mv apt-cyg-master/apt-cyg /usr/bin"); ($stdout,$stderr)=$handle->cmd($sudo."chmod -v 755 /usr/bin/apt-cyg", '__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf apt-cyg-master",'__display__'); my $packs='';$|=1; foreach my $pack (sort keys %need_packages) { ($stdout,$stderr)=$handle->cmd("apt-cyg install $pack", '__display__'); } if ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cwd('~'); # http://blogostuffivelearnt.blogspot.com/2012/07/ # smtp-mail-server-with-windows.html ($stdout,$stderr)=$handle->cmd( "chmod -v 755 /usr/bin/exim*",'__display__'); $handle->print('/bin/exim-config'); $prompt=$handle->prompt(); while (1) { my $output=fetch($handle); last if $output=~/$prompt/; print $output; if (-1<index $output,'local postmaster') { $handle->print(); } elsif (-1<index $output,'Is it') { $handle->print('yes'); } elsif (-1<index $output,'change that setting') { $handle->print('no'); } elsif (-1<index $output,'standard values') { $handle->print('yes'); } elsif (-1<index $output,'be links to') { $handle->print('yes'); } elsif (-1<index $output,'some CPAN') { $handle->print('no'); } elsif (-1<index $output,'install the exim') { $handle->print('yes'); } elsif (-1<index $output,'in minutes') { $handle->print(); } elsif (-1<index $output,'CYGWIN for the daemon') { $handle->print('default'); } elsif (-1<index $output,'the cygsla package') { $handle->print('yes'); } elsif (-1<index $output,'another privileged account') { $handle->print('no'); } elsif (-1<index $output,'enter the password') { $handle->print($service_and_cert_password); } elsif (-1<index $output,'Reenter') { $handle->print($service_and_cert_password); } elsif (-1<index $output,'start the exim') { $handle->print('yes'); } next; } } #if ($packs) { # print "\n\n Fatal Error!: The following Cygwin", # "\n packages are missing from", # "\n your installation:", # "\n\n $packs", # "\n\n Please report any bugs and send any", # "\n questions, thoughts or feedback to:", # "\n\n Brian.Kelly\@FullAuto.com.", # "\n\n"; # &Net::FullAuto::FA_Core::cleanup; #} #print "\nInstalling Microsoft IIS Web Server . . .\n\n"; # http://www.iis.net/learn/install/installing-iis-85/ # installing-iis-85-on-windows-server-2012-r2 # https://technet.microsoft.com/en-us/library/hh831475.aspx # http://twiki.org/cgi-bin/view/TWiki/TWikiOnWindowsIISCygwin # https://www.iis.net/configreference/system.webserver/fastcgi #($stdout,$stderr)=$handle->cmd("DISM.EXE /enable-feature /all ". # "/online /featureName:IIS-WebServerRole /featureName:IIS-WebServer ". # "/featureName:IIS-CommonHttpFeatures /featureName:IIS-StaticContent ". # "/featureName:IIS-DefaultDocument /featureName:IIS-DirectoryBrowsing ". # "/featureName:IIS-HttpErrors /featureName:IIS-HttpRedirect ". # "/featureName:IIS-ApplicationDevelopment /featureName:IIS-ASPNET ". # "/featureName:IIS-NetFxExtensibility /featureName:IIS-ASPNET45 ". # "/featureName:IIS-NetFxExtensibility45 /featureName:IIS-ASP ". # "/featureName:IIS-CGI /featureName:IIS-ISAPIExtensions ". # "/featureName:IIS-ISAPIFilter /featureName:IIS-ServerSideIncludes ". # "/featureName:IIS-HealthAndDiagnostics /featureName:IIS-HttpLogging ". # "/featureName:IIS-LoggingLibraries /featureName:IIS-RequestMonitor ". # "/featureName:IIS-HttpTracing /featureName:IIS-CustomLogging ". # "/featureName:IIS-ODBCLogging /featureName:IIS-Security ". # "/featureName:IIS-BasicAuthentication ". # "/featureName:IIS-WindowsAuthentication ". # "/featureName:IIS-DigestAuthentication ". # "/featureName:IIS-ClientCertificateMappingAuthentication ". # "/featureName:IIS-IISCertificateMappingAuthentication ". # "/featureName:IIS-URLAuthorization /featureName:IIS-RequestFiltering ". # "/featureName:IIS-IPSecurity /featureName:IIS-Performance ". # "/featureName:IIS-HttpCompressionStatic ". # "/featureName:IIS-HttpCompressionDynamic /featureName:IIS-WebDAV ". # "/featureName:IIS-WebServerManagementTools ". # "/featureName:IIS-ManagementScriptingTools ". # "/featureName:IIS-ManagementService ". # "/featureName:IIS-IIS6ManagementCompatibility ". # "/featureName:IIS-Metabase /featureName:IIS-WMICompatibility ". # "/featureName:IIS-LegacyScripts /featureName:NetFx4Extended-ASPNET45 ". # "/featureName:IIS-ApplicationInit /featureName:IIS-WebSockets ". # "/featureName:IIS-CertProvider /featureName:IIS-ManagementConsole ". # "/featureName:IIS-LegacySnapIn",'__display__'); #($stdout,$stderr)=$handle->cmd("DISM.EXE /online /enable-feature ". # "/featureName:IIS-WebServerRole /featureName:IIS-WebServer ". # "/featureName:IIS-CommonHttpFeatures /featureName:IIS-StaticContent ". # "/featureName:IIS-DefaultDocument /featureName:IIS-DirectoryBrowsing ". # "/featureName:IIS-HttpErrors /featureName:IIS-HealthAndDiagnostics ". # "/featureName:IIS-HttpLogging /featureName:IIS-Performance ". # "/featureName:IIS-HttpCompressionStatic /featureName:IIS-Security ". # "/featureName:IIS-RequestFiltering /featureName:IIS-CGI ". # "/featureName:IIS-WebServerManagementTools ". # "/featureName:IIS-ManagementConsole",'__display__'); #my $appcmd="$ENV{WINDIR}/SYSTEM32/inetsrv"; #($appcmd,$stderr)=$handle->cmd("cygpath -u $appcmd"); #my $cyglocb=$handle->cmd("cygpath -w /"); #my $cyglocw=$handle->cmd("cygpath -w ~"); #my $cyglocwf="$cyglocw\\FullAutoAPI"; #$cyglocw=~s/\\/\\\\/g; #$cyglocwf=~s/\\/\\\\/g; #($stdout,$stderr)=$handle->cwd($appcmd); #($stdout,$stderr)=$handle->cmd("pwd",'__display__'); #my $sleep=0; #while (1==1) { # my $ls_output=$handle->cmd("ls -1"); # last if -1<index $ls_output,'appcmd.exe'; # sleep 2; # last if $sleep++>300; #} #sleep 5; #($stdout,$stderr)=$handle->cmd("./appcmd add site /name:FullAutoAPI ". # "/id:2 /physicalPath:$cyglocwf\\root /bindings:http/*:4000", # '__display__'); #sleep 2; #($stdout,$stderr)=$handle->cmd("./appcmd set config -section:". # "system.webServer/fastCgi /+[\"fullpath=\'$cyglocb\\script\\". # "CGI_script.bat\',arguments=\'$cyglocwf\\script\\". # "fullautoapi_fastcgi.pl -e\',maxInstances=\'4\',". # "idleTimeout=\'300\',activityTimeout=\'30\',requestTimeout='\90\',". # "instanceMaxRequests=\'1000\',protocol=\'NamedPipe\',". # "flushNamedPipe=\'False\']\" /commit:apphost",'__display__'); #sleep 2; #($stdout,$stderr)=$handle->cmd("./appcmd set config -section:". # "system.webServer/handlers /+\"[name=\'FullAutoAPI\',". # "path=\'*\',verb=\'GET,HEAD,POST\',modules=". # "\'FastCgiModule\',scriptProcessor=\'$cyglocb\\script\\". # "CGI_Script.bat|$cyglocwf\\script\\fullautoapi_fastcgi.pl -e\',". # "resourceType=\'Unspecified\',requireAccess=\'Script\']\" ". # "/commit:apphost",'__display__'); #($stdout,$stderr)=$handle->cwd("FullAutoAPI/script"); #($stdout,$stderr)=$handle->cmd("touch CGI_Script.bat"); # # echo-ing/streaming files over ssh can be tricky. Use echo -e # and replace these characters with thier HEX # equivalents (use an external editor for quick # search and replace - and paste back results. # use copy/paste or cat file and copy/paste results.): # # ! - \\x21 ` - \\x60 # " - \\x22 \ - \\x5C # $ - \\x24 % - \\x25 # #$cyglocb=~s/\\/\\x5C/g; #my $content=<<END; #$cyglocb\\x5Cbin\\x5Cbash -lc \\x22/bin/perl \\x251 \\x252\\x22 #END #($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > CGI_Script.bat"); #($stdout,$stderr)=$handle->cwd("~"); #($stdout,$stderr)=$handle->cmd("iisreset /start",'__display__'); } ############### ## RABBITMQ ############### #($stdout,$stderr)=$handle->cmd( # "wget --random-wait --progress=dot ". # "https://github.com/erlang/otp/archive/maint.zip", # '__display__'); #($stdout,$stderr)=$handle->cmd("unzip -o maint.zip",'__display__'); #($stdout,$stderr)=$handle->cmd("rm -rvf maint.zip",'__display__'); #($stdout,$stderr)=$handle->cwd("otp-maint"); #($stdout,$stderr)=$handle->cmd("export ERL_TOP=`pwd`",'__display__'); #($stdout,$stderr)=$handle->cmd("./otp_build autoconf"); #($stdout,$stderr)=$handle->cmd("./configure",'__display__'); #($stdout,$stderr)=$handle->cmd("sudo make install",'__display__'); #($stdout,$stderr)=$handle->cwd(".."); #($stdout,$stderr)=$handle->cmd("sudo sed -i ". # "'s#secure_path = #secure_path = /usr/local/bin:/usr/local/sbin:#'". # " /etc/sudoers"); #($stdout,$stderr)=$handle->cmd("wget -qO- ". # "https://www.rabbitmq.com/download.html"); #my $source_flag=0; #my $rmq='';my $rmqtar='';my $rmqdir=''; #foreach my $line (split "\n", $stdout) { # if ($line=~/Source/) { # $source_flag=1; # } elsif ($source_flag) { # $rmq=$line; # $rmq=~s/^.*href=["](.*?)["].*$/$1/; # $rmq='https://www.rabbitmq.com'.$rmq; # ($rmqtar=$rmq)=~s/^.*\/(.*)$/$1/; # ($rmqdir=$rmqtar)=~s/^(.*).tar.gz/$1/; # last; # } #} #($stdout,$stderr)=$handle->cmd( # "wget --random-wait --progress=dot ".$rmq,'__display__'); #($stdout,$stderr)=$handle->cmd("tar zxvf $rmqtar",'__display__'); #($stdout,$stderr)=$handle->cmd("rm -rvf $rmqtar",'__display__'); #($stdout,$stderr)=$handle->cwd($rmqdir); #$handle->print('sudo su'); #$prompt=$handle->prompt(); #while (1) { # my $output.=Net::FullAuto::FA_Core::fetch($handle); # last if $output=~/$prompt/; # print $output; #} #$handle->print('export TARGET_DIR=/usr/local'); #while (1) { # my $output.=Net::FullAuto::FA_Core::fetch($handle); # last if $output=~/$prompt/; # print $output; #} #$handle->print('export SBIN_DIR=/usr/local'); #while (1) { # my $output.=Net::FullAuto::FA_Core::fetch($handle); # last if $output=~/$prompt/; # print $output; #} #$handle->print('export MAN_DIR=/usr/local'); #while (1) { # my $output.=Net::FullAuto::FA_Core::fetch($handle); # last if $output=~/$prompt/; # print $output; #} #$handle->print('make install'); #while (1) { # my $output.=Net::FullAuto::FA_Core::fetch($handle); # last if $output=~/$prompt/; # print $output; #} #$handle->print('exit'); #while (1) { # my $output.=Net::FullAuto::FA_Core::fetch($handle); # last if $output=~/$prompt/; # print $output; #} #($stdout,$stderr)=$handle->cwd(".."); #($stdout,$stderr)=$handle->cmd( # "wget --random-wait --progress=dot ". # "https://github.com/rabbitmq/rabbitmq-tutorials/archive/master.zip", # '__display__'); #($stdout,$stderr)=$handle->cmd("unzip -o master.zip",'__display__'); #($stdout,$stderr)=$handle->cmd("rm -rvf master.zip",'__display__'); #($stdout,$stderr)=$handle->cmd("sudo rabbitmq-server -detached", # '__display__'); # TEST FOR AMAZON EC2 INSTANCE #($stdout,$stderr)=$handle->cmd('wget --timeout=5 --tries=1 -qO- '. # 'http://169.254.169.254/latest/dynamic/instance-identity/'); #$public_ip=$stdout if $stdout=~/^\d+\.\d+\.\d+\.\d+\s*/s; #my $z=1; #while ($z==1) { # ($stdout,$stderr)=$handle->cmd("ps -ef",'__display__'); # if ($stdout=~/nginx/) { # my @psinfo=(); # foreach my $line (split /\n/, $stdout) { # next unless -1<index $line, 'nginx'; # @psinfo=split /\s+/, $line; # ($stdout,$stderr)=$handle->cmd($sudo."kill -9 $psinfo[2]"); # } last # } else { last } #} ($stdout,$stderr)=$handle->cmd($sudo."pkill nginx"); ($stdout,$stderr)=$handle->cmd($sudo."rm -rvf /usr/local/nginx",'__display__'); ($stdout,$stderr)=$handle->cmd("wget -qO- https://icanhazip.com"); $public_ip=$stdout if $stdout=~/^\d+\.\d+\.\d+\.\d+\s*/s; unless ($public_ip) { require Sys::Hostname; import Sys::Hostname; require Socket; import Socket; my($addr)=inet_ntoa((gethostbyname(Sys::Hostname::hostname))[4]); $public_ip=$addr if $addr=~/^\d+\.\d+\.\d+\.\d+\s*/s; } chomp($public_ip); $public_ip='127.0.0.1' unless $public_ip; unless ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "http://download.fedoraproject.org". "/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username epel-release-6-8.noarch.rpm", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd( "sudo rpm -ivh epel-release-6-8.noarch.rpm", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'rm -rvf epel-release-6-8.noarch.rpm', '__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'yum -y install uuid-devel '. 'pkgconfig libtool gcc-c++','__display__'); } ($stdout,$stderr)=$handle->cmd('mkdir -vp FullAutoAPI/deps', '__display__'); ($stdout,$stderr)=$handle->cmd( 'mkdir -vp FullAutoAPI/root/static/images', '__display__'); #($stdout,$stderr)=$handle->cmd("${sudo}perl -e \'use CPAN;". # "CPAN::HandleConfig-\>load;print \$CPAN::Config-\>{build_dir}\'"); #$builddir=$stdout; #my $fa_ver=$Net::FullAuto::VERSION; #($stdout,$stderr)=$handle->cmd( # "${sudo}ls -1t $builddir | grep Net-FullAuto-$fa_ver"); #my @lstmp=split /\n/,$stdout; #foreach my $line (@lstmp) { # unshift @ls_tmp, $line if $line!~/\.yml$/; #} ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/Docker_is.py ". "FullAutoAPI",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/automates_everything.jpg ". "FullAutoAPI/root/static/images",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/automationapi.jpg ". "FullAutoAPI/root/static/images",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/fullauto_com.jpg ". "FullAutoAPI/root/static/images",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/". "South-Shore-Food-Market-Ghost-sign_with_FA_1_faded_1024.jpg ". "FullAutoAPI/root/static/images",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/zeromq.jpg ". "FullAutoAPI/root/static/images",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/nginx.png ". "FullAutoAPI/root/static/images",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/wrapper.tt2 ". "FullAutoAPI/root",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/installer/FA.ico ". "FullAutoAPI/root/favicon.ico",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chmod -v 755 FullAutoAPI/root/static/images/*", '__display__'); ($stdout,$stderr)=$handle->cwd("FullAutoAPI/deps"); ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "http://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.gz", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username autoconf-latest.tar.gz",'__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd("tar zxvf autoconf-latest.tar.gz", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'rm -rvf autoconf-latest.tar.gz', '__display__'); ($stdout,$stderr)=$handle->cwd("autoconf-*"); ($stdout,$stderr)=$handle->cmd("./configure",'__display__'); ($stdout,$stderr)=$handle->cmd("make",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo."make install",'__display__'); ($stdout,$stderr)=$handle->cwd(".."); ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "https://github.com/jedisct1/libsodium/archive/master.zip", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username master.zip",'__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd("unzip -o master.zip",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'rm -rvf master.zip','__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -Rv $username:$username libsodium-master",'3600') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cwd('libsodium-master'); ($stdout,$stderr)=$handle->cmd('./autogen.sh','__display__'); ($stdout,$stderr)=$handle->cmd('./configure','__display__'); ($stdout,$stderr)=$handle->cmd('make','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'make install','__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); $do=1; if ($do==1) { # INSTALL LATEST VERSION OF PYTHON ($stdout,$stderr)=$handle->cmd($sudo. 'wget -qO- https://www.python.org/downloads/release'); $stdout=~s/^.*list-row-container menu.*?Python (.*?)[<].*$/$1/s; my $version=$stdout; ($stdout,$stderr)=$handle->cmd($sudo. "if test -f /usr/local/bin/python$version; then echo Exists; fi"); unless ($stdout=~/Exists/) { ($stdout,$stderr)=$handle->cmd($sudo. 'wget --random-wait --progress=dot '. "http://python.org/ftp/python/$version/Python-$version.tar.xz", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "tar xvf Python-$version.tar.xz", '__display__'); ($stdout,$stderr)=$handle->cwd("Python-$version"); ($stdout,$stderr)=$handle->cmd($sudo. './configure --prefix=/usr/local --exec-prefix=/usr/local '. '--enable-shared --enable-optimizations '. 'LDFLAGS="-Wl,-rpath /usr/local/lib"', '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'make','3600','__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'make altinstall','__display__'); $version=~s/^(\d+\.\d+).*$/$1/; ($stdout,$stderr)=$handle->cmd($sudo. "ln -s /usr/local/bin/python$version /usr/local/bin/python"); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); ($stdout,$stderr)=$handle->cmd($sudo. "/usr/local/bin/python$version -m ensurepip --default-pip", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "/usr/local/bin/python$version -m pip install ". "--upgrade pip setuptools wheel", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "/usr/local/bin/python$version -m pip install pyasn1", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "/usr/local/bin/python$version -m pip install pyasn1-modules", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "/usr/local/bin/python$version -m pip install --upgrade oauth2client", '__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); ($stdout,$stderr)=$handle->cmd($sudo. "/usr/local/bin/python$version -m pip install oauth2", '__display__'); unless ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd('echo /usr/local/lib > '. '~/local.conf','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'chmod -v 644 ~/local.conf', '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'mv -v ~/local.conf /etc/ld.so.conf.d','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'ldconfig'); } else { ($stdout,$stderr)=$handle->cmd( "python$version -m pip install awscli", '__display__'); } $sudo='sudo env "PATH=$PATH" '; ($stdout,$stderr)=$handle->cmd($sudo. 'python --version','__display__'); } } $do=0; if ($do==1) { ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "https://bootstrap.pypa.io/ez_setup.py",'__display__'); if ($^O eq 'cygwin') { # ez_setup.py uses curl by default which is broken with --location # in Cygwin. So using wget instead by forcing return False. ($stdout,$stderr)=$handle->cmd( "sed -i '/has_curl()/areturn False' ez_setup.py"); $handle->cmd_raw( "sed -i 's/\\(^return False$\\\)/ \\1/' ez_setup.py"); } else { ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username ez_setup.py",'__display__'); } ($stdout,$stderr)=$handle->cmd('python ez_setup.py','__display__'); ($stdout,$stderr)=$handle->cmd('easy_install pip','__display__'); # ($stdout,$stderr)=$handle->cmd( # 'git clone https://github.com/pypa/setuptools.git','__display__'); # ($stdout,$stderr)=$handle->cmd( # 'chown -Rv $username:$username setuptools','__display__') # if $^O ne 'cygwin'; # ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps/setuptools'); #print "OK1\n"; # ($stdout,$stderr)=$handle->cmd($sudo.'python setup.py install', # '__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); ($stdout,$stderr)=$handle->cmd( 'git clone https://github.com/google/oauth2client.git','__display__'); ($stdout,$stderr)=$handle->cwd('oauth2client'); ($stdout,$stderr)=$handle->cmd($sudo.'python setup.py install', '__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); unless ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd($sudo.'pip install httplib2','__display__'); ($stdout,$stderr)=$handle->cmd($sudo."ls -1 ". "/usr/local/lib/python2.7/site-packages",'__display__'); $stdout=~s/^.*(httplib2.*?egg).*$/$1/s; ($stdout,$stderr)=$handle->cmd($sudo."chmod o+r -v -R ". "/usr/local/lib/python2.7/site-packages/$stdout", '__display__'); } ($stdout,$stderr)=$handle->cmd($sudo.'pip install oauth2','__display__'); unless ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd('echo /usr/local/lib > '. 'local.conf','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'chmod -v 644 local.conf', '__display__'); ($stdout,$stderr)=$handle->cmd( $sudo.'mv -v local.conf /etc/ld.so.conf.d','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'ldconfig'); } else { ($stdout,$stderr)=$handle->cmd('pip install awscli','__display__'); } } } $do=1; if ($do==1) { ($stdout,$stderr)=$handle->cmd($sudo. 'git clone https://github.com/zeromq/zeromq4-x.git', '__display__'); ($stdout,$stderr)=$handle->cwd('zeromq4-x'); my $zmq_branch='v4.0.1'; ($stdout,$stderr)=$handle->cmd($sudo. "git checkout $zmq_branch",'__display__'); if ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd("./autogen.sh",'__display__'); $handle->cmd_raw('export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig'); ($stdout,$stderr)=$handle->cmd('./configure','__display__'); my $ad=" -no-undefined \\%NL%". " -avoid-version \\"; ($stdout,$stderr)=$handle->cmd( "sed -i \'/^libzmq_la_LDFLAGS = \\/a$ad\' ./Makefile"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ". "./Makefile"); } else { # Following cmd shows default pkg-config locations # pkg-config --variable pc_path pkg-config $handle->cmd_raw('export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig'); my $e='PKG_CONFIG_PATH=/usr/local/lib/pkgconfig '; ($stdout,$stderr)=$handle->cmd($sudo.$e."./autogen.sh",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo.$e.'./configure','__display__'); my $ad="Defaults env_keep += \"PKG_CONFIG_PATH\""; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'/_XKB_CHARSET/a$ad\' /etc/sudoers") } ($stdout,$stderr)=$handle->cmd($sudo.'make','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'make install','__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); } $do=1; if ($do==1) { # INSTALL LATEST VERSION OF NGINX # https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx # -dont-trust-the-tutorials-check-your-configuration/ # https://www.digitalocean.com/community/tutorials/ # understanding-and-implementing-fastcgi-proxying-in-nginx # http://dev.soup.io/post/1622791/I-managed-to-get-nginx-running-on # http://search.cpan.org/dist/Catalyst-Manual-5.9002/lib/Catalyst/ # Manual/Deployment/nginx/FastCGI.pod # https://serverfault.com/questions/171047/why-is-php-request-array-empty # https://codex.wordpress.org/Nginx # https://www.sitepoint.com/setting-up-php-behind-nginx-with-fastcgi/ # http://codingsteps.com/install-php-fpm-nginx-mysql-on-ec2-with-amazon-linux-ami/ # http://code.tutsplus.com/tutorials/revisiting-open-source-social-networking-installing-gnu-social--cms-22456 # https://wiki.loadaverage.org/clipbucket/installation_guides/install_like_loadaverage # https://karp.id.au/social/index.html # http://jeffreifman.com/how-to-install-your-own-private-e-mail-server-in-the-amazon-cloud-aws/ # https://www.wpwhitesecurity.com/creating-mysql-wordpress-database/ #($stdout,$stderr)=$handle->cmd($sudo.'groupadd www-data'); #($stdout,$stderr)=$handle->cmd($sudo.'adduser -r -m -g www-data www-data'); #$handle->print($sudo.'passwd www-data'); my $prompt=$handle->prompt(); while (0) { my $output.=fetch($handle); last if $output=~/$prompt/; print $output; if (-1<index $output,'New password:') { $handle->print($service_and_cert_password); $output=''; next; } elsif (-1<index $output,'Retype new password:') { $handle->print($service_and_cert_password); $output=''; next; } } my $nginx_path='/etc'; ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); ($stdout,$stderr)=$handle->cmd($sudo. 'rm -rvf /etc/nginx','__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "wget -qO- https://nginx.org/en/download.html"); $stdout=~s/^.*Mainline.*?\/download\/(.*?)\.tar\.gz.*$/$1/s; my $nginx=$stdout; ($stdout,$stderr)=$handle->cmd($sudo."wget --random-wait --progress=dot ". "http://nginx.org/download/$nginx.tar.gz",300,'__display__'); ($stdout,$stderr)=$handle->cmd($sudo."tar xvf $nginx.tar.gz",'__display__'); ($stdout,$stderr)=$handle->cwd($nginx); ($stdout,$stderr)=$handle->cmd($sudo."mkdir -vp objs/lib",'__display__'); ($stdout,$stderr)=$handle->cwd("objs/lib"); ($stdout,$stderr)=$handle->cmd("wget -qO- https://ftp.pcre.org/pub/pcre/"); my %pcre=(); my %conv=( Jan => 0, Feb => 1, Mar => 2, Apr => 3, May => 4, Jun => 5, Jul => 6, Aug => 7, Sep => 8, Oct => 9, Nov => 10, Dec => 11 ); foreach my $line (split /\n/, $stdout) { last unless $line; $line=~/^.*?["](.*?)["].*(\d\d-\w\w\w-\d\d\d\d \d\d:\d\d).*(\d+\w).*$/; my $file=$1;my $date=$2;my $size=$3; next if $file=~/^pcre2|\.sig$|\.tar\.gz$|\.tar\.bz2$/; next if $file!~/\.zip$/; next unless $date; $date=~/^(\d\d)-(\w\w\w)-(\d\d\d\d) (\d\d):(\d\d)$/; my $day=$1;my $month=$2;my $year=$3;my $hour=$4,my $minute=$5; my $timestamp=timelocal(0,$minute,$hour,$day,$conv{$month},--$year); $pcre{$timestamp}=[$file,$size]; } my $latest=(reverse sort keys %pcre)[0]; my $pcre=$pcre{$latest}->[0]; $pcre=~s/\.[^\.]+$//; my $checksum=''; foreach my $cnt (1..3) { ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "https://ftp.pcre.org/pub/pcre/$pcre.tar.gz",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "tar xvf $pcre.tar.gz",'__display__'); last unless $stderr; ($stdout,$stderr)=$handle->cmd($sudo. "rm -rfv $pcre.tar.gz",'__display__'); } ($stdout,$stderr)=$handle->cmd($sudo. "wget -qO- http://zlib.net/index.html"); my $zlib_ver=$stdout; my $sha__256=$stdout; $zlib_ver=~s/^.*? source code, version (\d+\.\d+\.\d+).*$/$1/s; $sha__256=~s/^.*?SHA-256 hash [<]tt[>](.*?)[<][\/]tt[>].*$/$1/s; foreach my $count (1..3) { ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "http://zlib.net/zlib-$zlib_ver.tar.gz",'__display__'); $checksum=$sha__256; ($stdout,$stderr)=$handle->cmd($sudo. "sha256sum -c - <<<\"$checksum zlib-$zlib_ver.tar.gz\"", '__display__'); unless ($stderr) { print(qq{ + CHECKSUM Test for zlib-$zlib_ver *PASSED* \n}); last } elsif ($count>=3) { print "FATAL ERROR! : CHECKSUM Test for ". "zlib-$zlib_ver.tar.gz *FAILED* ", "after $count attempts\n"; cleanup; } ($stdout,$stderr)=$handle->cmd($sudo. "rm -rvf zlib-$zlib_ver.tar.gz",'__display__'); } ($stdout,$stderr)=$handle->cmd($sudo."tar xvf zlib-$zlib_ver.tar.gz", '__display__'); my $ossl='openssl-1.1.1c'; foreach my $count (1..3) { $checksum='71b830a077276cbeccc994369538617a21bee808'; ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "https://www.openssl.org/source/$ossl.tar.gz", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "sha1sum -c - <<<\"$checksum $ossl.tar.gz\"",'__display__'); unless ($stderr) { print(qq{ + CHECKSUM Test for $ossl *PASSED* \n}); last } elsif ($count>=3) { print "FATAL ERROR! : CHECKSUM Test for $ossl.tar.gz *FAILED* ", "after $count attempts\n"; cleanup; } ($stdout,$stderr)=$handle->cmd($sudo. "rm -rvf $ossl.tar.gz",'__display__'); } ($stdout,$stderr)=$handle->cmd($sudo."tar xvf $ossl.tar.gz",'__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); # https://www.liberiangeek.net/2015/10/ # how-to-install-self-signed-certificates-on-nginx-webserver/ # https://www.hrupin.com/2017/07/how-to-automatically-restart-nginx ($stdout,$stderr)=$handle->cwd("~/FullAutoAPI/deps/$nginx"); # # echo-ing/streaming files over ssh can be tricky. Use echo -e # and replace these characters with thier HEX # equivalents (use an external editor for quick # search and replace - and paste back results. # use copy/paste or cat file and copy/paste results.): # # ! - \\x21 ` - \\x60 * - \\x2A # " - \\x22 \ - \\x5C # $ - \\x24 % - \\x25 # # https://www.lisenet.com/2014/ - bash approach to conversion my $inet_d_script=<<'END'; #\\x21/bin/sh # # nginx - this script starts and stops the nginx daemin # # chkconfig: - 85 15 # description: Nginx is an HTTP(S) server, HTTP(S) reverse \ # proxy and IMAP/POP3 proxy server # processname: nginx # config: /etc/nginx/nginx.conf # pidfile: /var/run/nginx.pid # user: nginx # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network # Check that networking is up. [ \\x22\\x24NETWORKING\\x22 = \\x22no\\x22 ] && exit 0 nginx=\\x22/usr/sbin/nginx\\x22 prog=\\x24(basename \\x24nginx) NGINX_CONF_FILE=\\x22/etc/nginx/nginx.conf\\x22 lockfile=/var/run/nginx.lock start() { [ -x \\x24nginx ] || exit 5 [ -f \\x24NGINX_CONF_FILE ] || exit 6 echo -n \\x24\\x22Starting \\x24prog: \\x22 daemon \\x24nginx -c \\x24NGINX_CONF_FILE retval=\\x24? echo [ \\x24retval -eq 0 ] && touch \\x24lockfile return \\x24retval } stop() { echo -n \\x24\\x22Stopping \\x24prog: \\x22 killproc \\x24prog -QUIT retval=\\x24? echo [ \\x24retval -eq 0 ] && rm -f \\x24lockfile return \\x24retval } restart() { configtest || return \\x24? stop start } reload() { configtest || return \\x24? echo -n \\x24\\x22Reloading \\x24prog: \\x22 killproc \\x24nginx -HUP RETVAL=\\x24? echo } force_reload() { restart } configtest() { \\x24nginx -t -c \\x24NGINX_CONF_FILE } rh_status() { status \\x24prog } rh_status_q() { rh_status >/dev/null 2>&1 } case \\x22\\x241\\x22 in start) rh_status_q && exit 0 \\x241 ;; stop) rh_status_q || exit 0 \\x241 ;; restart|configtest) \\x241 ;; reload) rh_status_q || exit 7 \\x241 ;; force-reload) force_reload ;; status) rh_status ;; condrestart|try-restart) rh_status_q || exit 0 ;; *) echo \\x24\\x22Usage: \\x240 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}\\x22 exit 2 esac END ($stdout,$stderr)=$handle->cmd("echo -e \"$inet_d_script\" > ". "~/nginx"); ($stdout,$stderr)=$handle->cmd($sudo.'mv -fv ~/nginx /etc/init.d', '__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'chmod -v +x /etc/init.d/nginx', '__display__'); ($stdout,$stderr)=$handle->cmd($sudo."chkconfig --add nginx"); ($stdout,$stderr)=$handle->cmd($sudo."chkconfig --level 345 nginx on"); ($stdout,$stderr)=$handle->cmd($sudo. 'yum -y install certbot-nginx','__display__'); # https://www.digitalocean.com/community/tutorials/ # how-to-secure-nginx-with-let-s-encrypt-on-centos-7 my $make_nginx="./configure --user=$username ". "--group=$username ". "--prefix=$nginx_path/nginx ". '--sbin-path=/usr/sbin/nginx '. "--conf-path=$nginx_path/nginx/nginx.conf ". '--pid-path=/var/run/nginx.pid '. '--lock-path=/var/run/nginx.lock '. '--error-log-path=/var/log/nginx/error.log '. '--http-log-path=/var/log/nginx/access.log '. "--with-http_ssl_module --with-pcre=objs/lib/$pcre ". "--with-zlib=objs/lib/zlib-$zlib_ver ". '--with-http_gzip_static_module '. '--with-http_ssl_module '. '--with-file-aio '. '--with-http_realip_module '. '--without-http_scgi_module '. '--without-http_uwsgi_module '. '--with-http_v2_module'; ($stdout,$stderr)=$handle->cmd($sudo.$make_nginx,'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i 's/-Werror //' ./objs/Makefile"); ($stdout,$stderr)=$handle->cmd($sudo.'make install','__display__'); # https://www.liberiangeek.net/2015/10/ # how-to-install-self-signed-certificates-on-nginx-webserver/ my $ngx="$nginx_path/nginx/nginx.conf"; ($stdout,$stderr)=$handle->cmd($sudo."sed -i 's/1024/64/' ".$ngx); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i 's/worker_processes 1;/worker_processes 2;/' ".$ngx); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i '0,/root html/{//d;}' ".$ngx); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i '0,/index index.html/{//d;}' ".$ngx); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'/koi8-r/a%NL% root ${home_dir}FullAutoAPI/root;\' ". $ngx); $handle->cmd_raw($sudo. "sed -i 's/\\(^root.*;$\\\)/ \\1/' $ngx"); $ad=' include fastcgi_params;%NL%'. " fastcgi_param SCRIPT_NAME %SQ%%SQ%;%NL%". ' fastcgi_param PATH_INFO $fastcgi_script_name;%NL%'. ' fastcgi_pass unix:/tmp/fullautoapi.socket;'; $ad=<<END; sed -i '1,/location/ {/location/a\\\ $ad }' $ngx END $handle->cmd_raw($sudo.$ad); $ad='%NL% location /static {'. "%NL% root ${home_dir}FullAutoAPI/root;". '%NL% }%NL%'; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'/404/a$ad\' ".$ngx); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ".$ngx); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \"s/%SQ%/\'/g\" ".$ngx); foreach my $port (443,444,445,443) { $avail_port= `true &>/dev/null </dev/tcp/127.0.0.1/$port && echo open || echo closed`; my $status=$avail_port; $avail_port=$port; chomp($status); last if $status eq 'closed'; } $ad='client_max_body_size 10M;'; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'/octet-stream/i$ad\' ".$ngx); $handle->cmd_raw($sudo. "sed -i 's/\\(^client_max_body_size 10M;$\\\)/ \\1/' $ngx"); #($stdout,$stderr)=$handle->cmd($sudo. # "sed -i \'s/^ listen 80/ listen ". # "\*:$avail_port ssl http2 default_server/\' ". # $nginx_path."/nginx/nginx.conf"); #($stdout,$stderr)=$handle->cmd($sudo. # "sed -i 's/SCRIPT_NAME/PATH_INFO/' ". # $nginx_path."/local/nginx/fastcgi_params"); #$ad='# Catalyst requires setting PATH_INFO (instead of SCRIPT_NAME)'. # ' to \$fastcgi_script_name'; #($stdout,$stderr)=$handle->cmd($sudo. # "sed -i \'/PATH_INFO/i$ad\' $nginx_path/nginx/fastcgi_params"); #$ad='fastcgi_param SCRIPT_NAME /;'; #($stdout,$stderr)=$handle->cmd($sudo. # "sed -i \'/PATH_INFO/a$ad\' $nginx_path/nginx/fastcgi_params"); #($stdout,$stderr)=$handle->cmd($sudo. # "sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ". # "$nginx_path/nginx/fastcgi_params"); # # echo-ing/streaming files over ssh can be tricky. Use echo -e # and replace these characters with thier HEX # equivalents (use an external editor for quick # search and replace - and paste back results. # use copy/paste or cat file and copy/paste results.): # # ! - \\x21 ` - \\x60 * - \\x2A # " - \\x22 \ - \\x5C # $ - \\x24 % - \\x25 # # https://www.lisenet.com/2014/ - bash approach to conversion my $script=<<END; use Net::FullAuto; \\x24Net::FullAuto::FA_Core::debug=1; my \\x24handle=connect_shell(); \\x24handle->print('$nginx_path/nginx/nginx -g \\x22daemon on;\\x22'); \\x24prompt=\\x24handle->prompt(); my \\x24output='';my \\x24password_not_submitted=1; while (1) { eval { local \\x24SIG{ALRM} = sub { die \\x22alarm\\x5Cn\\x22 };# \\x5Cn required alarm 10; my \\x24output=fetch(\\x24handle); last if \\x24output=~/\\x24prompt/; print \\x24output; if ((-1<index \\x24output,'Enter PEM pass phrase:') && \\x24password_not_submitted) { \\x24handle->print(\\x24ARGV[0]); \\x24password_not_submitted=0; } }; if (\\x24\@) { \\x24handle->print(); next; } } exit 0; END if ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cwd("~/WordPress"); my $vimrc=<<END; set paste set mouse-=a END ($stdout,$stderr)=$handle->cmd("echo -e \"$vimrc\" > ~/.vimrc"); ($stdout,$stderr)=$handle->cmd("mkdir -vp script",'__display__'); ($stdout,$stderr)=$handle->cmd("touch script/start_nginx.pl"); ($stdout,$stderr)=$handle->cmd("chmod -v 755 script/start_nginx.pl", '__display__'); ($stdout,$stderr)=$handle->cmd("chmod o+r $nginx_path/nginx/*", '__display__'); ($stdout,$stderr)=$handle->cmd("chmod -v 755 $nginx_path/nginx/nginx.exe", '__display__'); ($stdout,$stderr)=$handle->cmd("echo -e \"$script\" > ". "script/start_nginx.pl"); ($stdout,$stderr)=$handle->cmd("cygrunsrv -I nginx_first_time ". "-p /bin/perl -a ". "\'${home_dir}WordPress/script/start_nginx.pl ". "\"$service_and_cert_password\"'"); ($stdout,$stderr)=$handle->cmd("cygrunsrv --start nginx_first_time", '__display__'); ($stdout,$stderr)=$handle->cmd("touch script/first_time_start.flag"); } else { ($stdout,$stderr)=$handle->cmd($sudo. "sed -i 's/server_name localhost/". "server_name $domain_url www.$domain_url/' ". "$nginx_path/nginx/nginx.conf"); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'s/#user nobody;/user $username;/\' ". "$nginx_path/nginx/nginx.conf"); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i 's/#error_page 404 /404.html;/". "error_page 404 /404.html;/' ". "$nginx_path/nginx/nginx.conf"); ($stdout,$stderr)=$handle->cmd($sudo.'service nginx start', '__display__'); ($stdout,$stderr)=$handle->cwd("$nginx_path/nginx"); foreach my $num (1..3) { sleep 3; ($stdout,$stderr)=clean_filehandle($handle); $handle->print($sudo. "certbot --nginx -d $domain_url -d www.$domain_url"); $prompt=$handle->prompt(); my $output=''; while (1) { $output.=fetch($handle); last if $output=~/$prompt/; print $output; if (-1<index $output,'Attempt to reinstall') { $handle->print('1'); $output=''; } elsif (-1<index $output,'No redirect') { $handle->print('2'); $output=''; } elsif (-1<index $output,'Enter email address') { $handle->print('brian.kelly@fullauto.com'); $output=''; } elsif (-1<index $output,'Terms of Service') { $handle->print('A'); $output=''; } elsif (-1<index $output,'Would you be willing') { $handle->print('Y'); $output=''; } elsif ((-1<index $output,'existing certificate') && (-1==index $output,'--duplicate')) { $handle->print('C'); $output=''; } } ($stdout,$stderr)=clean_filehandle($handle); ($stdout,$stderr)=$handle->cmd($sudo. 'grep Certbot /etc/nginx/nginx.conf'); last if $stdout; } # https://ssldecoder.org ($stdout,$stderr)=$handle->cmd($sudo."service nginx restart", '__display__'); } } $do=0; if ($do==1) { # NGINX print "DOING NGINX\n"; # https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx # -dont-trust-the-tutorials-check-your-configuration/ # https://www.digitalocean.com/community/tutorials/ # understanding-and-implementing-fastcgi-proxying-in-nginx # http://dev.soup.io/post/1622791/I-managed-to-get-nginx-running-on # http://search.cpan.org/dist/Catalyst-Manual-5.9002/lib/Catalyst/ # Manual/Deployment/nginx/FastCGI.pod my $nginx='nginx-1.10.0'; $nginx='nginx-1.9.13' if $^O eq 'cygwin'; ($stdout,$stderr)=$handle->cmd($sudo."wget --random-wait --progress=dot ". "http://nginx.org/download/$nginx.tar.gz",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username $nginx.tar.gz",'__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd("tar xvf $nginx.tar.gz",'__display__'); ($stdout,$stderr)=$handle->cwd($nginx); ($stdout,$stderr)=$handle->cmd("mkdir -vp objs/lib",'__display__'); ($stdout,$stderr)=$handle->cwd("objs/lib"); my $pcre='pcre-8.40'; my $checksum=''; ($stdout,$stderr)=$handle->cmd($sudo."wget --random-wait --progress=dot ". "ftp://ftp.csx.cam.ac.uk/pub/software/". "programming/pcre/$pcre.tar.gz",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username $pcre.tar.gz",'__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd($sudo."tar xvf $pcre.tar.gz",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo."wget -qO- http://zlib.net/index.html"); my $zlib_ver=$stdout; my $sha__256=$stdout; $zlib_ver=~s/^.*? source code, version (\d+\.\d+\.\d+).*$/$1/s; $sha__256=~s/^.*?tar.gz.*?SHA-256 hash [<]tt[>](.*?)[<][\/]tt[>].*$/$1/s; foreach my $count (1..3) { ($stdout,$stderr)=$handle->cmd($sudo."wget --random-wait --progress=dot ". "http://zlib.net/zlib-$zlib_ver.tar.gz",'__display__'); $checksum=$sha__256; ($stdout,$stderr)=$handle->cmd($sudo. "sha256sum -c - <<<\"$checksum *zlib-$zlib_ver.tar.gz\"", '__display__'); unless ($stderr) { print(qq{ + CHECKSUM Test for zlib-$zlib_ver *PASSED* \n}); last } elsif ($count>=3) { print "FATAL ERROR! : CHECKSUM Test for ". "zlib-$zlib_ver.tar.gz *FAILED* ", "after $count attempts\n"; &Net::FullAuto::FA_Core::cleanup; } ($stdout,$stderr)=$handle->cmd($sudo."rm -rvf zlib-$zlib_ver.tar.gz", '__display__'); } ($stdout,$stderr)=$handle->cmd($sudo."tar xvf zlib-$zlib_ver.tar.gz", '__display__'); my $ossl='openssl-1.0.2h'; $checksum='577585f5f5d299c44dd3c993d3c0ac7a219e4949'; ($stdout,$stderr)=$handle->cmd($sudo."wget --random-wait --progress=dot ". "https://www.openssl.org/source/$ossl.tar.gz", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username $ossl.tar.gz",'__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd("sha1sum -c - <<<\"$checksum *$ossl.tar.gz\"", '__display__'); unless ($stderr) { print(qq{ + CHECKSUM Test for $ossl *PASSED* \n}); } else { ($stdout,$stderr)=$handle->cmd("rm -rvf $ossl.tar.gz",'__display__'); my $dc=1; print "FATAL ERROR! : CHECKSUM Test for $ossl.tar.gz *FAILED* ", "after $dc attempts\n"; &Net::FullAuto::FA_Core::cleanup; } ($stdout,$stderr)=$handle->cmd("tar xvf $ossl.tar.gz",'__display__'); ($stdout,$stderr)=$handle->cwd("~/FullAutoAPI/deps/$nginx"); my $make_nginx='./configure --sbin-path=/usr/local/nginx/nginx '. '--conf-path=/usr/local/nginx/nginx.conf '. '--pid-path=/usr/local/nginx/nginx.pid '. "--with-http_ssl_module --with-pcre=objs/lib/$pcre ". "--with-zlib=objs/lib/zlib-$zlib_ver"; ($stdout,$stderr)=$handle->cmd($make_nginx,'__display__'); ($stdout,$stderr)=$handle->cmd( $sudo."sed -i 's/-Werror //' ./objs/Makefile"); ($stdout,$stderr)=$handle->cmd($sudo.'make install','__display__'); # https://www.liberiangeek.net/2015/10/ # how-to-install-self-signed-certificates-on-nginx-webserver/ ($stdout,$stderr)=$handle->cmd( $sudo.'mkdir -vp /etc/nginx/ssl.key'); ($stdout,$stderr)=$handle->cmd( $sudo.'mkdir -vp /etc/nginx/ssl.crt'); ($stdout,$stderr)=$handle->cmd( $sudo.'mkdir -vp /etc/nginx/ssl.csr'); $handle->print( $sudo.'openssl genrsa -des3 -out '. "/etc/nginx/ssl.key/$public_ip.key 2048"); $prompt=$handle->prompt(); $prompt=~s/\$$//; while (1) { my $output.=fetch($handle); last if $output=~/$prompt/; print $output; if (-1<index $output,'pass phrase for') { $handle->print($service_and_cert_password); $output=''; next; } elsif (-1<index $output,'Verifying - Enter') { $handle->print($service_and_cert_password); $output=''; next; } } while (1) { my $trys=0; my $ereturn=eval { local $SIG{ALRM} = sub { die "alarm\n" }; # \n required alarm 7; $handle->print($sudo. "openssl req -new -key /etc/nginx/ssl.key/$public_ip.key ". "-out /etc/nginx/ssl.csr/$public_ip.csr"); my $test='';my $output=''; while (1) { $output.=Net::FullAuto::FA_Core::fetch($handle); $test.=$output; $test=~tr/\0-\11\14-\37\177-\377//d; return 'DONE' if $output=~/$prompt/; print $output; $test=~s/\n//gs; if ($test=~/Enter pass phrase.*key:/s) { $handle->print($service_and_cert_password); $output=''; $test=''; next; } elsif (-1<index $test,'[AU]:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'[Some-State]:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'city) []:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'Pty Ltd]:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'section) []:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'YOUR name) []:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'Address []:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'challenge password []:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'company name []:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test,'Country Name (2 letter code) [XX]') { $handle->print('.'); $output=''; $test=''; next; } elsif (-1<index $test,'State or Province Name (full name) []') { $handle->print('.'); $output=''; $test=''; next; } elsif ( -1<index $test,'Locality Name (eg, city) [Default City]:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test, 'Organization Name (eg, company) [Default Company Ltd]:') { $handle->print(); $output=''; $test=''; next; } elsif (-1<index $test, 'Common Name (eg, your name or your server\'s hostname) []') { $handle->print(); $output=''; $test=''; next; } } return 'DONE'; }; alarm(0); last if $ereturn eq 'DONE' || $trys++>3; } $handle->print($sudo. 'openssl x509 -req -days 365 -in '. "/etc/nginx/ssl.csr/$public_ip.csr -signkey ". "/etc/nginx/ssl.key/$public_ip.key -out ". "/etc/nginx/ssl.crt/$public_ip.crt"); while (1) { my $output=fetch($handle); last if $output=~/$prompt/; print $output; if (-1<index $output,'Enter pass phrase') { $handle->print($service_and_cert_password); } } ($stdout,$stderr)=$handle->cmd($sudo."sed -i 's/1024/64/' ". "/usr/local/nginx/nginx.conf"); $ad=" include fastcgi_params;%NL%". " fastcgi_pass localhost:3003;"; $ad=<<END; sed -i '1,/location/ {/location/a\\\ $ad }' /usr/local/nginx/nginx.conf END $handle->cmd_raw($sudo.$ad); $ad='%NL% location /static {'. "%NL% root ${home_dir}FullAutoAPI/root;". '%NL% }%NL%'. '%NL% ssl on;'. "%NL% ssl_certificate /etc/nginx/ssl.crt/$public_ip.crt;". "%NL% ssl_certificate_key /etc/nginx/ssl.key/$public_ip.key;". '%NL% ssl_protocols TLSv1 TLSv1.1 TLSv1.2;'. '%NL% ssl_ciphers '. '"HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";'; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'/404/a$ad\' /usr/local/nginx/nginx.conf"); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ". "/usr/local/nginx/nginx.conf"); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'s/^ listen 80/ listen ". "\*:443 ssl default_server/\' /usr/local/nginx/nginx.conf"); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i 's/SCRIPT_NAME/PATH_INFO/' ". "/usr/local/nginx/fastcgi_params"); $ad='# Catalyst requires setting PATH_INFO (instead of SCRIPT_NAME)'. ' to \$fastcgi_script_name'; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'/PATH_INFO/i$ad\' /usr/local/nginx/fastcgi_params"); $ad='fastcgi_param SCRIPT_NAME /;'; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'/PATH_INFO/a$ad\' /usr/local/nginx/fastcgi_params"); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ". "/usr/local/nginx/fastcgi_params"); # # echo-ing/streaming files over ssh can be tricky. Use echo -e # and replace these characters with thier HEX # equivalents (use an external editor for quick # search and replace - and paste back results. # use copy/paste or cat file and copy/paste results.): # # ! - \\x21 ` - \\x60 # " - \\x22 \ - \\x5C # $ - \\x24 % - \\x25 # my $script=<<END; use Net::FullAuto; \\x24Net::FullAuto::FA_Core::debug=1; my \\x24handle=connect_shell(); \\x24handle->print('/usr/local/nginx/nginx -g \\x22daemon on;\\x22'); \\x24prompt=\\x24handle->prompt(); my \\x24output='';my \\x24password_not_submitted=1; while (1) { eval { local \\x24SIG{ALRM} = sub { die \\x22alarm\\x5Cn\\x22 };# \\x5Cn required alarm 10; my \\x24output=Net::FullAuto::FA_Core::fetch(\\x24handle); last if \\x24output=~/\\x24prompt/; print \\x24output; if ((-1<index \\x24output,'Enter PEM pass phrase:') && \\x24password_not_submitted) { \\x24handle->print(\\x24ARGV[0]); \\x24password_not_submitted=0; } }; if (\\x24\@) { \\x24handle->print(); next; } } exit 0; END if ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cwd("~/FullAutoAPI"); my $vimrc=<<END; set paste set mouse-=a END ($stdout,$stderr)=$handle->cmd("echo -e \"$vimrc\" > ~/.vimrc"); ($stdout,$stderr)=$handle->cmd("mkdir -vp script",'__display__'); ($stdout,$stderr)=$handle->cmd("touch script/start_nginx.pl"); ($stdout,$stderr)=$handle->cmd("chmod -v 755 script/start_nginx.pl", '__display__'); ($stdout,$stderr)=$handle->cmd("chmod -v o+r /usr/local/nginx/*", '__display__'); ($stdout,$stderr)=$handle->cmd("chmod -v 755 /usr/local/nginx/nginx.exe", '__display__'); ($stdout,$stderr)=$handle->cmd("echo -e \"$script\" > ". "script/start_nginx.pl"); ($stdout,$stderr)=$handle->cmd("cygrunsrv -I nginx_first_time ". "-p /bin/perl -a ". "\'${home_dir}FullAutoAPI/script/start_nginx.pl ". "\"$service_and_cert_password\"'"); ($stdout,$stderr)=$handle->cmd("cygrunsrv --start nginx_first_time", '__display__'); ($stdout,$stderr)=$handle->cmd("touch script/first_time_start.flag"); } else { $handle->print($sudo."/usr/local/nginx/nginx"); $prompt=$handle->prompt(); while (1) { my $output=fetch($handle); last if $output=~/$prompt/; print $output; if (-1<index $output,'PEM pass phrase') { $handle->print($service_and_cert_password); } } } } $do=0; if ($do==1) { ($stdout,$stderr)=$handle->cwd("~/FullAutoAPI/deps"); my $go=$1;my $gosha1=$2; ($stdout,$stderr)=$handle->cmd($sudo."wget -qO- https://golang.org/dl"); if ($^O eq 'cygwin') { $stdout=~ /^.*?href=["]([^"]+windows-amd64.zip)["].*?[<]tt[>](.*?)[<].*$/s; $go=$1;$gosha1=$2; } else { $stdout=~ /^.*?href=["]([^"]+linux-amd64.tar.gz)["].*?[<]tt[>](.*?)[<].*$/s; $go=$1;$gosha1=$2; } ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ".$go, '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username $go",'__display__') if $^O ne 'cygwin'; $go=~s/^.*\/(.*)$/$1/; ($stdout,$stderr)=$handle->cmd("sha1sum -c - <<<\"$gosha1 *$go\"", '__display__'); unless ($stderr) { print(qq{ + CHECKSUM Test for $go *PASSED* \n}); } else { ($stdout,$stderr)=$handle->cmd($sudo."rm -rvf $go",'__display__'); print "FATAL ERROR! : CHECKSUM Test for $go *FAILED* "; &Net::FullAuto::FA_Core::cleanup; } if ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd("unzip -o $go",'__display__'); } else { ($stdout,$stderr)=$handle->cmd("tar zxvf $go",'__display__'); } ($stdout,$stderr)=$handle->cmd("rm -rvf $go",'__display__'); } $do=0; if ($do==1) { ($stdout,$stderr)=$handle->cmd($sudo.'wget -qO- '. 'https://github.com/membrane/service-proxy/releases/latest'); $stdout=~s/^.*?href=["]([^"]+zip)["].*$/$1/s; my $membrane_zip=$stdout; ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot https://github.com".$membrane_zip, '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username $membrane_zip",'__display__') if $^O ne 'cygwin'; $membrane_zip=~s/^.*\/(.*)$/$1/; ($stdout,$stderr)=$handle->cmd("unzip -o $membrane_zip",'__display__'); ($stdout,$stderr)=$handle->cmd("rm -rvf $membrane_zip",'__display__'); #($stdout,$stderr)=$handle->cmd('git clone --depth=1 '. # 'https://github.com/membrane/service-proxy.git','__display__'); exit; } unless (-e '/usr/bin/cpan') { if ($^O eq 'cygwin') { $handle->print('cpan'); } else { ($stdout,$stderr)=$handle->cmd($sudo.'yum -y install cpan', '__display__'); $handle->print($sudo.'cpan'); } $prompt=$handle->prompt(); while (1) { my $output=fetch($handle); last if $output=~/$prompt/; print 'm'.$output; if (-1<index $output,'possible automatically') { $handle->print('yes'); } elsif (-1<index $output,'by bootstrapping') { $handle->print('sudo'); } elsif (-1<index $output,'some CPAN') { $handle->print('no'); } elsif (-1<index $output,'pick from') { $handle->print('no'); } elsif (-1<index $output,'CPAN site') { $handle->print('http://www.cpan.org'); } elsif (-1<index $output,'ENTER to quit') { $handle->print(); } elsif ($output=~/cpan[[]\d+[]][>]/) { $handle->print('bye'); } } } ($stdout,$stderr)=$handle->cmd("export PERL_MM_USE_DEFAULT=1"); if ($^O eq 'cygwin') { my $show=<<END; ######################################## INSTALLING Starman ######################################## END print $show; $handle->cmd_raw($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","Starman")\'', '__display__'); $show=<<END; ######################################## INSTALLING HTTP::Server::Simple ######################################## END print $show; $handle->cmd_raw($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","HTTP::Server::Simple")\'', '__display__'); } my $show=<<END; ######################################## INSTALLING autodie ######################################## END print $show; ($stdout,$stderr)=$handle->cwd("~/FullAutoAPI/deps"); $stdout=$handle->cmd_raw($sudo. 'perl -MCPAN -e \'CPAN::Shell->get('. '"install","autodie")\'', '__display__'); $stdout=~s/^.*Checksum for (.*autodie.*gz) ok.*$/$1/s; my $gzfile=$stdout; ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $gzfile ~/FullAutoAPI/deps",'__display__'); $stdout=~/^(.*)\/(.*gz)$/; my $modpath=$1;my $modfile=$2; ($stdout,$stderr)=$handle->cmd( "tar zxvf $modfile",'__display__'); ($stdout,$stderr)=$handle->cwd("autodie*"); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i 's/\"Test::Perl/#\"Test::Perl/' Makefile.PL"); ($stdout,$stderr)=$handle->cmd($sudo. 'perl Makefile.PL','__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'make install','__display__'); ($stdout,$stderr)=$handle->cwd('..'); ($stdout,$stderr)=$handle->cmd($sudo. 'rm -rvf autodie*','__display__'); ($stdout,$stderr)=$handle->cwd("~/FullAutoAPI/deps"); $show=<<END; ######################################## INSTALLING Perl::Critic ######################################## END print $show; $handle->cmd_raw($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","Perl::Critic")\'', '__display__'); $show=<<END; ######################################## INSTALLING IO::CaptureOutput ######################################## END print $show; $handle->cmd_raw($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","IO::CaptureOutput")\'', '__display__'); $show=<<END; ######################################## INSTALLING Devel::CheckLib ######################################## END print $show; $handle->cmd_raw($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","Devel::CheckLib")\'', '__display__'); $show=<<END; ######################################## INSTALLING ExtUtils::Embed ######################################## END #print $show; #$handle->cmd_raw( # 'sudo perl -MCPAN -e \'CPAN::Shell->force('. # '"install","ExtUtils::Embed")\'', # '__display__'); my @cpan_modules = qw( Test::More Text::Glob File::Find::Rule Crypt::UnixCrypt_XS Digest::CRC Data::Integer Data::Float HTTP::Lite Authen::Passphrase DBICx::TestDatabase Class::Mix Crypt::MySQL Module::Build AnyEvent Test::Requires Proc::Guard ZMQ::LibZMQ4 CPAN::Meta ExtUtils::ParseXS Package::Generator Test::Output Compress::Raw::Bzip2 IO::Compress::Bzip2 Package::Anon Text::Diff Archive::Tar Archive::Zip inc::latest PAR::Dist Regexp::Common Pod::Checker Pod::Parser Pod::Man File::Slurp Test::Taint Test::Warnings Test::Without::Module Devel::LexAlias BSD::Resource IPC::System::Simple Sub::Identify Fatal Sub::Name Role::Tiny Test::LeakTrace Test::CleanNamespaces Test::Pod Test::Pod::Coverage Class::Load Class::Load::XS Algorithm::C3 SUPER Module::Refresh Declare::Constraints::Simple Devel::Cycle CGI Test::Memory::Cycle IO::String Mouse::Tiny DateTime::Format::MySQL Moose Moo MooseX::Role::WithOverloading Pod::Coverage::Moose MooseX::AttributeHelpers MooseX::ConfigFromFile MooseX::MarkAsMethods MooseX::SimpleConfig MooseX::StrictConstructor MooseX::NonMoose Net::FullAuto Time::HiRes Business::ISBN App::FatPacker JSON JSON::XS Test::DistManifest Term::Size::Any Type::Tiny File::ReadBackwards Imager Astro::MoonPhase Date::Manip XML::LibXML SQL::Translator Template::Alloy URI::Amazon::APA Catalyst::Runtime Proc::ProcessTable Parallel::Forker UUID::Tiny Regexp::Assemble Bytes::Random::Secure Math::Random::ISAAC::XS HTML::FormHandler Crypt::PassGen Catalyst::Controller::HTML::FormFu HTML::FormHandler::Model::DBIC HTML::FormHandler::Model::DBIC CatalystX::OAuth2 Task::Catalyst::Tutorial YAML::Syck Catalyst::Model::Adaptor ); #EXODIST/Test-Simple-1.001014.tar.gz #Test::Aggregate #Test::Aggregate::Nested # https://metacpan.org/pod/DBIx::Class::Manual::Cookbook#Predefined-searches # # http://ajct.info/2015/08/16/oauth-and-catalyst.html # # http://stackoverflow.com/questions/23652166/how-to-generate-oauth-2-client-id-and-secret # # https://bshaffer.github.io/oauth2-server-php-docs/grant-types/refresh-token/ # http://cygwin.1069669.n5.nabble.com/where-is-my-quot-usr-dict- # words-quot-or-quot-usr-share-dict-words-on-cygwin-1-7-td59328.html ($stdout,$stderr)=$handle->cwd('deps'); my $mirror='https://dl.fedoraproject.org/pub/fedora/linux/releases/'; # "http://mirrors.maine.edu/Fedora/releases/"; ($stdout,$stderr)=$handle->cmd($sudo."wget -qO- $mirror"); my @num=(); foreach my $line (split /\n/, $stdout) { next unless $line=~/DIR/; $line=~/^.*DIR.*href=["](\d+)\/["].*$/; my $num=$1; next unless $num; push @num, $num; } my $num=(reverse sort {$a<=>$b} @num)[0]; ($stdout,$stderr)=$handle->cmd($sudo. "wget -qO- $mirror$num/Server/x86_64/os/Packages/w/"); $stdout=~s/^.*(words.*?rpm).*$/$1/s; ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "$mirror$num/Server/x86_64/os/Packages/w/$stdout", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username words*.rpm", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd( "rpm2cpio words*.rpm | \(cd /; cpio -idmv\)"); ($stdout,$stderr)=$handle->cmd($sudo.'chmod -v 755 /usr/share/dict/', '__display__'); ($stdout,$stderr)=$handle->cwd("~/FullAutoAPI"); my $install_fullautoapi=<<'END'; o o o .oPYo. ooooo .oo o o o o o .oPYo. 8 8b 8 8 8 .P 8 8 8 8 8b 8 8 8 8 8`b 8 `Yooo. 8 .P 8 8 8 8 8`b 8 8 8 8 `b 8 `8 8 oPooo8 8 8 8 8 `b 8 8 oo 8 8 `b8 8 8 .P 8 8 8 8 8 `b8 8 8 8 8 `8 `YooP' 8 .P 8 8oooo 8oooo 8 8 `8 `YooP8 ........................................................ :::::::::::::::::::::::::::::::::::::::::::::::::::::::: _ ((_) / / _ _ _ \__/_ ___ __ _| |_ __ _| |_ _ ___| |_ / \ / __/ _` | __/ _` | | | | / __| __| Perl MVC _- | | | (_| (_| | || (_| | | |_| \__ \ | framework _ _-' \____/ \___\__,_|\__\__,_|_|\__, |___/\__|c ((_) ---\ |___/ \ \\_ Web Framework (_) (Catalyst Foundation is **NOT** a sponsor of the FullAuto© Project.) END foreach my $module (@cpan_modules) { next if $module=~/^\s*[#]/; my $show=<<END; ######################################## INSTALLING $module ######################################## END sleep 1; print $show; if ($module eq 'Catalyst::Runtime') { print $install_fullautoapi; sleep 10; } if ($module eq 'Regexp::Assemble' || $module eq 'ZMQ::LibZMQ4' || $module eq 'CatalystX::OAuth2') { $handle->print($sudo. 'perl -MCPAN -e \'CPAN::Shell->force('. "\"install\",\"$module\")\'" ) } else { $handle->print($sudo."cpan $module 2>&1"); } my $prompt=$handle->prompt(); my $error=0;my $force=0;my $tries=0;my $allout='';my $save=''; while (1) { my $done=eval { local $SIG{ALRM} = sub { die "alarm\n" }; # \n required alarm 120; select(undef,undef,undef,0.02); # sleep for 1/50th second; my $output=''; ($output,$save)=fetch($handle,$save,'__display__'); $allout.=$output; if ($output=~/$prompt/) { if ($error) { $error=0;$force=1; $handle->print($sudo. 'perl -MCPAN -e \'CPAN::Shell->force('. "\"install\",\"$module\")\'" ) } elsif ($output=~/y\s*y\s*y/s) { print "\n\nCLEARING MEMORY ...\n\n"; sleep 3; clean_filehandle($handle); $handle->close(); $handle=connect_shell(); return 'done'; } else { return 'done'; } } elsif ($output=~/y\s*y\s*y/s) { print "\n\nCLEARING MEMORY ...\n\n"; sleep 3; clean_filehandle($handle); $handle->close(); $handle=connect_shell(); return 'done'; } elsif ($output=~/build the XS Stash module/) { $handle->print('y'); } elsif ($output=~/use the XS Stash by default/) { $handle->print('y'); } elsif ($output=~/it permanently/) { $handle->print('yes'); } elsif ($output=~/from CPAN/) { $handle->print('yes'); } if (!$force && ((-1<index $allout,'[test_dynamic] Error 255') || (-1<index $allout,'Connection reset by peer'))) { $error=1; #$output=~s/$prompt//gs; } #print $output; return 'continue'; }; next if $done eq 'continue'; if ($done=~/^\d$/ && $done==1) { my $output=fetch($handle); my $attempt='attempts'; $attempt='attempt' if $tries==0; print "\n\n FATAL ERROR!: Could not install CPAN Module", ": $module\n\n", " --> $output\n", " after ",++$tries," $attempt\n\n"; cleanup; } elsif ($@ && ++$tries<4) { alarm(0);$allout=''; $handle->print("\003"); my $done=eval { local $SIG{ALRM} = sub { die "alarm\n" }; # \n required while (my $ln=fetch($handle)) { return 'done' if $ln=~/$prompt/s; } }; if ($@) { my $attempt='attempts'; $attempt='attempt' if $tries==0; print "\n\n FATAL ERROR!: Could not install CPAN Module", ": $module\n\n", " --> could not recover handle after \n", " ",++$tries," $attempt\n\n"; cleanup; } elsif ($done) { next } else { print "\n\n FATAL ERROR!: Could not install CPAN Module", " $module\n", " - Unknown Error after ", --$tries," attempts\n\n"; cleanup; } } elsif ($tries>3) { my $attempt='attempts'; print "\n\n FATAL ERROR!: Could not install CPAN Module", ": $module\n\n", " after ",++$tries," $attempt\n\n"; cleanup; } last if $done; } } $show=<<END; ######################################## INSTALLING Catalyst::Devel ######################################## END print $show; if ($^O eq 'cygwin') { $handle->print($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","Catalyst::Devel")\''); } else { $handle->print($sudo.'cpan Catalyst::Devel'); } $prompt=$handle->prompt();my $save=''; while (1) { my $output=''; ($output,$save)=fetch($handle,$save,'__display__'); last if $output=~/$prompt/; print $output; if (-1<index $output,'XS Stash module?') { $handle->print('y'); } if (-1<index $output,'XS Stash by default?') { $handle->print('y'); } } $show=<<END; ######################################## INSTALLING DBIx::Class ######################################## END $handle->cmd_raw($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","DBIx::Class")\'', '__display__'); $show=<<END; ######################################## INSTALLING DBIx::Class::Schema::Loader ######################################## END $handle->cmd_raw($sudo. 'cpan DBIx::Class::Schema::Loader', '__display__'); # $show=<<END; # ######################################## # # INSTALLING Net::RabbitFoot # ######################################## #END # print $show; # $handle->print($sudo.'cpan Net::RabbitFoot'); # $prompt=$handle->prompt(); # while (1) { # my $output.=fetch($handle); # last if $output=~/$prompt/; # print $output; # if (-1<index $output,'Skip further questions and use') { # $handle->print('y'); # $output=''; # next; # } # } # $show=<<END; # ######################################## # # INSTALLING YAML::Syck # ######################################## #END # print $show; # sleep 1; # $handle->cmd_raw($sudo.'cpan YAML::Syck','__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Controller::REST ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Controller::REST','__display__'); # $show=<<END; # ######################################## # # INSTALLING Catalyst::Model::Adaptor # ######################################## #END # print $show; # sleep 1; # $handle->cmd_raw("${sudo}cpan Catalyst::Model::Adaptor",'__display__'); $show=<<END; ######################################## INSTALLING Catalyst::View::JSON ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::View::JSON', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::View::TT::Alloy ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::View::TT::Alloy', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Plugin::Unicode ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Plugin::Unicode', '__display__'); $show=<<END; ######################################## INSTALLING DBIx::Class::PassphraseColumn ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan DBIx::Class::PassphraseColumn', '__display__'); $show=<<END; ######################################## INSTALLING Authen::Passphrase::BlowfishCrypt ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Authen::Passphrase::BlowfishCrypt', '__display__'); $show=<<END; ######################################## INSTALLING Method::Signatures::Simple ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Method::Signatures::Simple', '__display__'); # $show=<<END; # ######################################## # # INSTALLING HTML::FormHandler # ######################################## #END # print $show; # sleep 1; # $handle->cmd_raw("${sudo}cpan HTML::FormHandler", # '__display__'); # $show=<<END; # ######################################## # # INSTALLING HTML::FormHandler::Model::DBIC # ######################################## #END # print $show; # sleep 1; # $handle->cmd_raw("${sudo}cpan HTML::FormHandler::Model::DBIC", # '__display__'); $show=<<END; ######################################## INSTALLING CatalystX::SimpleLogin ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","CatalystX::SimpleLogin")\'', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Plugin::Session ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Plugin::Session', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Plugin::Session::Store::Memcached ######################################## END print $show; sleep 1; # http://vasil9v.tumblr.com/post/31921755331/compiling-memcached-on-cygwinwindows $handle->cmd_raw($sudo. 'cpan Catalyst::Plugin::Session::Store::Memcached', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Plugin::Session::State::Cookie ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Plugin::Session::State::Cookie', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Plugin::Authentication ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Plugin::Authentication', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Authentication::Store::DBIx::Class ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Authentication::Store::DBIx::Class', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Plugin::Authorization::Roles ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Plugin::Authorization::Roles', '__display__'); $show=<<END; ######################################## INSTALLING Time::Warp ######################################## END print $show; sleep 1; $handle->print($sudo. 'perl -MCPAN -e \'CPAN::Shell->notest('. '"install","Time::Warp")\''); $show=<<END; ######################################## INSTALLING DBIx::Class::TimeStamp ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan DBIx::Class::TimeStamp', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Controller::ActionRole ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Controller::ActionRole', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::ActionRole::ACL ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::ActionRole::ACL', '__display__'); $show=<<END; ######################################## INSTALLING FCGI ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo.'cpan FCGI', '__display__'); $show=<<END; ######################################## INSTALLING FCGI::ProcManager ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan FCGI::ProcManager', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::Helper::Model::DBIC::Schema ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::Helper::Model::DBIC::Schema', '__display__'); $show=<<END; ######################################## INSTALLING Catalyst::View::Email ######################################## END print $show; sleep 1; $handle->cmd_raw($sudo. 'cpan Catalyst::View::Email', '__display__'); $show=<<END; ######################################## INSTALLING Finance::Quote ######################################## END print $show; $handle->print($sudo.'cpan Finance::Quote'); $prompt=$handle->prompt(); while (1) { my $output.=fetch($handle); last if $output=~/$prompt/; print $output; if (-1<index $output,'traffic to external sites') { $handle->print('Y'); $output=''; next; } if (-1<index $output,'have network connectivity. [n]') { $handle->print('y'); $output=''; next; } } ($stdout,$stderr)=$handle->cwd('~'); ($stdout,$stderr)=$handle->cmd('catalyst.pl FullAutoAPI','__display__'); ($stdout,$stderr)=$handle->cwd('FullAutoAPI'); ($stdout,$stderr)=$handle->cmd('perl Makefile.PL','__display__'); # http://www.catalystframework.org/calendar/2011/15 # http://search.cpan.org/~bobtfish/Catalyst-Plugin-Authentication-0.10023/ my $pm_path="./lib/FullAutoAPI.pm"; $ad=" Session%NL%". " Session::Store::Memcached%NL%". " Session::State::Cookie%NL%". " Authentication%NL%". " Authorization::Roles%NL%". " +CatalystX::SimpleLogin"; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i '/ Static::Simple/a$ad' $pm_path"); $ad=" use_request_uri_for_path => 1,%NL%". " authentication => {%NL%". " default_realm => %SQ%users%SQ%,%NL%". " realms => {%NL%". " users => {%NL%". " credential => {%NL%". " class => %SQ%Password%SQ%,%NL%". " password_field => %SQ%password%SQ%,%NL%". " password_type => %SQ%self_check%SQ%%NL%". " },%NL%". " store => {%NL%". " class => %SQ%DBIx::Class%SQ%,%NL%". " user_model => %SQ%DB::Users%SQ%,%NL%". " role_relation => %SQ%roles%SQ%,%NL%". " role_field => %SQ%name%SQ%,%NL%". " }%NL%". " }%NL%". " },%NL%". " },%NL%". " %SQ%Controller::Login%SQ% => {%NL%". " traits => [%SQ%-RenderAsTTTemplate%SQ%],%NL%". " login_form_args => {%NL%". " authenticate_args => { active => %SQ%Y%SQ% },%NL%". " },%NL%". " },"; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i '/Send X-Catalyst header/a$ad' $pm_path"); $handle->cmd_raw($sudo. "sed -i 's/\\(^use_request_uri$\\\)/ \\1/' $pm_path"); $handle->cmd_raw($sudo. "sed -i 's/\\(^Session$\\\)/ \\1/' $pm_path"); $handle->cmd_raw($sudo. "sed -i 's/\\(^authentication =.*\\\)/ \\1/' $pm_path"); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" $pm_path"); ($stdout,$stderr)=$handle->cmd($sudo."sed -i \"s/%SQ%/\'/g\" $pm_path"); ($stdout,$stderr)=$handle->cmd("mkdir -vp root/login",'__display__'); ($stdout,$stderr)=$handle->cmd("touch root/login/login.tt2", '__display__'); my $content=<<'ENDD'; [% META title = 'Welcome to the FullAuto API Management Dashboard: Please Log In' %] <div> [% FOR field IN login_form.error_fields %] [% FOR error IN field.errors %] <p><span style=\\x22color: red;\\x22>[% field.label _ ': ' _ error %]</span></p> [% END %] [% END %] </div> <div> <form id=\\x22login_form\\x22 method=\\x22post\\x22 action=\\x22[% c.req.uri %]\\x22> <fieldset style=\\x22border: 0;\\x22> <table> <tr> <td><label class=\\x22label\\x22 for=\\x22username\\x22>Username:</label></td> <td><input type=\\x22text\\x22 name=\\x22username\\x22 value=\\x22\\x22 /></td> </tr> <tr> <td><label class=\\x22label\\x22 for=\\x22password\\x22>Password:</label></td> <td><input type=\\x22password\\x22 name=\\x22password\\x22 value=\\x22\\x22 /></td> </tr> <tr><td><input type=\\x22submit\\x22 name=\\x22submit\\x22 value=\\x22Login\\x22 /></td></tr> </table> </fieldset> </form> </div> ENDD ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/login/login.tt2"); ($stdout,$stderr)=$handle->cmd("mkdir -vp root/email",'__display__'); ($stdout,$stderr)=$handle->cmd("touch root/email/welcome.tt2", '__display__'); $content=<<'END'; <\\x21DOCTYPE html PUBLIC \\x22-//W3C//DTD XHTML 1.0 Transitional//EN\\x22 \\x22http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\x22> <html xmlns=\\x22http://www.w3.org/1999/xhtml\\x22 xml:lang=\\x22en\\x22 lang=\\x22en\\x22> <head> </head> <body> <h2 align=\\x22center\\x22>Welcome to the FullAuto API Management Dashboard.</h2> <p>Your username is: <span style=\\x22color: green;\\x22>[% username %]</span></p> <p>Your initial password is: <span style=\\x22color: red;\\x22>[% password %]</span></p> <p>Your client id is: <span style=\\x22color: purple;\\x22>[% client_id %]</span></p> <p>Your client secret is: <span style=\\x22color: purple;\\x22>[% client_secret %]</span></p> <p>You will be asked to change your password on first login.</p> </body> </html> END ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/email/welcome.tt2"); ($stdout,$stderr)=$handle->cmd("touch root/email/reset_password.tt2", '__display__'); $content=<<'END'; <\\x21DOCTYPE html PUBLIC \\x22-//W3C//DTD XHTML 1.0 Transitional//EN\\x22 \\x22http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\x22> <html xmlns=\\x22http://www.w3.org/1999/xhtml\\x22 xml:lang=\\x22en\\x22 lang=\\x22en\\x22> <head> </head> <body> <h2 align=\\x22center\\x22>Your FullAuto API Management Dashboard Password has been Reset</h2> <p>Your username is: <span style=\\x22color: green;\\x22>[% username %]</span></p> <p>Your password is: <span style=\\x22color: red;\\x22>[% password %]</span></p> <p>You will be asked to change your password on first login.</p> </body> </html> END ($stdout,$stderr)=$handle->cmd("mkdir -vp root/user",'__display__'); ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/user/list.tt2"); ($stdout,$stderr)=$handle->cmd("touch root/user/list.tt2", '__display__'); $content=<<'END'; [% META title = 'FullAuto API: User Admin' %] <br /> <a class=\\x22button\\x22 href=\\x22[% c.uri_for('/user/add') %]\\x22 onclick='this.blur();'><span>Add User</span></a> <br /> Displaying users [% pager.first %]-[% pager.last %] of [% pager.total_entries %] <table> <tr> <th>Username</th> <th>Name</th> <th>Email Address</th> <th>Client ID</th> <th>Client Secret</th> </tr> [% WHILE (u = users.next) %] <tr> <td><a href=\\x22[% c.uri_for('/user', u.id, 'edit') %]\\x22>[% u.username %]</a></td> <td>[% u.name %]</td> <td>[% u.email_address %]</td> <td>[% u.client_id %]</td> <td>[% u.client_secret %]</td> <td><a href=\\x22[% c.uri_for('/user', u.id, 'reset_password') %]\\x22>Reset Password</a></td> <td><a href=\\x22[% c.uri_for('/user', u.id, 'inactivate') %]\\x22>Inactivate</a></td> </tr> [% END %] </table> << <a href=\\x22[% c.req.uri_with({ page => pager.first_page }) %]\\x22>First</a> <a href=\\x22[% c.req.uri_with({ page => pager.previous_page })%]\\x22>Previous</a> | <a href=\\x22[% c.req.uri_with({ page => pager.next_page })%]\\x22>Next</a> <a href=\\x22[% c.req.uri_with({ page => pager.last_page }) %]\\x22>Last</a> >> END ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/user/list.tt2"); ($stdout,$stderr)=$handle->cmd("touch root/user/add.tt2", '__display__'); $content=<<'ENDD'; [% META title = 'FullAuto API: Add User' %] <div> <form name=\\x22[% form.name %]\\x22 action=\\x22[% c.req.uri %]\\x22 method=\\x22post\\x22> [% FOR field IN form.error_fields %] [% FOR error IN field.errors %] <p><span style=\\x22color: red;\\x22>[% field.label _ ': ' _ error %]</span></p> [% END %] [% END %] <fieldset style=\\x22border: 0;\\x22> <table> <tr> [% f = form.field('username') %] <td><label for=\\x22[% f.name %]\\x22>[% f.label %]:</label></td> <td><input type=\\x22text\\x22 size=30 name=\\x22[% f.name %]\\x22 id=\\x22[% f.name %]\\x22 value=\\x22[% f.fif %]\\x22></td> </tr> [% PROCESS user/edit_details.tt2 %] <tr> <td><input type=\\x22submit\\x22 name=\\x22submit\\x22 id=\\x22submit\\x22 value=\\x22Add\\x22 /></td> <td><a href=\\x22/user/list\\x22>Users List</a></td> </tr> </fieldset> </table> </form> </div> ENDD ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/user/add.tt2"); ($stdout,$stderr)=$handle->cmd("touch root/user/change_password.tt2", '__display__'); $content=<<'ENDD'; [% META title = 'FullAuto API: Change Password' %] <div> <form name=\\x22[% form.name %]\\x22 action=\\x22[% c.req.uri %]\\x22 method=\\x22post\\x22> [% FOR field IN form.error_fields %] [% FOR error IN field.errors %] <p><span style=\\x22color: red;\\x22>[% field.label _ ': ' _ error %]</span></p> [% END %] [% END %] <fieldset style=\\x22border: 0;\\x22> <table> [% FOREACH field_name = ['current_password', 'new_password', 'new_password_conf'] %] <tr> [% f = form.field(field_name) %] <td><label for=\\x22[% f.name %]\\x22>[% f.label %]:</label></td> <td><input type=\\x22password\\x22 name=\\x22[% f.name %]\\x22 id=\\x22[% f.name %]\\x22 value=\\x22[% f.fif %]\\x22></td> </tr> [% END %] <tr><td><input type=\\x22submit\\x22 name=\\x22submit\\x22 value=\\x22Change\\x22 /></td></tr> </fieldset> </table> </form> </div> ENDD ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/user/change_password.tt2"); ($stdout,$stderr)=$handle->cmd("touch root/user/edit.tt2", '__display__'); $content=<<'ENDD'; [% META title = 'FullAuto API: Edit User' %] <div> <form name=\\x22[% form.name %]\\x22 action=\\x22[% c.req.uri %]\\x22 method=\\x22post\\x22> [% FOR field IN form.error_fields %] [% FOR error IN field.errors %] <p><span style=\\x22color: red;\\x22>[% field.label _ ': ' _ error %]</span></p> [% END %] [% END %] <fieldset style=\\x22border: 0;\\x22> <table> [% PROCESS user/edit_details.tt2 %] <tr> <td><input type=\\x22submit\\x22 name=\\x22submit\\x22 id=\\x22submit\\x22 value=\\x22Update\\x22 /></td> <td><a href=\\x22/user/list\\x22>Users List</a></td> </tr> </fieldset> </table> </form> </div> ENDD ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/user/edit.tt2"); ($stdout,$stderr)=$handle->cmd("touch root/user/edit_details.tt2", '__display__'); $content=<<'ENDD'; [% FOREACH field_name = ['name', 'email_address', 'phone_number', 'mail_address'] %] <tr> [% f = form.field(field_name) %] <td><label class=\\x22text.label\\x22 for=\\x22[% f.name %]\\x22>[% f.label %]:</label></td> <td><input class=\\x22text\\x22 type=\\x22text\\x22 size=30 name=\\x22[% f.name %]\\x22 id=\\x22[% f.name %]\\x22 value=\\x22[% f.fif %]\\x22></td> </tr> [% END %] <tr> [% f = form.field('roles') %] <td><label for=\\x22[% f.name %]\\x22>Roles:</label></td> <td>[% f.render %]</td> </tr> ENDD ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/user/edit_details.tt2"); ($stdout,$stderr)=$handle->cmd("touch root/user/profile.tt2", '__display__'); $content=<<'ENDD'; [% META title = 'MyApp: User Profile' %] <div> <form name=\\x22[% form.name %]\\x22 action=\\x22[% c.req.uri %]\\x22 method=\\x22post\\x22> [% FOR field IN form.error_fields %] [% FOR error IN field.errors %] <p><span style=\\x22color: red;\\x22>[% field.label _ ': ' _ error %]</span></p> [% END %] [% END %] <fieldset style=\\x22border: 0;\\x22> <table> [% FOREACH field_name = ['name', 'email_address', 'phone_number', 'mail_address'] %] <tr> [% f = form.field(field_name) %] <td><label for=\\x22[% f.name %]\\x22>[% f.label %]:</label></td> <td><input type=\\x22text\\x22 size=30 name=\\x22[% f.name %]\\x22 id=\\x22[% f.name %]\\x22 value=\\x22[% f.fif %]\\x22></td> </tr> [% END %] <tr><td><input type=\\x22submit\\x22 name=\\x22submit\\x22 id=\\x22submit\\x22 value=\\x22Update\\x22 /></td></tr> </fieldset> </table> </form> </div> ENDD ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > root/user/profile.tt2"); ($stdout,$stderr)=$handle->cmd('mkdir -vp db lib/FullAutoAPI/Schema', '__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'chmod -v 777 db'); ($stdout,$stderr)=$handle->cwd('db'); my $have_fadb=1; unless (-e 'fullautoapi.db') { $have_fadb=0; #($stdout,$stderr)=$handle->cmd($sudo. # "wget --random-wait --progress=dot ". # "http://dev.catalyst.perl.org/repos/Catalyst/trunk/". # "examples/RestYUI/db/adventrest.db", # '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/RestYUI/db/adventrest.db .", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username adventrest.db", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd($sudo.'mv adventrest.db fullautoapi.db'); } ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI'); my $db_sql="db.sql"; $content=<<'END'; DROP TABLE IF EXISTS users; DROP TABLE IF EXISTS roles; DROP TABLE IF EXISTS user_roles; DROP TABLE IF EXISTS client; DROP TABLE IF EXISTS owner; DROP TABLE IF EXISTS access_token_to_refresh_token; DROP TABLE IF EXISTS refresh_token; DROP TABLE IF EXISTS refresh_token_to_access_token; DROP TABLE IF EXISTS code; DROP TABLE IF EXISTS token; CREATE TABLE token ( id INTEGER PRIMARY KEY AUTOINCREMENT, code_id INTEGER NOT NULL, timestamp TEXT, FOREIGN KEY (code_id) REFERENCES code(id) ); CREATE TABLE code ( client_id INTEGER NOT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, is_active INTEGER NOT NULL DEFAULT 1, owner_id INTEGER, FOREIGN KEY (client_id) REFERENCES client(id), FOREIGN KEY (owner_id) REFERENCES owner(id) ); CREATE TABLE refresh_token_to_access_token ( access_token_id INTEGER NOT NULL UNIQUE, code_id INTEGER NOT NULL, refresh_token_id INTEGER NOT NULL UNIQUE, PRIMARY KEY (access_token_id, code_id, refresh_token_id), FOREIGN KEY (access_token_id) REFERENCES token(id), FOREIGN KEY (code_id) REFERENCES code(id), FOREIGN KEY (refresh_token_id) REFERENCES refresh_token(id) ); CREATE TABLE refresh_token ( id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE, code_id INTEGER NOT NULL, timestamp TEXT, FOREIGN KEY (code_id) REFERENCES code(id) ); CREATE TABLE access_token_to_refresh_token ( access_token_id INTEGER NOT NULL UNIQUE, code_id INTEGER NOT NULL, refresh_token_id INTEGER NOT NULL UNIQUE, PRIMARY KEY (access_token_id, code_id, refresh_token_id), FOREIGN KEY (access_token_id) REFERENCES token(id), FOREIGN KEY (code_id) REFERENCES code(id), FOREIGN KEY (refresh_token_id) REFERENCES refresh_token(id) ); CREATE TABLE owner ( id INTEGER PRIMARY KEY AUTOINCREMENT ); CREATE TABLE client ( id INTEGER PRIMARY KEY, endpoint TEXT NOT NULL, client_secret TEXT ); CREATE TABLE users ( id INTEGER PRIMARY KEY, active CHAR(1) NOT NULL, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, password_expires TIMESTAMP, name TEXT NOT NULL, email_address TEXT NOT NULL, phone_number TEXT, mail_address TEXT, client_id INTEGER, client_secret TEXT, FOREIGN KEY (client_id) REFERENCES client(id) ); CREATE TABLE roles ( id INTEGER PRIMARY KEY, name TEXT NOT NULL UNIQUE ); CREATE TABLE user_roles ( user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE, role_id INTEGER NOT NULL REFERENCES roles(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE, PRIMARY KEY (user_id, role_id) ); INSERT INTO users (username, active, name, email_address, password) VALUES ( 'admin', 'Y', 'Administrator', 'admin@fullauto.com', 'password' ); INSERT INTO roles (name) VALUES ('admin'); INSERT INTO roles (name) VALUES ('can_edit'); INSERT INTO user_roles (user_id, role_id) VALUES ( (SELECT id FROM users WHERE username = 'admin'), (SELECT id FROM roles WHERE name = 'admin') ); END #CREATE TABLE user ( # user_id TYPE text NOT NULL PRIMARY KEY, # fullname TYPE text NOT NULL, # description TYPE text NOT NULL #); #END ($stdout,$stderr)=$handle->cmd("touch $db_sql"); ($stdout,$stderr)=$handle->cmd("chmod -v 777 $db_sql",'__display__'); ($stdout,$stderr)=$handle->cmd("echo \"$content\" > $db_sql"); ($stdout,$stderr)=$handle->cmd("chmod -v 644 $db_sql",'__display__'); ($stdout,$stderr)=$handle->cmd('sqlite3 db/fullautoapi.db < db.sql') unless $have_fadb; ($stdout,$stderr)=$handle->cmd('chmod -v 777 db/fullautoapi.db', '__display__'); my $client_path="./lib/FullAutoAPI/Schema/Result/Client.pm"; ($stdout,$stderr)=$handle->cmd("./script/fullautoapi_create.pl ". "model DB DBIC::Schema FullAutoAPI::Schema create=static ". "components=TimeStamp,PassphraseColumn ". "moniker_map='{ users => \"Users\" }' ". "on_connect_do='PRAGMA foreign_keys=ON' quote_char='\"' ". "dbi:SQLite:db/fullautoapi.db", '__display__') unless $have_fadb; $ad="%NL%sub find_refresh {%NL%". " shift->codes->search( { is_active => 1 } )%NL%". " ->related_resultset(%SQ%refresh_tokens%SQ%)->find(\@_);%NL%". "}"; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/DO NOT MODIFY THIS/a$ad' $client_path"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "${sudo}sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ".$client_path); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i \"s/%SQ%/\'/g\" ". $client_path); my $refreshtoken_path="./lib/FullAutoAPI/Schema/Result/RefreshToken.pm"; $ad="%NL%".# this is a has many but will only ever return a single record%NL%". "# because of the constraint on the relationship table%NL%". "__PACKAGE__->has_many(%NL%". " from_access_token_map =>%NL%". " %SQ%FullAutoAPI::Schema::Result::AccessTokenToRefreshToken%SQ% => {%NL%". " %SQ%foreign.refresh_token_id%SQ% => %SQ%self.id%SQ%,%NL%". " %SQ%foreign.code_id%SQ% => %SQ%self.code_id%SQ%%NL%". " }%NL%". ");%NL%". "__PACKAGE__->many_to_many(%NL%". " from_access_token_map_m2m => from_access_token_map => %SQ%access_token%SQ% );%NL%". "%NL%". "# this is a has many but will only ever return a single record%NL%". "# because of the constraint on the relationship table%NL%". "__PACKAGE__->has_many(%NL%". " to_access_token_map =>%NL%". " %SQ%FullAutoAPI::Schema::Result::RefreshTokenToAccessToken%SQ% => {%NL%". " %SQ%foreign.refresh_token_id%SQ% => %SQ%self.id%SQ%,%NL%". " %SQ%foreign.code_id%SQ% => %SQ%self.code_id%SQ%%NL%". " }%NL%". ");%NL%". "__PACKAGE__->many_to_many(%NL%". " to_access_token_map_m2m => to_access_token_map => %SQ%access_token%SQ% );%NL%". "%NL%". "sub from_access_token { shift->from_access_token_map_m2m->first }%NL%". "sub to_access_token { shift->to_access_token_map_m2m->first }%NL%". "%NL%". "sub create_access_token {%NL%". " my (\$self) = \@_;%NL%". " my \$code = \$self->code;%NL%". " my \$token;%NL%". " \$self->result_source->storage->txn_do(%NL%". " sub {%NL%". " # create a new token from this refresh token%NL%". " \$token = \$code->tokens->create(%NL%". " { from_refresh_token_map => [ { refresh_token => \$self } ] } );%NL%". "%NL%". " # create a new refresh token and add it to the new token%NL%". " my \$refresh = \$code->refresh_tokens->create( {} );%NL%". " \$token->to_refresh_token_map->create(%NL%". " { code => \$code, refresh_token => \$refresh } );%NL%". " }%NL%". " );%NL%". " return \$token;%NL%". "}%NL%". "%NL%". "# if we have already created a token from this refresh, de-activate it". "%NL%%NL%". "sub is_active { !shift->to_access_token_map->count }%NL%". "%NL%". "sub as_string { shift->id }"; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/DO NOT MODIFY THIS/a$ad' $refreshtoken_path"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "${sudo}sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ".$refreshtoken_path); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i \"s/%SQ%/\'/g\" ". $refreshtoken_path); $refreshtoken_path= "./lib/FullAutoAPI/Schema/Result/RefreshTokenToAccessToken.pm"; ($stdout,$stderr)=$handle->cmd("${sudo}sed -i ". "\'s/\> \"refresh_token_id\" \}/\> \"refresh_token_id\"/\' ". $refreshtoken_path); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i ". "\'s/\> \"access_token_id\" \}/\> \"access_token_id\"/\' ". $refreshtoken_path); $ad=" code_id => \"code_id\" },"; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/\> \"refresh_token_id\",/a$ad' $refreshtoken_path"); ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/\> \"access_token_id\",/a$ad' $refreshtoken_path"); $handle->cmd_raw( "${sudo}sed -i 's/\\(^code_id.*\\\)/ \\1/' $refreshtoken_path"); $refreshtoken_path= "./lib/FullAutoAPI/Schema/Result/AccessTokenToRefreshToken.pm"; ($stdout,$stderr)=$handle->cmd("${sudo}sed -i ". "\'s/\> \"refresh_token_id\" \}/\> \"refresh_token_id\"/\' ". $refreshtoken_path); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i ". "\'s/\> \"access_token_id\" \}/\> \"access_token_id\"/\' ". $refreshtoken_path); $ad=" code_id => \"code_id\" },"; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/\> \"refresh_token_id\",/a$ad' $refreshtoken_path"); ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/\> \"access_token_id\",/a$ad' $refreshtoken_path"); $handle->cmd_raw( "${sudo}sed -i 's/\\(^code_id.*\\\)/ \\1/' $refreshtoken_path"); my $code_path="./lib/FullAutoAPI/Schema/Result/Code.pm"; $ad="%NL%sub as_string { shift->id }%NL%". "%NL%". "sub activate {%NL%". " my(\$self, \$owner_id) = \@_;%NL%". " \$self->update( { is_active => 1, owner_id => \$owner_id } )%NL%". "}"; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/DO NOT MODIFY THIS/a$ad' $code_path"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "${sudo}sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ".$code_path); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i \"s/%SQ%/\'/g\" ". $code_path); my $token_path="./lib/FullAutoAPI/Schema/Result/Token.pm"; $ad="# this is a has many but will only ever return a single record%NL%". "# because of the constraint on the relationship table%NL%". "__PACKAGE__->has_many(%NL%". " from_refresh_token_map =>%NL%". " %SQ%FullAutoAPI::Schema::Result::RefreshTokenToAccessToken%SQ% => {%NL%". " %SQ%foreign.access_token_id%SQ% => %SQ%self.id%SQ%,%NL%". " %SQ%foreign.code_id%SQ% => %SQ%self.code_id%SQ%%NL%". " }%NL%". ");%NL%". "__PACKAGE__->many_to_many(%NL%". " from_refresh_token_map_m2m => from_refresh_token_map => %SQ%refresh_token%SQ% );%NL%". "%NL%". "# this is a has many but will only ever return a single record%NL%". "# because of the constraint on the relationship table%NL%". "__PACKAGE__->has_many(%NL%". " to_refresh_token_map =>%NL%". " %SQ%FullAutoAPI::Schema::Result::AccessTokenToRefreshToken%SQ% => {%NL%". " %SQ%foreign.access_token_id%SQ% => %SQ%self.id%SQ%,%NL%". " %SQ%foreign.code_id%SQ% => %SQ%self.code_id%SQ%%NL%". " }%NL%". ");%NL%". "__PACKAGE__->many_to_many(%NL%". " to_refresh_token_map_m2m => to_refresh_token_map => %SQ%refresh_token%SQ% );%NL%". "%NL%". "sub from_refresh_token { shift->from_refresh_token_map_m2m->first }%NL%". "sub to_refresh_token { shift->to_refresh_token_map_m2m->first }%NL%". "%NL%". "sub as_string { shift->id }%NL%". "sub type {%SQ%bearer%SQ%}%NL%". "sub expires_in {3600}%NL%". "sub owner { shift->code->owner }"; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/DO NOT MODIFY THIS/a$ad' $token_path"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "${sudo}sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ".$token_path); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i \"s/%SQ%/\'/g\" ". $token_path); $content=<<ENDD; package FullAutoAPI::Schema::ResultSet::Client; use parent 'DBIx::Class::ResultSet'; sub find_refresh { shift->related_resultset('codes')->search( { is_active => 1 } ) ->related_resultset('refresh_tokens')->find(\@_); } 1; __END__ =pod =head1 NAME FUllAutoAPI::Schema::ResultSet::Client =head1 VERSION version 0.001004 =head1 AUTHOR Eden Cardim <edencardim\@gmail.com> =head1 COPYRIGHT AND LICENSE This software is copyright (c) 2015 by Suretec Systems Ltd. This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. =cut ENDD my $resultset_path="./lib/FullAutoAPI/Schema/ResultSet/Client.pm"; ($stdout,$stderr)=$handle->cmd( "mkdir -vp ./lib/FullAutoAPI/Schema/ResultSet",'__display__'); ($stdout,$stderr)=$handle->cmd("touch $resultset_path"); ($stdout,$stderr)=$handle->cmd( $sudo."chmod -v 777 $resultset_path",'__display__'); ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > $resultset_path"); my $user_path="./lib/FullAutoAPI/Schema/Result/Users.pm"; $ad="%NL%__PACKAGE__->add_columns(%NL%". " %SQ%+password%SQ% => {%NL%". " passphrase => %SQ%rfc2307%SQ%,%NL%". " passphrase_class => %SQ%BlowfishCrypt%SQ%,%NL%". " passphrase_args => {%NL%". " cost => 14,%NL%". " salt_random => 20,%NL%". " },%NL%". " passphrase_check_method => %SQ%check_password%SQ%,%NL%". " }%NL%". ");"; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/DO NOT MODIFY THIS/a$ad' $user_path"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "${sudo}sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" $user_path"); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i \"s/%SQ%/\'/g\" $user_path"); ($stdout,$stderr)=$handle->cmd("./script/fullautoapi_create.pl ". "controller OAuth2::Provider",'__display__'); ($stdout,$stderr)=$handle->cwd('deps'); ($stdout,$stderr)=$handle->cmd($sudo."wget -qO- http://libevent.org/"); $stdout=~/^.*Stable releases.*?href=["](.*?)["].*?href=["](.*?)["].*$/s; my $le_rel=$1;my $le_asc=$2; ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ".$le_rel,'__display__'); $le_rel=~s/^.*\/(.*)$/$1/; $le_asc=~s/^.*\/(.*)$/$1/; ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username $le_rel", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ".$le_asc,'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username $le_asc", '__display__') if $^O ne 'cygwin'; $le_rel=~s/^.*\/(.*.tar.gz)$/$1/; ($stdout,$stderr)=$handle->cmd("tar xvf $le_rel",'__display__'); $stdout=~s/^.*\n(.*)\/.*$/$1/s; ($stdout,$stderr)=$handle->cwd($stdout); ($stdout,$stderr)=$handle->cmd('./autogen.sh','__display__'); ($stdout,$stderr)=$handle->cmd('./configure',300,'__display__'); ($stdout,$stderr)=$handle->cmd('make','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'make install','__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/deps'); ($stdout,$stderr)=$handle->cmd($sudo."wget -qO- http://memcached.org/"); print $stderr if $stderr; $stdout=~/^.*?Tar.Gz Download.*?href=["](.*?)["].*$/s; my $mc_rel=$1; unless ($mc_rel) { ($stdout,$stderr)=$handle->cmd($sudo. "wget -qO- http://memcached.org/ -S --content-on-error", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot --no-check-certificate ". "https://github.com/memcached/memcached/archive/master.zip", '__display__'); ($stdout,$stderr)=$handle->cmd('unzip -o master.zip','__display__'); $mc_rel='memcached-master'; ($stdout,$stderr)=$handle->cwd($mc_rel); ($stdout,$stderr)=$handle->cmd('./autogen.sh','__display__'); #&exit_on_error("$stdout\n\n Output from http://memcached.org/"); } else { ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ".$mc_rel,'__display__'); $mc_rel=~s/^.*\/(.*.tar.gz)$/$1/; ($stdout,$stderr)=$handle->cmd("tar xvf $mc_rel",'__display__'); $stdout=~s/^.*\n(.*)\/.*$/$1/s; ($stdout,$stderr)=$handle->cwd($stdout); } ($stdout,$stderr)=$handle->cmd('./configure','__display__'); if ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd("sed -i 's/ -Werror//' Makefile"); ($stdout,$stderr)=$handle->cmd("sed -i ". "'s#struct sigaction a#// struct sigaction a#' testapp.c"); ($stdout,$stderr)=$handle->cmd("sed -i ". "'s#sigemptyset#// sigemptyset#' testapp.c"); ($stdout,$stderr)=$handle->cmd("sed -i ". "'s#sigaction(#// sigaction(#' testapp.c"); ($stdout,$stderr)=$handle->cmd("sed -i ". "'s#{ \"cache_redzone#// { \"cache_redzone#' testapp.c"); } ($stdout,$stderr)=$handle->cmd('make','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'make install','__display__'); unless ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cwd('scripts'); ($stdout,$stderr)=$handle->cmd($sudo. 'cp -v memcached.service /etc/systemd/system', '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'s#bin#local/bin#\' ". '/etc/systemd/system/memcached.service'); ($stdout,$stderr)=$handle->cmd($sudo. 'systemctl daemon-reload'); ($stdout,$stderr)=$handle->cmd($sudo. 'cp -v memcached.sysconfig /etc/sysconfig/memcached', '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "sed -i \'s/nobody/$username/\' /etc/sysconfig/memcached"); ($stdout,$stderr)=$handle->cmd($sudo. 'chmod -v 777 /var/run','__display__'); } ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI'); # # echo-ing/streaming files over ssh can be tricky. Use echo -e # and replace these characters with thier HEX # equivalents (use an external editor for quick # search and replace - and paste back results. # use copy/paste or cat file and copy/paste results.): # # ! - \\x21 ` - \\x60 # " - \\x22 \ - \\x5C # $ - \\x24 % - \\x25 # $content=<<'END'; #\\x21/usr/bin/env perl use strict; use warnings; use lib 'lib'; BEGIN { \\x24ENV{CATALYST_DEBUG} = 0 } use FullAutoAPI; use DateTime; my \\x24admin = FullAutoAPI->model('DB::Users')->search({ username => 'admin' }) ->single; \\x24admin->update({ password => 'admin', password_expires => DateTime->now }); END ($stdout,$stderr)=$handle->cmd($sudo.'touch script/set_admin_password.pl'); ($stdout,$stderr)=$handle->cmd($sudo. 'chmod -v 777 script/set_admin_password.pl', '__display__'); ($stdout,$stderr)=$handle->cmd( "echo -e \"$content\" > script/set_admin_password.pl"); my $pro_path="./lib/FullAutoAPI/Controller/OAuth2/Provider.pm"; ($stdout,$stderr)=$handle->cmd($sudo."sed -i ". "\"s/Catalyst::Controller/Catalyst::Controller::ActionRole/\" ". $pro_path); $ad="%NL%". "with %SQ%CatalystX::OAuth2::Controller::Role::Provider%SQ%;%NL%". "%NL%". "__PACKAGE__->config(%NL%". " store => {%NL%". " class => %SQ%DBIC%SQ%,%NL%". " client_model => %SQ%DB::Client%SQ%%NL%". " }%NL%". ");%NL%". "%NL%". "sub request : Chained(%SQ%/%SQ%) Args(0) ". "Does(%SQ%OAuth2::RequestAuth%SQ%) {%NL%". " my ( \$self, \$c ) = \@_;%NL%". "%NL%". " my \$oauth2 = \$c->req->oauth2;%NL%". "%NL%". " \$oauth2->{enable_client_secret}=0;%NL%". "}%NL%". "%NL%". "sub grant : Chained(%SQ%/%SQ%) Args(0) ". "Does(%SQ%OAuth2::GrantAuth%SQ%) {%NL%". " my ( \$self, \$c ) = \@_;%NL%". "%NL%". " my \$oauth2 = \$c->req->oauth2;%NL%". "%NL%". " \$c->user_exists and \$oauth2->user_is_valid(1)%NL%". " or \$c->detach(%SQ%/passthrulogin%SQ%);%NL%". "}%NL%". "%NL%". "sub token : Chained(%SQ%/%SQ%) Args(0) ". "Does(%SQ%OAuth2::AuthToken::ViaAuthGrant%SQ%) {%NL%". " my ( \$self, \$c ) = \@_;%NL%". "%NL%". " my \$oauth2 = \$c->req->oauth2;%NL%". "%NL%". " \$oauth2->{refresh_token}=1;%NL%". "}%NL%". "%NL%". "sub refresh : Chained(%SQ%/%SQ%) Args(0) ". "Does(%SQ%OAuth2::AuthToken::ViaRefreshToken%SQ%) {}%NL%"; ($stdout,$stderr)=$handle->cmd($sudo. "sed -i '/ActionRole/a$ad' $pro_path"); ($stdout,$stderr)=$handle->cmd( # bash shell specific $sudo."sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" $pro_path"); ($stdout,$stderr)=$handle->cmd($sudo."sed -i \"s/%SQ%/\'/g\" $pro_path"); $content=<<'END'; name: FullAutoAPI Model::DB: schema_class: FullAutoAPI::Schema connect_info: - DBI:SQLite:dbname=__path_to(db/fullautoapi.db)__ - \\x22\\x22 - \\x22\\x22 END ($stdout,$stderr)=$handle->cmd($sudo."touch fullautoapi.yml"); ($stdout,$stderr)=$handle->cmd($sudo."chmod -v 777 fullautoapi.yml", '__display__'); ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > fullautoapi.yml"); ($stdout,$stderr)=$handle->cmd($sudo."chmod -v 644 fullautoapi.yml", '__display__'); $content=<<'END'; <View::Email::Template>     <sender>         mailer Sendmail     </sender>     template_prefix email     <default>         content_type text/html         charset utf-8         view TT     </default> </View::Email::Template>  default_view TT END ($stdout,$stderr)=$handle->cmd($sudo.'chmod -v 777 fullautoapi.conf', '__display__'); ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" >> fullautoapi.conf"); ($stdout,$stderr)=$handle->cmd($sudo.'chmod -v 644 fullautoapi.conf', '__display__'); ($stdout,$stderr)=$handle->cmd( "./script/fullautoapi_create.pl controller User",'__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'rm -rvf lib/FullAutoAPI/Controller/User.pm', '__display__'); my $view_path='./lib/FullAutoAPI/View/TT.pm'; ($stdout,$stderr)=$handle->cmd( "./script/fullautoapi_create.pl view TT TT",'__display__'); ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i \'s/\.tt/\.tt2/\' $view_path"); $ad='WRAPPER => %SQ%wrapper.tt2%SQ%,'; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i \'/render_die/a$ad\' $view_path"); $handle->cmd_raw( "${sudo}sed -i 's/\\(^WRAPPER =.*\\\)/ \\1/' $view_path"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "${sudo}sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" $view_path"); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i \"s/%SQ%/\'/g\" $view_path"); ($stdout,$stderr)=$handle->cmd($sudo. 'mkdir -vp root/static/jquery','__display__'); ($stdout,$stderr)=$handle->cwd('root/static/jquery'); ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "https://code.jquery.com/ui/1.11.3/jquery-ui.js", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username jquery-ui.js", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "https://code.jquery.com/jquery-1.11.3.js", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username jquery-1.11.3.js", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/root'); # http://www.sitepoint.com/working-jquery-datatables/ ($stdout,$stderr)=$handle->cmd($sudo. "wget --random-wait --progress=dot ". "https://github.com/DataTables/DataTables/archive/master.zip", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username master.zip", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd('unzip -o master.zip','__display__'); ($stdout,$stderr)=$handle->cmd($sudo.'rm -rvf master.zip','__display__'); ($stdout,$stderr)=$handle->cwd('DataTables-master'); ($stdout,$stderr)=$handle->cmd('cp -Rv media ..','__display__'); ($stdout,$stderr)=$handle->cwd('examples'); ($stdout,$stderr)=$handle->cmd('cp -Rv resources ../..','__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI'); ($stdout,$stderr)=$handle->cmd("./script/fullautoapi_create.pl ". "view Email::Template Email::Template",'__display__'); # # echo-ing/streaming files over ssh can be tricky. Use echo -e # and replace these characters with thier HEX # equivalents (use an external editor for quick # search and replace - and paste back results. # use copy/paste or cat file and copy/paste results.): # # ! - \\x21 ` - \\x60 # " - \\x22 \ - \\x5C # $ - \\x24 % - \\x25 # $content=<<END; package FullAutoAPI::Controller::User; use strict; use warnings; use Moose; use DBI; use namespace::autoclean; use ZMQ::LibZMQ4; use ZMQ::Constants qw(:all); use JSON::XS; use YAML; use Carp::Assert; use Crypt::PassGen 'passgen'; use FullAutoAPI::Form::AddUser (); use FullAutoAPI::Form::EditUser (); use FullAutoAPI::Form::ChangePassword (); use FullAutoAPI::Form::UserProfile (); use Math::Random::ISAAC::XS; use Bytes::Random::Secure; use constant NBR_WORKERS => 2; use constant READY => \\x22\\x5C001\\x22; use constant FRONTEND_URL => \\x22ipc://${home_dir}FullAutoAPI/frontend.ipc\\x22; BEGIN { extends 'Catalyst::Controller::ActionRole' } with 'CatalystX::OAuth2::Controller::Role::WithStore'; BEGIN { extends 'Catalyst::Controller::REST' } BEGIN { if (\\x24^O eq 'cygwin') { if (-e 'script/first_time_start.flag') { unlink 'script/first_time_start.flag'; } else { my \\x24out=\\x60/bin/cygrunsrv -L\\x60; if (-1<index \\x24out,'nginx_first_time') { \\x60/bin/cygrunsrv -R nginx_first_time\\x60; } } } } __PACKAGE__->config( store => { class => 'DBIC', client_model => 'DB::Client' } ); __PACKAGE__->config( 'default' => 'application/json', 'map' => { 'text/html' => [ 'View', 'TT' ], 'text/xml' => [ 'View', 'TT' ], 'text/x-yaml' => 'YAML', 'application/json' => 'JSON', 'text/x-json' => 'JSON', 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ], 'text/x-data-denter' => [ 'Data::Serializer', 'Data::Denter' ], 'text/x-data-taxi' => [ 'Data::Serializer', 'Data::Taxi' ], 'application/x-storable' => [ 'Data::Serializer', 'Storable' ], 'application/x-freezethaw' => [ 'Data::Serializer', 'FreezeThaw' ], 'text/x-config-general' => [ 'Data::Serializer', 'Config::General' ], 'application/x-www-form-urlencoded' => 'JSON', }, ); sub cmd : Path('/cmd') : Args(0) : ActionClass('REST') { } sub cmd_POST : Chained('/') Args(0) Does('OAuth2::ProtectedResource') { my ( \\x24self, \\x24c ) = \@_; my \\x24auth = \\x24c->req->header('Authorization')||''; my ( \\x24type, \\x24token ) = split ' ', \\x24auth; my \\x24token_obj = \\x24self->store->verify_client_token(\\x24token); print \\x22EXPIRES_IN=\\x22,\\x24token_obj->expires_in,\\x22\\\\\\\\n\\x22; print \\x22TOKEN=\\x22,\\x24token,\\x22\\\\\\\\n\\x22; my \\x24cmd_data = ''; my \\x24cmd = ''; my \\x24file = ''; if ( \\x24c->req->data ) { print \\x22REQUEST DATA=\\x22,Data::Dump::Streamer::Dump(\\x24c->req->data)->Out(),\\x22\\\\\\\\n\\x22; \\x24cmd_data = \\x24c->req->data; unless (ref \\x24cmd_data->{'cmd'} eq 'ARRAY') { \\x24cmd_data->{'cmd'}=[ \\x24cmd_data->{'cmd'} ]; } \\x24cmd=encode_json \\x24cmd_data->{'cmd'}; } elsif ( \\x24c->req->uploads ) { print \\x22REQUEST UPLOADS=\\x22,Data::Dump::Streamer::Dump(\\x24c->req->uploads)->Out(),\\x22\\\\\\\\n\\x22; for my \\x24field ( \\x24c->req->upload ) { my \\x24upload = \\x24c->req->upload(\\x24field); \\x24cmd = encode_json [[ 'upload', \\x24upload->filename, \\x24upload->slurp() ]]; last; } } else { return \\x24self->status_bad_request(\\x24c, message => 'You must provide a cmd to execute\\x21' ); } my \\x24id = 'Client-'.\\x24\\x24; my \\x24ctx = zmq_init(); my \\x24socket = zmq_socket(\\x24ctx,ZMQ_REQ); my \\x24rv = zmq_setsockopt(\\x24socket,ZMQ_IDENTITY,\\x24id); assert(\\x24rv == 0, 'setting socket options'); \\x24rv = zmq_connect(\\x24socket,FRONTEND_URL()); assert(\\x24rv == 0,'connecting client ...'); print \\x22\\x24id sending cmd\\\\\\\\n\\x22; \\x24rv = zmq_msg_send(\\x24cmd,\\x24socket); my \\x24reply = zmq_recvmsg(\\x24socket); print \\x22\\x24id got a result -> \\x22,zmq_msg_data(\\x24reply),\\x22\\\\\\\\n\\x22; my \\x24return_entity = { result => zmq_msg_data(\\x24reply), }; \\x24self->status_ok( \\x24c, entity => \\x24return_entity, ); } sub base : Chained('/base') PathPrefix CaptureArgs(0) {} sub admin : Chained('base') PathPart('') CaptureArgs(0) Does('ACL') RequiresRole('admin') ACLDetachTo('denied') {} sub change_password : Chained('base') PathPart('change_password') Args(0) { my (\\x24self, \\x24c) = \@_; my \\x24form = FullAutoAPI::Form::ChangePassword->new; \\x24c->stash(form => \\x24form); return unless \\x24form->process( user => \\x24c->user, params => \\x24c->req->body_parameters, ); \\x24c->user->update({ password => \\x24form->field('new_password')->value, password_expires => undef, }); \\x24c->res->redirect(\\x24c->uri_for('/rest/demo', { status_msg => 'Password changed successfully' })); } sub profile : Chained('base') PathPart('profile') Args(0) { my (\\x24self, \\x24c) = \@_; my \\x24form = FullAutoAPI::Form::UserProfile->new; \\x24c->stash(form => \\x24form); return unless \\x24form->process( schema => \\x24c->model('DB')->schema, item_id => \\x24c->user->id, params => \\x24c->req->body_parameters, ); \\x24c->res->redirect(\\x24c->uri_for('/user', { status_msg => 'Profile Updated' })); } sub user_list : Path('/user') :Args(0) : ActionClass('REST') { } sub user_list_GET { my ( \\x24self, \\x24c ) = \@_; my \\x24draw = \\x24c->req->params->{draw} || 0; my \\x24start = \\x24c->req->params->{start} || 0; my \\x24per_page = \\x24c->req->params->{length} || 10; my \\x24page = 1; if (\\x24start<\\x24per_page) { \\x24page=1; } else { \\x24page=int(\\x24start/\\x24per_page)+1; } my \\x24id = 'Client-'.\\x24\\x24; my \\x24ctx = zmq_init(); my \\x24socket = zmq_socket(\\x24ctx,ZMQ_REQ); my \\x24rv = zmq_setsockopt(\\x24socket,ZMQ_IDENTITY,\\x24id); assert(\\x24rv == 0, 'setting socket options'); \\x24rv = zmq_connect(\\x24socket,FRONTEND_URL()); assert(\\x24rv == 0,'connecting client ...'); print \\x22\\x24id sending Hello\\\\\\\\n\\x22; \\x24rv = zmq_msg_send(encode_json(['Hello']),\\x24socket); my \\x24reply = zmq_recvmsg(\\x24socket); assert(\\x24reply); print \\x22\\x24id got a reply -> \\x22,zmq_msg_data(\\x24reply),\\x22\\\\\\\\n\\x22; # We'll use an array now: my \@user_list; my \\x24rs = \\x24c->model('DB::User') ->search(undef, { rows => \\x24per_page })->page( \\x24page ); while ( my \\x24user_row = \\x24rs->next ) { push \@user_list, { \\x24user_row->get_columns, uri => \\x24c->uri_for( '/user/' . \\x24user_row->user_id )->as_string }; } \\x24self->status_ok( \\x24c, entity => { draw => \\x24draw, recordsTotal => \\x24rs->pager->total_entries, recordsFiltered => \\x24rs->pager->total_entries, data => [ \@user_list ] }); }; sub single_user : Path('/user') : Args(1) : ActionClass('REST') { my ( \\x24self, \\x24c, \\x24user_id ) = \@_; \\x24c->stash->{'user'} = \\x24c->model('DB::User')->find(\\x24user_id); } sub single_user_POST { my ( \\x24self, \\x24c, \\x24user_id ) = \@_; my \\x24new_user_data = \\x24c->req->data; if ( \\x21defined(\\x24new_user_data) ) { return \\x24self->status_bad_request(\\x24c, message => 'You must provide a user to create or modify\\x21' ); } if ( \\x24new_user_data->{'user_id'} ne \\x24user_id ) { return \\x24self->status_bad_request( \\x24c, message => 'Cannot create or modify user ' . \\x24new_user_data->{'user_id'} . ' at ' . \\x24c->req->uri->as_string . '; the user_id does not match\\x21' ); } foreach my \\x24required (qw(user_id fullname description)) { return \\x24self->status_bad_request( \\x24c, message => 'Missing required field: ' . \\x24required ) if \\x21exists( \\x24new_user_data->{\\x24required} ); } my \\x24user = \\x24c->model('DB::User')->update_or_create( user_id => \\x24new_user_data->{'user_id'}, fullname => \\x24new_user_data->{'fullname'}, description => \\x24new_user_data->{'description'}, ); my \\x24return_entity = { user_id => \\x24user->user_id, fullname => \\x24user->fullname, description => \\x24user->description, }; if ( \\x24c->stash->{'user'} ) { \\x24self->status_ok( \\x24c, entity => \\x24return_entity, ); } else { \\x24self->status_created( \\x24c, location => \\x24c->req->uri->as_string, entity => \\x24return_entity, ); } } *single_user_PUT = *single_user_POST; sub single_user_GET { my ( \\x24self, \\x24c, \\x24user_id ) = \@_; my \\x24user = \\x24c->stash->{'user'}; if ( defined(\\x24user) ) { \\x24self->status_ok( \\x24c, entity => { user_id => \\x24user->user_id, fullname => \\x24user->fullname, description => \\x24user->description, } ); } else { \\x24self->status_not_found( \\x24c, message => 'Could not find User '.\\x24user_id.'\\x21' ); } } sub single_user_DELETE { my ( \\x24self, \\x24c, \\x24user_id ) = \@_; my \\x24user = \\x24c->stash->{'user'}; if ( defined(\\x24user) ) { \\x24user->delete; \\x24self->status_ok( \\x24c, entity => { user_id => \\x24user->user_id, fullname => \\x24user->fullname, description => \\x24user->description, } ); } else { \\x24self->status_not_found( \\x24c, message => 'Cannot delete non-existent user '.\\x24user_id.'\\x21' ); } } sub list : Chained('admin') PathPart('list') Args(0) { my (\\x24self, \\x24c) = \@_; my \\x24users = \\x24c->model('DB::Users')->search( { active => 'Y'}, { order_by => ['username'], page => (\\x24c->req->param('page') || 1), rows => 20, } ); \\x24c->stash( users => \\x24users, pager => \\x24users->pager, ); } sub add : Chained('admin') PathPart('add') Args(0) { my (\\x24self, \\x24c) = \@_; my \\x24form = FullAutoAPI::Form::AddUser->new; \\x24c->stash(form => \\x24form); my \\x24user = \\x24c->model('DB::Users')->new_result({}); my \\x24client = \\x24c->model('DB::Client')->new_result({}); my (\\x24temp_password) = passgen(NWORDS => 1, NLETT => 8); \\x24user->password(\\x24temp_password); \\x24user->password_expires(DateTime->now); \\x24user->active('Y'); return unless \\x24form->process( schema => \\x24c->model('DB')->schema, item => \\x24user, params => \\x24c->req->body_parameters, ); my \\x24client_id=\\x24user->id.time(); \\x24user->client_id(\\x24client_id); \\x24client->id(\\x24client_id); \\x24client->endpoint('/cmd'); my \\x24secret=Bytes::Random::Secure::random_bytes_base64(30); \\x24user->client_secret(\\x24secret); \\x24user->update; \\x24client->client_secret(\\x24secret); \\x24client->insert; \\x24c->stash->{email} = { to => \\x24user->email_address, from => 'admin\@MyOrg.com', subject => 'Welcome to the FullAuto API', content_type => 'text/html', template => 'email/welcome.tt2', }; \\x24c->stash( username => \\x24user->username, password => \\x24temp_password, client_id => \\x24client->id, client_secret => \\x24client->client_secret, ); \\x24c->forward(\\x24c->view('Email::Template')); \\x24c->res->redirect(\\x24c->uri_for(\\x24self->action_for('list'), { status_msg => 'User ' . \\x24user->username . ' created successfully' . ', initial password emailed ' . 'to ' . \\x24user->email_address })); } sub user : Chained('admin') PathPart('') CaptureArgs(1) { my (\\x24self, \\x24c, \\x24user_id) = \@_; \\x24c->stash(user => \\x24c->model('DB::Users')->find(\\x24user_id)); } sub inactivate : Chained('user') PathPart('inactivate') Args(0) { my (\\x24self, \\x24c) = \@_; my \\x24user = \\x24c->stash->{user}; \\x24user->update({ active => 'N' }); my \\x24username = \\x24user->username; \\x24c->res->redirect(\\x24c->uri_for(\\x24self->action_for('list'), { status_msg => \\x22User \\x24username inactivated\\x22 })); } sub reset_password : Chained('user') PathPart('reset_password') Args(0) { my (\\x24self, \\x24c) = \@_; my \\x24user = \\x24c->stash->{user}; my (\\x24temp_password) = passgen(NWORDS => 1, NLETT => 8); \\x24user->password(\\x24temp_password); \\x24user->password_expires(DateTime->now); \\x24user->update; \\x24c->stash->{email} = { to => \\x24user->email_address, from => 'admin\@MyOrg.com', subject => 'Your FullAuto API Management Dashboard Password has been Reset', content_type => 'text/html', template => 'reset_password.tt2', }; \\x24c->stash( username => \\x24user->username, password => \\x24temp_password, ); \\x24c->forward(\\x24c->view('Email::Template')); \\x24c->res->redirect(\\x24c->uri_for(\\x24self->action_for('list'), { status_msg => 'Password reset email for ' . \\x24user->username . ' sent to ' . \\x24user->email_address })); } sub edit : Chained('user') PathPart('edit') Args(0) { my (\\x24self, \\x24c) = \@_; my \\x24form = FullAutoAPI::Form::EditUser->new; \\x24c->stash(form => \\x24form); return unless \\x24form->process( schema => \\x24c->model('DB')->schema, item_id => \\x24c->stash->{user}->id, params => \\x24c->req->body_parameters, ); \\x24c->res->redirect(\\x24c->uri_for(\\x24self->action_for('list'), { status_msg => 'User ' . \\x24c->stash->{user}->username . ' updated successfully' })); } sub denied : Private { my (\\x24self, \\x24c) = \@_; \\x24c->res->redirect(\\x24c->uri_for('/rest/demo', { status_msg => \\x22Access Denied\\x22 })); } 1; END ($stdout,$stderr)=$handle->cwd('lib/FullAutoAPI/Controller'); ($stdout,$stderr)=$handle->cmd("touch User.pm"); ($stdout,$stderr)=$handle->cmd($sudo."chmod -v 777 User.pm",'__display__'); ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > User.pm"); $content=<<END; package FullAutoAPI::Controller::Rest; use Moose; use namespace::autoclean; BEGIN {extends 'Catalyst::Controller::ActionRole'; } sub base : Chained('/base') PathPrefix CaptureArgs(0) {} sub rest : Chained('base') PathPart('demo') Args(0) { my (\\x24self, \\x24c) = \@_; \\x24c->stash(template => 'rest/demo.tt2'); } sub denied : Private { my (\\x24self, \\x24c) = \@_; \\x24c->res->redirect(\\x24c->uri_for(\\x24self->action_for('rest'), {status_msg => \\x22Access Denied\\x22})); } __PACKAGE__->meta->make_immutable; 1; END ($stdout,$stderr)=$handle->cmd($sudo.'touch Rest.pm'); ($stdout,$stderr)=$handle->cmd($sudo."chmod -v 777 Rest.pm",'__display__'); ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > Rest.pm"); $ad='sub home : Chained(%SQ%/base%SQ%) PathPart(%SQ%%SQ%) Args(0) {'. '%NL% my ($self, $c) = @_;%NL%%NL%'. ' $c->res->redirect($c->uri_for(%SQ%/rest/demo%SQ%));%NL%'. '}%NL%%NL%'; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i \'/sub index :Path/i$ad\' ./Root.pm"); ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i '/index :Path :/,+6d' ./Root.pm"); ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i 's/index/home/' ./Root.pm"); $ad='%NL%sub base : Chained(%SQ%/login/required%SQ%) PathPrefix '. 'CaptureArgs(0) {%NL%'. ' my ($self, $c) = @_;%NL%'. '%NL%'. ' if ($c->action ne $c->controller(%SQ%User%SQ%)->action_for('. '%SQ%change_password%SQ%)%NL%'. ' && $c->user_exists%NL%'. ' && $c->user->password_expires%NL%'. ' && $c->user->password_expires <= DateTime->now)%NL%'. ' {%NL% '. '$c->res->redirect($c->uri_for(%SQ%/user/change_password%SQ%, {%NL%'. ' status_msg => %SQ%Password Expired%SQ%%NL%'. ' }));%NL%'. ' $c->detach;%NL%'. ' }%NL%'. '}%NL%'; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i \'/home : Chained/i$ad\' ./Root.pm"); ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i 's#default :Path#default : Chained(%SQ%/base%SQ%) ". "PathPart(%SQ%%SQ%) Args#' ./Root.pm"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "${sudo}sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ./Root.pm"); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i \"s/%SQ%/\'/g\" ./Root.pm"); ($stdout,$stderr)=$handle->cwd("~/FullAutoAPI/lib/FullAutoAPI"); ($stdout,$stderr)=$handle->cmd("mkdir -vp Form"); ($stdout,$stderr)=$handle->cwd("Form"); $content=<<END; package FullAutoAPI::Form::AddUser; use HTML::FormHandler::Moose; extends 'FullAutoAPI::Form::EditUser'; use namespace::autoclean; has_field 'username' => ( type => 'Text', label => 'User name', required => 1, ); __PACKAGE__->meta->make_immutable; 1; END ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > AddUser.pm"); $content=<<END; package FullAutoAPI::Form::ChangePassword; use HTML::FormHandler::Moose; extends 'HTML::FormHandler'; use namespace::autoclean; use Method::Signatures::Simple; has user => (is => 'rw'); has_field 'current_password' => ( type => 'Password', label => 'Current Password', required => 1, ); method validate_current_password(\\x24field) { \\x24field->add_error('Incorrect password') if not \\x24self->user->check_password(\\x24field->value); } has_field 'new_password' => ( type => 'Password', label => 'New Password', required => 1, minlength => 5, ); after validate => method { if (\\x24self->field('new_password')->value eq \\x24self->field('current_password')->value ) { \\x24self->field('new_password') ->add_error('Must be different from current password'); } }; has_field 'new_password_conf' => ( type => 'PasswordConf', label => 'New Password (again)', password_field => 'new_password', required => 1, minlength => 5, ); has_field submit => (type => 'Submit', value => 'Change'); __PACKAGE__->meta->make_immutable; 1; END ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > ChangePassword.pm"); $content=<<END; package FullAutoAPI::Form::EditUser; use HTML::FormHandler::Moose; extends 'FullAutoAPI::Form::UserProfile'; use namespace::autoclean; has_field 'roles' => ( type => 'Multiple', widget => 'checkbox_group', label_column => 'name', label => '', ); __PACKAGE__->meta->make_immutable; 1; END ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > EditUser.pm"); $content=<<END; package FullAutoAPI::Form::UserProfile; use HTML::FormHandler::Moose; extends 'HTML::FormHandler::Model::DBIC'; use namespace::autoclean; has '+item_class' => (default => 'Users'); has_field 'name' => ( type => 'Text', required => 1 ); has_field 'email_address' => ( type => 'Email', required => 1 ); has_field 'phone_number' => ( type => 'Text' ); has_field 'mail_address' => ( type => 'Text' ); has_field submit => ( type => 'Submit', value => 'Update' ); __PACKAGE__->meta->make_immutable; 1; END ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > UserProfile.pm"); ($stdout,$stderr)=$handle->cmd($sudo."chmod -v 644 UserProfile.pm", '__display__'); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/root/static'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/RestYUI/root/static/json2.js .", '__display__'); #($stdout,$stderr)=$handle->cmd($sudo. # "wget --random-wait --progress=dot ". # "http://dev.catalyst.perl.org/repos/Catalyst/trunk/". # "examples/RestYUI/root/static/json2.js", # '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username json2.js", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd('mkdir -vp yui','__display__'); ($stdout,$stderr)=$handle->cwd('yui'); my @yuifiles=('utilities.js','dom.js','connection.js','event.js', 'yahoo.js'); foreach my $file (@yuifiles) { ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/RestYUI/root/static/yui/$file .", '__display__'); #($stdout,$stderr)=$handle->cmd($sudo. # "wget --random-wait --progress=dot ". # "http://dev.catalyst.perl.org/repos/Catalyst/trunk/". # "examples/RestYUI/root/static/yui/$file", # '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username $file", '__display__') if $^O ne 'cygwin'; } ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/root'); ($stdout,$stderr)=$handle->cmd('mkdir -vp user','__display__'); ($stdout,$stderr)=$handle->cwd('user'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/RestYUI/root/user/single_user.tt .", '__display__'); #($stdout,$stderr)=$handle->cmd($sudo. # "wget --random-wait --progress=dot ". # "http://dev.catalyst.perl.org/repos/Catalyst/trunk/". # "examples/RestYUI/root/user/single_user.tt", # '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "chown -v $username:$username single_user.tt", '__display__') if $^O ne 'cygwin'; ($stdout,$stderr)=$handle->cmd( "sed -i 's/POSTT/POST/' single_user.tt"); ($stdout,$stderr)=$handle->cmd( "mv single_user.tt single_user.tt2"); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI/root'); ($stdout,$stderr)=$handle->cmd($sudo.'rm -rvf rest'); ($stdout,$stderr)=$handle->cmd('mkdir -vp rest','__display__'); ($stdout,$stderr)=$handle->cwd('rest'); # # echo-ing/streaming files over ssh can be tricky. Use echo -e # and replace these characters with thier HEX # equivalents (use an external editor for quick # search and replace - and paste back results. # use copy/paste or cat file and copy/paste results.): # # ! - \\x21 ` - \\x60 # " - \\x22 \ - \\x5C # $ - \\x24 % - \\x25 # $content=<<END; <\\x21DOCTYPE html> <html> <head> <meta charset=\\x22utf-8\\x22> <meta name=\\x22viewport\\x22 content=\\x22initial-scale=1.0, maximum-scale=2.0\\x22> <title>Catalyst REST Example</title> <link rel=\\x22stylesheet\\x22 type=\\x22text/css\\x22 href=\\x22https://cdn.datatables.net/1.10.8/css/jquery.dataTables.min.css\\x22> <link rel=\\x22stylesheet\\x22 type=\\x22text/css\\x22 href=\\x22resources/demo.css\\x22></script> <script type=\\x22text/javascript\\x22 language=\\x22javascript\\x22 src=\\x22//code.jquery.com/jquery-1.11.3.min.js\\x22></script> <script type=\\x22text/javascript\\x22 language=\\x22javascript\\x22 src=\\x22https://cdn.datatables.net/1.10.8/js/jquery.dataTables.min.js\\x22></script> <script type=\\x22text/javascript\\x22 language=\\x22javascript\\x22 class=\\x22init\\x22> \\x24(document).ready(function() { \\x24(\\x22#example\\x22).dataTable({ \\x22processing\\x22: true, \\x22serverSide\\x22: true, \\x22ajax\\x22: \\x22[%c.uri_for( c.controller('User').action_for('user_list') ) %]?page=1&content-type=application/json\\x22, \\x22aoColumns\\x22: [{ \\x22mData\\x22:\\x22user_id\\x22, },{ \\x22mData\\x22: \\x22fullname\\x22, },{ \\x22mData\\x22: \\x22description\\x22, }] }); } ); </script> </head> <body class=\\x22dt-example\\x22> <div class=\\x22container\\x22> <section> <h1>Catalyst REST Example <span>Using JQuery DataTable</span></h1> <div class=\\x22info\\x22> <p>FullAuto was used to stand up this fully functional Catalyst REST installation. The following table is full of demo user data. To add or update a user, manually modify the browser URL like so: <br><br><code>[%c.uri_for( c.controller('User').action_for('user_list') ) %]/user_id</code></p> <p>Data can be accessed on the command line: <br><br><code>curl -X GET -k -H 'Content-Type: application/json' [%c.uri_for( c.controller('User').action_for('user_list') ) %]</code> <br><br><code> curl -X GET -k \\x22[% c.req.base %]request?client_id=<client_id>&response_type=code&redirect_uri=/cmd\\x22 </code><br><br><code> curl -X GET -k \\x22[% c.req.base %]/token?grant_type=authorization_code&client_id=<client_id>&redirect_uri=/cmd&code=<code>\\x22 </code><br><br><code> curl -X POST -k -H 'Authorization: Bearer <token>' -H 'Content-Type: application/json' -d '{\\x22cmd\\x22:\\x22hostname\\x22}' [% c.req.base %]cmd </code></p> </div> <table id=\\x22example\\x22 class=\\x22display\\x22 cellspacing=\\x220\\x22 width=\\x22100%\\x22> <thead> <tr> <th>ID</th> <th>Full Name</th> <th>Description</tn> </tr> </thead> <tfoot> <tr> <th>ID</th> <th>Full Name</th> <th>Description</th> </tr> </tfoot> </table> </div> </section> </div> </body> </html> END ($stdout,$stderr)=$handle->cmd("echo -e \"$content\" > demo.tt2"); ($stdout,$stderr)=$handle->cwd('~/FullAutoAPI'); $ad="use Net::FullAuto;%NL%". "use Net::FullAuto::Cloud::fa_amazon;%NL%". "use ZMQ::LibZMQ4;%NL%". "use ZMQ::Constants qw(:all);%NL%". "use JSON::XS;%NL%". "use YAML;%NL%". "use Carp::Assert;%NL%". "use Crypt::PassGen %SQ%passgen%SQ%;%NL%". "use Math::Random::ISAAC::XS;%NL%". "use Bytes::Random::Secure;%NL%%NL%". "use constant NBR_WORKERS => 2;%NL%". "use constant READY => \"\\\\001\";%NL%". "%NL%". "use constant BACKEND_URL =>%NL%". " %SQ%ipc://${home_dir}FullAutoAPI/backend.ipc%SQ%;%NL%". "use constant FRONTEND_URL =>%NL%". " %SQ%ipc://${home_dir}FullAutoAPI/frontend.ipc%SQ%;%NL%". "%NL%". "use Parallel::Forker;%NL%". "%NL%". "my \$fa_sub=sub {%NL%". "%NL%". " # A bit of custom config riding/hacking to use the application". "%SQ%s%NL%". " # config for the DB.%NL%". " my \$config_file = %SQ%${home_dir}FullAutoAPI/fullautoapi.yml". "%SQ%;%NL%". " my \$config_data = YAML::LoadFile( \$config_file );%NL%". " #my \$args = \$config_data->{\"Model::ZeroMQ\"}->{args};%NL%". "%NL%". " my \$id = %SQ%Worker-%SQ%.\$\$;%NL%%NL%". " my \$ctx = zmq_init();%NL%". " my \$socket = zmq_socket(\$ctx,ZMQ_REQ);%NL%%NL%". " my \$rv = zmq_setsockopt(\$socket,ZMQ_IDENTITY,\$id);%NL%". " assert(\$rv == 0);%NL%%NL%". " \$rv = zmq_connect(\$socket,BACKEND_URL());%NL%". " assert(\$rv == 0,%SQ%connecting to backend%SQ%);%NL%%NL%". " print \"\$id sending READY\\n\";%NL%". "%NL%". " \$rv = zmq_msg_send(READY(),\$socket);%NL%". " assert(\$rv);%NL%". "%NL%". " my \$buf = zmq_msg_init();%NL%". "%NL%". " my (\$fullauto,\$stdout,\$stderr,\$exitcode,". "\$connect_error)=(%SQ%%SQ%,%SQ%%SQ%,%SQ%%SQ%,%SQ%%SQ%,%SQ%%SQ%);%NL%". " (\$fullauto,\$connect_error)=connect_shell();%NL%". "%NL%". " use Time::HiRes;%NL%". " # http://www.unitconversion.org/unit_converter/time-ex.html%NL%". " my \$msg = zmq_msg_init();%NL%". " my \$handles={};%NL%". " while (1) {%NL%". "%NL%". " my \@msg=();%NL%". " if (zmq_msg_recv(\$buf,\$socket,ZMQ_DONTWAIT)) {%NL%". " push \@msg, zmq_msg_data(\$buf);%NL%". " while (zmq_getsockopt(\$socket,ZMQ_RCVMORE)) {%NL%". " zmq_msg_recv(\$buf,\$socket);%NL%". " push \@msg, zmq_msg_data(\$buf);%NL%". " }%NL%". " }%NL%". " if (getppid==1) {%NL%". " `pgrep -P \$\$ | xargs kill -TERM`;%NL%". " exit;%NL%". " }%NL%". " if (\$#msg) {%NL%". " print \"\$id got: \$msg[2] from \$msg[0]\\n\";%NL%". " print \"\$id sending OK to \$msg[0]\\n\";%NL%". " zmq_msg_send(\$msg[0],\$socket,ZMQ_SNDMORE);%NL%". " zmq_msg_send(%SQ%%SQ%,\$socket,ZMQ_SNDMORE);%NL%". " my \$cmds=decode_json \$msg[2];%NL%". " if (\$cmds->[0] eq %SQ%Hello%SQ%) {%NL%". " zmq_msg_send(encode_json([%SQ%Hello Back%SQ%]),%NL%". " \$socket);%NL%". " next;%NL%". " }%NL%". " \$cmds=[\$cmds] unless ref \$cmds eq %SQ%ARRAY%SQ%;%NL%". " my \$out=[];%NL%". " foreach my \$cmd (\@{\$cmds}) {%NL%". " if (ref \$cmd eq %SQ%ARRAY%SQ%) {%NL%". " if (\$cmd->[0] eq %SQ%cmd%SQ%) {%NL%". " (\$stdout,\$stderr)=\$fullauto->cmd(%NL%". " \$cmd->[1],%SQ%__display__%SQ%);%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " } elsif (\$cmd->[0] eq %SQ%cmd_raw%SQ%) {%NL%". " (\$stdout,\$stderr)=\$fullauto->cmd_raw(%NL%". " \$cmd->[1]);%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " } elsif (\$cmd->[0] eq %SQ%cwd%SQ%) {%NL%". " (\$stdout,\$stderr)=\$fullauto->cwd(%NL%". " \$cmd->[1]);%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " } elsif (\$cmd->[0] eq %SQ%aws_configure%SQ%) {%NL%". " my \$key=\$cmd->[1];%NL%". " my \$secret=\$cmd->[2];%NL%". " \$aws_configure->(\$key,\$secret);%NL%". " } elsif (\$cmd->[0] eq %SQ%upload%SQ%) {%NL%". " open(FH,\">/tmp/\$cmd->[1]\") || warn \$!;%NL%". " print FH \$cmd->[2];%NL%". " close FH;%NL%". " } elsif (\$cmd->[0] eq %SQ%label%SQ%) {%NL%". " print \"LABEL=\".\$cmd->[1]->[0];%NL%". " if (exists \$handles->{\$cmd->[1]->[0]}) {%NL%". " if (\$cmd->[1]->[1] eq %SQ%cmd%SQ%) {%NL%". " (\$stdout,\$stderr)=\$handles->{%NL%". " \$cmd->[1]->[0]}->cmd(%NL%". " \$cmd->[1]->[2]);%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " } elsif (\$cmd->[1]->[0] eq %SQ%close%SQ%) {%NL%". " (\$stdout,\$stderr)=\$handles->{%NL%". " \$cmd->[1]->[0]}->close();%NL%". " delete \$handles->{\$cmd->[1]->[0]};%NL%". " \$stdout=\"\$cmd->[1]->[0] CLOSED\";%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " } elsif (\$cmd->[1]->[1] eq 'docker_run') {%NL%". " (\$stdout,\$stderr)=\$handles->{%NL%". " \$cmd->[1]->[0]}->docker_run(%NL%". " \$cmd->[1]->[2]);%NL%". " (\$stdout,\$stderr)=\$handles->{%NL%". " \$cmd->[1]->[0]}->cmd(%NL%". " %SQ%hostname%SQ%);%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " } elsif (\$cmd->[1]->[1] eq %NL%". " %SQ%docker_attach%SQ%) {%NL%". " (\$stdout,\$stderr)=\$handles->{%NL%". " \$cmd->[1]->[0]}->docker_attach(%NL%". " \$cmd->[1]->[2]);%NL%". " (\$stdout,\$stderr)=\$handles->{%NL%". " \$cmd->[1]->[0]}->cmd(%NL%". " %SQ%hostname%SQ%);%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " } elsif (\$cmd->[1]->[1] eq%NL%". " %SQ%docker_exit%SQ%) {%NL%". " (\$stdout,\$stderr)=\$handles->{%NL%". " \$cmd->[1]->[0]}->docker_exit();%NL%". " (\$stdout,\$stderr)=\$handles->{%NL%". " \$cmd->[1]->[0]}->cmd(%NL%". " %SQ%hostname%SQ%);%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " }%NL%". " }%NL%". " } elsif (\$cmd->[0] eq %SQ%connect_secure%SQ%) {%NL%". " my \$identityfile=\$cmd->[1]->{%NL%". " %SQ%identityfile%SQ%};%NL%". " my \$pwd=`pwd`;%NL%". " chomp(\$pwd);%NL%". " \$identityfile=\$pwd.%SQ%/%SQ%.\$identityfile if%NL%". " -1==index(\$identityfile,%SQ%/%SQ%);%NL%". " my (\$connect_label) = passgen(NWORDS => 1,%NL%". " NLETT => 8);%NL%". " my \$server={%NL%". " Label => \$connect_label,%NL%". " IP => \$cmd->[1]->{%SQ%ip%SQ%},%NL%". " Login => \$cmd->[1]->{%SQ%login%SQ%},%NL%". " IdentityFile => \$identityfile,%NL%". " NoRetry => \$cmd->[1]->{%SQ%noretry%SQ%}||". "%SQ%%SQ%,%NL%". " debug => \$cmd->[1]->{%SQ%debug%SQ%}||0%NL%". " };%NL%". " my \$error=%SQ%%SQ%;my \$stdout=%SQ%%SQ%;%NL%". " my \$stderr=%SQ%%SQ%;%NL%". " (\$handles->{\$connect_label},\$error)=%NL%". " connect_ssh(\$server);%NL%". " if (\$error) {%NL%". " \$stdout=%SQ%%SQ%;%NL%". " \$stderr=\$error;%NL%". " } else {%NL%". " \$stdout=\$connect_label%NL%". " }%NL%". " push \@{\$out},[\$stdout,\$stderr];%NL%". " }%NL%". " } else {%NL%". " (\$stdout,\$stderr)=\$fullauto->cmd(\$cmd);%NL%". " push \@{\$out},[\$stdout,\$stderr]%NL%". " }%NL%". " }%NL%". " \$stdout=encode_json \$out;%NL%". " zmq_msg_send(\$stdout,\$socket);%NL%". " }%NL%". " Time::HiRes::sleep (.0001);%NL%". "%NL%". " }%NL%". "};%NL%". "%NL%". "my \$zeromq_broker=sub {%NL%". "%NL%". " print \"LOADING BROKER\\n\";%NL%". "%NL%". " my \$ctx = zmq_init();%NL%". " my \$frontend = zmq_socket(\$ctx, ZMQ_ROUTER);%NL%". " my \$backend = zmq_socket(\$ctx, ZMQ_ROUTER);%NL%". "%NL%". " my \$rv = zmq_bind(\$frontend,FRONTEND_URL());%NL%". " assert(\$rv == 0);%NL%". "%NL%". " \$rv = zmq_bind(\$backend,BACKEND_URL());%NL%". " assert(\$rv == 0);%NL%". "%NL%". " my \@workers;%NL%". "%NL%". " my (\$w_addr,\$delim,\$c_addr,\$data);%NL%". " my \$items = [%NL%". "%NL%". " {%NL%". " events => ZMQ_POLLIN,%NL%". " socket => \$frontend,%NL%". " callback => sub {%NL%". "%NL%". " if (-1<\$#workers) {%NL%". "%NL%". " print \"frontend…\\n\";%NL%". "%NL%". " my \$buf = zmq_msg_init();%NL%". " my \@msg=();%NL%". " if (zmq_msg_recv(\$buf,\$frontend)) {%NL%". " push \@msg, zmq_msg_data(\$buf);%NL%". " while (zmq_getsockopt(\$frontend,ZMQ_RCVMORE)) {%NL%". " zmq_msg_recv(\$buf,\$frontend);%NL%". " push \@msg, zmq_msg_data(\$buf);%NL%". " }%NL%". " }%NL%". "%NL%". " assert(\$#msg);%NL%". "%NL%". " assert(\$#workers < NBR_WORKERS());%NL%". "%NL%". " zmq_msg_send(pop(\@workers),\$backend,ZMQ_SNDMORE);%NL%". " zmq_msg_send(%SQ%%SQ%,\$backend,ZMQ_SNDMORE);%NL%". " zmq_msg_send(\$msg[0],\$backend,ZMQ_SNDMORE);%NL%". " zmq_msg_send(%SQ%%SQ%,\$backend,ZMQ_SNDMORE);%NL%". " zmq_msg_send(\$msg[2],\$backend,);%NL%". "%NL%". " }%NL%". " },%NL%". " },%NL%". " {%NL%". " events => ZMQ_POLLIN,%NL%". " socket => \$backend,%NL%". " callback => sub {%NL%". "%NL%". " print \"backend…\\n\";%NL%". "%NL%". " my \$buf = zmq_msg_init();%NL%". " my \@msg=();%NL%". " if (zmq_msg_recv(\$buf,\$backend)) {%NL%". " push \@msg, zmq_msg_data(\$buf);%NL%". " while (zmq_getsockopt(\$backend,ZMQ_RCVMORE)) {%NL%". " zmq_msg_recv(\$buf,\$backend);%NL%". " push \@msg, zmq_msg_data(\$buf);%NL%". " }%NL%". " }%NL%". "%NL%". " assert(\$#msg);%NL%". "%NL%". " \$w_addr = \$msg[0];%NL%". " push(\@workers,\$w_addr);%NL%". "%NL%". " \$delim = \$msg[1];%NL%". " assert(\$delim eq %SQ%%SQ%);%NL%". "%NL%". " \$c_addr = \$msg[2];%NL%". "%NL%". " if(\$c_addr ne READY()){%NL%". " \$delim = \$msg[3];%NL%". " assert (\$delim eq %SQ%%SQ%);%NL%". "%NL%". " \$data = \$msg[4];%NL%". "%NL%". " print %SQ%sending %SQ%.\$data.%SQ% to %SQ%.\$c_addr.\"\\n\";%NL%". "%NL%". " zmq_msg_send(\$c_addr,\$frontend,ZMQ_SNDMORE);%NL%". " zmq_msg_send(%SQ%%SQ%,\$frontend,ZMQ_SNDMORE);%NL%". " zmq_msg_send(\$data,\$frontend);%NL%". "%NL%". " } else {%NL%". " print %SQ%worker checking in: %SQ%.\$w_addr.\"\\n\";%NL%". " }%NL%". " },%NL%". " },%NL%". " ];%NL%". " while(1){%NL%". " zmq_poll(\$items);%NL%". " select undef,undef,undef,0.025;%NL%". " if (getppid==1) {%NL%". " `pgrep -P \$\$ | xargs kill -TERM`;%NL%". " exit;%NL%". " }%NL%". " }%NL%". "%NL%". "};%NL%". "%NL%". "my \$Fork = new Parallel::Forker();%NL%". "\$Fork->schedule(run_on_start => \$zeromq_broker)->run()%NL%". " if \$Fork->in_parent;%NL%". "setpgrp(0,0) unless \$Fork->in_parent;%NL%". "%NL%". "for (1..NBR_WORKERS()) {%NL%". "%NL%". " my \$Fork = new Parallel::Forker();%NL%". " #\$SIG{TERM} = sub { \$Fork->kill_tree_all(%SQ%TERM%SQ%) ". "if \$Fork && \$Fork->in_parent; die \"Quitting...\\n\"; };%NL%". " \$Fork->schedule(run_on_start => \$fa_sub)->run()%NL%". " if \$Fork->in_parent;%NL%". " setpgrp(0,0) unless \$Fork->in_parent;%NL%". "%NL%". "}%NL%"; ($stdout,$stderr)=$handle->cmd( "${sudo}sed -i \'/use Catalyst::ScriptRunner/i$ad\' ". "./script/fullautoapi_fastcgi.pl"); ($stdout,$stderr)=$handle->cmd( # bash shell specific "${sudo}sed -i \'s/%NL%/\'\"`echo \\\\\\n`/g\" ". "./script/fullautoapi_fastcgi.pl"); ($stdout,$stderr)=$handle->cmd("${sudo}sed -i \"s/%SQ%/\'/g\" ". "./script/fullautoapi_fastcgi.pl"); ($stdout,$stderr)=$handle->cmd("${sudo}ldconfig"); ($stdout,$stderr)=$handle->cmd('./script/set_admin_password.pl'); if ($^O eq 'cygwin') { ($stdout,$stderr)=$handle->cmd("cygrunsrv -I memcached ". "-p /usr/local/bin/memcached"); ($stdout,$stderr)=$handle->cmd("cygrunsrv -I fullautoapi ". "-y memcached -p /cygdrive/c/cygwin64/bin/bash -a ". "'-lc \"/bin/perl /home/$username/FullAutoAPI/script/". "fullautoapi_fastcgi.pl -l localhost:3003\"'"); ($stdout,$stderr)=$handle->cmd("cygrunsrv --start fullautoapi"); sleep 15; print "\n ACCESS FULLAUTO API MANAGEMENT DASHBOARD AT:\n\n", " https://$domain_url -OR- https://localhost\n"; } else { ($stdout,$stderr)=$handle->cmd($sudo. "chown -Rv $username:$username .",'3600'); #($stdout,$stderr)=$handle->cmd($sudo. # "cp -v $builddir/$ls_tmp[0]/api/memcached /etc/init.d", # '__display__'); #($stdout,$stderr)=$handle->cmd($sudo. # 'chmod -v 755 /etc/init.d/memcached','__display__'); ($stdout,$stderr)=$handle->cmd($sudo. "cp -v $builddir/$ls_tmp[0]/api/fullautoapi /etc/init.d", '__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'chmod -v 755 /etc/init.d/fullautoapi','__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'chmod -v 777 /var/log','__display__'); ($stdout,$stderr)=$handle->cmd($sudo. 'chmod -v 777 /var/lock/subsys','__display__'); print "\n STARTING FULLAUTO API MANAGEMENT DASHBOARD . . .\n\n", ($stdout,$stderr)=$handle->cmd($sudo. 'service fullautoapi start','__display__'); sleep 15; print "\n ACCESS FULLAUTO API MANAGEMENT DASHBOARD AT:\n\n", " https://$domain_url\n"; } my $thanks=<<'END'; ______ _ , / / / ' ) / / --/ /_ __. ____ /_ / / __ . . / (_/ / /_(_/|_/ / <_/ <_ (__/_(_)(_/_' For Trying // _ _ _ _____ _ _ _ _ | \ | | ___| |_ | ___| _| | | / \ _ _| |_ | | \| |/ _ \ __| o o | |_ | | | | | | / _ \| | | | __/ | \ | |\ | __/ |_ o o | _|| |_| | | |/ ___ \ |_| | || | |_| \_|\___|\__| |_| \__,_|_|_/_/ \_\__,_|\__\___/ (C) Copyright (C) 2000-2034 Brian M. Kelly Brian.Kelly@FullAuto.com END eval { local $SIG{ALRM} = sub { die "alarm\n" }; # \n required alarm 15; print $thanks; print " \n Press Any Key to EXIT ... "; <STDIN>; };alarm(0); print "\n\n"; #print "\n\n\n Please wait at least a minute for the Default Browser\n", # " to start with your new Catalyst installation!\n\n\n"; &Net::FullAuto::FA_Core::cleanup; }; my $standup_fullautoapi=sub { my $catalyst="]T[{select_fullautoapi_setup}"; my $password="]I[{'enter_password',1}"; my $domain_url="]I[{'domain_url',1}"; my $cnt=0; $configure_fullautoapi->($catalyst,$password,$domain_url); return '{choose_demo_setup}<'; }; my $fullautoapi_setup_summary=sub { package fullautoapi_setup_summary; use JSON::XS; my $region="]T[{awsregions}"; $region=~s/^"//; $region=~s/"$//; my $type="]T[{select_type}"; $type=~s/^"//; $type=~s/"$//; my $money=$type; $money=~s/^.*-> \$(.*?) +(?:[(].+[)] )*\s*per hour$/$1/; $type=substr($type,0,(index $type,' ->')-3); my $catalyst="]T[{select_fullautoapi_setup}"; $catalyst=~s/^"//; $catalyst=~s/"$//; print "REGION=$region and TYPE=$type\n"; print "CATALYST=$catalyst\n"; my $num_of_servers=0; my $ol=$catalyst; $ol=~s/^.*(\d+)\sServer.*$/$1/; if ($ol==1) { $main::aws->{'CatalystFramework.org'}->[0]=[]; } elsif ($ol=~/^\d+$/ && $ol) { foreach my $n (0..$ol) { $main::aws->{'CatalystFramework.org'}=[] unless exists $main::aws->{'CatalystFramework.org'}; $main::aws->{'CatalystFramework.org'}->[$n]=[]; } } $num_of_servers=$ol; my $cost=int($num_of_servers)*$money; my $cents=''; if ($cost=~/^0\./) { $cents=$cost; $cents=~s/^0\.//; if (length $cents>2) { $cents=~s/^(..)(.*)$/$1.$2/; $cents=~s/^0//; $cents=' ('.$cents.' cents)'; } else { $cents=' ('.$cents.' cents)'; } } my $show_cost_banner=<<'END'; _ _ ___ _ ___ /_\ __ __ ___ _ __| |_ / __|___ __| ||__ \ / _ \/ _/ _/ -_) '_ \ _| | (__/ _ (_-< _|/_/ /_/ \_\__\__\___| .__/\__| \___\___/__/\__(_) |_| END $show_cost_banner.=<<END; Note: There is a \$$cost per hour cost$cents to launch $num_of_servers AWS EC2 $type servers for the FullAuto Demo: $catalyst END my %show_cost=( Name => 'show_cost', Item_1 => { Text => "I accept the \$$cost$cents per hour cost", Result => $standup_fullautoapi, }, Item_2 => { Text => "Return to Choose Demo Menu", Result => sub { return '{choose_demo_setup}<' }, }, Item_3 => { Text => "Exit FullAuto", Result => sub { Net::FullAuto::FA_Core::cleanup() }, }, Scroll => 1, Banner => $show_cost_banner, ); return \%show_cost; }; our $choose_strong_password=sub { package choose_strong_password; my $password_banner=<<'END'; ___ _ ___ _ / __| |_ _ _ ___ _ _ __ _ | _ \__ _ _______ __ _____ _ _ __| | \__ \ _| '_/ _ \ ' \/ _` | | _/ _` (_-<_-< V V / _ \ '_/ _` | |___/\__|_| \___/_||_\__, | |_| \__,_/__/__/\_/\_/\___/_| \__,_| |___/ END use Crypt::GeneratePassword qw(word); my $word=''; foreach my $count (1..10) { print "\n Generating Password ...\n"; $word=eval { local $SIG{ALRM} = sub { die "alarm\n" }; # \n required alarm 7; my $word=word(10,15,3,5,6); print "\n Trying Password - $word ...\n"; die if -1<index $word,'*'; die if -1<index $word,'$'; die if -1<index $word,'+'; return $word; }; alarm 0; last if $word; } $password_banner.=<<END; The Web Server (NGINX) and the SSL Certificate each need a strong password. Use the one supplied here, or create your own. To create your own, use the [DEL] key to clear the highlighted input box first. *** BE SURE TO WRITE IT DOWN AND KEEP IT SOMEWHERE SAFE! *** Input box with === border is highlighted (active) input box. Use [TAB] key to switch focus between input boxes. Password ]I[{1,\'$word\',50} Confirm ]I[{2,\'$word\',50} END my $enter_password={ Name => 'enter_password', Input => 1, Result => $standup_fullautoapi, #Result => #$Net::FullAuto::ISets::Local::FullAutoAPI_is::select_fullautoapi_setup, Banner => $password_banner, }; return $enter_password; }; our $domain_url=sub { package domain_url; use Net::FullAuto; my $handle=connect_shell(); my ($stdout,$stderr)=$handle->cmd("wget -qO- http://icanhazip.com"); my $public_ip=$stdout if $stdout=~/^\d+\.\d+\.\d+\.\d+\s*/s; unless ($public_ip) { require Sys::Hostname; import Sys::Hostname; require Socket; import Socket; my($addr)=inet_ntoa((gethostbyname(Sys::Hostname::hostname))[4]); $public_ip=$addr if $addr=~/^\d+\.\d+\.\d+\.\d+\s*/s; } chomp($public_ip); $public_ip='127.0.0.1' unless $public_ip; my $domain_url_banner=<<'END'; ___ _ _ _ ___ _ | \ ___ _ __ __ _(_)_ _ | | | | _ \ | | |) / _ \ ' \/ _` | | ' \ | |_| | / |__ |___/\___/_|_|_\__,_|_|_||_| \___/|_|_\____| END $domain_url_banner.=<<END; Type or paste the domain url for the site: *** A properly registered domain url is necessary! *** Make sure the DNS A/AAAA record(s) for this domain contain(s) this IP address --> $public_ip Domain URL ]I[{1,'fullautosoftware.net',46} END my $domain_url={ Name => 'domain_url', Input => 1, Result => $choose_strong_password, #Result => #$Net::FullAuto::ISets::Local::WordPress_is::select_wordpress_setup, Banner => $domain_url_banner, }; return $domain_url; }; our $select_fullautoapi_setup=sub { my @options=('FullAuto Automation API on This Host'); my $fullautoapi_setup_banner=<<'END'; _ ___ _ _ _ _ ((_) | __| _| | | /_\ _ _| |_ | / | _| || | | |/ _ \ || | _/ | \ Automates _ / |_| \_,_|_|_/_/ \_\_,_|\__\___/c Everything _| |_ \__/_ ___ __ _| |_ __ _| |_ _ ___| |_ |_ _| / \ / __/ _` | __/ _` | | | | / __| __| Perl MVC |_| _- | | | (_| (_| | || (_| | | |_| \__ \ | framework _ _-' \____/ \___\__,_|\__\__,_|_|\__, |___/\__|c ((_) ---\ |___/ \ \\_ Web Framework & Automation API via RESTful (_) Choose the FullAutoAPI setup you wish to install on this localhost: END my %select_fullautoapi_setup=( Name => 'select_fullautoapi_setup', Item_1 => { Text => ']C[', Convey => \@options, #Result => $standup_fullautoapi, Result => $domain_url, }, Scroll => 1, Banner => $fullautoapi_setup_banner, ); return \%select_fullautoapi_setup }; sub exit_on_error { eval { local $SIG{ALRM} = sub { die "alarm\n" }; # \n required alarm 1800; print "\n FATAL ERROR!:\n\n "; print $_[0]; print " \n\n Press Any Key to EXIT ... "; <STDIN>; };alarm(0); print "\n\n"; &Net::FullAuto::FA_Core::cleanup; } 1