Compare commits
	
		
			47 Commits
		
	
	
		
			11_0_0-4_e
			...
			11_0_0-30_
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 78bb7743c1 | |||
| 87f6a46502 | |||
| a08767919c | |||
| 2b83be6d70 | |||
| 6c1b6ed1f4 | |||
| 3fa8ab5eda | |||
| 55465e3081 | |||
| e5b9a012d9 | |||
| fbdf3170ec | |||
| 87d1d072c0 | |||
| d49db26f26 | |||
| c4f9d67abc | |||
| fe62bd3e39 | |||
| df6d21dbc9 | |||
| 9c9592f861 | |||
| 4d2097d2da | |||
| 44a9ecc0e1 | |||
| 785ebcfaaf | |||
| 127ea74a8b | |||
| b9f6392c1d | |||
| 659f060eb6 | |||
| 1087a8a5a2 | |||
| 6a5a756438 | |||
| 91ca26de27 | |||
| 8b93232bbe | |||
| ed1c3e13b1 | |||
| 095a0a1499 | |||
| d16ea6a847 | |||
| e70cc67430 | |||
| b097acafab | |||
| 5d7655a709 | |||
| a58df95aa9 | |||
| 251b454470 | |||
| 174d511899 | |||
| 4be8a1411f | |||
| ba431a8a7d | |||
| 77a7849898 | |||
| fb5b0942d6 | |||
| 5edc830f9b | |||
| 473cb57a47 | |||
| 55b85496d4 | |||
| 2fd6f8b630 | |||
| a428e91c92 | |||
| 03955eecea | |||
| 891fc73ce3 | |||
| e7d7b6afb8 | |||
| 1837bc9a18 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -2,3 +2,4 @@ | ||||
| *.log | ||||
| *spec-20* | ||||
| *.tar.xz | ||||
| *.bak | ||||
|   | ||||
							
								
								
									
										68
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								README.md
									
									
									
									
									
								
							| @@ -13,10 +13,70 @@ SMEServer Koozali developed git repo for smeserver-manager smeserver | ||||
| <br />https://wiki.koozali.org/Server_Manager_2_Howto_incorporate_a_legacy_contrib | ||||
|  | ||||
| ## Bugzilla | ||||
| Show list of outstanding bugs: [here](https://bugs.koozali.org/buglist.cgi?component=smeserver-manager&product=SME%20Server%2010.X&query_format=advanced&limit=0&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=CONFIRMED) | ||||
| Show list of outstanding bugs: | ||||
| [All](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEEDINFO&bug_status=IN_PROGRESS&bug_status=RESOLVED&bug_status=VERIFIED&cf_package=smeserver-manager&classification=SME+Server&list_id=105756&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)   | ||||
| [Confirmed](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=CONFIRMED&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)   | ||||
| [Unconfirmed](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=UNCONFIRMED&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)   | ||||
| [Need info](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=NEEDINFO&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)   | ||||
| [In progress](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=IN_PROGRESS&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)   | ||||
| [Resolved](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=RESOLVED&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced)   | ||||
| [Verified](https://bugs.koozali.org/buglist.cgi?action=wrap&bug_status=VERIFIED&cf_package=smeserver-manager&classification=SME+Server&order=changeddate+DESC%2Ccomponent%2Cpriority%2Cbug_severity&query_format=advanced) | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| <br />*This description has been generated by an LLM AI system and cannot be relied on to be fully correct.* | ||||
| *Once it has been checked, then this comment will be deleted* | ||||
| <br /> | ||||
| The *smeserver-manager* is a web-based management interface for the SME Server (formerly known as e-smith server and gateway). SME Server is a Linux-based distribution designed for small to medium-sized enterprises, providing a wide range of network services and simplified server management. | ||||
|  | ||||
| It is based on the perl Mojolicious package. Mojolicious is a real-time web framework for Perl, which provides a range of functionalities that make it a powerful and flexible tool for web development. | ||||
|  | ||||
| ### Features | ||||
|  | ||||
| #### Web-Based Management Interface: | ||||
| smeserver-manager provides an intuitive and user-friendly web interface that allows administrators to manage various aspects of the server without needing deep technical knowledge or command-line skills. | ||||
|  | ||||
| #### User and Group Management: | ||||
| It allows you to easily add, remove, and manage user accounts and groups. The interface simplifies creating email accounts, setting passwords, and configuring user permissions. | ||||
|  | ||||
| #### Network Configuration: | ||||
| You can configures network settings such as IP addresses, DNS, DHCP, and gateway settings. The interface also provides options for setting up VPNs, remote access, and firewall rules. | ||||
|  | ||||
| #### File Sharing and Storage: | ||||
| Enables and manages file sharing services like Samba (for Windows file sharing) and NFS (for Unix/Linux file sharing). Administrators can easily create shared folders and manage permissions. | ||||
|  | ||||
| #### Email Services: | ||||
| Configure and manage email services, including setting up mail domains, user mailboxes, and SMTP/IMAP/POP3 settings. It also provides options for spam and virus filtering. | ||||
|  | ||||
| #### Web Services: | ||||
| Host and manage websites using the integrated web server (usually Apache). It supports virtual hosting, where multiple websites can be hosted on the same server. | ||||
|  | ||||
| #### Backup and Restore: | ||||
| Perform backups of essential data and server configurations. The interface provides options for scheduled backups and restoring from backup files. | ||||
|  | ||||
| #### Software Updates and Installation: | ||||
| Keep the server up-to-date with the latest security patches and software updates. The interface helps in installing and updating software packages and extensions. | ||||
|  | ||||
| #### Monitoring and Reporting: | ||||
| Monitor server performance and health. The interface provides logs, status reports, and alerts for various server components, including disk usage, network traffic, and system load. | ||||
|  | ||||
|  | ||||
| ### Installation and Access | ||||
|  | ||||
| Typically, smeserver-manager is installed by default on SME Server. To access the interface: | ||||
|  | ||||
| Open a web browser on a device connected to the same network as the SME Server. Enter the server's IP address or hostname followed by /server-manager in the address bar (e.g., https://192.168.1.1/server-manager).  | ||||
| You will be prompted to log in. Use the administrator credentials set during the SME Server installation. | ||||
|  | ||||
| ### Benefits | ||||
|  | ||||
| Simplicity: Makes it easy for non-technical users to manage a server. | ||||
| Centralized Management: Provides a single point of control for various server functionalities. | ||||
| Efficiency: Saves time and reduces complexity in server management tasks. | ||||
| Security: Regular updates and built-in security features ensure the server remains secure. | ||||
|  | ||||
| ### Considerations | ||||
|  | ||||
| Learning Curve: While designed to be user-friendly, some features may still require a basic understanding of server and network management concepts. | ||||
| Dependencies: Relies on specific packages and configurations of SME Server, and may not be directly applicable to other Linux distributions. | ||||
|  | ||||
| ### Summary | ||||
|  | ||||
| SMEserver-manager is a powerful tool that brings simplicity and efficiency to server management for small to medium-sized enterprises. By providing a centralized, web-based interface, it allows administrators to manage users, network settings, file sharing, email services, web hosting, and more, all from a single location. | ||||
|   | ||||
| @@ -47,6 +47,9 @@ for my $event ( qw( smeserver-manager-update smanager-refresh bootstrap-console- | ||||
|  | ||||
| event_link('systemd-default', "smeserver-manager-update", '88'); | ||||
| event_link('systemd-reload', "smeserver-manager-update", '89'); | ||||
| templates2events("/etc/rsyslog.conf", "smeserver-manager-update"); | ||||
| safe_symlink("restart", | ||||
|     "root/etc/e-smith/events/smeserver-manager-update/services2adjust/rsyslog"); | ||||
|  | ||||
| use esmith::Build::Backup qw(:all); | ||||
| backup_includes("smeserver-manager", qw( | ||||
|   | ||||
| @@ -33,6 +33,8 @@ use esmith::I18N; | ||||
|  | ||||
| use Data::Dumper;	# activate if DEBUG | ||||
|  | ||||
| binmode(STDOUT, ":encoding(UTF-8)"); | ||||
|  | ||||
| my $navigation_ignore =  | ||||
| 	"(\.\.?|Swttheme\.pm|Login\.pm|Request\.pm|Modules\.pm(-.*)?)"; | ||||
|  | ||||
| @@ -46,131 +48,193 @@ my @files = grep (!/^${navigation_ignore}$/, readdir (FUNCTIONS)); | ||||
| closedir FUNCTIONS; | ||||
|  | ||||
| my @langs = $i18n->availableLanguages();  | ||||
| #my @langs = ('en', 'fr');  | ||||
| #print Dumper(\@langs); | ||||
| #my @langs = ('tr');  #Temp override | ||||
|  | ||||
|  | ||||
| foreach my $lang (@langs) | ||||
| { | ||||
|     my $long_lex = SMNGR_LIB.'/'.I18NMODULES."/General/general_$lang.lex"; | ||||
|     next unless ( -e $long_lex ); | ||||
| 	my $long_lex = SMNGR_LIB.'/'.I18NMODULES."/General/general_$lang.lex"; | ||||
| 	next unless ( -e $long_lex ); | ||||
|  | ||||
|     open(LEX, '<:encoding(UTF-8)', $long_lex) | ||||
|          or die "Couldn't open ", $long_lex, " for reading.\n"; | ||||
|     my @gen_lex = <LEX>; | ||||
|     close LEX; | ||||
| 	open(LEX, '<:encoding(UTF-8)', $long_lex) | ||||
| 		 or die "Couldn't open ", $long_lex, " for reading.\n"; | ||||
| 	my @gen_lex = <LEX>; | ||||
| 	close LEX; | ||||
|  | ||||
|     foreach my $file (@files) | ||||
|     { | ||||
| 	next if (-d SMNGR_LIB.'/'.WEBFUNCTIONS . "/$file"); | ||||
| #        next unless ( $file =~ m/D.*\.pm$/ ); | ||||
|         next unless ( $file =~ m/[A-Z].*\.pm$/ ); | ||||
|  | ||||
| 	my $file2 = lc($file); | ||||
| 	$file2 =~ s/\.pm$//; | ||||
|  | ||||
|     #--------------------------------------------------  | ||||
|     # extract heading, description and weight information | ||||
|     # from Mojo controller | ||||
|     #--------------------------------------------------  | ||||
| 	open(SCRIPT, SMNGR_LIB.'/'.WEBFUNCTIONS . "/$file"); | ||||
|         my $heading            	= undef; | ||||
|         my $description        	= undef; | ||||
|         my $heading_weight     	= undef; | ||||
|         my $description_weight 	= undef; | ||||
|         my $menucat		= undef; | ||||
|         my $routes		= undef; | ||||
|  | ||||
|         while ( <SCRIPT> ) | ||||
| 	#my @files = ('Portforwarding.pm');  #Temp override | ||||
| 	foreach my $file (@files) | ||||
| 	{ | ||||
| 	    $heading = $1 if (/^\s*#\s*heading\s*:\s*(.+?)\s*$/); | ||||
| 	    $description = $1  | ||||
| 		if (/^\s*#\s*description\s*:\s*(.+?)\s*$/); | ||||
| 	    ($heading_weight, $description_weight) = ($1, $2)  | ||||
| 		if (/^\s*#\s*navigation\s*:\s*(\d+?)\s+(\d+?)\s*$/); | ||||
| 	    $menucat = $1  | ||||
| 		if (/^\s*#\s*menu\s*:\s*(.+?)\s*$/); | ||||
| 		next if (-d SMNGR_LIB.'/'.WEBFUNCTIONS . "/$file"); | ||||
| 		#        next unless ( $file =~ m/D.*\.pm$/ ); | ||||
| 			next unless ( $file =~ m/[A-Z].*\.pm$/ ); | ||||
|  | ||||
| 	    last if (defined $heading and  | ||||
| 		defined $description and | ||||
| 		defined $heading_weight and | ||||
| 		defined $description_weight and | ||||
| 		defined $menucat); | ||||
| 		my $file2 = lc($file); | ||||
| 		$file2 =~ s/\.pm$//; | ||||
| 		#--------------------------------------------------  | ||||
| 		# extract heading, description and weight information | ||||
| 		# from Mojo controller | ||||
| 		#--------------------------------------------------  | ||||
| 		open(SCRIPT, SMNGR_LIB.'/'.WEBFUNCTIONS . "/$file"); | ||||
| 		my $heading            	= undef; | ||||
| 		my $description        	= undef; | ||||
| 		my $heading_weight     	= undef; | ||||
| 		my $description_weight 	= undef; | ||||
| 		my $menucat		= undef; | ||||
| 		my $routes		= undef; | ||||
|  | ||||
| 	    # routes : end  (stop before eof if 'menu' is not here before 'routes'!!! | ||||
| 	    $routes = $1 if (/^\s*#\s*routes\s*:\s*(.+?)\s*$/); | ||||
| 	    last if (defined $routes and $routes eq 'end'); | ||||
| 		while ( <SCRIPT> ) | ||||
| 		{ | ||||
| 			$heading = $1 if (/^\s*#\s*heading\s*:\s*(.+?)\s*$/); | ||||
| 			$description = $1  | ||||
| 			if (/^\s*#\s*description\s*:\s*(.+?)\s*$/); | ||||
| 			($heading_weight, $description_weight) = ($1, $2)  | ||||
| 			if (/^\s*#\s*navigation\s*:\s*(\d+?)\s+(\d+?)\s*$/); | ||||
| 			$menucat = $1  | ||||
| 			if (/^\s*#\s*menu\s*:\s*(.+?)\s*$/); | ||||
|  | ||||
| 			last if (defined $heading and  | ||||
| 			defined $description and | ||||
| 			defined $heading_weight and | ||||
| 			defined $description_weight and | ||||
| 			defined $menucat); | ||||
|  | ||||
| 			# routes : end  (stop before eof if 'menu' is not here before 'routes'!!! | ||||
| 			$routes = $1 if (/^\s*#\s*routes\s*:\s*(.+?)\s*$/); | ||||
| 			last if (defined $routes and $routes eq 'end'); | ||||
| 		} | ||||
| 		close SCRIPT; | ||||
|  | ||||
| 		print "updating script $file for lang $lang\n"if DEBUG; | ||||
| 		my $navdb = $navdbs{$lang}; | ||||
| 		my $navinfo = NAVDIR.'/'.NAVIGATIONDIR . "/navigation.$lang"; | ||||
| 		$navdb ||= esmith::NavigationDB->open($navinfo); | ||||
| 		$navdb ||= esmith::NavigationDB->create($navinfo) or | ||||
| 			die "Couldn't create $navinfo\n"; | ||||
| 			$navdbs{$lang} ||= $navdb; | ||||
| 		my $rec = $navdb->get($file2) ||  | ||||
| 			$navdb->new_record($file2, { type => 'panel' } ); | ||||
| 		 | ||||
| 		my @panel_lex = (); | ||||
| 		$long_lex = SMNGR_LIB.'/'.I18NMODULES.'/'.ucfirst($file2)."/${file2}_$lang.lex"; | ||||
| 		if ( -e $long_lex ) { | ||||
| 			open(LEX, '<:encoding(UTF-8)', $long_lex) | ||||
| 				 or die "Couldn't open ", $long_lex, " for reading.\n"; | ||||
| 			@panel_lex = <LEX>; | ||||
| 			close LEX; | ||||
| 		} | ||||
| 		#Extract the prefix for this module | ||||
| 		my @keys = values @panel_lex;  # Get all values from the array | ||||
| 		 | ||||
| 		my $i = 0;                    # Initialize the index | ||||
| 		my $found = 0;                # Flag to check if the prefix was found | ||||
| 		my $prefix = "xx_";			  # Probably never match!! | ||||
|  | ||||
| 		while ($i < @keys) {          # Loop until we run out of entries | ||||
| 			my $extracted_value = $keys[$i] || "";  # The current entry | ||||
| 			#print("Extracted val: ".$extracted_value."\n"); | ||||
|  | ||||
| 			# Extract prefix from the second value (up to and including the first underscore) | ||||
| 			#my ($prefix) = $second_value =~ /^'(.*?_)/;  # Match everything up to and including the first underscore | ||||
| 			($prefix) = $extracted_value =~ /^'(.*?_)/;  # Match everything up to and including the first underscore | ||||
| 			 | ||||
| 			if (defined $prefix) { | ||||
| 				$found = 1;           # Set found flag to true | ||||
| 				last;                 # Exit the loop if prefix is found | ||||
| 			} else { | ||||
| 				#print("Extracted Val: " . $extracted_value . "\n"); | ||||
| 			} | ||||
|  | ||||
| 			$i++;                     # Increment the index to check the next entry | ||||
| 		} | ||||
|  | ||||
| 		if (!$found) { | ||||
| 			print(STDERR "No valid prefix found in any entries: ".$file2." (".$lang.")\n"); # if DEBUG; | ||||
| 			$prefix = "xx_";			  # Probably never match!! | ||||
| 			 | ||||
| 		} | ||||
| 		#print("Prefix: ".$prefix." ".$file2." (".$lang.")\n"); | ||||
| 		 | ||||
| 		my %Lexicon = (); | ||||
| 		push(@panel_lex, @gen_lex); | ||||
| 		my $top_error = 0; | ||||
|  | ||||
| 		chomp @panel_lex; | ||||
| 		for (@panel_lex) { | ||||
| 			next unless $_;	# first one empty | ||||
| 			my ($k, $v) = split / => /, $_; | ||||
| 		#	errors on split to $v (use DEBUG to see) | ||||
| 			if ( $k and $v ) { | ||||
| 				$k =~ s/\'//g; | ||||
| 				$v =~ s/\'//g; | ||||
| 				$v =~ s/,$//g; | ||||
| 				$Lexicon{ lc($k) } = $v; | ||||
| 			} else { | ||||
| 				$k = "?" unless ($k); | ||||
| 				print STDERR "Error for $lang $file2 on $k \n" if DEBUG; | ||||
| 				$top_error++; | ||||
| 			} | ||||
| 		} | ||||
| 		if ( $top_error > 0) { | ||||
| 			if ( DEBUG ) { | ||||
| 				print STDERR "$top_error errors for $lang $file2\n"; | ||||
| 				#		print Dumper(\@panel_lex); | ||||
| 				#		print Dumper(\%Lexicon); | ||||
| 				#		exit 1; | ||||
| 			} | ||||
| 		} | ||||
| 		$heading = "" unless defined $heading; | ||||
| 		$description = "" unless defined $description; | ||||
| 		# Get the base language code from $lang | ||||
| 		my $base_lang = (split('-', $lang))[0]; | ||||
| 		my $loc_heading =  process_localization( \%Lexicon, $heading, $lang, $prefix ); | ||||
| 		my $loc_description =  process_localization( \%Lexicon, $description, $lang, $prefix ); | ||||
| 		$loc_heading =~ s/^\s*(\w.*?)\s*$/$1/; | ||||
| 		$loc_description =~ s/^\s*(\w.*?)\s*$/$1/; | ||||
|  | ||||
| 		$rec->merge_props( | ||||
| 			Heading => $loc_heading, | ||||
| 			Description => $loc_description, | ||||
| 			HeadingWeight => localise( \%Lexicon, $heading_weight ), | ||||
| 			DescriptionWeight => localise( \%Lexicon, $description_weight ), | ||||
| 			MenuCat => (defined $menucat ? $menucat : 'A')); | ||||
| 	} | ||||
| 	close SCRIPT; | ||||
|  | ||||
| 	print "updating script $file for lang $lang\n" if DEBUG; | ||||
| 	#warn "trying to close for lang $lang\n"; | ||||
| 	my $navdb = $navdbs{$lang}; | ||||
| 	my $navinfo = NAVDIR.'/'.NAVIGATIONDIR . "/navigation.$lang"; | ||||
| 	$navdb ||= esmith::NavigationDB->open($navinfo); | ||||
| 	$navdb ||= esmith::NavigationDB->create($navinfo) or | ||||
| 	    die "Couldn't create $navinfo\n"; | ||||
|         $navdbs{$lang} ||= $navdb; | ||||
| 	my $rec = $navdb->get($file2) ||  | ||||
| 	    $navdb->new_record($file2, { type => 'panel' } ); | ||||
|  | ||||
| 	my @panel_lex = (); | ||||
| 	$long_lex = SMNGR_LIB.'/'.I18NMODULES.'/'.ucfirst($file2)."/${file2}_$lang.lex"; | ||||
| 	if ( -e $long_lex ) { | ||||
| 	    open(LEX, '<:encoding(UTF-8)', $long_lex) | ||||
|     		 or die "Couldn't open ", $long_lex, " for reading.\n"; | ||||
| 	    @panel_lex = <LEX>; | ||||
| 	    close LEX; | ||||
| 	} | ||||
|  | ||||
| 	my %Lexicon = (); | ||||
| 	push(@panel_lex, @gen_lex); | ||||
| 	my $top_error = 0; | ||||
|  | ||||
| 	chomp @panel_lex; | ||||
| 	for (@panel_lex) { | ||||
| 	    next unless $_;	# first one empty | ||||
| 	    my ($k, $v) = split / => /, $_; | ||||
| #	errors on split to $v (use DEBUG to see) | ||||
| 	    if ( $k and $v ) { | ||||
| 		$k =~ s/\'//g; | ||||
| 		$v =~ s/\'//g; | ||||
| 		$v =~ s/,$//g; | ||||
| 		$Lexicon{ $k } = $v; | ||||
| 	    } else { | ||||
| 		$k = "?" unless ($k); | ||||
| 		print STDERR "Error for $lang $file2 on $k \n" if DEBUG; | ||||
| 		$top_error++; | ||||
| 	    } | ||||
| 	} | ||||
| 	if ( $top_error > 0) { | ||||
| 	    if ( DEBUG ) { | ||||
| 	        print STDERR "$top_error errors for $lang $file2\n"; | ||||
| #		print Dumper(\@panel_lex); | ||||
| #		print Dumper(\%Lexicon); | ||||
| #		exit 1; | ||||
| 	    } | ||||
| 	} | ||||
|  | ||||
| 	my $loc_heading =  localise( \%Lexicon, $heading ); | ||||
| 	my $loc_description =  localise( \%Lexicon, $description ); | ||||
| 	$loc_heading =~ s/^\s*(\w.*?)\s*$/$1/; | ||||
| 	$loc_description =~ s/^\s*(\w.*?)\s*$/$1/; | ||||
|  | ||||
| 	$rec->merge_props( | ||||
| 	    Heading => $loc_heading, | ||||
| 	    Description => $loc_description, | ||||
| 	    HeadingWeight => localise( \%Lexicon, $heading_weight ), | ||||
| 	    DescriptionWeight => localise( \%Lexicon, $description_weight ), | ||||
| 	    MenuCat => (defined $menucat ? $menucat : 'A')); | ||||
|     } | ||||
|     #warn "trying to close for lang $lang\n"; | ||||
|     my $navdb = $navdbs{$lang}; | ||||
|     $navdb->close(); | ||||
| 	$navdb->close(); | ||||
| } | ||||
|  | ||||
|  | ||||
| sub localise { | ||||
|     my ($lexicon, $string) = @_; | ||||
|     #print("Looking up:".$string."\n"); | ||||
|     $string  = "" unless defined $string; | ||||
|     return $lexicon->{$string} || $string; | ||||
|     my $lc_string = lc($string); | ||||
|     my $res = $lexicon->{$lc_string} || $string; | ||||
|     #print("Returning:".$res."\n"); | ||||
|     return $res; | ||||
| } | ||||
|  | ||||
| # Subroutine to process localization | ||||
| sub process_localization { | ||||
|     my ($lexicon_ref, $heading, $lang, $prefix) = @_; | ||||
|  | ||||
|     # Localized heading based on original heading | ||||
|     my $loc_heading = localise($lexicon_ref, $heading); | ||||
|  | ||||
|     # Get the base language code from $lang | ||||
|     my $base_lang = (split('-', $lang))[0]; | ||||
|  | ||||
|     # Check the condition | ||||
|     if ($loc_heading eq $heading && $base_lang ne 'en') { | ||||
|         # Construct the new key by combining the prefix and the original heading | ||||
|         my $key = $prefix . $heading; | ||||
|         # Localize using the constructed key | ||||
|         $loc_heading = localise($lexicon_ref, $key); | ||||
|         # See if it got a hit | ||||
|         if ($loc_heading eq $key){ | ||||
| 			$loc_heading = $heading; | ||||
| 		} | ||||
|     } | ||||
|      | ||||
|     return $loc_heading; # Optionally return the localized heading | ||||
| } | ||||
|   | ||||
| @@ -40,5 +40,10 @@ | ||||
|             $OUT .= "        Require ip $localAccess $externalSSLAccess\n"; | ||||
|         } | ||||
|         $OUT .= "    </Location>\n"; | ||||
|         # prevent caching of manager files in browser | ||||
|         $OUT .= "   <LocationMatch \"/$place/.+\.(html|cgi)\$\">\n"; | ||||
|         $OUT .= "                   Header set Cache-Control no-store\n"; | ||||
|         $OUT .= "   </LocationMatch>\n"; | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										4
									
								
								root/etc/e-smith/templates/etc/rsyslog.conf/32smanager
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								root/etc/e-smith/templates/etc/rsyslog.conf/32smanager
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| #smanager | ||||
| :programname, isequal, "smanager"            /var/log/smanager/smanager.log | ||||
| & stop | ||||
|  | ||||
| @@ -67,5 +67,21 @@ hr.sme-copyrightbar { | ||||
| color: #8ebe43; | ||||
| background-color: #8ebe43; | ||||
|     } | ||||
|        | ||||
| /* flag container no flag */ | ||||
| #flag-container span { | ||||
|   font-size: 24px; | ||||
| } | ||||
|  | ||||
| .fallback-box { | ||||
|   display: inline-block; /* Make it inline-block to fit around the content */ | ||||
|   border: 2px solid gray; /* Change the border color as desired */ | ||||
|   padding: 10px; /* Add some padding */ | ||||
|   border-radius: 10px; /* Round the corners of the box */ | ||||
|   font-size: 60px; /* Adjust size if needed */ | ||||
|   margin-top: 10px; /* Add some margin */ | ||||
|   text-align: center; /* Center text inside the box */ | ||||
| } | ||||
|  | ||||
| HERE | ||||
| } | ||||
|   | ||||
| @@ -234,7 +234,7 @@ a.menu-title { | ||||
|     width: 100%; | ||||
| } | ||||
| #h2e11 { | ||||
|     width: 70%; | ||||
|     width: 50%; | ||||
|     float: left; | ||||
| } | ||||
| #h2e12 { | ||||
| @@ -257,9 +257,9 @@ a.menu-title { | ||||
|     width: 70%; | ||||
| } | ||||
|  | ||||
| #h2e22,#h2e23 { | ||||
| #h2e22,#h2e23,#h2e12 { | ||||
|     float: left; | ||||
|     width: 10%; | ||||
|     width: 14em; | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| @@ -273,6 +273,7 @@ a.menu-title { | ||||
|     left: 2px; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*end*/ | ||||
| EOF | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,27 @@ | ||||
| document.addEventListener('DOMContentLoaded', () => { | ||||
|   const flagContainer = document.getElementById('flag-container'); | ||||
|  | ||||
|   // Function to get the browser's locale | ||||
|   function getBrowserLocale() { | ||||
|     return navigator.language || navigator.userLanguage; | ||||
|   } | ||||
|  | ||||
|   // Function to map locale to country code | ||||
|   function getCountryCodeFromLocale(locale) { | ||||
|     const localeParts = locale.split('-'); | ||||
|     return localeParts.length > 1 ? localeParts[1] : localeParts[0]; | ||||
|   } | ||||
|  | ||||
|   // Function to create and display the flag icon | ||||
|   function displayFlagIcon(countryCode) { | ||||
|     const flagIcon = document.createElement('span'); | ||||
|     flagIcon.className = `flag-icon flag-icon-${countryCode.toLowerCase()}`; | ||||
|     flagIcon.id = 'flag-icon'; | ||||
|     flagContainer.appendChild(flagIcon); | ||||
|   } | ||||
|  | ||||
|   // Main logic | ||||
|   const locale = getBrowserLocale(); | ||||
|   const countryCode = getCountryCodeFromLocale(locale); | ||||
|   displayFlagIcon(countryCode); | ||||
| }); | ||||
| @@ -1,4 +1,6 @@ | ||||
| /usr/share/smanager/log/production.log { | ||||
| /var/log/smanager/smanager.log { | ||||
|   su root root | ||||
|   create 600 root root | ||||
|   weekly | ||||
|   copytruncate | ||||
|   rotate 12 | ||||
|   | ||||
| @@ -7,7 +7,7 @@ After=network.target | ||||
| Type=simple | ||||
| SyslogIdentifier=smanager | ||||
| WorkingDirectory=/usr/share/smanager/script | ||||
| PIDFile=/var/run/smanager.pid | ||||
| PIDFile=/run/smanager.pid | ||||
| ExecStartPre=/sbin/e-smith/service-status smanager | ||||
| ExecStart=/usr/bin/hypnotoad srvmngr -f | ||||
| ExecStop=/usr/bin/hypnotoad -s srvmngr | ||||
|   | ||||
| @@ -25,8 +25,16 @@ use SrvMngr::Plugin::I18N; | ||||
| use SrvMngr::I18N; | ||||
| use SrvMngr::Model::Main; | ||||
|  | ||||
| use SrvMngr::Plugin::WithoutCache; | ||||
|  | ||||
| our $VERSION = '1.420'; | ||||
| #this is overwrittrn with the "release" by the spec file - release can be "99.el8.sme" | ||||
| our $VERSION = '';  | ||||
| #Extract the release value | ||||
| if ($VERSION =~ /^(\d+)/) { | ||||
|     $VERSION = $1;  # $1 contains the matched numeric digits | ||||
| } else { | ||||
|     $VERSION = '999' #No leading numeric digits found | ||||
| } | ||||
| $VERSION = eval $VERSION; | ||||
|  | ||||
| use Exporter 'import'; | ||||
| @@ -210,6 +218,8 @@ sub setup_plugins { | ||||
|     $self->plugin('TagHelpers'); | ||||
|  | ||||
|     $self->plugin('RenderFile'); | ||||
|      | ||||
|     $self->plugin('SrvMngr::Plugin::WithoutCache'); | ||||
|  | ||||
|     # CSRF protection if production mode | ||||
| #    $self->plugin('Mojolicious::Plugin::CSRFDefender' => { | ||||
| @@ -624,7 +634,7 @@ sub getNavigation { | ||||
| 	{ | ||||
| 	    $heading = $rec->prop('Heading'); | ||||
| 	    $description = $rec->prop('Description'); | ||||
| 	    $headingWeight = $rec->prop('HeadingWeight'); | ||||
| 	    $headingWeight = $rec->prop('HeadingWeight') || 99999; #Stop noise in logs if file in dir does not have nav header. | ||||
| 	    $descriptionWeight = $rec->prop('DescriptionWeight'); | ||||
| 	    $urlpath = $rec->prop('UrlPath') || ''; | ||||
| 	    $menucat = $rec->prop('MenuCat') || 'A';	# admin menu (default) | ||||
|   | ||||
| @@ -37,6 +37,8 @@ use esmith::BackupHistoryDB; | ||||
| use esmith::util; | ||||
| use esmith::lockfile; | ||||
|  | ||||
| use esmith::BlockDevices; | ||||
|  | ||||
| use constant DEBUG => $ENV{MOJO_SMANAGER_DEBUG} || 0; | ||||
|  | ||||
| our $cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
| @@ -1576,19 +1578,33 @@ sub get_BackupwkDest_options { | ||||
|     my @usbdisks = (); | ||||
|  | ||||
|     if ( $VFSType eq 'usb' ) { | ||||
|         foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) { | ||||
|             $udi =~ m/^(\S+)/; | ||||
|         my $devices = esmith::BlockDevices->new ('allowmount' => 'disabled'); | ||||
|         my ($valid, $invalid) = $devices->checkBackupDrives(0); | ||||
|  | ||||
|             my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted); | ||||
|  | ||||
|             if ($is_mounted eq "false\n") { | ||||
|                 my $vollbl = qx(hal-get-property --udi $1 --key volume.label); | ||||
|                 $vollbl =~ m/^(\S+)/; | ||||
|                 if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';} | ||||
|                 chomp $vollbl; | ||||
|                 push @usbdisks, $vollbl; | ||||
|         if ( ${$valid}[0] ) { | ||||
|             foreach ( @{$valid} ) { | ||||
|                 push @usbdisks, $devices->label($_); | ||||
|             } | ||||
|         } | ||||
|   | ||||
|         if (!$usbdisks[0]){ | ||||
| 			 push (@usbdisks,$c->l('bac_No suitable local devices found')); | ||||
| 		} | ||||
|         $devices->destroy; | ||||
|  | ||||
|          #foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) { | ||||
|             #$udi =~ m/^(\S+)/; | ||||
|  | ||||
|             #my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted); | ||||
|  | ||||
|             #if ($is_mounted eq "false\n") { | ||||
|                 #my $vollbl = qx(hal-get-property --udi $1 --key volume.label); | ||||
|                 #$vollbl =~ m/^(\S+)/; | ||||
|                 #if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';} | ||||
|                 #chomp $vollbl; | ||||
|                 #push @usbdisks, $vollbl; | ||||
|             #} | ||||
|         #} | ||||
|     #    return undef unless ($usbdisks[0]); | ||||
|     } | ||||
|  | ||||
| @@ -1985,31 +2001,50 @@ sub dmount { | ||||
| 	return ( qx(/bin/mount -t nfs -o nolock "$host:/$share" $mountdir 2>&1) ); | ||||
|     }  | ||||
|     elsif ($VFSType eq 'usb') { | ||||
|         my $device = ""; | ||||
|         my $blkdev = ""; | ||||
|          my $device = ""; | ||||
|         my $vollbl = ""; | ||||
|         foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) { | ||||
|           $udi =~ m/^(\S+)/; | ||||
|           my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted); | ||||
|  | ||||
|           if ($is_mounted eq "false\n") { | ||||
|               $blkdev = qx(hal-get-property --udi $1 --key block.device); | ||||
|               if ($blkdev =~ m/^(\S+)/) {$blkdev = $1;} | ||||
|           } | ||||
|           if ($is_mounted eq "false\n") { | ||||
|               $vollbl = qx(hal-get-property --udi $1 --key volume.label); | ||||
|               $vollbl =~ m/^(\S+)/; | ||||
|               if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';} | ||||
|           } | ||||
|         my $devices = esmith::BlockDevices->new ('allowmount' => 'disabled'); | ||||
|         my ($valid, $invalid) = $devices->checkBackupDrives(0); | ||||
|  | ||||
|           chomp $vollbl; | ||||
|           chomp $blkdev; | ||||
|           $vollbl = "media/$vollbl"; | ||||
|           if  ($vollbl eq $share) { | ||||
|             $device = $blkdev; | ||||
|           }  | ||||
|         if ( ${$valid}[0] ) { | ||||
|             foreach ( @{$valid} ) { | ||||
|                 $vollbl = $devices->label($_); | ||||
|                 if ( $share eq "media/$vollbl" ) { | ||||
|                     $device = "/dev/$_"; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return ( qx(/bin/mount $device "/$share" 2>&1) ); | ||||
|         $devices->destroy; | ||||
|         return ( qx (mount $device /$share 2>&1) ); | ||||
|   | ||||
| #------------------------------------------------------------------------------------------------------- | ||||
|         #my $device = ""; | ||||
|         #my $blkdev = ""; | ||||
|         #my $vollbl = ""; | ||||
|         #foreach my $udi (qx(hal-find-by-property --key volume.fsusage --string filesystem)) { | ||||
|           #$udi =~ m/^(\S+)/; | ||||
|           #my $is_mounted = qx(hal-get-property --udi $1 --key volume.is_mounted); | ||||
|  | ||||
|           #if ($is_mounted eq "false\n") { | ||||
|               #$blkdev = qx(hal-get-property --udi $1 --key block.device); | ||||
|               #if ($blkdev =~ m/^(\S+)/) {$blkdev = $1;} | ||||
|           #} | ||||
|           #if ($is_mounted eq "false\n") { | ||||
|               #$vollbl = qx(hal-get-property --udi $1 --key volume.label); | ||||
|               #$vollbl =~ m/^(\S+)/; | ||||
|               #if ($vollbl =~ /^\s/) {$vollbl = 'nolabel';} | ||||
|           #} | ||||
|  | ||||
|           #chomp $vollbl; | ||||
|           #chomp $blkdev; | ||||
|           #$vollbl = "media/$vollbl"; | ||||
|           #if  ($vollbl eq $share) { | ||||
|             #$device = $blkdev; | ||||
|           #}  | ||||
|         #} | ||||
|          #return ( qx(/bin/mount $device "/$share" 2>&1) ); | ||||
| #------------------------------------------------------------------------------------------------------- | ||||
|     } else { | ||||
| 	return ("Error while mounting $host/$share : $VFSType not supported.\n"); | ||||
|     } | ||||
|   | ||||
| @@ -12,6 +12,9 @@ use strict; | ||||
| use warnings; | ||||
| use Mojo::Base 'Mojolicious::Controller'; | ||||
|  | ||||
| use constant FALSE => 0; | ||||
| use constant TRUE  => 1; | ||||
|  | ||||
| use Locale::gettext; | ||||
| use SrvMngr::I18N; | ||||
|  | ||||
| @@ -36,7 +39,7 @@ sub main { | ||||
|     my $title = $c->l('mai_FORM_TITLE'); | ||||
|  | ||||
|     $mai_datas{'trt'} = 'LIST'; | ||||
|     $mai_datas{fetchmailmethod} = $cdb->get_prop('fetchmail', 'Method'); | ||||
|     $mai_datas{fetchmailmethod} = $c->l($cdb->get_prop('fetchmail', 'Method')); | ||||
|  | ||||
|     $c->stash( title => $title, notif => '', mai_datas => \%mai_datas ); | ||||
|     $c->render(template => 'emailsettings'); | ||||
| @@ -56,13 +59,16 @@ sub do_display { | ||||
|     my ($notif, $dest) = ''; | ||||
|  | ||||
|     $mai_datas{'trt'} = $trt; | ||||
| 	$cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|  | ||||
|         if ( $trt eq 'ACC' ) { | ||||
| 	    $dest = 'emailaccess'; | ||||
| 	    $mai_datas{fetchmailmethod} = $cdb->get_prop('fetchmail', 'Method'); | ||||
|         } | ||||
| 	if ( $trt eq 'ACC' )  | ||||
|     { | ||||
| 		$dest = 'emailaccess'; | ||||
| 		$mai_datas{fetchmailmethod} = $cdb->get_prop('fetchmail', 'Method'); | ||||
|     } | ||||
|  | ||||
|         if ( $trt eq 'FIL' ) { | ||||
|     if ( $trt eq 'FIL' )  | ||||
|     { | ||||
| 	    $dest = 'emailfilter'; | ||||
| 	    $mai_datas{'virusstatus'} = $c->get_virus_status(); | ||||
| 	    $mai_datas{'spamstatus'} = $cdb->get_prop('spamassassin', 'status'); | ||||
| @@ -72,9 +78,10 @@ sub do_display { | ||||
| 	    $mai_datas{spamsortspam} = $cdb->get_prop('spamassassin', 'SortSpam'); | ||||
| 	    $mai_datas{spamsubjecttag} = $cdb->get_prop('spamassassin', 'SubjectTag'); | ||||
| 	    $mai_datas{spamsubject} = $cdb->get_prop('spamassassin', 'Subject'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         if ( $trt eq 'REC' ) { | ||||
|     if ( $trt eq 'REC' )  | ||||
|     { | ||||
| 	    $dest = 'emailreceive'; | ||||
| 	    $mai_datas{fetchmailmethod} = $cdb->get_prop('fetchmail', 'Method'); | ||||
| 	    $mai_datas{freqoffice} = $cdb->get_prop('fetchmail', 'FreqOffice'); | ||||
| @@ -86,9 +93,10 @@ sub do_display { | ||||
| 	    $mai_datas{specifyheader} = get_secondary_mail_use_envelope(); | ||||
| 	    $mai_datas{secondarymailenvelope} = $cdb->get_prop('fetchmail', 'SecondaryMailEnvelope'); | ||||
|  | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|         if ( $trt eq 'DEL' ) { | ||||
|     if ( $trt eq 'DEL' )  | ||||
|     { | ||||
| 	    $dest = 'emaildeliver'; | ||||
| 	    $mai_datas{emailunknownuser} = $cdb->get_value('EmailUnknownUser') || '"returntosender'; | ||||
| 	    $mai_datas{delegatemailserver} = $cdb->get_value('DelegateMailServer'); | ||||
| @@ -96,7 +104,7 @@ sub do_display { | ||||
| 	    $mai_datas{smtpauthproxystatus} = $cdb->get_prop('smtp-auth-proxy', 'status') || 'disabled'; | ||||
| 	    $mai_datas{smtpauthproxyuserid} = $cdb->get_prop('smtp-auth-proxy', 'Userid') || ''; | ||||
| 	    $mai_datas{smtpauthproxypassword} = $cdb->get_prop('smtp-auth-proxy', 'Passwd') || ''; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|  | ||||
|     $c->stash( title => $title, notif => $notif, mai_datas => \%mai_datas ); | ||||
| @@ -115,103 +123,113 @@ sub do_update { | ||||
|  | ||||
|     my %mai_datas = (); | ||||
|     $mai_datas{trt} = $trt; | ||||
| 	$cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|  | ||||
|     my $title = $c->l('mai_FORM_TITLE'); | ||||
|  | ||||
|     my ($dest, $res, $result) = ''; | ||||
|  | ||||
|     if ( $trt eq 'ACC' ) { | ||||
|     if ( $trt eq 'ACC' )  | ||||
|     { | ||||
|      	$dest = 'emailaccess'; | ||||
| 			#	$mai_datas{xxx}	= $c->param('XXX'); | ||||
| 			 | ||||
| 			# controls | ||||
| 			#	$res = xxxxxxx( $c ); | ||||
| 			#	$result .= $res unless $res eq 'OK'; | ||||
|  | ||||
| 	$dest = 'emailaccess'; | ||||
| #	$mai_datas{xxx}	= $c->param('XXX'); | ||||
| 			if ( ! $result )  | ||||
| 			{ | ||||
| 	    	$res = $c->change_settings_access(); | ||||
| 	    	$result .= $res unless $res eq 'OK'; | ||||
| 	    	if ( ! $result )  | ||||
| 				{  | ||||
| 					$result = $c->l('mai_SUCCESS');  | ||||
|     		} | ||||
| 			} | ||||
|    	} | ||||
|  | ||||
| 	# controls | ||||
| #	$res = xxxxxxx( $c ); | ||||
| #	$result .= $res unless $res eq 'OK'; | ||||
|     if ( $trt eq 'FIL' )  | ||||
| 			{ | ||||
| 			$dest = 'emailfilter'; | ||||
| 			#	$mai_datas{xxx}	= $c->param('XXX'); | ||||
| 			 | ||||
| 			# controls | ||||
| 			#	$res = zzzzzz( $c ); | ||||
| 			#	$result .= $res unless $res eq 'OK'; | ||||
|  | ||||
| 	if ( ! $result ) { | ||||
| 	    $res = $c->change_settings_access(); | ||||
| 	    $result .= $res unless $res eq 'OK'; | ||||
| 	    if ( ! $result ) {  | ||||
| 		$result = $c->l('mai_SUCCESS');  | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| 			if ( ! $result )  | ||||
| 			{ | ||||
| 	    	$res = $c->change_settings_filtering(); | ||||
| 	    	$result .= $res unless $res eq 'OK'; | ||||
| 	    	if ( ! $result )  | ||||
| 				{  | ||||
| 					$result = $c->l('mai_SUCCESS');  | ||||
|     		} | ||||
| 			} | ||||
|    	} | ||||
|  | ||||
|     if ( $trt eq 'FIL' ) { | ||||
|     if ( $trt eq 'REC' )  | ||||
| 		{ | ||||
| 			$dest = 'emailreceive'; | ||||
| 			#	$mai_datas{xxx}	= $c->param('XXX'); | ||||
| 			 | ||||
| 			# controls | ||||
| 			#	$res = yyyyyyyyy( $c ); | ||||
| 			#	$result .= $res unless $res eq 'OK'; | ||||
|  | ||||
| 	$dest = 'emailfilter'; | ||||
| #	$mai_datas{xxx}	= $c->param('XXX'); | ||||
| 			if ( ! $result )  | ||||
| 			{ | ||||
| 	    	$res = $c->change_settings_reception(); | ||||
| 	    	$result .= $res unless $res eq 'OK'; | ||||
| 	    	if ( ! $result )  | ||||
| 				{  | ||||
| 					$result = $c->l('mai_SUCCESS');  | ||||
|     		} | ||||
| 			} | ||||
|    	} | ||||
|  | ||||
| 	# controls | ||||
| #	$res = zzzzzz( $c ); | ||||
| #	$result .= $res unless $res eq 'OK'; | ||||
|     if ( $trt eq 'DEL' )  | ||||
| 		{ | ||||
| 			$dest = 'emaildeliver'; | ||||
| 			#	$mai_datas{xxx}	= $c->param('XXX'); | ||||
| 			 | ||||
| 			# controls | ||||
| 			$res = $c->ip_number_or_blank( $c->param('DelegateMailServer') ); | ||||
| 			$result .= $res . ' DMS <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	if ( ! $result ) { | ||||
| 	    $res = $c->change_settings_filtering(); | ||||
| 	    $result .= $res unless $res eq 'OK'; | ||||
| 	    if ( ! $result ) {  | ||||
| 		$result = $c->l('mai_SUCCESS');  | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| 			$res = $c->validate_smarthost( $c->param('SMTPSmartHost') ); | ||||
| 			$result .= $res . ' SH <br>' unless $res eq 'OK'; | ||||
|  | ||||
|     if ( $trt eq 'REC' ) { | ||||
| 			$res = $c->nonblank_if_smtpauth( $c->param('SMTPSmartHost') ); | ||||
| 			$result .= $res . ' SH <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	$dest = 'emailreceive'; | ||||
| #	$mai_datas{xxx}	= $c->param('XXX'); | ||||
| 			$res = $c->nonblank_if_smtpauth( $c->param('SMTPAUTHPROXY_Userid') ); | ||||
| 			$result .= $res . ' USR <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	# controls | ||||
| #	$res = yyyyyyyyy( $c ); | ||||
| #	$result .= $res unless $res eq 'OK'; | ||||
| 			$res = $c->nonblank_if_smtpauth( $c->param('SMTPAUTHPROXY_Passwd') ); | ||||
| 			$result .= $res . ' PWD <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	if ( ! $result ) { | ||||
| 	    $res = $c->change_settings_reception(); | ||||
| 	    $result .= $res unless $res eq 'OK'; | ||||
| 	    if ( ! $result ) {  | ||||
| 		$result = $c->l('mai_SUCCESS');  | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|     if ( $trt eq 'DEL' ) { | ||||
|  | ||||
| 	$dest = 'emaildeliver'; | ||||
| #	$mai_datas{xxx}	= $c->param('XXX'); | ||||
|  | ||||
| 	# controls | ||||
| 	$res = $c->ip_number_or_blank( $c->param('DelegateMailServer') ); | ||||
| 	$result .= $res . ' DMS <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	$res = $c->validate_smarthost( $c->param('SMTPSmartHost') ); | ||||
| 	$result .= $res . ' SH <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	$res = $c->nonblank_if_smtpauth( $c->param('SMTPSmartHost') ); | ||||
| 	$result .= $res . ' SH <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	$res = $c->nonblank_if_smtpauth( $c->param('SMTPAUTHPROXY_Userid') ); | ||||
| 	$result .= $res . ' USR <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	$res = $c->nonblank_if_smtpauth( $c->param('SMTPAUTHPROXY_Passwd') ); | ||||
| 	$result .= $res . ' PWD <br>' unless $res eq 'OK'; | ||||
|  | ||||
| 	if ( ! $result ) { | ||||
| 	    $res = $c->change_settings_delivery(); | ||||
| 	    $result .= $res unless $res eq 'OK'; | ||||
| 	    if ( ! $result ) {  | ||||
| 		$result = $c->l('mai_SUCCESS'); | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| 			if ( ! $result )  | ||||
| 			{ | ||||
| 				$res = $c->change_settings_delivery(); | ||||
| 				$result .= $res unless $res eq 'OK'; | ||||
| 				if ( ! $result )  | ||||
| 				{  | ||||
| 					$result = $c->l('mai_SUCCESS'); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|  | ||||
|     # common part | ||||
|  | ||||
|     if ($res ne 'OK') { | ||||
| 	$c->stash( error => $result ); | ||||
| 	$c->stash( title => $title, mai_datas => \%mai_datas ); | ||||
| 	return $c->render( $dest ); | ||||
|     } | ||||
|     if ($res ne 'OK')  | ||||
| 			{ | ||||
| 			$c->stash( error => $result ); | ||||
| 			$c->stash( title => $title, mai_datas => \%mai_datas ); | ||||
| 			return $c->render( $dest ); | ||||
|     	} | ||||
|  | ||||
|     my $message = "emailsettings updates $trt DONE"; | ||||
|     $c->app->log->info($message); | ||||
| @@ -221,7 +239,6 @@ sub do_update { | ||||
|  | ||||
| }; | ||||
|  | ||||
|  | ||||
| sub get_virus_status { | ||||
|  | ||||
|     my ($c, $localise) = @_; | ||||
| @@ -249,10 +266,10 @@ sub localise_status { | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_prop { | ||||
| sub get_db_prop { | ||||
|  | ||||
|     my ($c, $item, $prop, $default) = @_; | ||||
|  | ||||
|      | ||||
|     return $cdb->get_prop($item, $prop) || $default; | ||||
| } | ||||
|  | ||||
| @@ -364,6 +381,48 @@ sub get_current_imap_access { | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_current_smtp_ssl_auth { | ||||
|     my ($c, $localise, $soru, $debug) = @_; | ||||
|     die "Error: \$soru must be either 's' or 'u':$soru.\n" unless $soru eq 's' || $soru eq 'u'; | ||||
| 	 | ||||
| 	$cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|  | ||||
|     # Initialize variables with default values | ||||
|     my $smtpStatus = 'none'; | ||||
|     my $smtpAccess = 'none'; | ||||
|     my $smtpAuth = 'disabled';  # assuming 'disabled' as a default | ||||
|      | ||||
|      | ||||
|  | ||||
|     # Fetch SMTP settings based on the value of `$soru` | ||||
|     if ($soru eq "u") { | ||||
|         $smtpStatus = $cdb->get_prop('uqpsmtpd', 'status') || 'enabled'; # Fetch from uqpsmtpd | ||||
|         $smtpAccess = $cdb->get_prop('uqpsmtpd', 'access') || 'public'; | ||||
|         $smtpAuth = 'enabled'; # Assuming authentication is enabled in this context | ||||
|     } else {  | ||||
|         $smtpStatus = $cdb->get_prop('sqpsmtpd', 'status') || 'enabled';  # Fetch from sqpsmtpd | ||||
|         $smtpAccess = $cdb->get_prop('sqpsmtpd', 'access') || 'public';  | ||||
|         $smtpAuth = 'enabled';  # Assuming authentication is enabled in this context | ||||
|     } | ||||
|      | ||||
|     # Retrieve SMTP SSL authentication options | ||||
|     my $options = $c->get_smtp_ssl_auth_options(); | ||||
|  | ||||
|      | ||||
|     if ($soru eq "u" && $debug ) { | ||||
| 		$c->stash('smtp'=>[$smtpStatus,$smtpAccess,$smtpAuth,$soru,$options->{$smtpAccess},$c->l($options->{$smtpAccess})]); | ||||
| #		die "Stop $soru in get_current_smtp_ssl_auth"; | ||||
| 	} | ||||
|      | ||||
|  | ||||
|     # Return appropriate message based on SMTP settings | ||||
|     if ($smtpStatus eq 'enabled' && $smtpAuth eq 'enabled') { | ||||
|         return $localise ? $c->l($options->{$smtpAccess}) : $smtpAccess; | ||||
|     } | ||||
|      | ||||
|     return $localise ? $c->l($options->{disabled}) : 'disabled'; | ||||
| } | ||||
|  | ||||
| sub get_current_smtp_auth { | ||||
|  | ||||
|     my ($c, $localise) = @_; | ||||
| @@ -371,16 +430,13 @@ sub get_current_smtp_auth { | ||||
|     my $smtpStatus = $cdb->get_prop('qpsmtpd', 'status') || 'enabled'; | ||||
|     my $smtpAuth = $cdb->get_prop('qpsmtpd', 'Authentication') || 'enabled'; | ||||
|  | ||||
|     my $smtpsStatus = $cdb->get_prop('sqpsmtpd', 'status') || 'enabled'; | ||||
|     my $smtpsAuth = $cdb->get_prop('sqpsmtpd', 'Authentication') || 'enabled'; | ||||
|  | ||||
|     my $options = get_smtp_auth_options(); | ||||
|  | ||||
|     if ($smtpStatus eq 'enabled' && $smtpAuth eq 'enabled') | ||||
|     if ($smtpStatus eq 'enabled' && $smtpAuth eq 'disabled') | ||||
|     { | ||||
|         return $localise ? $c->l($options->{public}) : 'public'; | ||||
|     } | ||||
|     elsif ($smtpsStatus eq 'enabled' && $smtpsAuth eq 'enabled') | ||||
|     elsif ($smtpStatus eq 'enabled' && $smtpAuth eq 'enabled') | ||||
|     { | ||||
|         return $localise ? $c->l($options->{publicSSL}) : 'publicSSL'; | ||||
|     } | ||||
| @@ -388,6 +444,8 @@ sub get_current_smtp_auth { | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| sub get_current_webmail_status { | ||||
|  | ||||
|   my ($c, $localise) = @_; | ||||
| @@ -395,19 +453,16 @@ sub get_current_webmail_status { | ||||
|   # determine status of webmail | ||||
|   my $WebmailStatus = "disabled"; | ||||
|  | ||||
|   my $IMPStatus = $cdb->get_prop('imp', 'status') || 'disabled'; | ||||
|  | ||||
|   my $HordeStatus = $cdb->get_prop('horde', 'status') || 'disabled'; | ||||
|   my $RoundcubeStatus = $cdb->get_prop('roundcube', 'status') || 'disabled'; | ||||
|  | ||||
|   my $MysqlStatus = $cdb->get_prop('mariadb', 'status') || 'disabled'; | ||||
|  | ||||
|   my $PHPStatus = $cdb->get_prop('php', 'status') || 'disabled'; | ||||
|   my $PHPStatus = $cdb->get_prop('php81-php-fpm', 'status') || 'disabled'; | ||||
|  | ||||
|   my $Networkaccess = $cdb->get_prop('horde','access') || 'disabled'; | ||||
|   my $Networkaccess = $cdb->get_prop('roundcube','access') || 'disabled'; | ||||
|  | ||||
|   # all four components must be on for webmail to be working | ||||
|   if ( ( $IMPStatus eq "enabled" ) | ||||
|        && ( $HordeStatus eq "enabled" ) | ||||
|   # all 3 components must be on for webmail to be working | ||||
|   if ( ( $RoundcubeStatus eq "enabled" ) | ||||
|        && ( $MysqlStatus eq "enabled" ) | ||||
|        && ( $PHPStatus eq "enabled"   )  | ||||
|        && ( $Networkaccess eq "public")) | ||||
| @@ -415,8 +470,7 @@ sub get_current_webmail_status { | ||||
|       $WebmailStatus = "enabledSSL"; | ||||
|     } | ||||
|  | ||||
|   elsif ( ( $IMPStatus eq "enabled" ) | ||||
|        && ( $HordeStatus eq "enabled" ) | ||||
|   elsif ( ( $RoundcubeStatus eq "enabled" ) | ||||
|        && ( $MysqlStatus eq "enabled" ) | ||||
|        && ( $PHPStatus eq "enabled"   ) | ||||
|        && ( $Networkaccess eq "private" )) | ||||
| @@ -491,13 +545,58 @@ sub get_imap_options { | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_smtp_auth_opt { | ||||
|  | ||||
|     my $c = shift; | ||||
|  | ||||
|     return [[ $c->l('mai_SECURE_SMTP') => 'publicSSL'], | ||||
| 	    [ $c->l('Only allow insecure access') => 'public'], | ||||
| 	    [ $c->l('DISABLED') => 'disabled'] | ||||
| 	    ]; | ||||
| } | ||||
|  | ||||
| sub get_smtp_auth_options { | ||||
|      | ||||
|     my $c = shift; | ||||
|  | ||||
|     my %options = ( disabled => 'DISABLED', publicSSL  => 'mai_SECURE_SMTP', public => 'mai_INSECURE_SMTP'); | ||||
|     my %options = ( publicSSL  => 'mai_SECURE_SMTP', public => 'Only allow insecure access',disabled => 'DISABLED'); | ||||
|  | ||||
|     \%options; | ||||
|     return \%options; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_smtp_ssl_auth_options { | ||||
|      | ||||
|     my $c = shift; | ||||
|  | ||||
|     my %options = ( public  => 'Allow public access', local => 'Allow local access only',disabled => 'DISABLED'); | ||||
|  | ||||
|     return \%options; | ||||
| } | ||||
| sub get_smtp_ssl_auth_opt { | ||||
|  | ||||
|     my $c = shift; | ||||
|  | ||||
|     return [[ $c->l('Allow public access') => 'public'], | ||||
| 	    [ $c->l('Allow local access only') => 'local'], | ||||
| 	    [ $c->l('DISABLED') => 'disabled'] | ||||
| 	    ]; | ||||
| } | ||||
|  | ||||
| sub get_key_by_value { | ||||
|     my ($hash_ref, $target_value) = @_; | ||||
|      | ||||
|     # Iterate over the hash | ||||
|     while (my ($key, $value) = each %$hash_ref) { | ||||
|         return $key if $value eq $target_value; | ||||
|     } | ||||
|      | ||||
|     return undef; # Return undef if no match is found | ||||
| } | ||||
| sub get_value_by_key { | ||||
|     my ($hash_ref, $key) = @_; | ||||
|      | ||||
|     return $hash_ref->{$key}; # Return the value associated with the key | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -507,8 +606,7 @@ sub get_webmail_opt { | ||||
|  | ||||
|     return [[ $c->l('DISABLED') => 'disabled' ], | ||||
| 	    [ $c->l('mai_ENABLED_SECURE_ONLY') => 'enabledSSL' ], | ||||
| 	    [ $c->l('mai_ONLY_LOCAL_NETWORK_SSL') => 'localnetworkSSL' ], | ||||
| 	    [ $c->l('mai_ENABLED_BOTH') => 'public' ]]; | ||||
| 	    [ $c->l('mai_ONLY_LOCAL_NETWORK_SSL') => 'localnetworkSSL' ]]; | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -519,10 +617,10 @@ sub get_webmail_options { | ||||
|  | ||||
|     my %options = (  | ||||
| 		disabled   => 'DISABLED',  | ||||
|                enabledSSL => 'mai_ENABLED_SECURE_ONLY', | ||||
|                localnetworkSSL => 'mai_ONLY_LOCAL_NETWORK_SSL' ); | ||||
| 		enabledSSL => 'mai_ENABLED_SECURE_ONLY', | ||||
| 		localnetworkSSL => 'mai_ONLY_LOCAL_NETWORK_SSL'); | ||||
|  | ||||
|     \%options; | ||||
|     return \%options; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -538,15 +636,6 @@ sub get_retrieval_opt { | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_smtp_auth_opt { | ||||
|  | ||||
|     my $c = shift; | ||||
|  | ||||
|     return [[ $c->l('DISABLED') => 'disabled'], | ||||
| 	    [ $c->l('mai_SECURE_SMTP') => 'publicSSL'], | ||||
| 	    [ $c->l('mai_INSECURE_SMTP') => 'public']]; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_emailunknownuser_options { | ||||
|  | ||||
| @@ -658,6 +747,7 @@ sub display_multidrop { | ||||
| sub change_settings_reception { | ||||
|  | ||||
|     my $c = shift; | ||||
|     $cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|  | ||||
|     my $FetchmailMethod = ( $c->param('FetchmailMethod') || 'standard' ); | ||||
|  | ||||
| @@ -701,18 +791,47 @@ sub change_settings_reception { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     my $smtpAuth = ($c->param('SMTPAuth') || 'public'); | ||||
|     if ($smtpAuth eq 'public') { | ||||
|         $cdb->set_prop("qpsmtpd", "Authentication", "enabled" ); | ||||
|         $cdb->set_prop("sqpsmtpd", "Authentication", "enabled" ); | ||||
|     } elsif ($smtpAuth eq 'publicSSL') { | ||||
|         $cdb->set_prop("qpsmtpd", "Authentication", "disabled" ); | ||||
|         $cdb->set_prop("sqpsmtpd", "Authentication", "enabled" ); | ||||
|     } else { | ||||
|         $cdb->set_prop("qpsmtpd", "Authentication", "disabled" ); | ||||
|         $cdb->set_prop("sqpsmtpd", "Authentication", "disabled" ); | ||||
|     } | ||||
| 	# Need code here for all 3 options - 25, 465 ad 587 | ||||
| 	# Options for 25 are enabled and disabled | ||||
| 	#    for 465 and 587 are (access) public, local and (status) disabled | ||||
| 	 | ||||
|      | ||||
|     #my $smtpAuth = ($c->param('SMTPAuth') || 'public'); | ||||
|     #if ($smtpAuth eq 'public') { | ||||
|         #$cdb->set_prop("qpsmtpd", "Authentication", "enabled" ); | ||||
|         #$cdb->set_prop("sqpsmtpd", "Authentication", "enabled" ); | ||||
|     #} elsif ($smtpAuth eq 'publicSSL') { | ||||
|         #$cdb->set_prop("qpsmtpd", "Authentication", "disabled" ); | ||||
|         #$cdb->set_prop("sqpsmtpd", "Authentication", "enabled" ); | ||||
|     #} else { | ||||
|         #$cdb->set_prop("qpsmtpd", "Authentication", "disabled" ); | ||||
|         #$cdb->set_prop("sqpsmtpd", "Authentication", "disabled" ); | ||||
|     #} | ||||
|  | ||||
| 	my @keys = qw(qpsmtpd uqpsmtpd sqpsmtpd); | ||||
|  | ||||
| 	foreach my $key (@keys) { | ||||
| 		my $param_name = $key eq 'qpsmtpd' ? 'SMTPAuth'  | ||||
| 						  : $key eq 'uqpsmtpd' ? 'uSMTPAuth' | ||||
| 						  : 'sSMTPAuth';  # Defaults to 'sSMTPAuth' for 'sqpsmtpd' | ||||
| 		my $SMTPAuth = $c->param($param_name); | ||||
| 		if ($SMTPAuth eq 'disabled') { | ||||
| 			$cdb->set_prop($key, 'status', 'disabled'); | ||||
| 			$cdb->set_prop($key, 'access', 'disabled'); | ||||
| 		} else { | ||||
| 			$cdb->set_prop($key, 'status', 'enabled'); | ||||
| 			if ($key eq 'qpsmtpd') { | ||||
| 				my $auth_status = $SMTPAuth eq 'publicSSL' ? 'enabled' : 'disabled'; | ||||
| 				$cdb->set_prop($key, 'Authentication', $auth_status); | ||||
| 				$cdb->set_prop($key, 'access', 'public'); | ||||
| 			} else { | ||||
| 				$cdb->set_prop($key, 'Authentication', 'enabled'); | ||||
| 				my $auth_key = ($key eq 'uqpsmtpd') ? 'uSMTPAuth' : 'sSMTPAuth'; | ||||
| 				my $access_value = $c->param($auth_key) eq 'public' ? 'public' : 'local'; | ||||
| 				$cdb->set_prop($key, 'access', $access_value); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|     unless ( system( "/sbin/e-smith/signal-event", "email-update" ) == 0 ) | ||||
|     { | ||||
| 	return $c->l('mai_ERROR_UPDATING_CONFIGURATION'); | ||||
| @@ -724,6 +843,7 @@ sub change_settings_reception { | ||||
| sub change_settings_delivery { | ||||
|  | ||||
|     my ($c) = shift; | ||||
|     $cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|  | ||||
|     my $EmailUnknownUser = ($c->param('EmailUnknownUser') || 'returntosender'); | ||||
|  | ||||
| @@ -752,7 +872,8 @@ sub change_settings_delivery { | ||||
| sub change_settings_access { | ||||
|  | ||||
|     my $c = shift; | ||||
|  | ||||
| 	$cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|      | ||||
|     my $pop3Access = ($c->param('POPAccess') || 'private'); | ||||
|     if ($pop3Access eq 'disabled') { | ||||
|         $cdb->set_prop('pop3', "status", "disabled" ); | ||||
| @@ -802,38 +923,22 @@ sub change_settings_access { | ||||
|     #------------------------------------------------------------ | ||||
|  | ||||
|     my $webmail = ($c->param('WebMail') || 'disabled'); | ||||
|     if ( $webmail eq "enabled" ) { | ||||
|       $cdb->set_prop('php', "status", $webmail ); | ||||
|       $cdb->set_prop('mariadb',"status", $webmail ); | ||||
|       $cdb->set_prop('imp',"status", $webmail ); | ||||
|       $cdb->set_prop('horde', "status", $webmail ); | ||||
|       $cdb->set_prop('imp',"access", "full" ); | ||||
|       $cdb->set_prop('horde',"access", "public" ); | ||||
|       $cdb->set_prop('horde',"HttpsOnly", "no" ); | ||||
|     } | ||||
|     elsif ( $webmail eq "enabledSSL" ) { | ||||
|       $cdb->set_prop('php',"status", "enabled" ); | ||||
|     if ( $webmail eq "enabledSSL" ) { | ||||
|       $cdb->set_prop('php81-php-fpm',"status", "enabled" ); | ||||
|       $cdb->set_prop('mariadb',"status", "enabled" ); | ||||
|       $cdb->set_prop('imp',"status", 'enabled' ); | ||||
|       $cdb->set_prop('horde',"status", 'enabled' ); | ||||
|       $cdb->set_prop('imp',"access", "SSL" ); | ||||
|       $cdb->set_prop('horde',"access", "public" ); | ||||
|       $cdb->set_prop('horde',"HttpsOnly", "yes" ); | ||||
|       $cdb->set_prop('roundcube',"status", 'enabled' ); | ||||
|       $cdb->set_prop('roundcube',"access", "public" ); | ||||
|     } | ||||
|  | ||||
|     elsif ( $webmail eq "localnetworkSSL" ) { | ||||
|       $cdb->set_prop('php',"status", "enabled" ); | ||||
|       $cdb->set_prop('php81-php-fpm',"status", "enabled" ); | ||||
|       $cdb->set_prop('mariadb',"status", "enabled" ); | ||||
|       $cdb->set_prop('imp',"status", 'enabled' ); | ||||
|       $cdb->set_prop('horde',"status", 'enabled' ); | ||||
|       $cdb->set_prop('imp',"access", "SSL" ); | ||||
|       $cdb->set_prop('horde',"access", "private" ); | ||||
|       $cdb->set_prop('horde',"HttpsOnly", "yes" ); | ||||
|       $cdb->set_prop('roundcube',"status", 'enabled' ); | ||||
|       $cdb->set_prop('roundcube',"access", "private" ); | ||||
|      } | ||||
|  | ||||
|     else { | ||||
|       $cdb->set_prop('imp',"status", 'disabled' ); | ||||
|       $cdb->set_prop('horde',"status", 'disabled' ); | ||||
|       $cdb->set_prop('roundcube',"status", 'disabled' ); | ||||
|     } | ||||
|  | ||||
|     unless ( system( "/sbin/e-smith/signal-event", "email-update" ) == 0 ) { | ||||
| @@ -847,6 +952,8 @@ sub change_settings_access { | ||||
| sub change_settings_filtering { | ||||
|  | ||||
|     my $c = shift; | ||||
|     $cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|  | ||||
|  | ||||
|     my $virus_status = ( $c->param('VirusStatus') || 'disabled' ); | ||||
|     $cdb->set_prop("qpsmtpd", 'VirusScan', $virus_status); | ||||
| @@ -860,7 +967,7 @@ sub change_settings_filtering { | ||||
|                         Subject | ||||
| 			SubjectTag) ) | ||||
|     { | ||||
| 	$cdb->set_prop('spamassassin', $param, $c->param("Spam$param")); | ||||
| 	  $cdb->set_prop('spamassassin', $param, $c->param("Spam$param")); | ||||
|     } | ||||
|  | ||||
|     my $patterns_status = $c->adjust_patterns() ? 'enabled' : 'disabled'; | ||||
| @@ -868,7 +975,7 @@ sub change_settings_filtering { | ||||
|  | ||||
|     unless ( system( "/sbin/e-smith/signal-event", "email-update" ) == 0 ) | ||||
|     { | ||||
| 	return $c->l('mai_ERROR_UPDATING_CONFIGURATION'); | ||||
| 	    return $c->l('mai_ERROR_UPDATING_CONFIGURATION'); | ||||
|     } | ||||
|  | ||||
|     return 'OK'; | ||||
| @@ -922,4 +1029,4 @@ sub validate_smarthost { | ||||
| } | ||||
|  | ||||
|  | ||||
| 1; | ||||
| 1; | ||||
| @@ -0,0 +1,472 @@ | ||||
| # | ||||
| # Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-11-16 10:30:16  | ||||
| # | ||||
| # | ||||
| # Routines to be edited by the developer to provide content and validation for parameters | ||||
| # and provison of the control data for table(s) | ||||
| # | ||||
| use esmith::util; | ||||
| use esmith::util::network; | ||||
| use esmith::ConfigDB; | ||||
| use esmith::HostsDB; | ||||
| use esmith::AccountsDB; | ||||
| use esmith::NetworksDB; | ||||
| use esmith::DomainsDB; | ||||
|  | ||||
| use constant FALSE => 0; | ||||
| use constant TRUE  => 1; | ||||
|  | ||||
|  | ||||
| #The most common ones | ||||
| our $cdb = esmith::ConfigDB->open()   || die("Couldn't open config db"); | ||||
| our $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); | ||||
| our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); | ||||
| our $hdb = esmith::HostsDB->open() 	  || die("Couldn't open Hosts db"); | ||||
| our $ddb = esmith::DomainsDB->open()  || die("Couldn't open Domains db"); | ||||
|  | ||||
| # Validation routines - parameters for each panel | ||||
|  | ||||
| 	sub validate_LIST { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		# Validation for each field  | ||||
| 		my $ret = ""; | ||||
| 		 | ||||
| 		if (! TRUE) #validate $c->param('InternalIP') | ||||
| 			{$ret .= 'Validation for InternalIP failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('ExternalIP') | ||||
| 			{$ret .= 'Validation for ExternalIP failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('InternetIP') | ||||
| 			{$ret .= 'Validation for InternetIP failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('Issuer') | ||||
| 			{$ret .= 'Validation for Issuer failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('Expiry') | ||||
| 			{$ret .= 'Validation for Expiry failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('NotBefore') | ||||
| 			{$ret .= 'Validation for NotBefore failed';}	 | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub validate_PARAMS { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		# Validation for each field  | ||||
| 		my $ret = ""; | ||||
| 		if (! TRUE) #validate $c->param('status') | ||||
| 			{$ret .= 'Validation for status failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('hookScript') | ||||
| 			{$ret .= 'Validation for hookScript failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('hostOverride') | ||||
| 			{$ret .= 'Validation for hostOverride failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('ACCEPT_TERMS') | ||||
| 			{$ret .= 'Validation for ACCEPT_TERMS failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('API') | ||||
| 			{$ret .= 'Validation for API failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('keysize') | ||||
| 			{$ret .= 'Validation for keysize failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('configure') | ||||
| 			{$ret .= 'Validation for configure failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('Email') | ||||
| 			{$ret .= 'Validation for Email failed';}	 | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub validate_CHECKALLDOMAINS { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		# Validation for each field  | ||||
| 		my $ret = ""; | ||||
| 		 | ||||
| 		if (! TRUE) #validate $c->param('AllDomainsCheck') | ||||
| 			{$ret .= 'Validation for AllDomainsCheck failed';}	 | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub validate_CHECKALLENABLEDDOMAINS { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		# Validation for each field  | ||||
| 		my $ret = ""; | ||||
| 		 | ||||
| 		if (! TRUE) #validate $c->param('EnabledDomainsCheck') | ||||
| 			{$ret .= 'Validation for EnabledDomainsCheck failed';}	 | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub validate_CHECKONEDOMAIN { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		# Validation for each field  | ||||
| 		my $ret = ""; | ||||
| 		 | ||||
| 		if (! TRUE) #validate $c->param('OneDomainToCheck') | ||||
| 			{$ret .= 'Validation for OneDomainToCheck failed';}	 | ||||
| 		if (! TRUE) #validate $c->param('OneDomainsCheck') | ||||
| 			{$ret .= 'Validation for OneDomainsCheck failed';}	 | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| # Get singleton data for each panel | ||||
|  | ||||
| 	sub get_data_for_panel_LIST { | ||||
| 		# Return a hash with the fields required which will be loaded into the shared data  | ||||
| 		my $c = shift; | ||||
| #		my ($reply, $err, $server_cert) = Net::SSLeay::sslcat('localhost', 443, '/'); | ||||
| #		my $issuer = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($server_cert)); | ||||
| #		my $before = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notBefore($server_cert)); | ||||
| #		my $expiry = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($server_cert)); | ||||
|  | ||||
| 		my %ret = ( | ||||
| 			'Data1'=>'Data for LIST', #Example | ||||
| 			# fields from Inputs in LIST $fields['LIST'] | ||||
| 			'InternalIP'=>$cdb->get_prop('InternalInterface','IPAddress'), | ||||
| 			'ExternalIP'=>$cdb->get_prop('ExternalInterface','IPAddress'), | ||||
| 			'InternetIP'=>$c->get_my_ip(), | ||||
| 			'Issuer'=>'$issuer', | ||||
| 			'Expiry'=>'$expiry', | ||||
| 			'NotBefore'=>'$before', | ||||
| 		); | ||||
| 		return %ret; | ||||
| 	} | ||||
|  | ||||
| 	sub get_data_for_panel_PARAMS { | ||||
| 		# Return a hash with the fields required which will be loaded into the shared data  | ||||
| 		my $c = shift; | ||||
| 		my %ret = ( | ||||
| 			'Data1'=>'Data for PARAMS', #Example | ||||
| 			# fields from Inputs in PARAMS $fields['PARAMS'] | ||||
| 				'status'=>$cdb->get_prop('letsencrypt', 'status', 'disabled'), | ||||
| 				'hookScript'=>$cdb->get_prop('letsencrypt', 'hookScript', 'disabled'), | ||||
| 				'hostOverride'=>$cdb->get_prop('letsencrypt', 'hostOverride', 'disabled'), | ||||
| 				'ACCEPT_TERMS'=>$cdb->get_prop('letsencrypt', 'ACCEPT_TERMS', ''), | ||||
| 				'API'=>$cdb->get_prop('letsencrypt', 'API', '2'), | ||||
| 				'keysize'=>$cdb->get_prop('letsencrypt', 'keysize', '4096'), | ||||
| 				'configure'=>$cdb->get_prop('letsencrypt', 'configure', 'none' ), | ||||
| 				'email'=>$cdb->get_prop('letsencrypt', 'email') | ||||
| 		); | ||||
| 		return %ret; | ||||
| 	} | ||||
|  | ||||
| 	sub get_data_for_panel_CHECKALLDOMAINS { | ||||
| 		# Return a hash with the fields required which will be loaded into the shared data  | ||||
| 		my $c = shift; | ||||
| 		my %ret = ( | ||||
| 			'Data1'=>'Data for CHECKALLDOMAINS', #Example | ||||
| 			# fields from Inputs in CHECKALLDOMAINS $fields['CHECKALLDOMAINS'] | ||||
| 			'AllDomainsCheck'=>$c->update_all_domains(), | ||||
| 			 | ||||
| 		); | ||||
| 		return %ret; | ||||
| 	} | ||||
|  | ||||
| 	sub get_data_for_panel_CHECKALLENABLEDDOMAINS { | ||||
| 		# Return a hash with the fields required which will be loaded into the shared data  | ||||
| 		my $c = shift; | ||||
| 		my %ret = ( | ||||
| 			'Data1'=>'Data for CHECKALLENABLEDDOMAINS', #Example | ||||
| 			# fields from Inputs in CHECKALLENABLEDDOMAINS $fields['CHECKALLENABLEDDOMAINS'] | ||||
| 			'EnabledDomainsCheck'=>$c->update_enabled_domains(), | ||||
| 			 | ||||
| 		); | ||||
| 		return %ret; | ||||
| 	} | ||||
|  | ||||
| 	sub get_data_for_panel_CHECKONEDOMAIN { | ||||
| 		# Return a hash with the fields required which will be loaded into the shared data  | ||||
| 		my $c = shift; | ||||
| 		my %ret = ( | ||||
| 			'Data1'=>'Data for CHECKONEDOMAIN', #Example | ||||
| 			# fields from Inputs in CHECKONEDOMAIN $fields['CHECKONEDOMAIN'] | ||||
| 			'OneDomainToCheck'=>$c->param("CHECKONEDOMAIN"), | ||||
| 			'OneDomainsCheck'=>$c->update_one_domain($c->param("CHECKONEDOMAIN")) | ||||
| 		); | ||||
| 		return %ret; | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| # Get control data for table(s) | ||||
|  | ||||
| 	# Define a constant hash for field name mapping | ||||
| 	use constant DomainList_FIELD_MAPPING => ( | ||||
| 		'Table1-Domain name / HOSTNAME' => 'Domain', | ||||
| 		'Table1-Brief description' => 'Description', | ||||
| 		'Table1-Content' => 'Content', | ||||
| 		'Table1-LABEL_NAMESERVERS' => 'Nameservers', | ||||
| 		'Table1-LABEL_POINT' => 'Source-for-Table1-LABEL_POINT', | ||||
| 		'Table1-LABEL_LECERT' => 'letsencryptSSLcert', | ||||
| 		'Table1-IS_IN_CERT' => 'isincert', | ||||
| 		'Table1-CHECK' => 'Check' | ||||
| 		#'target_field2' => 'source_field2', | ||||
| 		# Add more mappings as needed | ||||
| 	); | ||||
| 	 | ||||
| 	 | ||||
| use constant TEST_DOMAIN_LIST => ( | ||||
|     { "domain" => "Domain1","fred" => "fred1" , "description"=>"Description1"}, | ||||
|     { "domain" => "Domain2", "fred" => "fred2", "description"=>"Description2" }, | ||||
|     { "domain" => "Domain3", "fred" => "fred3", "description"=>"Description3" }, | ||||
|     # Add more test entries as needed | ||||
| ); | ||||
|  | ||||
| sub actual_DomainList { | ||||
| 	my $c = shift; | ||||
| 	# Actual code for extracting DomainList | ||||
| 	my @list = (); | ||||
| #	my @rv = Net::SSLeay::X509_get_subjectAltNames($server_cert); | ||||
| #	foreach my $element (@rv) { | ||||
| #		 next if $element  =~ /^\d+$/; ; | ||||
| #		 #print $element . "\n"; | ||||
| #		 push @list, $element; | ||||
| #	} | ||||
| 	my @data = (); | ||||
| 	my $check = $c->l('Check Domain'); | ||||
| 	for ($ddb->domains) | ||||
| 	{ | ||||
| 		my $ns = $_->prop('Nameservers') || 'internet'; | ||||
| 		my $le = $_->prop('letsencryptSSLcert') || 'disabled';#letsencrypt configure all | ||||
| 		my $dname= $_->key; | ||||
| 		my $isincert = "N"; | ||||
| 		my $link = $c->create_link("letsencryptd","CHECKONEDOMAIN",""); | ||||
| 		my $checklink = "<a href='".$link."&CHECKONEDOMAIN=".$_->key."'>".$check."</a>"; | ||||
| 		#my $checklink = "<a href=''>check</a>"; | ||||
| 		$isincert = "Y" if ( $dname ~~ @list); | ||||
| 		# domain | ||||
| 		push @data,  | ||||
| 			{ Domain => $_->key,  | ||||
| 			  $_->props,   | ||||
| 			  letsencryptSSLcert => $le,  | ||||
| 			  isincert => $isincert, | ||||
| 			  Check => $checklink,  | ||||
| 			  Nameservers => $ns, | ||||
| 		   }; | ||||
| 		#and hosts  | ||||
| 		for my $h ($hdb->get_hosts_by_domain($dname)) | ||||
| 		{ | ||||
| 			next if $ddb->get($h->key); | ||||
| 			next unless ($h->prop('HostType') eq "Self" || $h->prop('HostType') eq "Local"); | ||||
| 			$le = $h->prop('letsencryptSSLcert') || 'disabled';#letsencrypt configure all | ||||
| 			$isincert = "N"; | ||||
| 			$isincert = "Y" if ( $h->key ~~ @list); | ||||
| 			push @data, | ||||
| 			  { Domain => "--> ". $h->key,  | ||||
| 				 $h->props, | ||||
| 				 Description=>$h->prop('ExternalIP')|| $h->prop('InternalIP')||"", | ||||
| 				Content => $h->prop('HostType'), | ||||
| 				isincert => $isincert, | ||||
| 				Check => "", #$checklink | ||||
| 				Nameservers => $c->l($ns), | ||||
| 			  } | ||||
| 		} | ||||
| 	} | ||||
| 	return @data; | ||||
| } | ||||
|  | ||||
| sub get_DomainList { | ||||
|     # Return an array of hashes of the contents for each row and column for DomainList | ||||
| 	my $c = shift; | ||||
|     my @source_records = $c->actual_DomainList(); #TEST_DOMAIN_LIST #Replace by code or call to produce contents of table; | ||||
|     my @transformed_records; | ||||
|     my %Field_Mapping = DomainList_FIELD_MAPPING; | ||||
|     # Iterate over each record in the source array | ||||
|     for my $source_record (@source_records) { | ||||
|         my %transformed_record; | ||||
|         # Iterate over each key-value pair in the $Field_Mapping constant | ||||
|         while (my ($target, $source) = each %Field_Mapping) { | ||||
|             # Check if the source field exists in the source record | ||||
|             if (exists $source_record->{$source}) { | ||||
|                 # Assign the source field value to the target field in the transformed record | ||||
|                 $transformed_record{$target} = $source_record->{$source}; | ||||
|             } | ||||
|         } | ||||
|         # Add transformed record to the array if it's not empty | ||||
|         push @transformed_records, \%transformed_record if %transformed_record; | ||||
|     } | ||||
|     return \@transformed_records; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| # Return hash with values from row in which link clicked on table | ||||
|  | ||||
| 	sub get_selected_LIST { | ||||
| 		my $c = shift; | ||||
| 		my $selected = shift; #Parameter is name of selected row. | ||||
| 		my $is_new_record = shift; #Indicates new record required (defaults) | ||||
| 		my %ret = {}; | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub get_selected_PARAMS { | ||||
| 		my $c = shift; | ||||
| 		my $selected = shift; #Parameter is name of selected row. | ||||
| 		my $is_new_record = shift; #Indicates new record required (defaults) | ||||
| 		my %ret = {}; | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub get_selected_CHECKALLDOMAINS { | ||||
| 		my $c = shift; | ||||
| 		my $selected = shift; #Parameter is name of selected row. | ||||
| 		my $is_new_record = shift; #Indicates new record required (defaults) | ||||
| 		my %ret = {}; | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub get_selected_CHECKALLENABLEDDOMAINS { | ||||
| 		my $c = shift; | ||||
| 		my $selected = shift; #Parameter is name of selected row. | ||||
| 		my $is_new_record = shift; #Indicates new record required (defaults) | ||||
| 		my %ret = {}; | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub get_selected_CHECKONEDOMAIN { | ||||
| 		my $c = shift; | ||||
| 		my $selected = shift; #Parameter is name of selected row. | ||||
| 		my $is_new_record = shift; #Indicates new record required (defaults) | ||||
| 		my %ret = {}; | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| #after sucessful modify or create or whatever and submit then perfom (if the params validate) | ||||
|  | ||||
| 	sub perform_LIST { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		my $ret = ""; | ||||
| 		my $db = $cdb; #maybe one of the others | ||||
| 		my $dbkey = 'ChangeThis'; | ||||
| 		 | ||||
| 		if (! TRUE) #copy or perform with value: InternalIP e.g. $db->set_prop($dbkey,'InternalIP',$c->param('InternalIP'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for InternalIP';} | ||||
| 		if (! TRUE) #copy or perform with value: ExternalIP e.g. $db->set_prop($dbkey,'ExternalIP',$c->param('ExternalIP'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for ExternalIP';} | ||||
| 		if (! TRUE) #copy or perform with value: InternetIP e.g. $db->set_prop($dbkey,'InternetIP',$c->param('InternetIP'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for InternetIP';} | ||||
| 		if (! TRUE) #copy or perform with value: Issuer e.g. $db->set_prop($dbkey,'Issuer',$c->param('Issuer'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for Issuer';} | ||||
| 		if (! TRUE) #copy or perform with value: Expiry e.g. $db->set_prop($dbkey,'Expiry',$c->param('Expiry'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for Expiry';} | ||||
| 		if (! TRUE) #copy or perform with value: NotBefore e.g. $db->set_prop($dbkey,'NotBefore',$c->param('NotBefore'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for NotBefore';} | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub perform_PARAMS { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		my $ret = ""; | ||||
| 		my $db = $cdb; #maybe one of the others | ||||
| 		my $dbkey = 'letsencrypt'; | ||||
| 		# To make it write to DB as comment, delete this (regex) string in each if statement "TRUE\) \#copy or perform with value: .* e.g." | ||||
| 		 | ||||
| 		if (!  $db->set_prop($dbkey,'status',$c->param('status'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for status';} | ||||
| 		if (!  $db->set_prop($dbkey,'hookScript',$c->param('hookScript'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for hookScript';} | ||||
| 		if (!  $db->set_prop($dbkey,'hostOverride',$c->param('hostOverride'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for hostOverride';} | ||||
| 		if (!  $db->set_prop($dbkey,'ACCEPT_TERMS',$c->param('ACCEPT_TERMS'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for ACCEPT_TERMS';} | ||||
| 		if (!  $db->set_prop($dbkey,'API',$c->param('API'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for API';} | ||||
| 		if (!  $db->set_prop($dbkey,'keysize',$c->param('keysize'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for keysize';} | ||||
| 		if (!  $db->set_prop($dbkey,'configure',$c->param('configure'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for configure';} | ||||
| 		if (!  $db->set_prop($dbkey,'email',$c->param('email'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for email';} | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
| 	 | ||||
| 	sub perform_CHECKALLDOMAINS { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		my $ret = ""; | ||||
| 		my $db = $cdb; #maybe one of the others | ||||
| 		my $dbkey = 'ChangeThis'; | ||||
| 		 | ||||
| 		if (! TRUE) #copy or perform with value: AllDomainsCheck e.g. $db->set_prop($dbkey,'AllDomainsCheck',$c->param('AllDomainsCheck'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for AllDomainsCheck';} | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub perform_CHECKALLENABLEDDOMAINS { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		my $ret = ""; | ||||
| 		my $db = $cdb; #maybe one of the others | ||||
| 		my $dbkey = 'ChangeThis'; | ||||
| 		 | ||||
| 		if (! TRUE) #copy or perform with value: EnabledDomainsCheck e.g. $db->set_prop($dbkey,'EnabledDomainsCheck',$c->param('EnabledDomainsCheck'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for EnabledDomainsCheck';} | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
| 	sub perform_CHECKONEDOMAIN { | ||||
| 		my $c = shift; | ||||
| 		my $prefix_data = shift; #Data hash as parameter | ||||
| 		my $ret = ""; | ||||
| 		my $db = $cdb; #maybe one of the others | ||||
| 		my $dbkey = 'ChangeThis'; | ||||
| 		 | ||||
| 		if (! TRUE) #copy or perform with value: OneDomainToCheck e.g. $db->set_prop($dbkey,'OneDomainToCheck',$c->param('OneDomainToCheck'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for OneDomainToCheck';} | ||||
| 		if (! TRUE) #copy or perform with value: OneDomainsCheck e.g. $db->set_prop($dbkey,'OneDomainsCheck',$c->param('OneDomainsCheck'),type=>'service')) | ||||
| 			{$ret .= 'Perform/save failed for OneDomainsCheck';} | ||||
| 		if ($ret eq "") {$ret = 'ok';} | ||||
| 		return $ret; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| sub create_link{ | ||||
| 	# WIP | ||||
| 	my ($c,$route, $panel, $index) = @_; | ||||
| 	my $link = "$route?trt=$panel&Selected=$index"; | ||||
| 	return $link; | ||||
| } | ||||
|  | ||||
| sub get_my_ip | ||||
| { | ||||
|     my ($self, $item, $prop, $default) = @_; | ||||
|     my $output = `/usr/sbin/e-smith/getmyip`; | ||||
|     return  $output || "IP"; | ||||
| } | ||||
|  | ||||
| sub update_one_domain | ||||
| { | ||||
|     my ($self,$domain) = @_; | ||||
|     return "$domain not domain" unless ($ddb->get($domain) || $hdb->get($domain)); | ||||
|     ($domain) = ($domain =~ /([\w\p{L}.]+)/);  | ||||
|     my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains " " $domain `; | ||||
|     return  $output || "-empty-"; | ||||
| } | ||||
|  | ||||
| sub update_all_domains | ||||
| { | ||||
|     my $self = shift; | ||||
|     my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains "" "" all `; | ||||
|     return  $output || "-empty-"; | ||||
| } | ||||
|  | ||||
| sub update_enabled_domains | ||||
| { | ||||
|     my $self = shift; | ||||
|     my $output = `/etc/e-smith/events/actions/letsencrypt-setdomains "" "" enabled `; | ||||
|     return  $output || "-empty-"; | ||||
| } | ||||
|  | ||||
|  | ||||
| 1; | ||||
							
								
								
									
										429
									
								
								root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								root/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,429 @@ | ||||
| package SrvMngr::Controller::Letsencrypt; | ||||
| # | ||||
| # Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43  | ||||
| # | ||||
| #---------------------------------------------------------------------- | ||||
| # heading     : Network | ||||
| # description : Letsencrypt certificate | ||||
| # navigation  : 6000 6600 | ||||
| # | ||||
| # name : letsencrypt,    method : get,   url : /letsencrypt,   ctlact : Letsencrypt#main | ||||
| # name : letsencryptu,   method : post,  url : /letsencryptu,  ctlact : Letsencrypt#do_update | ||||
| # name : letsencryptd,   method : get,   url : /letsencryptd,  ctlact : Letsencrypt#do_display | ||||
| # | ||||
| # routes : end | ||||
| # | ||||
| # Documentation: https://wiki.contribs.org/Letsencrypt | ||||
| #---------------------------------------------------------------------- | ||||
|  | ||||
| # | ||||
| # Scheme of things: | ||||
| # | ||||
| # TBA!! | ||||
|  | ||||
| use strict; | ||||
| use warnings; | ||||
| use Mojo::Base 'Mojolicious::Controller'; | ||||
|  | ||||
| use constant FALSE => 0; | ||||
| use constant TRUE  => 1; | ||||
|  | ||||
| use Locale::gettext; | ||||
| use SrvMngr::I18N; | ||||
| use SrvMngr qw(theme_list init_session); | ||||
|  | ||||
| use Data::Dumper; | ||||
|  | ||||
| use esmith::util; | ||||
| use esmith::util::network; | ||||
| use esmith::ConfigDB; | ||||
| use esmith::AccountsDB; | ||||
| use esmith::NetworksDB; | ||||
| use esmith::HostsDB; | ||||
| use esmith::DomainsDB; | ||||
|  | ||||
|  | ||||
|  | ||||
| require '/usr/share/smanager/lib/SrvMngr/Controller/Letsencrypt-Custom.pm';  #The code that is to be added by the developer | ||||
|  | ||||
| sub main { | ||||
| # | ||||
| # Initial entry - route is "/<whatever>" | ||||
| # | ||||
| #set initial panel | ||||
| #for initial panel: | ||||
| 	#Specifiy panel to enter | ||||
| 	#load up _data hash with DB fields | ||||
| 	#load up stash with pointer(s) to control fields hash(= get-)) | ||||
| 		#and a pointer to the prefix_data hash | ||||
| #render initial panel | ||||
|  | ||||
|     my $c = shift; | ||||
|     $c->app->log->info( $c->log_req ); | ||||
|  | ||||
| 	#The most common ones | ||||
| 	my $cdb = esmith::ConfigDB->open()   || die("Couldn't open config db"); | ||||
| 	my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); | ||||
| 	my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); | ||||
| 	my $hdb = esmith::HostsDB->open() 	  || die("Couldn't open Hosts db"); | ||||
| 	my $ddb = esmith::DomainsDB->open()  || die("Couldn't open Domains db"); | ||||
|  | ||||
|     my %lets_data = (); | ||||
|     my $title = $c->l('lets_Letsencrypt_certificate'); | ||||
|     my $modul = ''; | ||||
|  | ||||
|     $lets_data{'trt'} = 'LIST'; | ||||
|      | ||||
|     #Load any DB entries into the <prefix>_data area so as they are preset in the form | ||||
|     # which DB - this only really works if the initial panel is a PARAMS type panel and not a TABLE | ||||
|     my $db = $cdb; #pickup local or global db or Default to config | ||||
|      | ||||
| 	 | ||||
| 	$c->do_display($lets_data{'trt'}); | ||||
| 	 | ||||
| } | ||||
|  | ||||
| # Post request with params - submit from the form  | ||||
| sub do_update { | ||||
| # | ||||
| # Return after submit pushed on panel (this is a post) - route is "/<whatever>u" | ||||
| # parameters in the params hash. | ||||
| # | ||||
| #load up all params into prefix_data hash: | ||||
| #By panel (series of if statements - only one executed): | ||||
| 		#call validate-PANEL() - return ret = ok or error message | ||||
| 			 | ||||
| #if validation not ok: | ||||
| 	#render back to current panel with error message in stash | ||||
| #otherwise: | ||||
| 	#By panel (series of if statements - only one executed): | ||||
| 		#do whatever is required: call perform-PANEL() - return "ok" or Error Message | ||||
| 			#call signal-event for any global actions specified (check it exists - error and continue?) | ||||
| 			#if action smeserver-<whatever>-update exists | ||||
| 				#signal_event smeserver-<whatever>-update | ||||
| 			#call signal-event for any specific actions for thids panel (check it exists first - error and continue) | ||||
| 		#set success in stash | ||||
| 		#if no "nextpanel" entry: | ||||
| 			#set firstpanel | ||||
| 		#else  | ||||
| 			#set nextpanel | ||||
| 		#call render | ||||
| 	 | ||||
|     my $c = shift; | ||||
|     $c->app->log->info($c->log_req); | ||||
| 	my $modul = ''; | ||||
|  | ||||
| 	#The most common ones - you might want to comment out any not used. | ||||
| 	my $cdb = esmith::ConfigDB->open()   || die("Couldn't open config db"); | ||||
| 	my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); | ||||
| 	my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); | ||||
| 	my $hdb = esmith::HostsDB->open() 	  || die("Couldn't open Hosts db"); | ||||
| 	my $ddb = esmith::DomainsDB->open()  || die("Couldn't open Domains db"); | ||||
|  | ||||
|     my %lets_data = (); | ||||
|     my $title = $c->l('lets_Letsencrypt_certificate'); | ||||
|  | ||||
| 	# Accessing all POST parameters | ||||
|     my %params = $c->req->params->to_hash; | ||||
|  | ||||
|     # Get number of POST parameters | ||||
|     my $num_params = keys %params; | ||||
|      | ||||
|     #Params are available in the hash "params" - copy to the prefix_data hash | ||||
|     #while (my ($key, $value) = each %{$c->req->params->to_hash}) { | ||||
|     #    $lets_data{$key} = $value; | ||||
|     #} | ||||
|  | ||||
|     # the value of trt will tell you which panel has returned     | ||||
|     my $trt = $c->param('trt') || 'LIST'; #hidden control on every form. | ||||
|     my $ret = 'ok'; | ||||
|  | ||||
|     #Validate the parameters in a custom sub one for each panel (although only one of these will be executed) | ||||
|     my $thispanel; | ||||
|      | ||||
| 		if ($trt eq 'LIST'){ | ||||
| 			#Validate form parameters for panel LIST | ||||
| 			$ret = $c->validate_LIST(\%lets_data); | ||||
| 			$thispanel = 'LIST'; | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'PARAMS'){ | ||||
| 			#Validate form parameters for panel PARAMS | ||||
| 			$ret = $c->validate_PARAMS(\%lets_data); | ||||
| 			$thispanel = 'PARAMS'; | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKALLDOMAINS'){ | ||||
| 			#Validate form parameters for panel CHECKALLDOMAINS | ||||
| 			$ret = $c->validate_CHECKALLDOMAINS(\%lets_data); | ||||
| 			$thispanel = 'CHECKALLDOMAINS'; | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKALLENABLEDDOMAINS'){ | ||||
| 			#Validate form parameters for panel CHECKALLENABLEDDOMAINS | ||||
| 			$ret = $c->validate_CHECKALLENABLEDDOMAINS(\%lets_data); | ||||
| 			$thispanel = 'CHECKALLENABLEDDOMAINS'; | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKONEDOMAIN'){ | ||||
| 			#Validate form parameters for panel CHECKONEDOMAIN | ||||
| 			$ret = $c->validate_CHECKONEDOMAIN(\%lets_data); | ||||
| 			$thispanel = 'CHECKONEDOMAIN'; | ||||
| 		} | ||||
| 	 | ||||
| 	if ($ret ne "ok"){ | ||||
| 		$c->do_display($thispanel); | ||||
| 	} else { | ||||
| 		#Do whatever is needed, including writing values to the DB | ||||
| 		 | ||||
| 		 | ||||
| 			if ($trt eq 'LIST'){ | ||||
| 				#do whatever is required ... | ||||
| 				$ret = $c->perform_LIST(\%lets_data); | ||||
| 				if ($ret ne "ok") { | ||||
| 					# return to the panel with error message | ||||
| 					$c->stash(error => $c->l($ret)); | ||||
| 					$c->stash(  | ||||
| 						title => $title,  | ||||
| 						modul => $modul, | ||||
| 						lets_data  => \%lets_data | ||||
| 					); | ||||
| 					$c->render(template => "letsencrypt");	 | ||||
| 				} else { | ||||
| 					$c->stash( success => $c->l('lets_LIST_panel_action_was_successful')); #A bit bland - edit it in the lex file | ||||
| 				} | ||||
| 			} | ||||
| 		 | ||||
| 			if ($trt eq 'PARAMS'){ | ||||
| 				#do whatever is required ... | ||||
| 				$ret = $c->perform_PARAMS(\%lets_data); | ||||
| 				if ($ret ne "ok") { | ||||
| 					# return to the panel with error message | ||||
| 					$c->stash(error => $c->l($ret)); | ||||
| 					$c->stash(  | ||||
| 						title => $title,  | ||||
| 						modul => $modul, | ||||
| 						lets_data  => \%lets_data | ||||
| 					); | ||||
| 					$c->render(template => "letsencrypt");	 | ||||
| 				} else { | ||||
| 					$c->stash( success => $c->l('lets_PARAMS_panel_action_was_successful')); #A bit bland - edit it in the lex file | ||||
| 				} | ||||
| 			} | ||||
| 		 | ||||
| 			if ($trt eq 'CHECKALLDOMAINS'){ | ||||
| 				#do whatever is required ... | ||||
| 				$ret = $c->perform_CHECKALLDOMAINS(\%lets_data); | ||||
| 				if ($ret ne "ok") { | ||||
| 					# return to the panel with error message | ||||
| 					$c->stash(error => $c->l($ret)); | ||||
| 					$c->stash(  | ||||
| 						title => $title,  | ||||
| 						modul => $modul, | ||||
| 						lets_data  => \%lets_data | ||||
| 					); | ||||
| 					$c->render(template => "letsencrypt");	 | ||||
| 				} else { | ||||
| 					$c->stash( success => $c->l('lets_CHECKALLDOMAINS_panel_action_was_successful')); #A bit bland - edit it in the lex file | ||||
| 				} | ||||
| 			} | ||||
| 		 | ||||
| 			if ($trt eq 'CHECKALLENABLEDDOMAINS'){ | ||||
| 				#do whatever is required ... | ||||
| 				$ret = $c->perform_CHECKALLENABLEDDOMAINS(\%lets_data); | ||||
| 				if ($ret ne "ok") { | ||||
| 					# return to the panel with error message | ||||
| 					$c->stash(error => $c->l($ret)); | ||||
| 					$c->stash(  | ||||
| 						title => $title,  | ||||
| 						modul => $modul, | ||||
| 						lets_data  => \%lets_data | ||||
| 					); | ||||
| 					$c->render(template => "letsencrypt");	 | ||||
| 				} else { | ||||
| 					$c->stash( success => $c->l('lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful')); #A bit bland - edit it in the lex file | ||||
| 				} | ||||
| 			} | ||||
| 		 | ||||
| 			if ($trt eq 'CHECKONEDOMAIN'){ | ||||
| 				#do whatever is required ... | ||||
| 				$ret = $c->perform_CHECKONEDOMAIN(\%lets_data); | ||||
| 				if ($ret ne "ok") { | ||||
| 					# return to the panel with error message | ||||
| 					$c->stash(error => $c->l($ret)); | ||||
| 					$c->stash(  | ||||
| 						title => $title,  | ||||
| 						modul => $modul, | ||||
| 						lets_data  => \%lets_data | ||||
| 					); | ||||
| 					$c->render(template => "letsencrypt");	 | ||||
| 				} else { | ||||
| 					$c->stash( success => $c->l('lets_CHECKONEDOMAIN_panel_action_was_successful')); #A bit bland - edit it in the lex file | ||||
| 				} | ||||
| 			} | ||||
| 		 | ||||
| 		# and call any signal-events needed | ||||
| 		#TBD | ||||
| 		# Setup shared data and call panel | ||||
| 		if ('none' eq 'none') { | ||||
| 			$lets_data{'trt'} = 'LIST'; | ||||
| 		} else { | ||||
| 			$lets_data{'trt'} = 'none'; | ||||
| 		}	 | ||||
| 		$c->do_display($lets_data{'trt'}); | ||||
| 	}  | ||||
| } | ||||
|  | ||||
| sub do_display { | ||||
| # | ||||
| # Return after link clicked in table (this is a get) - route is "/<whatever>d" | ||||
| # Expects ?trt=PANEL&selected="TableRowName" plus any other required | ||||
| # | ||||
| # OR it maybe a post from the main panel to add a new record  | ||||
| # | ||||
| #load up all supplied params into prefix_data hash | ||||
| #call get-selected-PANEL() - returns hash of all relevent parameters | ||||
| #load up returned hash into prefix_data | ||||
| #render - to called panel | ||||
|  | ||||
|     my ($c,$trt) = @_; | ||||
|     $c->app->log->info($c->log_req); | ||||
|  | ||||
| 	#The most common ones - you might want to comment out any not used. | ||||
| 	my $cdb = esmith::ConfigDB->open()   || die("Couldn't open config db"); | ||||
| 	my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); | ||||
| 	my $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); | ||||
| 	my $hdb = esmith::HostsDB->open() 	  || die("Couldn't open Hosts db"); | ||||
| 	my $ddb = esmith::DomainsDB->open()  || die("Couldn't open Domains db"); | ||||
|      | ||||
|     my %lets_data = (); | ||||
|     my $title = $c->l('lets_Letsencrypt_certificate'); | ||||
|     my $modul = ""; | ||||
|  | ||||
| 	# Accessing all parameters | ||||
|     my %params = $c->req->params->to_hash; | ||||
|  | ||||
|     # Get number of parameters | ||||
|     my $num_params = keys %params; | ||||
|      | ||||
|     #Tag as Post or Get (ie. create new entry or edit existing one | ||||
|     my $is_new_record = ($c->req->method() eq 'POST'); | ||||
|      | ||||
|     #Params are available in the hash "params" - copy to the prefix_data hash | ||||
|     #while (my ($key, $value) = each %{$c->req->params->to_hash}) { | ||||
|     #    $lets_data{$key} = $value; | ||||
|     #} | ||||
|  | ||||
|     # the value of trt will tell you which panel has returned    | ||||
|     if (! $trt){  | ||||
| 		$trt = $c->param('trt') || 'LIST'; #Indicates where to go now | ||||
| 	} | ||||
|   | ||||
|     # Now add in the params from the selected row from the table | ||||
| 		 | ||||
|     my %selectedrow; | ||||
|      | ||||
| 		if ($trt eq 'LIST'){ | ||||
| 			#Validate Get selected row (if applicable)  LIST | ||||
| 				%selectedrow = $c->get_selected_LIST($lets_data{'Selected'},$is_new_record); | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'PARAMS'){ | ||||
| 			#Validate Get selected row (if applicable)  PARAMS | ||||
| 				%selectedrow = $c->get_selected_PARAMS($lets_data{'Selected'},$is_new_record); | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKALLDOMAINS'){ | ||||
| 			#Validate Get selected row (if applicable)  CHECKALLDOMAINS | ||||
| 				%selectedrow = $c->get_selected_CHECKALLDOMAINS($lets_data{'Selected'},$is_new_record); | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKALLENABLEDDOMAINS'){ | ||||
| 			#Validate Get selected row (if applicable)  CHECKALLENABLEDDOMAINS | ||||
| 				%selectedrow = $c->get_selected_CHECKALLENABLEDDOMAINS($lets_data{'Selected'},$is_new_record); | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKONEDOMAIN'){ | ||||
| 			#Validate Get selected row (if applicable)  CHECKONEDOMAIN | ||||
| 				%selectedrow = $c->get_selected_CHECKONEDOMAIN($lets_data{'Selected'},$is_new_record); | ||||
| 		} | ||||
| 	 | ||||
|   | ||||
| 	#Copy in the selected row params to the prefix_data hash to pass to the panel | ||||
| 	while (my ($key, $value) = each %selectedrow){ | ||||
|         $lets_data{$key} = $value; | ||||
|     } | ||||
| 	# Where to go now | ||||
| 	$lets_data{'trt'} = $trt; | ||||
| 	 | ||||
| 	# Set up other shared data according to the panel to go to | ||||
|      | ||||
| 		if ($trt eq 'LIST'){ | ||||
| 			# pickup any other contents needed and load them into hash shared with panel | ||||
| 			my %returned_hash; | ||||
| 			# subroutine returns a hash directly | ||||
| 			%returned_hash = $c->get_data_for_panel_LIST(); | ||||
| 			# Copy each key-value pair from the returned hash to the prefix data hash | ||||
| 			while (my ($key, $value) = each %returned_hash) { | ||||
| 				$lets_data{$key} = $value; | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'PARAMS'){ | ||||
| 			# pickup any other contents needed and load them into hash shared with panel | ||||
| 			my %returned_hash; | ||||
| 			# subroutine returns a hash directly | ||||
| 			%returned_hash = $c->get_data_for_panel_PARAMS(); | ||||
| 			# Copy each key-value pair from the returned hash to the prefix data hash | ||||
| 			while (my ($key, $value) = each %returned_hash) { | ||||
| 				$lets_data{$key} = $value; | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKALLDOMAINS'){ | ||||
| 			# pickup any other contents needed and load them into hash shared with panel | ||||
| 			my %returned_hash; | ||||
| 			# subroutine returns a hash directly | ||||
| 			%returned_hash = $c->get_data_for_panel_CHECKALLDOMAINS(); | ||||
| 			# Copy each key-value pair from the returned hash to the prefix data hash | ||||
| 			while (my ($key, $value) = each %returned_hash) { | ||||
| 				$lets_data{$key} = $value; | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKALLENABLEDDOMAINS'){ | ||||
| 			# pickup any other contents needed and load them into hash shared with panel | ||||
| 			my %returned_hash; | ||||
| 			# subroutine returns a hash directly | ||||
| 			%returned_hash = $c->get_data_for_panel_CHECKALLENABLEDDOMAINS(); | ||||
| 			# Copy each key-value pair from the returned hash to the prefix data hash | ||||
| 			while (my ($key, $value) = each %returned_hash) { | ||||
| 				$lets_data{$key} = $value; | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
| 		if ($trt eq 'CHECKONEDOMAIN'){ | ||||
| 			# pickup any other contents needed and load them into hash shared with panel | ||||
| 			my %returned_hash; | ||||
| 			# subroutine returns a hash directly | ||||
| 			%returned_hash = $c->get_data_for_panel_CHECKONEDOMAIN(); | ||||
| 			# Copy each key-value pair from the returned hash to the prefix data hash | ||||
| 			while (my ($key, $value) = each %returned_hash) { | ||||
| 				$lets_data{$key} = $value; | ||||
| 			} | ||||
| 		} | ||||
| 	 | ||||
| 	 | ||||
| 	# and table control fields | ||||
|      $c->stash(DomainList=>$c->get_DomainList()); | ||||
|       | ||||
| 	 | ||||
| 	# Data for panel | ||||
| 	$c->stash(  | ||||
| 		title 			=> $title,  | ||||
| 		modul => $modul, | ||||
| 		lets_data  => \%lets_data | ||||
| 	); | ||||
| 	$c->render(template => "letsencrypt"); | ||||
| }     | ||||
| 1; | ||||
| @@ -171,9 +171,11 @@ sub add_portforward { | ||||
| 	#work out which protocol   	 | ||||
| 	my $fdb; | ||||
| 	if ($proto eq 'TCP') { | ||||
| 		$tcp_db = esmith::ConfigDB->open('portforward_tcp') || die "Can't open portforward_tcp database: $!\n"; | ||||
| 		$fdb = $tcp_db; | ||||
| 	} | ||||
| 	else { | ||||
| 		$udp_db = esmith::ConfigDB->open('portforward_udp') || die "Can't open portforward_udp database: $!\n"; | ||||
| 		$fdb = $udp_db; | ||||
| 	} | ||||
| 	#Get the other values  | ||||
|   | ||||
| @@ -26,165 +26,182 @@ use Socket qw( inet_aton ); | ||||
|  | ||||
| #our @ISA = qw(esmith::FormMagick Exporter); | ||||
|  | ||||
| our @EXPORT = qw( networkAccess_list passwordLogin_list get_ssh_permit_root_login get_ssh_access get_telnet_mode | ||||
| 		get_ftp_access  get_ftp_password_login_access | ||||
| 		get_value get_prop get_ssh_password_auth | ||||
| 		validate_network_and_mask ip_number_or_blank subnet_mask_or_blank | ||||
| 		get_ipsecrw_sessions pptp_and_dhcp_range | ||||
| ); | ||||
| our @EXPORT = | ||||
|   qw( networkAccess_list passwordLogin_list get_ssh_permit_root_login get_ssh_access get_telnet_mode | ||||
|   get_ftp_access  get_ftp_password_login_access | ||||
|   get_value get_prop get_ssh_password_auth | ||||
|   validate_network_and_mask ip_number_or_blank subnet_mask_or_blank | ||||
|   get_ipsecrw_sessions pptp_and_dhcp_range | ||||
|   ); | ||||
|  | ||||
| #		get_pptp_sessions | ||||
|  | ||||
| our $db = esmith::ConfigDB->open || warn "Couldn't open configuration database"; | ||||
|  | ||||
|  | ||||
| sub main { | ||||
|  | ||||
|     my $c = shift; | ||||
|     $c->app->log->info($c->log_req); | ||||
|     $c->app->log->info( $c->log_req ); | ||||
|  | ||||
|     my $title = $c->l('rma_FORM_TITLE'); | ||||
|     my $notif = ''; | ||||
|     my $title     = $c->l('rma_FORM_TITLE'); | ||||
|     my $notif     = ''; | ||||
|     my %rma_datas = (); | ||||
|  | ||||
| 	$db = esmith::ConfigDB->open || warn "Couldn't open configuration database"; | ||||
|  | ||||
|     #$rma_datas{ipsecrwSess}  = $c->get_ipsecrw_sessions(); | ||||
|     #$rma_datas{pptpSessions} = $c->get_pptp_sessions(); | ||||
|     $rma_datas{sshAccess} = $c->get_ssh_access(); | ||||
|     $rma_datas{sshPermitRootLogin} = $c->get_ssh_permit_root_login(); | ||||
|     $rma_datas{sshAccess}                 = $c->get_ssh_access(); | ||||
|     $rma_datas{sshPermitRootLogin}        = $c->get_ssh_permit_root_login(); | ||||
|     $rma_datas{sshPasswordAuthentication} = $c->get_ssh_password_auth(); | ||||
|     $rma_datas{sshTCPPort} = $c->get_ssh_port(); | ||||
|     $rma_datas{ftpAccess} = $c->get_ftp_access(); | ||||
|     $rma_datas{ftpPasswordAccess} = $c->get_ftp_password_login_access(); | ||||
|     $rma_datas{sshTCPPort}                = $c->get_ssh_port(); | ||||
|     $rma_datas{ftpAccess}                 = $c->get_ftp_access(); | ||||
|     $rma_datas{ftpPasswordAccess}         = $c->get_ftp_password_login_access(); | ||||
|  | ||||
|     #$rma_datas{telnetAccess} = $c->get_telnet_access; | ||||
|  | ||||
|     $c->stash( title => $title, notif => $notif, rma_datas => \%rma_datas ); | ||||
|     $c->render(template => 'remoteaccess'); | ||||
|  | ||||
| }; | ||||
|     $c->render( template => 'remoteaccess' ); | ||||
|  | ||||
| } | ||||
|  | ||||
| sub do_action { | ||||
|  | ||||
|     my $c = shift; | ||||
|     $c->app->log->info($c->log_req); | ||||
|     $c->app->log->info( $c->log_req ); | ||||
|  | ||||
|     my $title = $c->l('rma_FORM_TITLE'); | ||||
|     my ($result, $res, $trt) = ''; | ||||
|     my ( $result, $res, $trt ) = ''; | ||||
|     my %rma_datas = (); | ||||
|  | ||||
|     $rma_datas{ipsecrwSess}  = ($c->param ('IpsecrwSess') || ''); | ||||
|     $rma_datas{ipsecrwReset}  = ($c->param ('IpsecrwReset') || ''); | ||||
| 	$db = esmith::ConfigDB->open || warn "Couldn't open configuration database"; | ||||
|  | ||||
|     $rma_datas{ipsecrwSess}  = ( $c->param('IpsecrwSess')  || '' ); | ||||
|     $rma_datas{ipsecrwReset} = ( $c->param('IpsecrwReset') || '' ); | ||||
|  | ||||
|     #$rma_datas{pptpSessions} = ($c->param ('PptpSessions') || '0'); | ||||
|  | ||||
|     $rma_datas{validFromNetwork} = ($c->param ('ValidFromNetwork') || ''); | ||||
|     $rma_datas{validFromMask} = ($c->param ('ValidFromMask') || ''); | ||||
|     $rma_datas{validFromNetwork} = ( $c->param('ValidFromNetwork') || '' ); | ||||
|     $rma_datas{validFromMask}    = ( $c->param('ValidFromMask')    || '' ); | ||||
| ##	my @remove = $q->param('validFromRemove');  ???????? the first one only !! | ||||
|     my @vals = $c->param ('Remove_nets'); | ||||
|     my @vals = $c->param('Remove_nets'); | ||||
|     $rma_datas{remove_nets} = join ',', @vals; | ||||
|  | ||||
|     $rma_datas{sshaccess} = ($c->param ('SshAccess') || 'off'); | ||||
|     $rma_datas{sshPermitRootLogin} = ($c->param ('SshPermitRootLogin') || 'no'); | ||||
|     $rma_datas{sshPasswordAuthentication} = ($c->param ('SshPasswordAuthentication') || 'no'); | ||||
|     $rma_datas{sshTCPPort} = ($c->param ('SshTCPPort') || '22'); | ||||
|     $rma_datas{sshaccess} = ( $c->param('SshAccess') || 'off' ); | ||||
|     $rma_datas{sshPermitRootLogin} = | ||||
|       ( $c->param('SshPermitRootLogin') || 'no' ); | ||||
|     $rma_datas{sshPasswordAuthentication} = | ||||
|       ( $c->param('SshPasswordAuthentication') || 'no' ); | ||||
|     $rma_datas{sshTCPPort} = ( $c->param('SshTCPPort') || '22' ); | ||||
|  | ||||
|     $rma_datas{ftpAccess} = ($c->param ('FtpAccess') || 'off'); | ||||
|     $rma_datas{ftpPasswordAccess} = ($c->param ('FtpPasswordAccess') || 'private'); | ||||
|     $rma_datas{ftpAccess} = ( $c->param('FtpAccess') || 'off' ); | ||||
|     $rma_datas{ftpPasswordAccess} = | ||||
|       ( $c->param('FtpPasswordAccess') || 'private' ); | ||||
|  | ||||
|     $rma_datas{telnetAccess} = ($c->param ('TelnetAccess') || 'off'); | ||||
|     $rma_datas{telnetAccess} = ( $c->param('TelnetAccess') || 'off' ); | ||||
|  | ||||
|     # validate | ||||
|     my $v = $c->validation; | ||||
|     return $c->render('remoteaccess') unless $v->has_data; | ||||
|  | ||||
|     #$v->optional('PptpSessions')->num(0, 999)->is_valid; | ||||
|     $v->optional('ValidFromNetwork')->size(7, 15)->is_valid; | ||||
|     $v->optional('ValidFromMask')->size(7, 15)->is_valid; | ||||
|     $v->required('SshTCPPort')->num(1, 65535)->is_valid; | ||||
|     if ( $c->param('ValidFromNetwork') ne "" ) { | ||||
|         $v->optional('ValidFromNetwork')->size( 7, 15 )->is_valid; | ||||
|     } | ||||
|     if ( $c->param('ValidFromMask') ne "" ) { | ||||
|         $v->optional('ValidFromMask')->size( 7, 15 )->is_valid; | ||||
|     } | ||||
|     $v->required('SshTCPPort')->num( 1, 65535 )->is_valid; | ||||
|  | ||||
|     $result .= 'field validation error' if $v->has_error; | ||||
|  | ||||
|     if ( ! $result ) { | ||||
|     if ( !$result ) { | ||||
|  | ||||
| 	# controls | ||||
| 	#$res = pptp_and_dhcp_range( $c, $rma_datas{pptpSessions} ); | ||||
| 	#$result .= $res . ' ' unless $res eq 'OK'; | ||||
|         # controls | ||||
|         #$res = pptp_and_dhcp_range( $c, $rma_datas{pptpSessions} ); | ||||
|         #$result .= $res . ' ' unless $res eq 'OK'; | ||||
|  | ||||
| 	$res = ip_number_or_blank( $c, $rma_datas{validFromNetwork} ); | ||||
| 	$result .= $res . ' ' unless $res eq 'OK'; | ||||
|         $res = ip_number_or_blank( $c, $rma_datas{validFromNetwork} ); | ||||
|         $result .= $res . ' ' unless $res eq 'OK'; | ||||
|  | ||||
| 	$res = subnet_mask_or_blank( $c, $rma_datas{validFromMask} ); | ||||
| 	$result .= $res . ' ' unless $res eq 'OK'; | ||||
|         $res = subnet_mask_or_blank( $c, $rma_datas{validFromMask} ); | ||||
|         $result .= $res . ' ' unless $res eq 'OK'; | ||||
|  | ||||
| 	$res = validate_network_and_mask( $c, $rma_datas{validFromNetwork}, $rma_datas{validFromMask} ); | ||||
| 	$result .= $res . ' ' unless $res eq 'OK'; | ||||
|         $res = validate_network_and_mask( | ||||
|             $c, | ||||
|             $rma_datas{validFromNetwork}, | ||||
|             $rma_datas{validFromMask} | ||||
|         ); | ||||
|         $result .= $res . ' ' unless $res eq 'OK'; | ||||
|  | ||||
| 	#$result .= ' blocked for testing !' . $rma_datas{remove_nets}; | ||||
|         #$result .= ' blocked for testing !' . $rma_datas{remove_nets}; | ||||
|     } | ||||
|  | ||||
|     if ( ! $result ) { | ||||
|     if ( !$result ) { | ||||
|         $res = change_settings( $c, %rma_datas ); | ||||
|         $result .= $res unless $res eq 'OK'; | ||||
|     } | ||||
|  | ||||
|     if ( ! $result ) { | ||||
|         $result = $c->l('rma_ACTION_SUCCEEDED');  | ||||
|         $trt = 'SUC'; | ||||
|      | ||||
|     if ( $result eq "" ) { | ||||
|         $result = $c->l('rma_SUCCESS'); | ||||
|         $trt    = 'SUC'; | ||||
|     } | ||||
|  | ||||
|     $c->stash( title => $title, notif => $result, rma_datas => \%rma_datas ); | ||||
|  | ||||
|     if ( $trt ne 'SUC' ) { | ||||
| 	return $c->render(template => 'remoteaccess'); | ||||
|     #return $c->render( template => 'remoteaccess' ); | ||||
|  | ||||
|     if ( $trt eq 'SUC' ) { | ||||
| 		$c->stash( title => $title,modul => $result); | ||||
|         return $c->render( template => 'module' ); | ||||
|     } | ||||
|  | ||||
|     $c->redirect_to('/remoteaccess'); | ||||
|  | ||||
| }; | ||||
|     return $c->render( template => 'remoteaccess' ); | ||||
|     #$c->redirect_to('/remoteaccess'); | ||||
|  | ||||
| } | ||||
|  | ||||
| sub networkAccess_list { | ||||
|     my $c = shift; | ||||
|     return  [[ $c->l('rma_NO_ACCESS') => 'off'],  | ||||
| 	    [ $c->l('NETWORKS_ALLOW_LOCAL') => 'private'],  | ||||
| 	    [ $c->l('NETWORKS_ALLOW_PUBLIC') => 'public']]; | ||||
|     return [ | ||||
|         [ $c->l('rma_NO_ACCESS')         => 'off' ], | ||||
|         [ $c->l('NETWORKS_ALLOW_LOCAL')  => 'private' ], | ||||
|         [ $c->l('NETWORKS_ALLOW_PUBLIC') => 'public' ] | ||||
|     ]; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub passwordLogin_list { | ||||
|     my $c = shift; | ||||
|     return  [[$c->l('rma_PASSWORD_LOGIN_PRIVATE') => 'private'], | ||||
| 	     [$c->l('rma_PASSWORD_LOGIN_PUBLIC') => 'public']]; | ||||
|     return [ | ||||
|         [ $c->l('rma_PASSWORD_LOGIN_PRIVATE') => 'private' ], | ||||
|         [ $c->l('rma_PASSWORD_LOGIN_PUBLIC')  => 'public' ] | ||||
|     ]; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_prop { | ||||
|  | ||||
|   my ($c, $item, $prop) = @_; | ||||
|   warn "You must specify a record key"    unless $item; | ||||
|   warn "You must specify a property name" unless $prop; | ||||
|   my $record = $db->get($item) or warn "Couldn't get record for $item"; | ||||
|   return $record ? $record->prop($prop) : undef; | ||||
|     my ( $c, $item, $prop ) = @_; | ||||
|     warn "You must specify a record key"    unless $item; | ||||
|     warn "You must specify a property name" unless $prop; | ||||
|     my $record = $db->get($item) or warn "Couldn't get record for $item"; | ||||
|     return $record ? $record->prop($prop) : undef; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_value { | ||||
|  | ||||
|   my $c = shift; | ||||
|   my $item = shift; | ||||
|   return ($db->get($item)->value()); | ||||
|     my $c    = shift; | ||||
|     my $item = shift; | ||||
|     return ( $db->get($item)->value() ); | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_ftp_access { | ||||
|  | ||||
|     my $status = get_prop('','ftp','status') || 'disabled'; | ||||
|     my $status = get_prop( '', 'ftp', 'status' ) || 'disabled'; | ||||
|     return 'off' unless $status eq 'enabled'; | ||||
|  | ||||
|     my $access = get_prop('','ftp','access') || 'private'; | ||||
|     return ($access  eq 'public') ? 'normal' : 'private'; | ||||
|     my $access = get_prop( '', 'ftp', 'access' ) || 'private'; | ||||
|     return ( $access eq 'public' ) ? 'normal' : 'private'; | ||||
| } | ||||
|  | ||||
|  | ||||
| #sub get_pptp_sessions { | ||||
| #  my $status = get_prop('','pptpd','status'); | ||||
| #  if (defined($status) && ($status eq 'enabled')) { | ||||
| @@ -192,314 +209,317 @@ sub get_ftp_access { | ||||
| #  return '0'; | ||||
| #} | ||||
|  | ||||
|  | ||||
| sub get_ssh_permit_root_login { | ||||
|     return(get_prop('','sshd','PermitRootLogin') || 'no'); | ||||
|     return ( get_prop( '', 'sshd', 'PermitRootLogin' ) || 'no' ); | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_ssh_password_auth { | ||||
|     return(get_prop('','sshd','PasswordAuthentication') || 'yes'); | ||||
|     return ( get_prop( '', 'sshd', 'PasswordAuthentication' ) || 'yes' ); | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_ssh_access { | ||||
|  | ||||
|   my $status = get_prop('','sshd','status'); | ||||
|   if (defined($status) && ($status eq 'enabled')) { | ||||
|     my $access = get_prop('','sshd','access'); | ||||
|     $access = ($access eq 'public') ? 'public' : 'private'; | ||||
|     return($access); | ||||
|   } | ||||
|   else { | ||||
|     return('off'); | ||||
|   } | ||||
|     my $status = get_prop( '', 'sshd', 'status' ); | ||||
|     if ( defined($status) && ( $status eq 'enabled' ) ) { | ||||
|         my $access = get_prop( '', 'sshd', 'access' ); | ||||
|         $access = ( $access eq 'public' ) ? 'public' : 'private'; | ||||
|         return ($access); | ||||
|     } | ||||
|     else { | ||||
|         return ('off'); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_ssh_port { | ||||
|     return(get_prop('$c','sshd','TCPPort') || '22'); | ||||
|     return ( get_prop( '$c', 'sshd', 'TCPPort' ) || '22' ); | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_ftp_password_login_access { | ||||
|  | ||||
|     my $status = get_prop('','ftp','status') || 'disabled'; | ||||
|     my $status = get_prop( '', 'ftp', 'status' ) || 'disabled'; | ||||
|     return 'private' unless $status eq 'enabled'; | ||||
|  | ||||
|     my $access = get_prop('','ftp','LoginAccess') || 'private'; | ||||
|     my $access = get_prop( '', 'ftp', 'LoginAccess' ) || 'private'; | ||||
|  | ||||
|     return ($access  eq 'public') ? 'public' : 'private'; | ||||
|     return ( $access eq 'public' ) ? 'public' : 'private'; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_telnet_mode { | ||||
|  | ||||
|   my $telnet = $db->get('telnet'); | ||||
|   return('off') unless $telnet; | ||||
|   my $status = $telnet->prop('status') || 'disabled'; | ||||
|   return('off') unless $status eq 'enabled'; | ||||
|   my $access = $telnet->prop('access') || 'private'; | ||||
|   return ($access eq "public") ? "public" : "private"; | ||||
|     my $telnet = $db->get('telnet'); | ||||
|     return ('off') unless $telnet; | ||||
|     my $status = $telnet->prop('status') || 'disabled'; | ||||
|     return ('off') unless $status eq 'enabled'; | ||||
|     my $access = $telnet->prop('access') || 'private'; | ||||
|     return ( $access eq "public" ) ? "public" : "private"; | ||||
| } | ||||
|  | ||||
| sub get_ipsecrw_sessions { | ||||
|  | ||||
| sub get_ipsecrw_sessions  { | ||||
|  | ||||
|   my $status = $db->get('ipsec')->prop('RoadWarriorStatus'); | ||||
|   if (defined($status) && ($status eq 'enabled')) { | ||||
|     return($db->get('ipsec')->prop('RoadWarriorSessions') || '0'); | ||||
|   } | ||||
|   else { | ||||
|     return('0'); | ||||
|   } | ||||
|     my $status = $db->get('ipsec')->prop('RoadWarriorStatus'); | ||||
|     if ( defined($status) && ( $status eq 'enabled' ) ) { | ||||
|         return ( $db->get('ipsec')->prop('RoadWarriorSessions') || '0' ); | ||||
|     } | ||||
|     else { | ||||
|         return ('0'); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| sub get_ipsecrw_status { | ||||
|  | ||||
|   return undef unless ( $db->get('ipsec')); | ||||
|   return $db->get('ipsec')->prop('RoadWarriorStatus'); | ||||
|     return undef unless ( $db->get('ipsec') ); | ||||
|     return $db->get('ipsec')->prop('RoadWarriorStatus'); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| sub pptp_and_dhcp_range { | ||||
|  | ||||
|   my $c = shift; | ||||
|   my $val = shift || 0; | ||||
|   my $dhcp_status     = $db->get_prop('dhcpd','status') || 'disabled'; | ||||
|   my $dhcp_end        = $db->get_prop('dhcpd','end') || ''; | ||||
|   my $dhcp_start      = $db->get_prop('dhcpd','start') || ''; | ||||
|     my $c           = shift; | ||||
|     my $val         = shift || 0; | ||||
|     my $dhcp_status = $db->get_prop( 'dhcpd', 'status' ) || 'disabled'; | ||||
|     my $dhcp_end    = $db->get_prop( 'dhcpd', 'end' )    || ''; | ||||
|     my $dhcp_start  = $db->get_prop( 'dhcpd', 'start' )  || ''; | ||||
|  | ||||
|     if ( $dhcp_status eq 'enabled' ) { | ||||
|         my $ip_start     = unpack 'N', inet_aton($dhcp_start); | ||||
|         my $ip_end       = unpack 'N', inet_aton($dhcp_end); | ||||
|         my $ip_count     = $ip_end - $ip_start; | ||||
|         return 'OK' if( $val < $ip_count ); | ||||
|         return $c->l('rma_NUMBER_OF_PPTP_CLIENTS_MUST_BE_LESSER_THAN_NUMBER_OF_IP_IN_DHCP_RANGE'); | ||||
|     } else { | ||||
|         my $ip_start = unpack 'N', inet_aton($dhcp_start); | ||||
|         my $ip_end   = unpack 'N', inet_aton($dhcp_end); | ||||
|         my $ip_count = $ip_end - $ip_start; | ||||
|         return 'OK' if ( $val < $ip_count ); | ||||
|         return $c->l( | ||||
| 'rma_NUMBER_OF_PPTP_CLIENTS_MUST_BE_LESSER_THAN_NUMBER_OF_IP_IN_DHCP_RANGE' | ||||
|         ); | ||||
|     } | ||||
|     else { | ||||
|         return 'OK'; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| sub _get_valid_from { | ||||
|  | ||||
| 	my $c = shift; | ||||
|     my $c = shift; | ||||
|  | ||||
| 	my $rec = $db->get('httpd-admin'); | ||||
| 	return undef unless($rec); | ||||
| 	my @vals = (split ',', ($rec->prop('ValidFrom') || '')); | ||||
| 	return @vals; | ||||
|     my $rec = $db->get('httpd-admin'); | ||||
|     return undef unless ($rec); | ||||
|     my @vals = ( split ',', ( $rec->prop('ValidFrom') || '' ) ); | ||||
|     return @vals; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub ip_number_or_blank { | ||||
|  | ||||
|     my $c = shift; | ||||
|     my $c  = shift; | ||||
|     my $ip = shift; | ||||
|  | ||||
|     if (!defined($ip) || $ip eq "") { | ||||
| 	return 'OK'; | ||||
|     if ( !defined($ip) || $ip eq "" ) { | ||||
|         return 'OK'; | ||||
|     } | ||||
|     return ip_number($c, $ip); | ||||
|     return ip_number( $c, $ip ); | ||||
| } | ||||
|  | ||||
|  | ||||
| sub subnet_mask_or_blank { | ||||
|  | ||||
|     my $c = shift; | ||||
|     my $c    = shift; | ||||
|     my $mask = shift; | ||||
|  | ||||
|     if (!defined($mask) || $mask eq "") { | ||||
|     if ( !defined($mask) || $mask eq "" ) { | ||||
|         return "OK"; | ||||
|     } | ||||
|  | ||||
|     chomp $mask ; | ||||
|     chomp $mask; | ||||
|  | ||||
|     return ( subnet_mask( $mask ) ne 'OK' ) ? $c->l('rma_INVALID_SUBNET_MASK') . " (" . $mask . ")" : 'OK'; | ||||
|     return ( subnet_mask($mask) ne 'OK' ) | ||||
|       ? $c->l('rma_INVALID_SUBNET_MASK') . " (" . $mask . ")" | ||||
|       : 'OK'; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub validate_network_and_mask { | ||||
|  | ||||
|   my $c = shift; | ||||
|   my $net = shift  || ""; | ||||
|   my $mask = shift || ""; | ||||
|     my $c    = shift; | ||||
|     my $net  = shift || ""; | ||||
|     my $mask = shift || ""; | ||||
|  | ||||
|   if ($net xor $mask) { | ||||
|     return $c->l('rma_ERR_INVALID_PARAMS' . " (" . $net."/".$mask . ")"); | ||||
|   } | ||||
|   return 'OK'; | ||||
|     if ( $net xor $mask ) { | ||||
|         return $c->l( | ||||
|             'rma_ERR_INVALID_PARAMS' . " (" . $net . "/" . $mask . ")" ); | ||||
|     } | ||||
|     return 'OK'; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub change_settings { | ||||
|  | ||||
|     my ($c, %rma_datas) = @_; | ||||
|     my ( $c, %rma_datas ) = @_; | ||||
|  | ||||
|     #------------------------------------------------------------ | ||||
|     # good; go ahead and change the access. | ||||
|     #------------------------------------------------------------ | ||||
|  | ||||
|     my $rec = $db->get('telnet'); | ||||
|     if($rec) { | ||||
|     	if ($rma_datas{telnetAccess} eq "off") { | ||||
| 	    $rec->set_prop('status','disabled'); | ||||
|     	} else { | ||||
| 	    $rec->set_prop('status','enabled'); | ||||
| 	    $rec->set_prop('access', $rma_datas{telnetAccess}); | ||||
|       	} | ||||
|     if ($rec) { | ||||
|         if ( $rma_datas{telnetAccess} eq "off" ) { | ||||
|             $rec->set_prop( 'status', 'disabled' ); | ||||
|         } | ||||
|         else { | ||||
|             $rec->set_prop( 'status', 'enabled' ); | ||||
|             $rec->set_prop( 'access', $rma_datas{telnetAccess} ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     $rec = $db->get('sshd') || $db->new_record('sshd', {type => 'service'}); | ||||
|     $rec->set_prop('TCPPort', $rma_datas{sshTCPPort}); | ||||
|     $rec->set_prop('status', ( $rma_datas{sshaccess} eq "off" ? 'disabled' : 'enabled')); | ||||
|     $rec->set_prop('access', $rma_datas{sshaccess}); | ||||
|     $rec->set_prop('PermitRootLogin', $rma_datas{sshPermitRootLogin}); | ||||
|     $rec->set_prop('PasswordAuthentication', $rma_datas{sshPasswordAuthentication}); | ||||
|  | ||||
|     $rec = $db->get('sshd') || $db->new_record( 'sshd', { type => 'service' } ); | ||||
|     $rec->set_prop( 'TCPPort', $rma_datas{sshTCPPort} ); | ||||
|     $rec->set_prop( 'status', | ||||
|         ( $rma_datas{sshaccess} eq "off" ? 'disabled' : 'enabled' ) ); | ||||
|     $rec->set_prop( 'access',          $rma_datas{sshaccess} ); | ||||
|     $rec->set_prop( 'PermitRootLogin', $rma_datas{sshPermitRootLogin} ); | ||||
|     $rec->set_prop( 'PasswordAuthentication', | ||||
|         $rma_datas{sshPasswordAuthentication} ); | ||||
|  | ||||
|     $rec = $db->get('ftp'); | ||||
|     if($rec) { | ||||
|     	if ($rma_datas{ftpAccess} eq "off") { | ||||
| 	    $rec->set_prop('status', 'disabled'); | ||||
| 	    $rec->set_prop('access', 'private'); | ||||
| 	    $rec->set_prop('LoginAccess', 'private'); | ||||
|     	} elsif ($rma_datas{ftpAccess} eq "normal") { | ||||
| 	    $rec->set_prop('status', 'enabled'); | ||||
| 	    $rec->set_prop('access', 'public'); | ||||
| 	    $rec->set_prop('LoginAccess', $rma_datas{ftpPasswordAccess}); | ||||
|     	} else { | ||||
| 	    $rec->set_prop('status', 'enabled'); | ||||
| 	    $rec->set_prop('access', 'private'); | ||||
| 	    $rec->set_prop('LoginAccess', $rma_datas{ftpPasswordAccess}); | ||||
|     	} | ||||
|     if ($rec) { | ||||
|         if ( $rma_datas{ftpAccess} eq "off" ) { | ||||
|             $rec->set_prop( 'status',      'disabled' ); | ||||
|             $rec->set_prop( 'access',      'private' ); | ||||
|             $rec->set_prop( 'LoginAccess', 'private' ); | ||||
|         } | ||||
|         elsif ( $rma_datas{ftpAccess} eq "normal" ) { | ||||
|             $rec->set_prop( 'status',      'enabled' ); | ||||
|             $rec->set_prop( 'access',      'public' ); | ||||
|             $rec->set_prop( 'LoginAccess', $rma_datas{ftpPasswordAccess} ); | ||||
|         } | ||||
|         else { | ||||
|             $rec->set_prop( 'status',      'enabled' ); | ||||
|             $rec->set_prop( 'access',      'private' ); | ||||
|             $rec->set_prop( 'LoginAccess', $rma_datas{ftpPasswordAccess} ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| #	if ($rma_datas{pptpSessions} == 0) { | ||||
| #	$db->get('pptpd')->set_prop('status', 'disabled'); | ||||
| #    } else { | ||||
| #	$db->get('pptpd')->set_prop('status', 'enabled'); | ||||
| #	$db->get('pptpd')->set_prop('sessions', $rma_datas{pptpSessions}); | ||||
| #    } | ||||
|     #	if ($rma_datas{pptpSessions} == 0) { | ||||
|     #	$db->get('pptpd')->set_prop('status', 'disabled'); | ||||
|     #    } else { | ||||
|     #	$db->get('pptpd')->set_prop('status', 'enabled'); | ||||
|     #	$db->get('pptpd')->set_prop('sessions', $rma_datas{pptpSessions}); | ||||
|     #    } | ||||
|  | ||||
|     if ( $rma_datas{validFromNetwork} && $rma_datas{validFromMask} ) { | ||||
| 	unless (add_new_valid_from( $c, $rma_datas{validFromNetwork}, $rma_datas{validFromMask} )) { | ||||
| 	    return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'new net'; | ||||
| 	} | ||||
|         unless ( | ||||
|             add_new_valid_from( | ||||
|                 $c, | ||||
|                 $rma_datas{validFromNetwork}, | ||||
|                 $rma_datas{validFromMask} | ||||
|             ) | ||||
|           ) | ||||
|         { | ||||
|             return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'new net'; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     if ( $rma_datas{remove_nets} ) { | ||||
| 	unless (remove_valid_from( $c, $rma_datas{remove_nets} )) { | ||||
| 	    return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'del net'; | ||||
| 	} | ||||
|         unless ( remove_valid_from( $c, $rma_datas{remove_nets} ) ) { | ||||
|             return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'del net'; | ||||
|         } | ||||
|     } | ||||
|    | ||||
|  | ||||
|     # reset ipsec roadwarrior CA,server,client certificates | ||||
|     if ($rma_datas{ipsecrwReset}) { | ||||
| 	system('/sbin/e-smith/roadwarrior', 'reset_certs') == 0 or | ||||
| 	    return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'rst ipsec'; | ||||
|     if ( $rma_datas{ipsecrwReset} ) { | ||||
|         system( '/sbin/e-smith/roadwarrior', 'reset_certs' ) == 0 | ||||
|           or return $c->l('rma_ERROR_UPDATING_CONFIGURATION') . 'rst ipsec'; | ||||
|     } | ||||
|  | ||||
|     if ( $rma_datas{ipsecrwSess} ) { | ||||
| 	set_ipsecrw_sessions( $c, $rma_datas{ipsecrwSess} ); | ||||
|         set_ipsecrw_sessions( $c, $rma_datas{ipsecrwSess} ); | ||||
|     } | ||||
|  | ||||
|     unless ( system( "/sbin/e-smith/signal-event", "remoteaccess-update" ) == 0 ) { | ||||
|     unless ( | ||||
|         system( "/sbin/e-smith/signal-event", "remoteaccess-update" ) == 0 ) | ||||
|     { | ||||
|         return $c->l('rma_ERROR_UPDATING_CONFIGURATION'); | ||||
|     } | ||||
|  | ||||
|     return 'OK'; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub set_ipsecrw_sessions { | ||||
|  | ||||
|     my $c = shift; | ||||
|     my $c        = shift; | ||||
|     my $sessions = shift; | ||||
|  | ||||
|     if (defined $sessions) { | ||||
| 	$db->get('ipsec')->set_prop('RoadWarriorSessions', $sessions); | ||||
| 	if (int($sessions) > 0) { | ||||
| 	    $db->get('ipsec')->set_prop('RoadWarriorStatus', 'enabled'); | ||||
| 	} | ||||
|     if ( defined $sessions ) { | ||||
|         $db->get('ipsec')->set_prop( 'RoadWarriorSessions', $sessions ); | ||||
|         if ( int($sessions) > 0 ) { | ||||
|             $db->get('ipsec')->set_prop( 'RoadWarriorStatus', 'enabled' ); | ||||
|         } | ||||
|     } | ||||
|     return ''; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub add_new_valid_from { | ||||
|  | ||||
| 	my $c = shift; | ||||
| 	my $net = shift; | ||||
| 	my $mask = shift; | ||||
|     my $c    = shift; | ||||
|     my $net  = shift; | ||||
|     my $mask = shift; | ||||
|  | ||||
| 	# we transform bit mask to regular mask | ||||
| 	$mask = get_reg_mask( $net, $mask ); | ||||
|   | ||||
| 	my $rec = $db->get('httpd-admin'); | ||||
| 	return $c->error('ERR_NO_RECORD') unless $rec; | ||||
|     # we transform bit mask to regular mask | ||||
|     $mask = get_reg_mask( $net, $mask ); | ||||
|  | ||||
| 	my $prop = $rec->prop('ValidFrom') || ''; | ||||
|     my $rec = $db->get('httpd-admin'); | ||||
|     return $c->error('ERR_NO_RECORD') unless $rec; | ||||
|  | ||||
| 	my @vals = split /,/, $prop; | ||||
| 	return '' if (grep /^$net\/$mask$/, @vals); # already have this entry | ||||
|     my $prop = $rec->prop('ValidFrom') || ''; | ||||
|  | ||||
| 	if ($prop ne '') { | ||||
| 		$prop .= ",$net/$mask"; | ||||
| 	} else { | ||||
| 		$prop = "$net/$mask"; | ||||
| 	} | ||||
|     my @vals = split /,/, $prop; | ||||
|     return '' if ( grep /^$net\/$mask$/, @vals );    # already have this entry | ||||
|  | ||||
| 	$rec->set_prop('ValidFrom', $prop); | ||||
|     if ( $prop ne '' ) { | ||||
|         $prop .= ",$net/$mask"; | ||||
|     } | ||||
|     else { | ||||
|         $prop = "$net/$mask"; | ||||
|     } | ||||
|  | ||||
| 	return 1; | ||||
|     $rec->set_prop( 'ValidFrom', $prop ); | ||||
|  | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| sub remove_valid_from { | ||||
|  | ||||
| 	my $c = shift; | ||||
| 	my $remove_nets = shift; | ||||
|     my $c           = shift; | ||||
|     my $remove_nets = shift; | ||||
|  | ||||
| 	my @remove = split /,/, $remove_nets; | ||||
|     my @remove = split /,/, $remove_nets; | ||||
|  | ||||
| #	my @remove = $c->param('Remove_nets'); | ||||
| 	my @vals = $c->_get_valid_from(); | ||||
|     #	my @remove = $c->param('Remove_nets'); | ||||
|     my @vals = $c->_get_valid_from(); | ||||
|  | ||||
| 	foreach my $entry (@remove) { | ||||
| 	 | ||||
| 	    return undef unless $entry; | ||||
|     foreach my $entry (@remove) { | ||||
|  | ||||
| 	    my ($net, $mask) = split (/\//, $entry); | ||||
|         return undef unless $entry; | ||||
|  | ||||
| 	    unless (@vals)  { | ||||
| 		print STDERR "ERROR: unable to load ValidFrom property from conf db\n"; | ||||
| 		return undef; | ||||
| 	    } | ||||
|         my ( $net, $mask ) = split( /\//, $entry ); | ||||
|  | ||||
| 	    # what if we don't have a mask because someone added an entry from | ||||
| 	    # the command line? by the time we get here, the panel will have | ||||
| 	    # added a 32 bit mask, so we don't know for sure if the value in db | ||||
| 	    # is $net alone or $net/255.255.255.255. we have to check for both | ||||
| 	    # in this special case... | ||||
| 	    @vals = (grep { $entry ne $_ && $net ne $_ } @vals); | ||||
| 	} | ||||
|         unless (@vals) { | ||||
|             print STDERR | ||||
|               "ERROR: unable to load ValidFrom property from conf db\n"; | ||||
|             return undef; | ||||
|         } | ||||
|  | ||||
| 	my $prop; | ||||
| 	if (@vals) { | ||||
| 	    $prop = join ',',@vals; | ||||
| 	} else { | ||||
| 	    $prop = ''; | ||||
| 	} | ||||
|         # what if we don't have a mask because someone added an entry from | ||||
|         # the command line? by the time we get here, the panel will have | ||||
|         # added a 32 bit mask, so we don't know for sure if the value in db | ||||
|         # is $net alone or $net/255.255.255.255. we have to check for both | ||||
|         # in this special case... | ||||
|         @vals = ( grep { $entry ne $_ && $net ne $_ } @vals ); | ||||
|     } | ||||
|  | ||||
| 	$db->get('httpd-admin')->set_prop('ValidFrom', $prop); | ||||
|     my $prop; | ||||
|     if (@vals) { | ||||
|         $prop = join ',', @vals; | ||||
|     } | ||||
|     else { | ||||
|         $prop = ''; | ||||
|     } | ||||
|  | ||||
| 	return 1; | ||||
|     $db->get('httpd-admin')->set_prop( 'ValidFrom', $prop ); | ||||
|  | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| 1; | ||||
| 1; | ||||
| @@ -0,0 +1,46 @@ | ||||
| package SrvMngr::Controller::Roundcubepanel; | ||||
|  | ||||
| #---------------------------------------------------------------------- | ||||
| # heading     : System | ||||
| # description : Roundcube webmail | ||||
| # navigation  : 99999 9999 | ||||
| #---------------------------------------------------------------------- | ||||
| #---------------------------------------------------------------------- | ||||
| # name   : roundcubepanel,    method : get,   url : /roundcubepanel,     ctlact : Roundcubepanel#main | ||||
| # | ||||
| # routes : end | ||||
| #---------------------------------------------------------------------- | ||||
|  | ||||
| use strict; | ||||
| use warnings; | ||||
|  | ||||
| use Mojo::Base 'Mojolicious::Controller'; | ||||
|  | ||||
| use Locale::gettext; | ||||
| use SrvMngr::I18N; | ||||
| use SrvMngr qw(theme_list init_session); | ||||
|  | ||||
| #use SrvMngr::Model::Main; | ||||
|  | ||||
|  | ||||
| sub main { | ||||
|  | ||||
|     my $c = shift; | ||||
|     $c->app->log->info($c->log_req); | ||||
|  | ||||
|     my $title = $c->l('Roundcube Webmail'); | ||||
|     my $roundcube_url = $c->param('url'); | ||||
|     my $roundcube_height = $c->param('height') | 600; | ||||
|     $c->stash( title => $title, modul => $roundcube_url, height => $roundcube_height ); | ||||
|     $c->render(template => 'roundcube'); | ||||
|  | ||||
| } | ||||
|  | ||||
| sub getroundcubeurl { | ||||
| 	my $c = shift; | ||||
| 	my $url = shift; | ||||
| 	return "/smanager/roundcube?url=$url"; | ||||
| } | ||||
|  | ||||
|  | ||||
| 1; | ||||
| @@ -23,14 +23,16 @@ use File::Basename; | ||||
|  | ||||
| our $cdb = esmith::ConfigDB->open || die "Couldn't open config db"; | ||||
|  | ||||
| my $dnf_status_file  = '/var/cache/dnf/dnf.status'; | ||||
|  | ||||
| #use File::stat; | ||||
|  | ||||
| our %dbs; | ||||
|  | ||||
| for ( qw(available installed updates) ) | ||||
| { | ||||
|     $dbs{$_} = esmith::ConfigDB->open_ro("yum_$_") or | ||||
| 	die "Couldn't open yum_$_ DB\n"; | ||||
|     $dbs{$_} = esmith::ConfigDB->open_ro("dnf_$_") or | ||||
| 	die "Couldn't open dnf_$_ DB\n"; | ||||
| } | ||||
|  | ||||
| for ( qw(repositories) ) | ||||
| @@ -52,10 +54,11 @@ sub main { | ||||
|  | ||||
|     $yum_datas{'trt'} = 'STAT'; | ||||
|  | ||||
|     if ( -e "/var/run/yum.pid" ) { | ||||
|     | ||||
|     if ( $c->is_dnf_running()) { | ||||
| 	$yum_datas{'trt'} = 'LOGF'; | ||||
| 	$dest = 'yumlogfile'; | ||||
|     } elsif ($cdb->get_prop('yum', 'LogFile')) { | ||||
|     } elsif ($cdb->get_prop('dnf', 'LogFile')) { | ||||
| 	$yum_datas{'trt'} = 'PSTU'; | ||||
| 	$yum_datas{'reconf'} = $cdb->get_value('UnsavedChanges', 'yes'); | ||||
| 	$dest = 'yumpostupg'; | ||||
| @@ -83,9 +86,9 @@ sub do_display { | ||||
|     $yum_datas{'trt'} = $trt; | ||||
|  | ||||
|     # force $trt if current logfile | ||||
|     if ( -e "/var/run/yum.pid" ) { | ||||
|     if ( $c->is_dnf_running() ) { | ||||
| 	$trt = 'LOGF'; | ||||
|     } elsif ($cdb->get_prop('yum', 'LogFile')) { | ||||
|     } elsif ($cdb->get_prop('dnf', 'LogFile')) { | ||||
| 	$trt = 'PSTU'; | ||||
|     } | ||||
|  | ||||
| @@ -106,13 +109,13 @@ sub do_display { | ||||
| 	} | ||||
|  | ||||
|         if ( $trt eq 'LOGF' ) { | ||||
| 	    if (-e "/var/run/yum.pid") { | ||||
| 	    if ($c->is_dnf_running()) { | ||||
| 	    $dest = 'yumlogfile'; | ||||
| 	    } | ||||
| 	} | ||||
| 	 | ||||
|         if ( $trt eq 'PSTU') { | ||||
| 	    if ($cdb->get_prop('yum', 'LogFile')) { | ||||
| 	    if ($cdb->get_prop('dnf', 'LogFile')) { | ||||
| 		$dest = 'yumpostupg'; | ||||
| 		$yum_datas{'reconf'} = $cdb->get_value('UnsavedChanges', 'yes'); | ||||
| 	    } | ||||
| @@ -221,7 +224,7 @@ sub do_update { | ||||
|     if ( $trt eq 'LOGF' ) { | ||||
|  | ||||
|     	$dest = 'yumlogfile'; | ||||
|         if ( ! -e "/var/run/yum.pid") { | ||||
|         if ( ! $c->is_dnf_running()) { | ||||
| 	    $yum_datas{trt} = 'SUC'; | ||||
| 	    $result = $c->l('yum_SUCCESS'); | ||||
|         } | ||||
| @@ -247,6 +250,24 @@ sub do_update { | ||||
|  | ||||
| }; | ||||
|  | ||||
| sub get_dnf_status { | ||||
|     #interrogate status file created and maintained by smeserver.py plugin for dnf. | ||||
|     my ($c) = @_; | ||||
|     my $file_name = $dnf_status_file; | ||||
|     my $content = "resolved"; | ||||
|     if ( -e "$file_name") { | ||||
| 	open my $fh, '<', $file_name or die "Can't open file: $!"; | ||||
| 	$content = <$fh>; | ||||
| 	close $fh; | ||||
|     } | ||||
|     return $content; | ||||
| } | ||||
|  | ||||
| sub is_dnf_running { | ||||
|     my ($c) = @_; | ||||
|     my $dnf_status = $c->get_dnf_status(); | ||||
|     return $dnf_status ne "resolved" && $dnf_status ne "config" && $dnf_status ne "sack"; | ||||
| } | ||||
|  | ||||
| sub is_empty { | ||||
|  | ||||
| @@ -289,7 +310,7 @@ sub package_functions_enabled { | ||||
|  | ||||
|     my ($c) = @_; | ||||
|  | ||||
|     return ($cdb->get_prop("yum", "PackageFunctions") eq "enabled"); | ||||
|     return ($cdb->get_prop("dnf", "PackageFunctions") eq "enabled"); | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -298,7 +319,7 @@ sub get_status { | ||||
|  | ||||
|     my ($c, $prop, $localise) = @_; | ||||
|  | ||||
|     my $status = $cdb->get_prop("yum", $prop) || 'disabled'; | ||||
|     my $status = $cdb->get_prop("dnf", $prop) || 'disabled'; | ||||
|  | ||||
|     return $status unless $localise; | ||||
|  | ||||
| @@ -433,7 +454,7 @@ sub change_settings { | ||||
| 			PackageFunctions | ||||
|             	) ) | ||||
|     { | ||||
| 	$cdb->set_prop('yum', $param, $c->param("yum_$param")); | ||||
| 	$cdb->set_prop("dnf", $param, $c->param("yum_$param")); | ||||
|     } | ||||
|  | ||||
|     my $check4updates = $c->param("yum_check4updates"); | ||||
| @@ -441,21 +462,21 @@ sub change_settings { | ||||
|  | ||||
|     if ($check4updates ne 'disabled') { $status = 'enabled'; } | ||||
|  | ||||
|     $cdb->set_prop('yum', 'check4updates', $check4updates); | ||||
|     $cdb->set_prop("dnf", 'check4updates', $check4updates); | ||||
|  | ||||
|     my $deltarpm = $c->param("yum_DeltaRpmProcess"); | ||||
|     $cdb->set_prop('yum', 'DeltaRpmProcess', $deltarpm); | ||||
|     $cdb->set_prop("dnf", 'DeltaRpmProcess', $deltarpm); | ||||
|  | ||||
|     my $downloadonly = $c->param("yum_DownloadOnly"); | ||||
|     if ($downloadonly ne 'disabled') { $status = 'enabled'; } | ||||
|  | ||||
|     $cdb->set_prop('yum', 'DownloadOnly', $downloadonly); | ||||
|     $cdb->set_prop("dnf", 'DownloadOnly', $downloadonly); | ||||
|  | ||||
|     my $AutoInstallUpdates = $c->param("yum_AutoInstallUpdates"); | ||||
|     if ($AutoInstallUpdates ne 'disabled') { $status = 'enabled'; } | ||||
|  | ||||
|     $cdb->set_prop('yum', 'AutoInstallUpdates', $AutoInstallUpdates); | ||||
|     $cdb->set_prop('yum', 'status', $status); | ||||
|     $cdb->set_prop("dnf", 'AutoInstallUpdates', $AutoInstallUpdates); | ||||
|     $cdb->set_prop("dnf", 'status', $status); | ||||
|  | ||||
|     my %selected = map {$_ => 1} @{$c->every_param('SelectedRepositories')}; | ||||
|  | ||||
| @@ -469,7 +490,7 @@ sub change_settings { | ||||
|  | ||||
|     $dbs{repositories}->reload; | ||||
|  | ||||
|     unless ( system( "/sbin/e-smith/signal-event", "yum-modify" ) == 0 ) | ||||
|     unless ( system( "/sbin/e-smith/signal-event", "dnf-modify" ) == 0 ) | ||||
|     { | ||||
| 	return $c->l('yum_ERROR_UPDATING_CONFIGURATION'); | ||||
|     } | ||||
| @@ -484,11 +505,11 @@ sub do_yum { | ||||
|  | ||||
|     for ( qw(SelectedGroups SelectedPackages) ) | ||||
|     { | ||||
| 	$cdb->set_prop("yum", $_, join(',', (@{$c->every_param($_)} ))); | ||||
| 	$cdb->set_prop("dnf", $_, join(',', (@{$c->every_param($_)} ))); | ||||
|     } | ||||
|  | ||||
|     esmith::util::backgroundCommand(0, | ||||
|         "/sbin/e-smith/signal-event", "yum-$function"); | ||||
|         "/sbin/e-smith/signal-event", "dnf-$function"); | ||||
|  | ||||
|     for ( qw(available installed updates) ) { | ||||
| 	$dbs{$_}->reload; | ||||
| @@ -517,7 +538,7 @@ sub format_yum_log { | ||||
|  | ||||
|     $cdb->reload; | ||||
|  | ||||
|     my $filepage = $cdb->get_prop('yum', 'LogFile'); | ||||
|     my $filepage = $cdb->get_prop('dnf', 'LogFile'); | ||||
|     return '' unless $filepage and ( -e "$filepage" ); | ||||
|  | ||||
|     my $out = sprintf "<PRE>"; | ||||
| @@ -537,7 +558,7 @@ sub post_upgrade_reboot { | ||||
|  | ||||
|     my $c = shift; | ||||
|  | ||||
|     $cdb->get_prop_and_delete('yum', 'LogFile'); | ||||
|     $cdb->get_prop_and_delete('dnf', 'LogFile'); | ||||
|     $cdb->reload; | ||||
|  | ||||
|     if (fork == 0) { | ||||
| @@ -552,7 +573,7 @@ sub post_upgrade_reboot { | ||||
| sub show_yum_log { | ||||
|     my $c = shift; | ||||
|     my $out = $c->format_yum_log(); | ||||
|     my $yum_log = $cdb->get_prop_and_delete('yum', 'LogFile'); | ||||
|     my $yum_log = $cdb->get_prop_and_delete('dnf', 'LogFile'); | ||||
|     return $out; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| 'bac_No suitable local devices found' => 'No suitable local devices found', | ||||
| 'bac_BACKUP_TITLE' => 'Backup or restore server data', | ||||
| 'bac_BACKUP_DESC' => '<P>The server provides two ways to back up and restore | ||||
| your server: using your local desktop or a tape drive.</P> | ||||
|   | ||||
| @@ -0,0 +1,72 @@ | ||||
| package SrvMngr::I18N::Modules::Letsencrypt::en; | ||||
| use strict; | ||||
| use warnings; | ||||
| use utf8; | ||||
| use Mojo::Base 'SrvMngr::I18N'; | ||||
|  | ||||
| use SrvMngr::I18N::Modules::General::en; | ||||
|  | ||||
| my %lexicon = ( | ||||
| # | ||||
| # Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 | ||||
| # | ||||
| 'lets_Manage_letsencrypt-config_settings:' => 'Manage letsencrypt-config settings', | ||||
| 'lets_HOOKSCRIPT_STATUS' => 'Hookscript Status', | ||||
| 'lets_SERVICE_STATUS' => 'Service Status', | ||||
| 'lets_EMAIL' => 'Email', | ||||
| 'lets_Back' => 'Back', | ||||
| 'lets_Internal_IP' => 'Internal IP', | ||||
| 'lets_Save' => 'Save', | ||||
| 'lets_Issuer' => 'Issuer', | ||||
| 'lets_IS_IN_CERT' => 'Is In cart', | ||||
| 'lets_For_this_Server' => 'For this Server', | ||||
| 'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain', | ||||
| 'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain which is enabled', | ||||
| 'lets_Check_just_one_domain' => 'Check just one domain', | ||||
| 'lets_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful', | ||||
| 'lets_Check_all_domains' => 'Check all domains', | ||||
| 'lets_LIST_panel_action_was_successful' => 'LIST panel action was successful', | ||||
| 'lets_Status_Report' => 'Status Report', | ||||
| 'lets_LABEL_NAMESERVERS' => 'Label timeservers', | ||||
| 'lets_Loop_through_and_check_the' => 'Loop through and check the letsencrypt status for a specific domain', | ||||
| 'lets_Letsencrypt_certificate' => 'Letsencrypt certificate', | ||||
| 'lets_Error_Status_Report' => 'Error Status Report', | ||||
| 'lets_Not_Before' => 'Not Before', | ||||
| 'lets_Content' => 'Content', | ||||
| 'lets_CONFIG_LETSENCRYPT' => 'confirm Letsencrypt', | ||||
| 'lets_API_STATUS' => 'ape Status', | ||||
| 'lets_ACCEPT_TERMS_STATUS' => 'Accept Terms Status', | ||||
| 'lets_Check_all_enabled_domains' => 'Check all enabled domains', | ||||
| 'lets_All_domains_check_result' => 'All domains check result', | ||||
| 'lets_CHECKALLDOMAINS_panel_action_was_successful' => 'CHECKALLDOMAINS panel action was successful', | ||||
| 'lets_Domains_name' => 'Domains name', | ||||
| 'lets_HOSTOVERRIDE_STATUS' => 'Hostoverride Status', | ||||
| 'lets_List_of_Domains_and_Hosts' => 'List of Domains and Hosts', | ||||
| 'lets_Brief_description' => 'Brief description', | ||||
| 'lets_KEYSIZE_STATUS' => 'Keysize Status', | ||||
| 'lets_Domain_name_/_HOSTNAME' => 'Domain name / HOSTNAME', | ||||
| 'lets_Enabled_domains_check_result' => 'Enabled domains check result', | ||||
| 'lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful' => 'CHECKALLENABLEDDOMAINS panel action was successful', | ||||
| 'lets_Internet_IP' => 'Internet IP', | ||||
| 'lets_Expiry' => 'Expiry', | ||||
| 'lets_CHECK_ALL_DOMAINS' => 'Check All Domains', | ||||
| 'lets_LABEL_POINT' => 'Label Point', | ||||
| 'lets_CHECK' => 'Check', | ||||
| 'lets_CONFIG' => 'Config', | ||||
| 'lets_Current_certificate_details' => 'Current certificate details', | ||||
| 'lets_LABEL_LECERT' => 'Label secret', | ||||
| 'lets_One_domain_check_result' => 'One domain check result', | ||||
| 'lets_CHECKONEDOMAIN_panel_action_was_successful' => 'CHECKONEDOMAIN panel action was successful', | ||||
| 'lets_CONFIGUREMODE_STATUS' => 'Configuremode Status', | ||||
| 'lets_CHECK_ALL_ENABLED_DOMAINS' => 'Check All Enabled Domains', | ||||
| 'lets_External_Interface_IP' => 'External Interface IP', | ||||
| 'lets_APPLY' => 'Apply', | ||||
| ); | ||||
|  | ||||
| our %Lexicon = ( | ||||
| 	%{ SrvMngr::I18N::Modules::General::en::Lexicon }, | ||||
| 	%lexicon | ||||
| ); | ||||
|  | ||||
|  | ||||
| 1; | ||||
| @@ -0,0 +1,54 @@ | ||||
| # | ||||
| # Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 | ||||
| # | ||||
| 'lets_Manage_letsencrypt-config_settings:' => 'Manage letsencrypt-config settings', | ||||
| 'lets_HOOKSCRIPT_STATUS' => 'Hookscript Status', | ||||
| 'lets_SERVICE_STATUS' => 'Service Status', | ||||
| 'lets_EMAIL' => 'Email', | ||||
| 'lets_Back' => 'Back', | ||||
| 'lets_Internal_IP' => 'Internal IP', | ||||
| 'lets_Save' => 'Save', | ||||
| 'lets_Issuer' => 'Issuer', | ||||
| 'lets_IS_IN_CERT' => 'Is In cart', | ||||
| 'lets_For_this_Server' => 'For this Server', | ||||
| 'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain', | ||||
| 'lets_Loop_through_checking_the_letsencrypt' => 'Loop through checking the letsencrypt status for each configured domain which is enabled', | ||||
| 'lets_Check_just_one_domain' => 'Check just one domain', | ||||
| 'lets_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful', | ||||
| 'lets_Check_all_domains' => 'Check all domains', | ||||
| 'lets_LIST_panel_action_was_successful' => 'LIST panel action was successful', | ||||
| 'lets_Status_Report' => 'Status Report', | ||||
| 'lets_LABEL_NAMESERVERS' => 'Label timeservers', | ||||
| 'lets_Loop_through_and_check_the' => 'Loop through and check the letsencrypt status for a specific domain', | ||||
| 'lets_Letsencrypt_certificate' => 'Letsencrypt certificate', | ||||
| 'lets_Error_Status_Report' => 'Error Status Report', | ||||
| 'lets_Not_Before' => 'Not Before', | ||||
| 'lets_Content' => 'Content', | ||||
| 'lets_CONFIG_LETSENCRYPT' => 'confirm Letsencrypt', | ||||
| 'lets_API_STATUS' => 'ape Status', | ||||
| 'lets_ACCEPT_TERMS_STATUS' => 'Accept Terms Status', | ||||
| 'lets_Check_all_enabled_domains' => 'Check all enabled domains', | ||||
| 'lets_All_domains_check_result' => 'All domains check result', | ||||
| 'lets_CHECKALLDOMAINS_panel_action_was_successful' => 'CHECKALLDOMAINS panel action was successful', | ||||
| 'lets_Domains_name' => 'Domains name', | ||||
| 'lets_HOSTOVERRIDE_STATUS' => 'Hostoverride Status', | ||||
| 'lets_List_of_Domains_and_Hosts' => 'List of Domains and Hosts', | ||||
| 'lets_Brief_description' => 'Brief description', | ||||
| 'lets_KEYSIZE_STATUS' => 'Keysize Status', | ||||
| 'lets_Domain_name_/_HOSTNAME' => 'Domain name / HOSTNAME', | ||||
| 'lets_Enabled_domains_check_result' => 'Enabled domains check result', | ||||
| 'lets_CHECKALLENABLEDDOMAINS_panel_action_was_successful' => 'CHECKALLENABLEDDOMAINS panel action was successful', | ||||
| 'lets_Internet_IP' => 'Internet IP', | ||||
| 'lets_Expiry' => 'Expiry', | ||||
| 'lets_CHECK_ALL_DOMAINS' => 'Check All Domains', | ||||
| 'lets_LABEL_POINT' => 'Label Point', | ||||
| 'lets_CHECK' => 'Check', | ||||
| 'lets_CONFIG' => 'Config', | ||||
| 'lets_Current_certificate_details' => 'Current certificate details', | ||||
| 'lets_LABEL_LECERT' => 'Label secret', | ||||
| 'lets_One_domain_check_result' => 'One domain check result', | ||||
| 'lets_CHECKONEDOMAIN_panel_action_was_successful' => 'CHECKONEDOMAIN panel action was successful', | ||||
| 'lets_CONFIGUREMODE_STATUS' => 'Configuremode Status', | ||||
| 'lets_CHECK_ALL_ENABLED_DOMAINS' => 'Check All Enabled Domains', | ||||
| 'lets_External_Interface_IP' => 'External Interface IP', | ||||
| 'lets_APPLY' => 'Apply', | ||||
							
								
								
									
										73
									
								
								root/usr/share/smanager/lib/SrvMngr/Plugin/Cache.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								root/usr/share/smanager/lib/SrvMngr/Plugin/Cache.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| package SrvMngr::Plugin::Cache; | ||||
| use Mojo::Base -base; | ||||
|  | ||||
| =head1 NAME | ||||
|  | ||||
| Mojolicious::Plugin::Renderer::WithoutCache::Cache - Mojo::Cache that doesn't cache | ||||
|  | ||||
| =head1 VERSION | ||||
|  | ||||
| Version 0.04 | ||||
|  | ||||
| =cut | ||||
|  | ||||
| our $VERSION = '0.04'; | ||||
| $VERSION = eval $VERSION; | ||||
|  | ||||
| =head1 SYNOPSIS | ||||
|  | ||||
| You probably don't want to use this directly. | ||||
|  | ||||
|     my $cache = Mojolicious::Plugin::Renderer::WithoutCache::Cache->new; | ||||
|     # this cache does nothing | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
|  | ||||
| A cache object that's compatible to Mojo::Cache but does nothing. It does | ||||
| not save or return any values. It's always empty. | ||||
|  | ||||
| =head1 METHODS | ||||
|  | ||||
| =head2 get | ||||
|  | ||||
| Does nothing. Returns C<undef>. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub get {} | ||||
|  | ||||
| =head2 set | ||||
|  | ||||
| Does nothing. Returns C<$self> so chaining is possible. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub set { shift; } | ||||
|  | ||||
| =head2 max_keys | ||||
|  | ||||
| Always returns zero. Can't be set. We don't want any keys. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub max_keys { 0 } | ||||
|  | ||||
| =head1 AUTHOR | ||||
|  | ||||
| simbabque, C<< <simbabque at cpan.org> >> | ||||
|  | ||||
| =head1 BUGS | ||||
|  | ||||
| Please report any bugs or feature requests through an issue | ||||
| on github at L<https://github.com/simbabque/Mojolicious-Plugin-Renderer-WithoutCache/issues>. | ||||
|  | ||||
| =head1 LICENSE | ||||
|  | ||||
| Copyright (C) simbabque. | ||||
|  | ||||
| This library is free software; you can redistribute it and/or modify | ||||
| it under the same terms as Perl itself. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| 1; | ||||
							
								
								
									
										94
									
								
								root/usr/share/smanager/lib/SrvMngr/Plugin/WithoutCache.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								root/usr/share/smanager/lib/SrvMngr/Plugin/WithoutCache.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| package SrvMngr::Plugin::WithoutCache; | ||||
| use Mojo::Base 'Mojolicious::Plugin'; | ||||
| use SrvMngr::Plugin::Cache; | ||||
|  | ||||
| =head1 NAME | ||||
|  | ||||
| Mojolicious::Plugin::Renderer::WithoutCache - Disable the template cache in your Mojo app | ||||
|  | ||||
| =begin html | ||||
|  | ||||
| <p> | ||||
| <a href="https://travis-ci.org/simbabque/Mojolicious-Plugin-Renderer-WithoutCache"><img src="https://travis-ci.org/simbabque/Mojolicious-Plugin-Renderer-WithoutCache.svg?branch=master"></a> | ||||
| <a href='https://coveralls.io/github/simbabque/Mojolicious-Plugin-Renderer-WithoutCache?branch=master'><img src='https://coveralls.io/repos/github/simbabque/Mojolicious-Plugin-Renderer-WithoutCache/badge.svg?branch=master' alt='Coverage Status' /></a> | ||||
| </p> | ||||
|  | ||||
| =end html | ||||
|  | ||||
| =head1 VERSION | ||||
|  | ||||
| Version 0.04 | ||||
|  | ||||
| =cut | ||||
|  | ||||
| our $VERSION = '0.04'; | ||||
| $VERSION = eval $VERSION; | ||||
|  | ||||
| =head1 SYNOPSIS | ||||
|  | ||||
| This plugin turns off the renderer's cache in L<Mojolicious> and L<Mojo::Lite> applications. | ||||
|  | ||||
|     use Mojolicious::Lite; | ||||
|     plugin 'Renderer::WithoutCache'; | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
|  | ||||
| This does what it says on the box. It turns off caching for the L<Mojolicious::Renderer> | ||||
| or any other renderer that's inside C<$app-E<gt>renderer> by injecting a cache object that | ||||
| does not do anything. This is superior to setting the C<max_keys> of L<Mojo::Cache> | ||||
| to C<0> if you plan to do a lot of uncached requests, because L<Mojolicious::Renderer> | ||||
| will still try to cache, and every time L<Mojo::Cache> sets a value in the cache it | ||||
| looks at the C<max_keys>, and then stops. | ||||
|  | ||||
| Doing nothing at all is cheaper. But not a lot really. | ||||
|  | ||||
| =head1 METHODS | ||||
|  | ||||
| =head2 register | ||||
|  | ||||
| Register the plugin in a L<Mojolicious> application. | ||||
|  | ||||
|     $plugin->register(Mojolicious->new); | ||||
|  | ||||
| =cut | ||||
|  | ||||
| sub register { | ||||
|     my ( $self, $app ) = @_; | ||||
|     $app->renderer->cache( SrvMngr::Plugin::Cache->new ); | ||||
| } | ||||
|  | ||||
| =head1 AUTHOR | ||||
|  | ||||
| simbabque, C<< <simbabque at cpan.org> >> | ||||
|  | ||||
| =head1 BUGS | ||||
|  | ||||
| Please report any bugs or feature requests through an issue | ||||
| on github at L<https://github.com/simbabque/Mojolicious-Plugin-Renderer-WithoutCache/issues>. | ||||
|  | ||||
| =head1 SUPPORT | ||||
|  | ||||
| You can find documentation for this module with the perldoc command. | ||||
|  | ||||
|     perldoc Mojolicious::Plugin::Renderer::WithoutCache | ||||
|  | ||||
| =head2 Why would I want to turn off the cache? | ||||
|  | ||||
| I don't know. | ||||
|  | ||||
| =head1 ACKNOWLEDGEMENTS | ||||
|  | ||||
| This plugin was inspired by Tom Hunt asking about turning the cache off | ||||
| on L<Stack Overflow|http://stackoverflow.com/q/41750243/1331451>. | ||||
|  | ||||
| =head1 LICENSE | ||||
|  | ||||
| Copyright (C) simbabque. | ||||
|  | ||||
| This library is free software; you can redistribute it and/or modify | ||||
| it under the same terms as Perl itself. | ||||
|  | ||||
| =cut | ||||
|  | ||||
| 1; | ||||
|  | ||||
| @@ -0,0 +1,90 @@ | ||||
| /* | ||||
| Generated by SM2Gen version: SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43 | ||||
| */ | ||||
| .Letsencrypt-panel {} | ||||
| .name {} | ||||
| .rout {} | ||||
| .grou {} | ||||
| .link2 {} | ||||
| .link3 {} | ||||
| .link4 {} | ||||
| .endg {} | ||||
| .subh2 {} | ||||
| .read4 {} | ||||
| .read5 {} | ||||
| .read6 {} | ||||
| .subh3 {} | ||||
| .read1 {} | ||||
| .read2 {} | ||||
| .read3 {} | ||||
| .subh4 {} | ||||
| .tabl1 {} | ||||
| thead .tabl1 {} | ||||
| tbody .tabl1 {} | ||||
| .name {} | ||||
| .rout {} | ||||
| .subh {} | ||||
| .para1 {} | ||||
| .sele1 {} | ||||
| .sele2 {} | ||||
| .sele3 {} | ||||
| .sele4 {} | ||||
| .sele5 {} | ||||
| .sele6 {} | ||||
| .sele7 {} | ||||
| .emai8 {} | ||||
| .subm9 {} | ||||
| .name {} | ||||
| .rout {} | ||||
| .head {} | ||||
| .subh {} | ||||
| .text1 {} | ||||
| .back2 {} | ||||
| .name {} | ||||
| .rout {} | ||||
| .head {} | ||||
| .subh {} | ||||
| .text1 {} | ||||
| .back2 {} | ||||
| .name {} | ||||
| .rout {} | ||||
| .head {} | ||||
| .subh {} | ||||
| .read1 {} | ||||
| .text2 {} | ||||
| .back3 {} | ||||
|  .inline-buttons { | ||||
|     display: flex; /* Use flexbox to arrange items horizontally */ | ||||
|     gap: 10px;     /* Optional: Add space between buttons */ | ||||
|   } | ||||
|  | ||||
|   .inline-buttons .link { | ||||
|     /* Additional styling can be added here if needed */ | ||||
|   } | ||||
|    | ||||
|    | ||||
|   .inline-buttons .link { | ||||
|     display: inline-block; /* Keep links as inline-block for button shape */ | ||||
|     padding: 7px 14px;     /* Adjusted padding to approximate 70% of the original */ | ||||
|     margin: 0;             /* Remove margin */ | ||||
|     background-color: #efefef; /* Light gray background color */ | ||||
|     color: black;          /* Text color */ | ||||
|     text-decoration: none; /* Remove underline */ | ||||
|     border: 2px solid #bbb; /* Thin, light gray border */ | ||||
|     border-radius: 3px;    /* Slightly rounded corners */ | ||||
|     font-size: 11.2px;     /* Adjusted font size to approximate 70% of the original */ | ||||
|     text-align: center;    /* Center the text */ | ||||
|     cursor: pointer;       /* Pointer cursor on hover */  } | ||||
|  | ||||
|   /* Hover and active effects for better interaction */ | ||||
|   .inline-buttons .link:hover { | ||||
|     background-color: #d9d9d9; /* Darker shade on hover */ | ||||
|   } | ||||
|  | ||||
|   .inline-buttons .link:active { | ||||
|     background-color: #c0c0c0; /* Even darker shade on click */ | ||||
|   } | ||||
|    | ||||
|   span .label { | ||||
| 	padding-top:13em; | ||||
|   } | ||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 10 KiB | 
| @@ -0,0 +1,278 @@ | ||||
| document.addEventListener('DOMContentLoaded', () => { | ||||
|   const flagContainer = document.getElementById('flag-container'); | ||||
|  | ||||
|         async function getCountryName(countryCode) { | ||||
|             try { | ||||
|                 const response = await fetch(`https://restcountries.com/v3.1/alpha/${countryCode}`); | ||||
|                 if (!response.ok) throw new Error('Country not found'); | ||||
|                 const data = await response.json(); | ||||
|                 // Return the name in the native language | ||||
|                 return data[0].name.common;  | ||||
|             } catch (error) { | ||||
|                 console.error(error); | ||||
|                 return 'Unknown Country'; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         function getFlagEmoji(locale) { | ||||
|             // Split the locale to get the language and country code | ||||
|             const parts = locale.split('-'); | ||||
|             let countryCode; | ||||
|  | ||||
|             // Handle single subtag (language only) or double subtag (language-country) | ||||
|             if (parts.length === 1) { | ||||
|                 countryCode = getCountryCodeFromLanguage(parts[0]); | ||||
|             } else if (parts.length === 2) { | ||||
|                 countryCode = parts[1].toLowerCase(); // Use the country code | ||||
|             } | ||||
|  | ||||
|             // If country code is not found, set a fallback output | ||||
|             if (!countryCode) { | ||||
|                 const fallback = `? ${locale.toUpperCase()}`; // Just a question mark and the full locale | ||||
|                 return { flag: fallback, isUnknown: true, countryName: 'Unknown Country' }; | ||||
|             } | ||||
|  | ||||
|             // Convert the country code to a flag emoji | ||||
|             return { | ||||
|                 flag: String.fromCodePoint(...[...countryCode.toUpperCase()].map(char => 0x1F1E6 + char.charCodeAt(0) - 'A'.charCodeAt(0))), | ||||
|                 isUnknown: false, | ||||
|                 countryCode: countryCode | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         function getCountryCodeFromLanguage(language) { | ||||
|             // Map languages to countries (this is an example, extend as needed) | ||||
|             const languageToCountryMap = { | ||||
|                   // Add more mappings as needed | ||||
|     "af": "NA", | ||||
|     "agq": "CM", | ||||
|     "ak": "GH", | ||||
|     "am": "ET", | ||||
|     "ar": "01", | ||||
|     "as": "IN", | ||||
|     "asa": "TZ", | ||||
|     "ast": "ES", | ||||
|     "az": "rl", | ||||
|     "bas": "CM", | ||||
|     "be": "BY", | ||||
|     "bem": "ZM", | ||||
|     "bez": "TZ", | ||||
|     "bg": "BG", | ||||
|     "bm": "ML", | ||||
|     "bn": "BD", | ||||
|     "bo": "CN", | ||||
|     "br": "FR", | ||||
|     "brx": "IN", | ||||
|     "bs": "rl", | ||||
|     "ca": "AD", | ||||
|     "ccp": "BD", | ||||
|     "ce": "RU", | ||||
|     "cgg": "UG", | ||||
|     "chr": "US", | ||||
|     "ckb": "IQ", | ||||
|     "cs": "CZ", | ||||
|     "cy": "GB", | ||||
|     "da": "DK", | ||||
|     "dav": "KE", | ||||
|     "de": "DE", | ||||
|     "dje": "NE", | ||||
|     "dsb": "DE", | ||||
|     "dua": "CM", | ||||
|     "dyo": "SN", | ||||
|     "dz": "BT", | ||||
|     "ebu": "KE", | ||||
|     "ee": "GH", | ||||
|     "el": "CY", | ||||
|     "en": "01", | ||||
|     "es": "ES", | ||||
|     "et": "EE", | ||||
|     "eu": "ES", | ||||
|     "ewo": "CM", | ||||
|     "fa": "AF", | ||||
|     "ff": "CM", | ||||
|     "fi": "FI", | ||||
|     "fil": "PH", | ||||
|     "fo": "FO", | ||||
|     "fr": "FR", | ||||
|     "fur": "IT", | ||||
|     "fy": "NL", | ||||
|     "ga": "IE", | ||||
|     "gd": "GB", | ||||
|     "gl": "ES", | ||||
|     "gsw": "CH", | ||||
|     "gu": "IN", | ||||
|     "guz": "KE", | ||||
|     "gv": "IM", | ||||
|     "ha": "GH", | ||||
|     "haw": "US", | ||||
|     "he": "IL", | ||||
|     "hi": "IN", | ||||
|     "hr": "HR", | ||||
|     "hsb": "DE", | ||||
|     "hu": "HU", | ||||
|     "hy": "AM", | ||||
|     "id": "ID", | ||||
|     "ig": "NG", | ||||
|     "ii": "CN", | ||||
|     "is": "IS", | ||||
|     "it": "IT", | ||||
|     "ja": "JP", | ||||
|     "jgo": "CM", | ||||
|     "jmc": "TZ", | ||||
|     "ka": "GE", | ||||
|     "kab": "DZ", | ||||
|     "kam": "KE", | ||||
|     "kde": "TZ", | ||||
|     "kea": "CV", | ||||
|     "khq": "ML", | ||||
|     "ki": "KE", | ||||
|     "kk": "KZ", | ||||
|     "kkj": "CM", | ||||
|     "kl": "GL", | ||||
|     "kln": "KE", | ||||
|     "km": "KH", | ||||
|     "kn": "IN", | ||||
|     "ko": "KP", | ||||
|     "kok": "IN", | ||||
|     "ks": "IN", | ||||
|     "ksb": "TZ", | ||||
|     "ksf": "CM", | ||||
|     "ksh": "DE", | ||||
|     "kw": "GB", | ||||
|     "ky": "KG", | ||||
|     "lag": "TZ", | ||||
|     "lb": "LU", | ||||
|     "lg": "UG", | ||||
|     "lkt": "US", | ||||
|     "ln": "AO", | ||||
|     "lo": "LA", | ||||
|     "lrc": "IQ", | ||||
|     "lt": "LT", | ||||
|     "lu": "CD", | ||||
|     "luo": "KE", | ||||
|     "Luo": "KE", | ||||
|     "luy": "KE", | ||||
|     "lv": "LV", | ||||
|     "mas": "KE", | ||||
|     "mer": "KE", | ||||
|     "mfe": "MU", | ||||
|     "mg": "MG", | ||||
|     "mgh": "MZ", | ||||
|     "mgo": "CM", | ||||
|     "mk": "MK", | ||||
|     "ml": "IN", | ||||
|     "mn": "MN", | ||||
|     "mr": "IN", | ||||
|     "ms": "BN", | ||||
|     "mt": "MT", | ||||
|     "mua": "CM", | ||||
|     "my": "MM", | ||||
|     "mzn": "IR", | ||||
|     "naq": "NA", | ||||
|     "nb": "NO", | ||||
|     "nd": "ZW", | ||||
|     "nds": "DE", | ||||
|     "ne": "IN", | ||||
|     "nl": "NL", | ||||
|     "nmg": "CM", | ||||
|     "nn": "NO", | ||||
|     "nnh": "CM", | ||||
|     "nus": "SS", | ||||
|     "nyn": "UG", | ||||
|     "om": "ET", | ||||
|     "or": "IN", | ||||
|     "os": "GE", | ||||
|     "pa": "ab", | ||||
|     "pl": "PL", | ||||
|     "ps": "AF", | ||||
|     "pt": "PT", | ||||
|     "qu": "BO", | ||||
|     "rm": "CH", | ||||
|     "rn": "BI", | ||||
|     "ro": "RO", | ||||
|     "rof": "TZ", | ||||
|     "ru": "RU", | ||||
|     "rw": "RW", | ||||
|     "rwk": "TZ", | ||||
|     "sah": "RU", | ||||
|     "saq": "KE", | ||||
|     "sbp": "TZ", | ||||
|     "se": "SE", | ||||
|     "seh": "MZ", | ||||
|     "ses": "ML", | ||||
|     "sg": "CF", | ||||
|     "shi": "tn", | ||||
|     "si": "LK", | ||||
|     "sk": "SK", | ||||
|     "sl": "SI", | ||||
|     "smn": "FI", | ||||
|     "sn": "ZW", | ||||
|     "so": "SO", | ||||
|     "sq": "AL", | ||||
|     "sr": "rl", | ||||
|     "sv": "AX", | ||||
|     "sw": "CD", | ||||
|     "ta": "IN", | ||||
|     "te": "IN", | ||||
|     "teo": "KE", | ||||
|     "tg": "TJ", | ||||
|     "th": "TH", | ||||
|     "ti": "ER", | ||||
|     "to": "TO", | ||||
|     "tr": "TR", | ||||
|     "tt": "RU", | ||||
|     "twq": "NE", | ||||
|     "tzm": "MA", | ||||
|     "ug": "CN", | ||||
|     "uk": "UA", | ||||
|     "ur": "IN", | ||||
|     "uz": "ab", | ||||
|     "vai": "tn", | ||||
|     "Vai": "tn", | ||||
|     "vi": "VN", | ||||
|     "vun": "TZ", | ||||
|     "wae": "CH", | ||||
|     "wo": "SN", | ||||
|     "xog": "UG", | ||||
|     "yav": "CM", | ||||
|     "yi": "01", | ||||
|     "yo": "BJ", | ||||
|     "yue": "ns", | ||||
|     "zgh": "MA", | ||||
|     "zh": "ns", | ||||
|     "zu": "ZA" | ||||
|  | ||||
|  | ||||
|             }; | ||||
|  | ||||
|             return languageToCountryMap[language] || null; | ||||
|         } | ||||
|  | ||||
|         async function displayLocaleAndFlag() { | ||||
|             // Get the browser locale | ||||
|             const userLocale = navigator.language || navigator.userLanguage; | ||||
|             const { flag, isUnknown, countryCode } = getFlagEmoji(userLocale); | ||||
|  | ||||
|             // Display the locale and the corresponding flag (or fallback) | ||||
|             //document.getElementById('locale').textContent = `Your Locale: ${userLocale}`; | ||||
|  | ||||
|             if (isUnknown) { | ||||
|                 const fallbackDiv = document.createElement('div'); | ||||
|                 fallbackDiv.className = 'fallback-box'; | ||||
|                 fallbackDiv.textContent = `? ${userLocale.toUpperCase()}`; // Only show ? and locale code inside the box | ||||
|                 //document.getElementById('flag-container').textContent = "Flag: "; | ||||
|                 document.getElementById('flag-container').appendChild(fallbackDiv); | ||||
|                 // Tooltip for fallback | ||||
|                 fallbackDiv.title = "Unknown Country"; // Tooltip for fallback | ||||
|             } else { | ||||
|                 const countryName = await getCountryName(countryCode); | ||||
|                 const flagSpan = document.createElement('span'); | ||||
|                 flagSpan.textContent = flag; // Use flag emoji | ||||
|                 flagSpan.title = countryName; // Tooltip for the flag in country language | ||||
|                 //document.getElementById('flag-container').textContent = "Flag: "; | ||||
|                 document.getElementById('flag-container').appendChild(flagSpan); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         displayLocaleAndFlag(); | ||||
| }); | ||||
| @@ -1,12 +1,17 @@ | ||||
| % layout 'default', title => "Sme server 2 - emailreceive"; | ||||
|  | ||||
| % content_for 'module' => begin | ||||
|  | ||||
| % use constant FALSE => 0; | ||||
| % use constant TRUE  => 1; | ||||
|  | ||||
| <div id='module' class='module emailreceive-panel'> | ||||
|  | ||||
|     % if ($config->{debug} == 1) { | ||||
| 	<p> | ||||
| 	%= dumper $c->current_route | ||||
| 	%= dumper $mai_datas | ||||
| 	%= dumper $c->param('SMTPAuth') | ||||
| 	</p> | ||||
|     % } | ||||
|  | ||||
| @@ -26,16 +31,65 @@ | ||||
| 	%=l 'mai_LABEL_MODE' | ||||
| 	</span><span class=input> | ||||
| 	% param 'FetchmailMethod' => $mai_datas->{fetchmailmethod} unless param 'FetchmailMethod'; | ||||
| <!-- | ||||
| 	<pre> | ||||
| 		%= dumper $mai_datas->{fetchmailmethod} | ||||
| 		%= dumper $c->get_retrieval_opt() | ||||
| 		%= param 'FetchmailMethod' | ||||
| 	</pre> | ||||
| --> | ||||
| 	%= select_field 'FetchmailMethod' => $c->get_retrieval_opt(), class => 'input' | ||||
| 	</span></p> | ||||
|  | ||||
| 	%=l 'mai_DESC_SMTP_AUTH_CONTROL' | ||||
| 	%#=l 'mai_DESC_SMTP_AUTH_CONTROL' | ||||
| 	<br /> | ||||
| 	%= l "SMTP port (25) main purpose is to receive emails from another server, STARTTLS is always offered, but auth if offered is only if STARTTLS is also used by client." | ||||
| 	<br /> | ||||
| 	%= l "SMTPS port (465) will require implicit SSL/TLS then authenticate to send." | ||||
| 	<br /> | ||||
| 	%= l "SMTP Submission port (587) will require STARTTLS, then authenticate to send." | ||||
| 	<br /> | ||||
|  | ||||
| 	% my $smtp_mesg=l('SMTP port %u allow client to authenticate:'); | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_SMTP_AUTH_CONTROL' | ||||
| 		%= sprintf($smtp_mesg,$c->get_db_prop('qpsmtpd','TCPPort',25));  | ||||
| 	</span><span class=input> | ||||
|     	% param 'SMTPAuth' => $c->get_current_smtp_auth() unless param 'SMTPAuth'; | ||||
| 	%= select_field 'SMTPAuth' => $c->get_smtp_auth_opt(), class => 'input' | ||||
|     	% param 'SMTPAuth' => $c->get_current_smtp_auth( FALSE ) unless param 'SMTPAuth'; | ||||
| <!-- | ||||
| 	<pre> | ||||
| 		%= dumper $c->get_smtp_auth_opt() | ||||
| 		%= dumper $c->get_current_smtp_auth(FALSE) | ||||
| 		%= dumper $c->get_db_prop("qpsmtpd","Authentication") | ||||
| 		%= param 'SMTPAuth' | ||||
| 	</pre> | ||||
| --> | ||||
| 		%= select_field 'SMTPAuth' => $c->get_smtp_auth_opt(), class => 'input' | ||||
| 	</span></p> | ||||
|  | ||||
| 	% my $smtp_mesg=l('SMTPS SSL/TLS auth: port %u status:'); | ||||
| 	<p><span class=label> | ||||
| 		%= sprintf($smtp_mesg,$c->get_db_prop('sqpsmtpd','TCPPort',465));  | ||||
| 	</span><span class=input> | ||||
| 		% param 'sSMTPAuth' => $c->get_current_smtp_ssl_auth(FALSE,'s', TRUE) unless param 'sSMTPAuth'; | ||||
| 	 | ||||
| 		%= select_field 'sSMTPAuth' => $c->get_smtp_ssl_auth_opt(), class => 'input' | ||||
| 	</span></p> | ||||
|  | ||||
| 	%my $smtp_mesg=l('Submission port %u status:'); | ||||
| 	<p><span class=label> | ||||
| 		%= sprintf($smtp_mesg,$c->get_db_prop('uqpsmtpd','TCPPort',587));  | ||||
| 	</span><span class=input> | ||||
|     	% param 'uSMTPAuth' => $c->get_current_smtp_ssl_auth(FALSE,'u', TRUE) unless param 'uSMTPAuth'; | ||||
| <!-- | ||||
| 	<pre> | ||||
| 		%= dumper $c->get_smtp_ssl_auth_opt() | ||||
| 		%= dumper $c->get_current_smtp_ssl_auth(FALSE,'s', TRUE) | ||||
| 		%= dumper $c->get_current_smtp_ssl_auth(FALSE,'u', TRUE) | ||||
| 		%= dumper $c->get_db_prop("uqpsmtpd","access") | ||||
| 		%= param 'uSMTPAuth' | ||||
| 	</pre> | ||||
| --> | ||||
| 	%= select_field 'uSMTPAuth' => $c->get_smtp_ssl_auth_opt(), class => 'input' | ||||
| 	</span></p> | ||||
|  | ||||
| 	<hr class="sectionbar" /> | ||||
| @@ -110,4 +164,4 @@ | ||||
|     % end     | ||||
|  | ||||
| </div> | ||||
| %end | ||||
| %end | ||||
| @@ -1,9 +1,13 @@ | ||||
| % layout 'default', title => "Sme server 2 - emailsettings"; | ||||
|  | ||||
| % content_for 'module' => begin | ||||
|  | ||||
| % use constant FALSE => 0; | ||||
| % use constant TRUE  => 1; | ||||
|  | ||||
| <div id='module' class='module emailsettings-panel'> | ||||
|  | ||||
|     % if ($config->{debug} == 1) { | ||||
|     % if ($config->{debug} == TRUE) { | ||||
| 	<p> | ||||
| 	%= dumper $c->current_route | ||||
| 	%= dumper $mai_datas | ||||
| @@ -22,19 +26,19 @@ | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_POP_ACCESS_CONTROL' | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_current_pop3_access( 1 ) | ||||
| 	%= $c->get_current_pop3_access( TRUE ) | ||||
| 	</span></p> | ||||
|  | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_IMAP_ACCESS_CONTROL' | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_current_imap_access( 1 ) | ||||
| 	%= $c->get_current_imap_access( TRUE ) | ||||
| 	</span></p> | ||||
|  | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_WEBMAIL' | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_current_webmail_status( 1 ) | ||||
| 	%= $c->get_current_webmail_status( TRUE ) | ||||
| 	</span></p> | ||||
|  | ||||
|     % 	my $btn = l('mai_DESC_STATE_ACCESS_BUTTON'); | ||||
| @@ -51,19 +55,19 @@ | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_VIRUS_SCAN' | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_virus_status(1) | ||||
| 	%= $c->get_virus_status(TRUE) | ||||
| 	</span></p> | ||||
|  | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_SPAM_SCAN' | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_spam_status(1) | ||||
| 	%= $c->get_spam_status(TRUE) | ||||
| 	</span></p> | ||||
|  | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_BLOCK_EXECUTABLE_CONTENT' | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_patterns_status(1) | ||||
| 	%= $c->get_patterns_status(TRUE) | ||||
| 	</span></p> | ||||
|  | ||||
|     % 	my $btn = l('mai_DESC_STATE_FILTERING_BUTTON'); | ||||
| @@ -83,12 +87,28 @@ | ||||
| 	%= $mai_datas->{fetchmailmethod} | ||||
| 	</span></p> | ||||
|  | ||||
| 	% my $smtp_mesg=l('SMTP port %u allow client to authenticate:'); | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_SMTP_AUTH_CONTROL' | ||||
| 		%= sprintf($smtp_mesg,$c->get_db_prop('qpsmtpd','TCPPort',25));  | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_current_smtp_auth( 1 ) | ||||
| 	%= $c->get_current_smtp_auth( TRUE ) | ||||
| 	</span></p> | ||||
|  | ||||
| 	% my $smtp_mesg=l('SMTPS SSL/TLS auth: port %u status:'); | ||||
| 	<p><span class=label> | ||||
| 		%= sprintf($smtp_mesg,$c->get_db_prop('sqpsmtpd','TCPPort',465));  | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_current_smtp_ssl_auth( TRUE, 's', FALSE ) | ||||
| 	</span></p> | ||||
|  | ||||
| 	%my $smtp_mesg=l 'Submission port %u status:'; | ||||
| 	<p><span class=label> | ||||
| 		%= sprintf($smtp_mesg,$c->get_db_prop('uqpsmtpd','TCPPort',587));  | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_current_smtp_ssl_auth( TRUE,'u', FALSE ) | ||||
| 	</span></p> | ||||
| 	<br /> | ||||
|  | ||||
|     % 	my $btn = l('mai_DESC_STATE_RECEPTION_BUTTON'); | ||||
|     <div class='center'> | ||||
| 	%= submit_button "$btn", class => 'action' | ||||
| @@ -103,7 +123,7 @@ | ||||
| 	<p><span class=label> | ||||
| 	%=l 'mai_LABEL_UNKNOWN' | ||||
| 	</span><span class=data2> | ||||
| 	%= $c->get_emailunknownuser_status( 1 ) | ||||
| 	%= $c->get_emailunknownuser_status( TRUE ) | ||||
| 	</span></p> | ||||
|  | ||||
| 	<p><span class=label> | ||||
| @@ -127,4 +147,4 @@ | ||||
|     % end     | ||||
|  | ||||
| </div> | ||||
| %end | ||||
| %end | ||||
| @@ -19,18 +19,35 @@ | ||||
|     %= content_for 'refresh' | ||||
|      | ||||
|     %= stylesheet '/js/datatables.min.css' | ||||
| 	%= javascript '/js/datatables.min.js' | ||||
| 	%= stylesheet '/js/jquery-ui.min.css' | ||||
| 	%= javascript '/js/jquery-ui.min.js' | ||||
| 	 | ||||
| 	%= stylesheet '/js/dataTables.buttons.min.js' | ||||
| 	%= stylesheet '/js/jszip.min.js' | ||||
| 	%= stylesheet '/js/pdfmake.min.js' | ||||
| 	%= stylesheet '/js/vfs_fonts.js' | ||||
| 	%= stylesheet '/js/buttons.html5.min.js' | ||||
| 	%= stylesheet '/js/buttons.print.min.js' | ||||
|  | ||||
| 	%= javascript '/js/datatables.min.js' | ||||
|  | ||||
| 	%= stylesheet '/js/jquery-ui.min.css' | ||||
|  | ||||
| 	%= javascript '/js/jquery-ui.min.js' | ||||
| 	%= javascript '/js/dataTables.buttons.min.js' | ||||
| 	%= javascript '/js/jszip.min.js' | ||||
| 	%= javascript '/js/pdfmake.min.js' | ||||
| 	%= javascript '/js/vfs_fonts.js' | ||||
| 	%= javascript '/js/buttons.html5.min.js' | ||||
| 	%= javascript '/js/buttons.print.min.js' | ||||
| 	%= javascript '/js/flag-by-locale.js' | ||||
|  | ||||
| 	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.5.0/css/flag-icon.min.css"> | ||||
| 	%= stylesheet '/css/sme-jquery-overrides.css' | ||||
| 	 | ||||
| 	<style> | ||||
| 	#busy-indicator { | ||||
| 		display: none; | ||||
| 		margin-top: 10px; | ||||
| 		font-weight: bold; | ||||
| 		color: red; | ||||
| 	} | ||||
| 	.busy { | ||||
| 		cursor: wait; /* Change the cursor to a 'wait' cursor */ | ||||
| 	} | ||||
| 	</style> | ||||
|  | ||||
|  | ||||
| </head> | ||||
|  | ||||
| @@ -91,46 +108,21 @@ | ||||
|  | ||||
| %= javascript '/js/sme-dataTable-setup.js' | ||||
|  | ||||
| %= javascript begin | ||||
| //Set menu to initial condition based on localStorage | ||||
| $(document).ready(function() { | ||||
| 	let menunavflag = window.localStorage.getItem('menunav'); | ||||
| 	if (menunavflag != "false"){ | ||||
| 		$('#menunav').toggle(true);	 | ||||
| 	} else { | ||||
| 		$('#menunav').toggle(false);	       | ||||
| 	} | ||||
| 	 | ||||
| 	let menuadmflag = window.localStorage.getItem('menuadm'); | ||||
| 	if (menuadmflag != "false"){ | ||||
| 		$('#menuadm').toggle(true);	 | ||||
| 	} else { | ||||
| 		$('#menuadm').toggle(false);	       | ||||
| 	} | ||||
| 	<script> | ||||
| 		$(document).ready(function() { | ||||
| 			// Handle form submission for any form | ||||
| 			$('form').on('submit', function(event) { | ||||
| 				// Disable the submit button | ||||
| 				$(this).find('button[type="submit"], input[type="submit"]').prop('disabled', true); | ||||
| 				// Show the busy indicator | ||||
| //				$('#busy-indicator').show(); | ||||
| 				 | ||||
| 				// Change the cursor to "wait" | ||||
| 				$('body').addClass('busy'); | ||||
| 			}); | ||||
| 		}); | ||||
| 	</script> | ||||
|  | ||||
| 	let menuuserflag = window.localStorage.getItem('menuuser'); | ||||
| 	if (menuuserflag != "false"){ | ||||
| 		$('#menuuser').toggle(true);	 | ||||
| 	} else { | ||||
| 		$('#menuuser').toggle(false);	       | ||||
| 	} | ||||
| 	 | ||||
| 	var sections = document.getElementsByClassName("section-title"); | ||||
| 	for (var i = 0, len = sections.length; i < len; i++) { | ||||
| 		var jqObj = $(sections[i]); | ||||
| 		var $section = jqObj.parent().next('div'); | ||||
| 		if(!$section.length){ | ||||
| 			return false; | ||||
| 		} | ||||
| 		let localStorageTag = "admSection-"+sections[i].innerHTML; | ||||
| 		if (window.localStorage.getItem(localStorageTag) != "false"){ | ||||
| 			$section.toggle(true); | ||||
| 		} else { | ||||
| 			$section.toggle(false);	       | ||||
| 		} | ||||
| 	} | ||||
| }) | ||||
| %end | ||||
|    | ||||
| </body> | ||||
| </html> | ||||
|   | ||||
| @@ -0,0 +1,69 @@ | ||||
| %# | ||||
| %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43  | ||||
| %# | ||||
| % layout 'default', title => "Sme server 2 - Letsencrypt certificate", share_dir => './'; | ||||
| %# css specific to this panel: | ||||
| % content_for 'module' => begin | ||||
| %= stylesheet '/css/letsencrypt.css' | ||||
| <div id="module" class="module Letsencrypt-panel"> | ||||
|  | ||||
|     % if ($config->{debug} == 1) { | ||||
| 	<pre> | ||||
| 		%= dumper $c->current_route | ||||
| 		%= dumper $lets_data->{trt} | ||||
| 	</pre> | ||||
|     % } | ||||
|      | ||||
|     <h1><%=$title%></h1> | ||||
|  | ||||
|     % if ( stash('modul')) { | ||||
| 	%= $c->render_to_string(inline => stash('modul') ); | ||||
|     % } | ||||
|  | ||||
|    	%if ($c->stash('first')) { | ||||
| 	    <br><p> | ||||
| 		%=$c->render_to_string(inline =>$c->l($c->stash('first'))) | ||||
| 		</p> | ||||
|  | ||||
| 	%} elsif ($c->stash('success')) { | ||||
| 		<div class='success '> | ||||
| 	       <h2><%=$c->l('lets_Status_Report') %></h2><p> | ||||
| 			%= $c->l($c->stash('success')); | ||||
| 			</p> | ||||
| 		</div> | ||||
|  | ||||
| 	%} elsif ($c->stash('error')) {  | ||||
| 	   <div class='sme-error'> | ||||
| 	       <h2><%=$c->l('lets_Error_Status_Report') %></h2><p> | ||||
| 			%= $c->l($c->stash('error')); | ||||
| 			</p> | ||||
|     	</div> | ||||
| 	%} | ||||
|  | ||||
| 	%#Routing to partials according to trt parameter. | ||||
| 	%#This ought to be cascading if/then/elsif, but is easier to just stack the if/then's rather like a case statement' | ||||
| 	 | ||||
| 	% if ($lets_data->{trt} eq "LIST") { | ||||
| 		%= include 'partials/_lets_LIST' | ||||
| 	%} | ||||
| 	 | ||||
| 	% if ($lets_data->{trt} eq "PARAMS") { | ||||
| 		%= include 'partials/_lets_PARAMS' | ||||
| 	%} | ||||
| 	 | ||||
| 	% if ($lets_data->{trt} eq "CHECKALLDOMAINS") { | ||||
| 		%= include 'partials/_lets_CHECKALLDOMAINS' | ||||
| 	%} | ||||
| 	 | ||||
| 	% if ($lets_data->{trt} eq "CHECKALLENABLEDDOMAINS") { | ||||
| 		%= include 'partials/_lets_CHECKALLENABLEDDOMAINS' | ||||
| 	%} | ||||
| 	 | ||||
| 	% if ($lets_data->{trt} eq "CHECKONEDOMAIN") { | ||||
| 		%= include 'partials/_lets_CHECKONEDOMAIN' | ||||
| 	%} | ||||
| 	 | ||||
|  | ||||
|  | ||||
| </div> | ||||
| %end | ||||
| @@ -1,8 +1,9 @@ | ||||
| <div id="footer"> | ||||
| <div id="footer" width=100%> | ||||
| <HR class="sme-copyrightbar"> | ||||
| <a href="https://mojolicious.org" target="_blank"><img src="images/sme-mojo-logo-white.png" style="position:relative;"></a> | ||||
| <font class="sme-copyright"> | ||||
| %	if ( $c->is_logged_in ) { | ||||
| 	SME Server <%= session 'releaseVersion' %> - Manager <%= $c->app->VERSION %> | ||||
| 	SME Server <%= session 'releaseVersion' %>-<%= $c->app->VERSION %> Manager II | ||||
| % } | ||||
| <br>Copyright 1999-2006 Mitel Corporation<br> | ||||
| %= session 'copyRight' | ||||
|   | ||||
| @@ -1,27 +1,128 @@ | ||||
| <style> | ||||
| #h2l1 { | ||||
|     display: flex;                  /* Use flexbox layout */ | ||||
|     justify-content: space-between; /* Space between child elements */ | ||||
|     align-items: center;           /* Center items vertically */ | ||||
| } | ||||
|  | ||||
| #h2e11 { | ||||
|     flex: 1;                       /* Allow the first div to take available space on the left */ | ||||
| } | ||||
|  | ||||
| #h2e12 {  | ||||
|     display: flex;                 /* Make this div a flex container */ | ||||
|     align-items: center;           /* Vertically center content in this div */ | ||||
|     margin-left: 20px;            /* Add margin to the left of this div */ | ||||
| } | ||||
|  | ||||
| #flag-container { | ||||
|     display: flex;                 /* Make this div a flex container */ | ||||
|     align-items: center;           /* Vertically center content in this div */ | ||||
|     margin-left: 20px;             /* Add margin to the left of the flag container */ | ||||
|     padding-right: 20px;           /* Add padding to the right side of the flag container */ | ||||
| } | ||||
|  | ||||
| .flag-icon { | ||||
|     width: 43px; | ||||
|     font-size: 20px; | ||||
| } | ||||
|  | ||||
| #legacy-button button { | ||||
|     background-color: #98d36e; /* Button background color */ | ||||
|     font-weight: lighter;      /* Lighter text for the button */ | ||||
|     color: #063;               /* Button text color */ | ||||
|     padding: 5px 10px;         /* Padding for the button */ | ||||
|     border: none;              /* Remove default button border */ | ||||
|     border-radius: 4px;        /* Rounded corners for button */ | ||||
|     cursor: pointer;           /* Change cursor on hover */ | ||||
| } | ||||
|  | ||||
| #legacy-button button:hover { | ||||
|     background-color: #82c961; /* Change color on hover */ | ||||
| } | ||||
|  | ||||
| .infobar { | ||||
|     display: flex;                  /* Use flexbox for alignment */ | ||||
|     justify-content: space-between; /* Space between child elements */ | ||||
|     align-items: center;            /* Center items vertically */ | ||||
|     padding: 10px;                  /* Adjust padding as desired */ | ||||
| } | ||||
|  | ||||
| #h2e21 { | ||||
|     flex: 1;                        /* Allow the first div to take available space on the left */ | ||||
| } | ||||
|  | ||||
| #h2e22 { | ||||
|     display: flex;                  /* Make this div a flex container */ | ||||
|     justify-content: center;        /* Center the help button */ | ||||
|     align-items: center;            /* Center vertically */ | ||||
|     flex: none;                    /* Prevent this div from growing */ | ||||
|     position: relative;             /* Relative position for centering */ | ||||
|     width: 100px;                  /* Set a width for the help button container */ | ||||
| } | ||||
|  | ||||
| #h2e23 { | ||||
|     margin-left: auto;              /* Push the third div to the right */ | ||||
| } | ||||
|  | ||||
| .login-button { | ||||
|     background-color: #98d36e;     /* Button background color */ | ||||
|     font-weight: bold;              /* Bold text */ | ||||
|     xxcolor: #ffffff;                 /* Button text color */ | ||||
|     padding: 8px 12px;              /* Adjust padding for button height */ | ||||
|     border: none;                   /* Remove default border */ | ||||
|     border-radius: 4px;             /* Rounded corners */ | ||||
|     cursor: pointer;                /* Change cursor on hover */ | ||||
| } | ||||
|  | ||||
| .login-button:hover { | ||||
|     background-color: #82c961;      /* Change color on hover */ | ||||
| } | ||||
|  | ||||
| #help-button { | ||||
|     text-decoration: none;          /* Remove underline from link */ | ||||
|     font-size: 20px;                /* Adjust font size as needed */ | ||||
|     padding: 8px 12px;              /* Add padding to the help link */ | ||||
|     background-color: #98d36e;      /* Background for visibility */ | ||||
|     border-radius: 4px;             /* Rounded corners */ | ||||
|     color: #000;                    /* Button text color */ | ||||
| } | ||||
|  | ||||
| #help-button:hover { | ||||
|     background-color: #82c961;      /* Change background on hover */ | ||||
| } | ||||
| </style> | ||||
|  | ||||
| <div id="header2" class="hd2"> | ||||
|     <div id="h2l1">  | ||||
| 	<div id="h2e11"> | ||||
| 	    <a target='_blank' href="http://www.koozali.org"><img src="images/smeserver_logo.jpg" height="40" alt="SME Server"></a> | ||||
| 	</div> | ||||
| <!--        <div id="h2e12"><h5><a href="initial">Server Manager</a> | ||||
|             <a href="/server-manager" target='_blank'>    (Prev SM)</a></h5> -->            | ||||
|         <div id="h2e12" style="float:right;"><br><a href="/server-manager" target='_blank'><button style="background-color:#98d36e;font-weight:bold;color:#063;">Legacy SM</button></a></div> | ||||
|     </div> | ||||
| 		<div id="h2e11"> | ||||
| 			<a target='_blank' href="http://www.koozali.org"><img src="images/smeserver_logo.jpg" height="40" alt="SME Server"></a> | ||||
| 		</div>  | ||||
|  | ||||
|     <div id="h2l2" class="infobar">  | ||||
| 	<div id="h2e21"> | ||||
|         <b> | ||||
|         <%= session 'SystemName' %>@<%= session 'DomainName' %></b>  | ||||
| 	</div> | ||||
|         <div id="h2e22"> | ||||
|           <a target="_parent" href="manual">  <b> ? </b>  </a>  | ||||
| 	</div> | ||||
| 	<div id="h2e23"> | ||||
| %    if ( not defined $c->session->{username} ) { | ||||
|           <a target="_parent" href="login"><b>Login</b></a>  | ||||
| %    } else { | ||||
|           <a target="_parent" href="logout"><b><%= $c->session->{username} %> Logout</b></a>  | ||||
| %    } | ||||
| 	</div> | ||||
| 		<div id="h2e22"> | ||||
| 			<a id="help-button" target="_parent" href="manual"><button> ? </button></a> | ||||
| 		</div> | ||||
|      | ||||
|         <div id="h2e12"> | ||||
| 			<a id="legacy-button" href="/server-manager" target='_blank'><button>Legacy SM</button></a> | ||||
|         </div> | ||||
| 		<div id="h2e23"> | ||||
| 			% if ( not defined $c->session->{username} ) { | ||||
| 				<a target="_parent" href="login"><button class="login-button">Login</button></a> | ||||
| 			% } else { | ||||
| 				<a target="_parent" href="logout"><button class="login-button"><%= $c->session->{username} %> Logout</button></a> | ||||
| 			% } | ||||
| 		</div> | ||||
| 		<div id="flag-container"> | ||||
| 			<!-- The flag icon will be inserted here --> | ||||
| 		</div> | ||||
|     </div> | ||||
| 	<div id="h2l2" class="infobar">  | ||||
| 		<div id="h2e21"> | ||||
| 			<b> | ||||
| 				<%= session 'SystemName' %>@<%= session 'DomainName' %></b>  | ||||
| 		</div> | ||||
| 		 | ||||
| 		 | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| 	<br> | ||||
| 	%= submit_button "$btn", class => 'action' | ||||
| 	</p> | ||||
|     %= hidden_field 'trt' => 'ADD'; | ||||
|  | ||||
|     % end     | ||||
|  | ||||
| @@ -71,9 +72,7 @@ | ||||
|     %    } | ||||
|     	</tbody> | ||||
|     	</table> | ||||
|  | ||||
| 	<%} %> | ||||
|  | ||||
|         %= hidden_field 'trt' => $iba_datas->{trt} | ||||
|  | ||||
| </div> | ||||
|   | ||||
| @@ -0,0 +1,39 @@ | ||||
| %# | ||||
| %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43  | ||||
| %# | ||||
| <div id="Letsencrypt-CHECKALLDOMAINS" class="partial Letsencrypt-CHECKALLDOMAINS"> | ||||
| 	<script> | ||||
| 		window.onload = function() { | ||||
| 		SelectInput(); | ||||
| 	}; | ||||
| 	</script> | ||||
| 	% if ($config->{debug} == 1) { | ||||
| 		<pre> | ||||
| 			%= dumper $lets_data | ||||
| 		</pre> | ||||
| 	% } | ||||
| 	% my $btn = l('lets_APPLY'); | ||||
| 	%= form_for "letsencryptu" => (method => 'POST') => begin | ||||
| 		% param 'trt' => $lets_data->{trt} unless param 'trt'; | ||||
| 		%= hidden_field 'trt' => $lets_data->{trt} | ||||
| 		%# Inputs etc in here. | ||||
|  | ||||
| 		<h1 class='head'><%=l('lets_Check_all_domains')%></h1> | ||||
| 	 | ||||
| 		<h2 class='subh'><%=l('lets_Loop_through_checking_the_letsencrypt')%></h2> | ||||
| 	 | ||||
| 		<span class=label> | ||||
| 			%=l('lets_All_domains_check_result') | ||||
| 		</span><span class=data> | ||||
| 			% param 'AllDomainsCheck' => $lets_data->{AllDomainsCheck} unless param 'AllDomainsCheck'; | ||||
| 			%= text_area 'AllDomainsCheck', cols=>40, rows=>10, Readonly=>'true' | ||||
| 		</span><br> | ||||
| 	 | ||||
| 		<span class='data'> | ||||
| 			%= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()' | ||||
| 		</span> | ||||
| 		 | ||||
| 	 | ||||
| 		%# Probably finally by a submit. | ||||
| 	%end     | ||||
| </div> | ||||
| @@ -0,0 +1,39 @@ | ||||
| %# | ||||
| %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43  | ||||
| %# | ||||
| <div id="Letsencrypt-CHECKALLENABLEDDOMAINS" class="partial Letsencrypt-CHECKALLENABLEDDOMAINS"> | ||||
| 	<script> | ||||
| 		window.onload = function() { | ||||
| 		SelectInput(); | ||||
| 	}; | ||||
| 	</script> | ||||
| 	% if ($config->{debug} == 1) { | ||||
| 		<pre> | ||||
| 			%= dumper $lets_data | ||||
| 		</pre> | ||||
| 	% } | ||||
| 	% my $btn = l('lets_APPLY'); | ||||
| 	%= form_for "letsencryptu" => (method => 'POST') => begin | ||||
| 		% param 'trt' => $lets_data->{trt} unless param 'trt'; | ||||
| 		%= hidden_field 'trt' => $lets_data->{trt} | ||||
| 		%# Inputs etc in here. | ||||
|  | ||||
| 		<h1 class='head'><%=l('lets_Check_all_enabled_domains')%></h1> | ||||
| 	 | ||||
| 		<h2 class='subh'><%=l('lets_Loop_through_checking_the_letsencrypt')%></h2> | ||||
| 	 | ||||
| 		<span class=label> | ||||
| 			%=l('lets_Enabled_domains_check_result') | ||||
| 		</span><span class=data> | ||||
| 			% param 'EnabledDomainsCheck' => $lets_data->{EnabledDomainsCheck} unless param 'EnabledDomainsCheck'; | ||||
| 			%= text_area 'EnabledDomainsCheck', cols=>40, rows=>10, Readonly=>'true' | ||||
| 		</span><br> | ||||
| 	 | ||||
| 		<span class='data'> | ||||
| 			%= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()' | ||||
| 		</span> | ||||
| 		 | ||||
| 	 | ||||
| 		%# Probably finally by a submit. | ||||
| 	%end     | ||||
| </div> | ||||
| @@ -0,0 +1,46 @@ | ||||
| %# | ||||
| %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43  | ||||
| %# | ||||
| <div id="Letsencrypt-CHECKONEDOMAIN" class="partial Letsencrypt-CHECKONEDOMAIN"> | ||||
| 	<script> | ||||
| 		window.onload = function() { | ||||
| 		SelectInput(); | ||||
| 	}; | ||||
| 	</script> | ||||
| 	% if ($config->{debug} == 1) { | ||||
| 		<pre> | ||||
| 			%= dumper $lets_data | ||||
| 		</pre> | ||||
| 	% } | ||||
| 	% my $btn = l('lets_APPLY'); | ||||
| 	%= form_for "letsencryptu" => (method => 'POST') => begin | ||||
| 		% param 'trt' => $lets_data->{trt} unless param 'trt'; | ||||
| 		%= hidden_field 'trt' => $lets_data->{trt} | ||||
| 		%# Inputs etc in here. | ||||
|  | ||||
| 		<h1 class='head'><%=l('lets_Check_just_one_domain')%></h1> | ||||
| 	 | ||||
| 		<h2 class='subh'><%=l('lets_Loop_through_and_check_the')%></h2> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_Domains_name') | ||||
| 		</span><span class=data> | ||||
| 			% param 'OneDomainToCheck' => $lets_data->{OneDomainToCheck} unless param 'OneDomainToCheck'; | ||||
| 			%= text_field 'OneDomainToCheck', size => '50', class => 'textinput OneDomainToCheck' , pattern=>'.*' , placeholder=>'OneDomainToCheck', Readonly=>'true' | ||||
| 		<br></span></p> | ||||
| 	 | ||||
| 		<span class=label> | ||||
| 			%=l('lets_One_domain_check_result') | ||||
| 		</span><span class=data> | ||||
| 			% param 'OneDomainsCheck' => $lets_data->{OneDomainsCheck} unless param 'OneDomainsCheck'; | ||||
| 			%= text_area 'OneDomainsCheck', cols=>40, rows=>10, Readonly=>'true' | ||||
| 		</span><br> | ||||
| 	 | ||||
| 		<span class='data'> | ||||
| 			%= submit_button l('lets_Back'), class => 'action back', onclick =>'history.back()' | ||||
| 		</span> | ||||
| 		 | ||||
| 	 | ||||
| 		%# Probably finally by a submit. | ||||
| 	%end     | ||||
| </div> | ||||
| @@ -0,0 +1,126 @@ | ||||
| %# | ||||
| %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43  | ||||
| %# | ||||
| <div id="Letsencrypt-LIST" class="partial Letsencrypt-LIST"> | ||||
| 	<script> | ||||
| 		window.onload = function() { | ||||
| 		SelectInput(); | ||||
| 	}; | ||||
| 	</script> | ||||
| 	% if ($config->{debug} == 1) { | ||||
| 		<pre> | ||||
| 			%= dumper $lets_data | ||||
| 		</pre> | ||||
| 	% } | ||||
| 	% my $btn = l('lets_APPLY'); | ||||
| 	%= form_for "letsencryptu" => (method => 'POST') => begin | ||||
| 		% param 'trt' => $lets_data->{trt} unless param 'trt'; | ||||
| 		%= hidden_field 'trt' => $lets_data->{trt} | ||||
| 		%# Inputs etc in here. | ||||
|  | ||||
| 		<div class=inline-buttons> | ||||
| 		 | ||||
| 	 | ||||
| 		<a href='letsencryptd?trt=PARAMS' class='link link2'> | ||||
| 			%= l('lets_CONFIG') | ||||
| 		</a> | ||||
| 		%#= link_to l('lets_CONFIG'), 'letsencryptd?trt=PARAMS' , class=>'link link2' | ||||
| 	 | ||||
| 	 | ||||
| 		<a href='letsencryptd?trt=CHECKALLDOMAINS' class='link link3'> | ||||
| 			%= l('lets_CHECK_ALL_DOMAINS') | ||||
| 		</a> | ||||
| 		%#= link_to l('lets_CHECK_ALL_DOMAINS'), 'letsencryptd?trt=CHECKALLDOMAINS' , class=>'link link3' | ||||
| 	 | ||||
| 	 | ||||
| 		<a href='letsencryptd?trt=CHECKALLENABLEDDOMAINS' class='link link4'> | ||||
| 			%= l('lets_CHECK_ALL_ENABLED_DOMAINS') | ||||
| 		</a> | ||||
| 		%#= link_to l('lets_CHECK_ALL_ENABLED_DOMAINS'), 'letsencryptd?trt=CHECKALLENABLEDDOMAINS' , class=>'link link4' | ||||
| 	 | ||||
| 	 | ||||
| 		</div> | ||||
| 		 | ||||
| 	 | ||||
| 		<h2 class='subh2'><%=l('lets_For_this_Server')%></h2> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_Internal_IP') | ||||
| 		</span><span class=data> | ||||
| 			% param 'InternalIP' => $lets_data->{InternalIP} unless param 'InternalIP'; | ||||
| 			%= text_field 'InternalIP', size => '50', class => 'textinput InternalIP' , pattern=>'.*' , placeholder=>'InternalIP', Readonly=>'true' | ||||
| 		<br></span></p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_External_Interface_IP') | ||||
| 		</span><span class=data> | ||||
| 			% param 'ExternalIP' => $lets_data->{ExternalIP} unless param 'ExternalIP'; | ||||
| 			%= text_field 'ExternalIP', size => '50', class => 'textinput ExternalIP' , pattern=>'.*' , placeholder=>'ExternalIP', Readonly=>'true' | ||||
| 		<br></span></p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_Internet_IP') | ||||
| 		</span><span class=data> | ||||
| 			% param 'InternetIP' => $lets_data->{InternetIP} unless param 'InternetIP'; | ||||
| 			%= text_field 'InternetIP', size => '50', class => 'textinput InternetIP' , pattern=>'.*' , placeholder=>'InternetIP', Readonly=>'true' | ||||
| 		<br></span></p> | ||||
| 	 | ||||
| 		<h2 class='subh3'><%=l('lets_Current_certificate_details')%></h2> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_Issuer') | ||||
| 		</span><span class=data> | ||||
| 			% param 'Issuer' => $lets_data->{Issuer} unless param 'Issuer'; | ||||
| 			%= text_field 'Issuer', size => '50', class => 'textinput Issuer' , pattern=>'.*' , placeholder=>'Issuer', Readonly=>'true' | ||||
| 		<br></span></p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_Expiry') | ||||
| 		</span><span class=data> | ||||
| 			% param 'Expiry' => $lets_data->{Expiry} unless param 'Expiry'; | ||||
| 			%= text_field 'Expiry', size => '50', class => 'textinput Expiry' , pattern=>'.*' , placeholder=>'Expiry', Readonly=>'true' | ||||
| 		<br></span></p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_Not_Before') | ||||
| 		</span><span class=data> | ||||
| 			% param 'NotBefore' => $lets_data->{NotBefore} unless param 'NotBefore'; | ||||
| 			%= text_field 'NotBefore', size => '50', class => 'textinput NotBefore' , pattern=>'.*' , placeholder=>'NotBefore', Readonly=>'true' | ||||
| 		<br></span></p> | ||||
| 	 | ||||
| 		<h2 class='subh4'><%=l('lets_List_of_Domains_and_Hosts')%></h2> | ||||
| 	 | ||||
| 		<br /><table class="sme-border TableSort sme-table tabl1 "> | ||||
| 			<thead class='tabl1'> | ||||
| 				<tr table-head-row> | ||||
| 					<th class='sme-border table-head-col table-head-col-Domain name / HOSTNAME '><%=l('lets_Domain_name_/_HOSTNAME')%></th> | ||||
| 					<th class='sme-border table-head-col table-head-col-Brief description '><%=l('lets_Brief_description')%></th> | ||||
| 					<th class='sme-border table-head-col table-head-col-Content '><%=l('lets_Content')%></th> | ||||
| 					<th class='sme-border table-head-col table-head-col-LABEL_NAMESERVERS '><%=l('lets_LABEL_NAMESERVERS')%></th> | ||||
| 					<th class='sme-border table-head-col table-head-col-LABEL_POINT '><%=l('lets_LABEL_POINT')%></th> | ||||
| 					<th class='sme-border table-head-col table-head-col-LABEL_LECERT '><%=l('lets_LABEL_LECERT')%></th> | ||||
| 					<th class='sme-border table-head-col table-head-col-IS_IN_CERT '><%=l('lets_IS_IN_CERT')%></th> | ||||
| 					<th class='sme-border table-head-col table-head-col-CHECK '><%=l('lets_CHECK')%></th> | ||||
| 				</tr> | ||||
| 			</thead> | ||||
| 			<tbody class='tabl1'> | ||||
| 				% my $control_data = $c->stash('DomainList'); | ||||
| 				% foreach my $row (@$control_data) { | ||||
| 				<tr class='table-row'> | ||||
| 					<td class='sme-border table-col table-col-Table1-Domain name / HOSTNAME'><%=$c->render_to_string(inline=>$row->{'Table1-Domain name / HOSTNAME'})%></td> | ||||
| 					<td class='sme-border table-col table-col-Table1-Brief description'><%=$c->render_to_string(inline=>$row->{'Table1-Brief description'})%></td> | ||||
| 					<td class='sme-border table-col table-col-Table1-Content'><%=$c->render_to_string(inline=>$row->{'Table1-Content'})%></td> | ||||
| 					<td class='sme-border table-col table-col-Table1-LABEL_NAMESERVERS'><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_NAMESERVERS'})%></td> | ||||
| 					<td class='sme-border table-col table-col-Table1-LABEL_POINT'><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_POINT'})%></td> | ||||
| 					<td class='sme-border table-col table-col-Table1-LABEL_LECERT'><%=$c->render_to_string(inline=>$row->{'Table1-LABEL_LECERT'})%></td> | ||||
| 					<td class='sme-border table-col table-col-Table1-IS_IN_CERT'><%=$c->render_to_string(inline=>$row->{'Table1-IS_IN_CERT'})%></td> | ||||
| 					<td class='sme-border table-col table-col-Table1-CHECK'><%=$c->render_to_string(inline=>$row->{'Table1-CHECK'})%></td>		 | ||||
| 				</tr> | ||||
| 				%} | ||||
| 			</tbody> | ||||
| 		</table> | ||||
| 		 | ||||
| 	 | ||||
| 		%# Probably finally by a submit. | ||||
| 	%end     | ||||
| </div> | ||||
| @@ -0,0 +1,97 @@ | ||||
| %# | ||||
| %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-12-01 15:22:43  | ||||
| %# | ||||
| <div id="Letsencrypt-PARAMS" class="partial Letsencrypt-PARAMS"> | ||||
| 	<script> | ||||
| 		window.onload = function() { | ||||
| 		SelectInput(); | ||||
| 	}; | ||||
| 	</script> | ||||
| 	% if ($config->{debug} == 1) { | ||||
| 		<pre> | ||||
| 			%= dumper $lets_data | ||||
| 		</pre> | ||||
| 	% } | ||||
| 	% my $btn = l('lets_APPLY'); | ||||
| 	%= form_for "letsencryptu" => (method => 'POST') => begin | ||||
| 		% param 'trt' => $lets_data->{trt} unless param 'trt'; | ||||
| 		%= hidden_field 'trt' => $lets_data->{trt} | ||||
| 		%# Inputs etc in here. | ||||
|  | ||||
| 		<h2 class='subh'><%=l('lets_Manage_letsencrypt-config_settings:')%></h2> | ||||
| 	 | ||||
| 		<p class='paragraph para1'> | ||||
| 			%=l('lets_CONFIG_LETSENCRYPT') | ||||
| 		</p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_SERVICE_STATUS') | ||||
| 		</span><span class=data> | ||||
| 			% my @status_options = [['Disabled' => 'disabled'], ['Enabled' => 'enabled'], ['TEST' => 'test']]; | ||||
| 			% param 'status' => $lets_data->{status} unless param 'status'; | ||||
| 			%= select_field 'status' => @status_options, class => 'input' | ||||
| 		<br></span>	</p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_HOOKSCRIPT_STATUS') | ||||
| 		</span><span class=data> | ||||
| 			% my @hookScript_options = [['Disabled' => 'disabled'], ['Enabled' => 'enabled']]; | ||||
| 			% param 'hookScript' => $lets_data->{hookScript} unless param 'hookScript'; | ||||
| 			%= select_field 'hookScript' => @hookScript_options, class => 'input' | ||||
| 		<br></span>	</p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_HOSTOVERRIDE_STATUS') | ||||
| 		</span><span class=data> | ||||
| 			% my @hostOverride_options = [['Disabled' => 'disabled'], ['Yes' => 'yes']]; | ||||
| 			% param 'hostOverride' => $lets_data->{hostOverride} unless param 'hostOverride'; | ||||
| 			%= select_field 'hostOverride' => @hostOverride_options, class => 'input' | ||||
| 		<br></span>	</p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_ACCEPT_TERMS_STATUS') | ||||
| 		</span><span class=data> | ||||
| 			% my @ACCEPT_TERMS_options = [['Disabled' => 'disabled'], ['Yes' => 'yes']]; | ||||
| 			% param 'ACCEPT_TERMS' => $lets_data->{ACCEPT_TERMS} unless param 'ACCEPT_TERMS'; | ||||
| 			%= select_field 'ACCEPT_TERMS' => @ACCEPT_TERMS_options, class => 'input' | ||||
| 		<br></span>	</p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_API_STATUS') | ||||
| 		</span><span class=data> | ||||
| 			% my @API_options = [['2' => '2']]; | ||||
| 			% param 'API' => $lets_data->{API} unless param 'API'; | ||||
| 			%= select_field 'API' => @API_options, class => 'input' | ||||
| 		<br></span>	</p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_KEYSIZE_STATUS') | ||||
| 		</span><span class=data> | ||||
| 			% my @keysize_options = [['2048' => '2048'], ['3072' => '3072'], ['4096' => '4096']]; | ||||
| 			% param 'keysize' => $lets_data->{keysize} unless param 'keysize'; | ||||
| 			%= select_field 'keysize' => @keysize_options, class => 'input' | ||||
| 		<br></span>	</p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_CONFIGUREMODE_STATUS') | ||||
| 		</span><span class=data> | ||||
| 			% my @configure_options = [['ALL' => 'all'], ['Domains' => 'domains'], ['HOSTS' => 'hosts'], ['NONE' => 'none']]; | ||||
| 			% param 'configure' => $lets_data->{configure} unless param 'configure'; | ||||
| 			%= select_field 'configure' => @configure_options, class => 'input' | ||||
| 		<br></span>	</p> | ||||
| 	 | ||||
| 		<p><span class=label> | ||||
| 			%=l('lets_EMAIL') | ||||
| 		</span><span class=data> | ||||
| 			% param 'email' => $lets_data->{email} unless param 'email'; | ||||
| 			%=email_field 'email', class => 'emai8' | ||||
| 		</span></p> | ||||
| 		 | ||||
| 	 | ||||
| 		<span class='data'> | ||||
| 			%= submit_button l('lets_Save'), class => 'action subm9' | ||||
| 		</span> | ||||
| 	 | ||||
| 		%# Probably finally by a submit. | ||||
| 	%end     | ||||
| </div> | ||||
| @@ -60,9 +60,10 @@ | ||||
| 			<span class=data> | ||||
| 				%=text_field 'networkRouter' | ||||
| 			</span><br><br> | ||||
|     		<div class='center'> | ||||
| 		%= submit_button "$btn", class => 'action' | ||||
| 		</div> | ||||
| 			<p> | ||||
| 			<br> | ||||
| 			%= submit_button "$btn", class => 'action' | ||||
| 			</p> | ||||
| 	%end | ||||
|  | ||||
| </div> | ||||
|   | ||||
| @@ -49,9 +49,11 @@ | ||||
| 			</span><br><br> | ||||
| 			%} | ||||
| 			%= hidden_field localnetwork=>$localnetwork | ||||
| 	        <div class='center'> | ||||
| 		%= submit_button "$btn", class => 'action' | ||||
| 		</div> | ||||
| 			<p> | ||||
| 			<br> | ||||
| 			%= submit_button "$btn", class => 'action' | ||||
| 			</p> | ||||
|  | ||||
| 	%end | ||||
|  | ||||
| </div> | ||||
|   | ||||
| @@ -37,10 +37,12 @@ | ||||
| 		%= $c->render_to_string(inline => l($ret{ret},$var1,$var2,$var3,$var4,$var5,$var6,$var7)); | ||||
|     	</div> | ||||
| 	%} | ||||
| 	<br><br> | ||||
|         <div class='center'> | ||||
|  | ||||
| 	<p> | ||||
| 	<br> | ||||
| 	%= submit_button "$btn", class => 'action' | ||||
| 	</div> | ||||
| 	</p> | ||||
|  | ||||
|     % end     | ||||
|  | ||||
| 	<br> | ||||
|   | ||||
| @@ -77,9 +77,11 @@ | ||||
| 			<span class=data> | ||||
| 				%=text_field 'cmmnt' | ||||
| 			</span><br><br> | ||||
| 	        <div class='center'> | ||||
| 		%= submit_button "$btn", class => 'action' | ||||
| 		</div> | ||||
| 			<p> | ||||
| 			<br> | ||||
| 			%= submit_button "$btn", class => 'action' | ||||
| 			</p> | ||||
|  | ||||
| 	%end | ||||
|  | ||||
| </div> | ||||
|   | ||||
| @@ -57,9 +57,10 @@ | ||||
| 		%#} | ||||
| 			%= hidden_field sport=>$sport | ||||
| 			%= hidden_field proto=>$proto | ||||
| 	        <div class='center'> | ||||
| 		%= submit_button "$btn", class => 'action' | ||||
| 		</div> | ||||
| 			<br> | ||||
| 			%= submit_button "$btn", class => 'action' | ||||
| 			</p> | ||||
|  | ||||
| 	%end | ||||
|  | ||||
| </div> | ||||
|   | ||||
| @@ -18,8 +18,6 @@ | ||||
| 	% my $var5 = @vars[4]; | ||||
| 	% my $var6 = @vars[5]; | ||||
|  | ||||
|  | ||||
|  | ||||
| 	%if ($ret{ret} eq "") { | ||||
| 	    %= $c->render_to_string(inline => l('pf_FIRST_PAGE_DESCRIPTION')); | ||||
| 	%} elsif (index($ret{ret},"SUCCESS") != -1) { | ||||
| @@ -33,21 +31,22 @@ | ||||
| 			%= $c->l($ret{ret},$var1,$var2,$var3,$var4,$var5,$var6); | ||||
|     	</div> | ||||
| 	%} | ||||
| 	<br><br> | ||||
|         <div class='center'> | ||||
|  | ||||
| 	<p> | ||||
| 	<br> | ||||
| 	%= submit_button "$btn", class => 'action' | ||||
| 	</div> | ||||
| 	</p> | ||||
|  | ||||
|  | ||||
|     % end    | ||||
|     | ||||
|    	<br> | ||||
|  | ||||
|     %	if ($empty){ | ||||
|             <br> | ||||
| 		%=l 'pf_NO_FORWARDS' | ||||
|     %	} else { | ||||
|         <br> | ||||
| 		%=l 'pf_SHOW_FORWARDS' | ||||
| 	<br> | ||||
| 	<br><br /> | ||||
| 		<table class="sme-border TableSort"><thead> | ||||
| 		<tr> | ||||
| 			<th class='sme-border'> | ||||
|   | ||||
| @@ -76,11 +76,17 @@ | ||||
|     % 			$actionRemove = "<a href='useraccountsd?CsrfDef=TOKEN&trt=DEL&user=" . $username . "'>" . "<button class='sme-remove-button' title=".l("REMOVE").">".l("REMOVE")."</button></a>";  | ||||
|     %		} | ||||
|     %	    } | ||||
|     %		 | ||||
|     %		my $thisdomain = session 'SystemName'; | ||||
|     %		$thisdomain .= ".".session 'DomainName'; | ||||
|     %#		my $thisdomain = "localhost"; | ||||
|  | ||||
|     	    <td class='sme-border' style="min-width:35em"> | ||||
| 				<%= $c->render_to_string(inline => $actionModify) %> | ||||
| 				<%= $c->render_to_string(inline => $actionResetPw) %> | ||||
| 				<%= $c->render_to_string(inline => $actionLock) %> | ||||
| 				<%= $c->render_to_string(inline => $actionRemove) %> | ||||
| 				<a href="<%= "roundcubepanel/?url=https://".$thisdomain."/" %>roundcube?_user=<%= $username %>"><button class="sme-email-button" title="<%= l('EMAIL') %>"><%= l('EMAIL') %></button></a> | ||||
|     	    </td> | ||||
|     	</tr> | ||||
|     %    } | ||||
|   | ||||
| @@ -213,10 +213,10 @@ | ||||
| 	</p> | ||||
|     %} | ||||
|  | ||||
|  | ||||
|         <div class='center'> | ||||
| 	<p> | ||||
| 	<br> | ||||
| 	%= submit_button "$btn", class => 'action' | ||||
| 	</div> | ||||
| 	</p> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,39 @@ | ||||
| % layout 'default', title => "Sme server 2 -  roundcube"; | ||||
|  | ||||
| % content_for 'module' => begin | ||||
|  | ||||
|  | ||||
| <div id='roundcube' class='roundcube roundcube-panel'> | ||||
|     % if ($config->{debug} == 1) { | ||||
| 		<p> | ||||
| 			%= dumper $c->current_route | ||||
| 		</p> | ||||
|     % } | ||||
|     % if ( stash 'error' ) { | ||||
|     	<br><div class=sme-error> | ||||
| 			%= $c->render_to_string(inline => stash 'error')  | ||||
| 		</div> | ||||
|     %} | ||||
|     <h1> roundcube - <%=$title %></h1><br> | ||||
|     <p>If the roundcube panel does not appear after logging in, then please check your password.</p><br /> | ||||
|  | ||||
|     % my $thisdomain = session 'SystemName'; | ||||
|     % $thisdomain .= ".".session 'DomainName'; | ||||
|     % my $url = $c->stash('modul'); | ||||
|     % my $username = 'admin'; | ||||
|     % if ($url =~ /[?&]_user=([^&]+)/) { | ||||
| 	%	$username = $1; | ||||
| 	%} | ||||
| 	 | ||||
| 	<a href="<%= "https://".$thisdomain."/" %>roundcube?_user=<%= $username %>"><button class="sme-fullwindow1-button" width=20em title="<%= l('Full Window') %>"><%= l('Full Window') %></button></a> | ||||
|  | ||||
|     % my $height = $c->stash('height') | '600px'; | ||||
|     % if ($height !~ /px$/) { $height = $height.'px';} | ||||
|     % if ($url eq "") { | ||||
| 	%	$url = "https://".$thisdomain."/roundcube"; | ||||
| 	%} | ||||
| 	<object id="roundcube" class="roundcube" data="<%=$url %>" style="width:99%;height:<%= $height %>;" title="<%= $c->stash('title') %>"  type="text/html" ><%= $c->stash('title') %> not found</object> | ||||
| </div> | ||||
|  | ||||
|  | ||||
| %end | ||||
| @@ -66,9 +66,10 @@ | ||||
| 	</span> | ||||
| 	<br><br></p> | ||||
|  | ||||
|     <div class='center'> | ||||
|     %= submit_button "$btn", class => 'action' | ||||
|     </div> | ||||
| 	<p> | ||||
| 	<br> | ||||
| 	%= submit_button "$btn", class => 'action' | ||||
| 	</p> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -79,9 +79,9 @@ | ||||
|  | ||||
|     	%=  hidden_field 'trt' => 'CONF' | ||||
| 	<br> | ||||
|     <div class='center'> | ||||
|     <!--<div class='center'>--> | ||||
| 	%= submit_button $c->l('SAVE'), class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -47,9 +47,9 @@ | ||||
|  | ||||
|     	%=  hidden_field 'trt' => 'INST' | ||||
| 	<br><br> | ||||
|     <div class='center'> | ||||
|     <!-- <div class='center'>--> | ||||
| 	%= submit_button $c->l('yum_INSTALL_SOFTWARE'), class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -34,9 +34,9 @@ | ||||
|     	%=  hidden_field 'trt' => 'PSTU' | ||||
|     	%=  hidden_field 'reconf' => $yum_datas->{reconf} | ||||
| 	<br> | ||||
|     <div class='center'> | ||||
|     <!-- <div class='center'>--> | ||||
| 	%= submit_button "$btn", class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -46,9 +46,9 @@ | ||||
|  | ||||
|     	%=  hidden_field 'trt' => 'REMO' | ||||
| 	<br> | ||||
|     <div class='center'> | ||||
|     <!--<div class='center'>--> | ||||
| 	%= submit_button $c->l('REMOVE'), class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
| @@ -33,9 +33,9 @@ | ||||
|  | ||||
|     	%=  hidden_field 'trt' => 'UPDT' | ||||
| 	<br> | ||||
|     <div class='center'> | ||||
|     <!--<div class='center'>--> | ||||
| 	%= submit_button $c->l('yum_INSTALL_UPDATES'), class => 'action' | ||||
|     </div> | ||||
|     <!--</div>--> | ||||
|  | ||||
|     % end | ||||
|  | ||||
|   | ||||
							
								
								
									
										0
									
								
								root/var/log/smanager/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								root/var/log/smanager/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -2,7 +2,7 @@ Summary: Sme server  navigation module : manager 2 | ||||
| %define name smeserver-manager | ||||
| Name: %{name} | ||||
| %define version 11.0.0 | ||||
| %define release 4 | ||||
| %define release 30 | ||||
| Version: %{version} | ||||
| Release: %{release}%{?dist} | ||||
| License: GPL | ||||
| @@ -35,6 +35,8 @@ Requires: perl(DBM::Deep) >= 2.0011-1 | ||||
| Requires: perl(Mojo::JWT) >= 0.08-1 | ||||
| Requires: mutt >= 1.5.21 | ||||
| Requires: smeserver-manager-jsquery >= 1.0 | ||||
| Requires: smeserver-lib >= 11.0 | ||||
| Requires: smeserver-certificates >= 11.0 | ||||
| #Requires: js-jquery > 2.2.4-3 (optional) | ||||
|  | ||||
| Provides: server-manager | ||||
| @@ -49,6 +51,11 @@ This RPM contributes the navigation bars for the smeserver-manager. New Mojolici | ||||
| %setup | ||||
|  | ||||
| %build | ||||
|  | ||||
| #extract the release number and drop it in to the version for SM2 footer. | ||||
| sed -i "s/our \$VERSION = '[^']*'/our \$VERSION = '%{release}'/g" root/usr/share/smanager/lib/SrvMngr.pm | ||||
|  | ||||
|  | ||||
| perl createlinks | ||||
|  | ||||
| # Force creation of potentially empty directories | ||||
| @@ -108,6 +115,91 @@ true | ||||
| %defattr(-,root,root) | ||||
|  | ||||
| %changelog | ||||
| * Fri Dec 13 2024 Brian Read <brianr@koozali.org> 11.0.0-30.sme | ||||
| - Add in letsencrypt panel, add requires for smeserver-lib and smeserver-certificates [SME: 12810] | ||||
|  | ||||
| * Tue Nov 26 2024 Brian Read <brianr@koozali.org> 11.0.0-29.sme | ||||
| - Fix remoteaccess panel, reformat pm file and bring success panel into line with other similar panels [SME: 12747] | ||||
|  | ||||
| * Fri Oct 18 2024 Brian Read <brianr@koozali.org> 11.0.0-28.sme | ||||
| - Add in emailsettings for port 25,465 and 587  [SME: 12750] | ||||
| - Comment out change to localhost for roundcube in _user_list email icon setting [SME: 12751] | ||||
|  | ||||
| * Sun Oct 06 2024 Brian Read <brianr@koozali.org> 11.0.0-27.sme | ||||
| - Add in change to _user_list.html.ep for access to roundcube email from useraccounts [SME: 12751] | ||||
|  | ||||
| * Fri Oct 04 2024 Brian Read <brianr@koozali.org> 11.0.0-26.sme | ||||
| - Add in email link to roundcube from user accounts [SME: 12751] | ||||
|  | ||||
| * Wed Oct 02 2024 Brian Read <brianr@koozali.org> 11.0.0-25.sme | ||||
| - Add in cursor change when save/submit pressed to indicate processing [SME: 12748] | ||||
|  | ||||
| * Wed Oct 02 2024 Brian Read <brianr@koozali.org> 11.0.0-24.sme | ||||
| - Messed up build - finger trouble [SME: 12753] | ||||
|  | ||||
| * Wed Oct 02 2024 Brian Read <brianr@koozali.org> 11.0.0-23.sme | ||||
| - Add release number to footer  [SME: 12753] | ||||
|  | ||||
| * Tue Sep 24 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-22.sme | ||||
| - fix typos, and tidy tabs [SME: 12744] | ||||
|  | ||||
| * Mon Sep 23 2024 Brian Read <brianr@koozali.org> 11.0.0-21.sme | ||||
| - Remove both option for webmail [SME: 12744] | ||||
| - Add in re-open DB for portforwarding and email settings. | ||||
|  | ||||
| * Mon Sep 23 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-20.sme | ||||
| - webmail switch panel to use roundcube [SME: 12742] | ||||
| - prevent browser from caching [SME: 12695] | ||||
|  | ||||
| * Thu Sep 05 2024 Brian Read <brianr@koozali.org> 11.0.0-19.sme | ||||
| - Add in mojo plugin WithoutCache [SME: 12695] | ||||
|  | ||||
| * Sun Aug 25 2024 Brian Read <brianr@koozali.org> 11.0.0-18.sme | ||||
| - Move flag to emojii from downloaded jpg. Fix singleton locale issue[SME: 12706] | ||||
|  | ||||
| * Thu Aug 22 2024 Brian Read <brianr@koozali.org> 11.0.0-17.sme | ||||
| - Left Align Software Install panels Submit button [SME: 12727] | ||||
|  | ||||
| * Wed Aug 21 2024 Brian Read <brianr@koozali.org> 11.0.0-16.sme | ||||
| - Typo uc DNF changed to lc dnf in Yum.pm [SME: 127245] | ||||
| - Monitor dnf running using dnf status file  | ||||
|  | ||||
| * Wed Aug 21 2024 Brian Read <brianr@koozali.org> 11.0.0-15.sme | ||||
| - Migrate SM2 Software installer panel from use of yum to dnf [SME: 12718] | ||||
|  | ||||
| * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-14.sme | ||||
| - Version skipped due to operator error! [SME: <none> ] | ||||
|  | ||||
| * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-13.sme | ||||
| - Fix sysles.css template - overwrote it by mistake [SME: 12706] | ||||
| - Also re-organised login and Legacy SM menus and help on top | ||||
|  | ||||
| * Sun Jul 28 2024 Brian Read <brianr@koozali.org> 11.0.0-12.sme | ||||
| - correct positio of flag-icon [SME: 12706] | ||||
|  | ||||
| * Sat Jul 27 2024 Brian Read <brianr@koozali.org> 11.0.0-11.sme | ||||
| - Add in flag icon indication of locale [SME: 12706] | ||||
|  | ||||
| * Fri Jul 26 2024 Brian Read <brianr@koozali.org> 11.0.0-10.sme | ||||
| - fix navigation2.conf to more correctly translate menus [SME: 12714] | ||||
|  | ||||
| * Thu May 09 2024 Brian Read <brianr@koozali.org> 11.0.0-9.sme | ||||
| - Add mojo logo to footer [SME: 12679] | ||||
| - Fix default for HeaderWeight to avoid noise in logs if no Nav header in file | ||||
| - Align buttons consistently [SME: 12680] | ||||
|  | ||||
| * Tue Apr 30 2024 Jean-Philippe Pialasse <jpp@koozali.org> 11.0.0-8.sme | ||||
| - create dedicated log files and logrotate [SME: 12664] | ||||
|  | ||||
| * Tue Apr 30 2024 Brian Read <brianr@koozali.org> 11.0.0-7.sme | ||||
| - Remove use of hel command and replace by call to BlockDevices lib [SME: 12644] | ||||
|  | ||||
| * Mon Apr 29 2024 Brian Read <brianr@koozali.org> 11.0.0-6.sme | ||||
| - Update layout for table extras [SME: 12656] | ||||
|  | ||||
| * Sun Apr 28 2024 Brian Read <brianr@koozali.org> 11.0.0-5.sme | ||||
| - Ibay create not getting into panel [SME: 12652] | ||||
|  | ||||
| * Tue Apr 23 2024 Brian Read <brianr@koozali.org> 11.0.0-4.sme | ||||
| - add in Nav numbers for Legacypanels.pm and ignore it when generating nav menu [SME:12643] | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user