init: provide config option for initial branch of push projects
[girocco/readme.git] / Girocco / Validator.pm
blob6cd7aacb4e21c45e0e33917b922edd20e6532caf
1 # This install-only package contains validation, sanity and default
2 # checks for the values set in Girocco::Config.
4 # It's only used during the install process.
5 # Normally the Girocco::Config file will "require" this module
6 # at the end (before it's frozen during installation).
7 # However, the install process specifically "use"s this module to
8 # guarantee the checks always run even if that "require" is removed.
10 package Girocco::Validator;
12 BEGIN {
13 # This check MUST NOT be inside the Girocco::Config package
14 scalar(eval 'keys %Girocco::Config::') or
15 die "Girocco::Config must already be 'use'd before ".__PACKAGE__." is 'use'd.\n";
18 package Girocco::Config;
20 use strict;
21 use warnings;
22 no strict 'vars'; # required since Config.pm declares the variables
24 BEGIN {
25 # Makes non-Config modules work with non-default Config
26 exists($INC{'Girocco/Config.pm'}) or
27 $INC{'Girocco/Config.pm'} = $INC{'Girocco/Validator.pm'};
31 ## ------------------------
32 ## Sanity checks & defaults
33 ## ------------------------
35 # Changing anything in this section can result in unexpected breakage
37 # Couple of sanity checks and default settings (do not change these)
38 require Digest::MD5;
39 require MIME::Base64;
40 defined($name) or $name = "";
41 $name =~ s/\s+/_/gs;
42 $nickname = lc((split(/[.]/, $name))[0]) unless defined($nickname) && $nickname ne "";
43 $nickname =~ s/\s+/_/gs;
44 our $tmpsuffix = substr(MIME::Base64::encode_base64(Digest::MD5::md5($name.':'.$nickname)),0,6);
45 $tmpsuffix =~ tr,+/,=_,;
46 defined($mirror_user) && $mirror_user ne "" or
47 die "Girocco::Config: \$mirror_user must be set even if to current user";
48 defined($basedir) && $basedir ne "" or
49 die "Girocco::Config: \$basedir must be set";
50 defined($sendmail_bin) && $sendmail_bin ne "" or
51 die "Girocco::Config: \$sendmail_bin must be set";
52 $sendmail_bin eq "sendmail.pl" and $sendmail_bin = "$basedir/bin/sendmail.pl";
53 defined($screen_acl_file) && $screen_acl_file ne "" or
54 $screen_acl_file = "$basedir/screen/giroccoacl";
55 defined($jailreporoot) or $jailreporoot = "";
56 $jailreporoot =~ s,^/+,,;
57 $reporoot ne "" or die "Girocco::Config: \$reporoot must be set";
58 $jailreporoot ne "" or die "Girocco::Config: \$jailreporoot must be set";
59 $disable_jailsetup = $disable_jailsetup ? 1 : '';
60 $notify_single_level = $notify_single_level ? 1 : '';
61 $fetch_stash_refs = $fetch_stash_refs ? 1 : '';
62 !$mob || $mob eq 'mob' or die "Girocco::Config: \$mob must be undef (or '') or 'mob'";
63 !defined($protect_fields) || ref($protect_fields) eq 'HASH' or
64 die "Girocco::Config: \$protect_fields must be a HASH ref or undefined";
65 ref($protect_fields) eq 'HASH' or $protect_fields = {};
66 $project_edit_timeout =~ /^[1-9][0-9]*$/ or
67 die "Girocco::Config: \$project_edit_timeout must be a positive integer";
68 5 <= $project_edit_timeout && $project_edit_timeout <= 86400 or
69 die "Girocco::Config: \$project_edit_timeout seems unreasonable: $project_edit_timeout";
70 !$min_key_length || $min_key_length =~ /^[1-9][0-9]*$/ or
71 die "Girocco::Config: \$min_key_length must be undef or numeric";
72 !defined($max_readme_size) || $max_readme_size =~ /^[0-9]+$/ or
73 die "Girocco::Config: \$max_readme_size must be a whole number";
74 defined($mailsh_sizelimit) && $mailsh_sizelimit =~ /^[1-9][0-9]*$/ or
75 die "Girocco::Config: \$mailsh_sizelimit must be a positive number";
76 !defined($initial_branch) || $initial_branch eq "" ||
77 $initial_branch !~ /^\/|^\.|[\x00-\x1f \x7f\[\[~^"'"<>*?\\:]|\@\{|\.\.|\.lock$|\.$|\/$/ or
78 die "Girocco::Config: \$initial_branch grossly invalid: $initial_branch";
79 $admincc = $admincc ? 1 : 0;
80 $rootcert = "$certsdir/girocco_root_crt.pem" if $httpspushurl && !$rootcert;
81 $clientcert = "$certsdir/girocco_client_crt.pem" if $httpspushurl && !$clientcert;
82 $clientkey = "$certsdir/girocco_client_key.pem" if $httpspushurl && !$clientkey;
83 $clientcertsuffix = "$certsdir/girocco_client_suffix.pem" if $httpspushurl && !$clientcertsuffix;
84 $mobusercert = "$certsdir/girocco_mob_user_crt.pem" if $httpspushurl && $mob && !$mobusercert;
85 $mobuserkey = "$certsdir/girocco_mob_user_key.pem" if $httpspushurl && $mob && !$mobuserkey;
86 our $mobpushurl = $pushurl;
87 $mobpushurl =~ s,^ssh://,ssh://mob@,i if $mobpushurl;
88 $disable_dsa = 1 unless $pushurl;
89 $disable_dsa = $disable_dsa ? 1 : '';
90 our $httpdnsname = ($gitweburl =~ m,https?://([A-Za-z0-9.-]+),i) ? lc($1) : undef if $gitweburl;
91 our $httpsdnsname = ($httpspushurl =~ m,https://([A-Za-z0-9.-]+),i) ? lc($1) : undef if $httpspushurl;
92 $SmartHTTPOnly = $SmartHTTPOnly ? 1 : '';
93 $TLSHost = $TLSHost ? 1 : '';
94 $pretrustedroot = $pretrustedroot ? 1 : '';
95 $suppress_git_ssh_logging = $suppress_git_ssh_logging ? 1 : '';
96 $git_daemon_any_host = $git_daemon_any_host ? 1 : '';
97 if ((!defined($git_daemon_host_list) || $git_daemon_host_list =~ /^\s*$/) &&
98 (defined($gitpullurl) && $gitpullurl =~ m{^git://\[?[A-Za-z0-9.-:]}i)) {
99 if ($gitpullurl =~ m{^[gG][iI][tT]://([A-Za-z0-9.-]+)(?:[/:]|$)} ||
100 $gitpullurl =~ m{^[gG][iI][tT]://\[([0-9a-zA-Z.:%]+)\](?:[/:]|$)}) {
101 my $gdhn = lc($1);
102 $gdhn ne "." and $gdhn =~ s/\.$//;
103 my $gdhnl = $gdhn; $gdhnl =~ s/(?<!^)(?<!\.)\..*$//;
104 $git_daemon_host_list="$gdhn";
105 do {$git_daemon_host_list.=" $_" unless index(" $git_daemon_host_list "," $_ ")>=0}
106 foreach $gdhnl, qw"localhost ::1 127.0.0.1";
109 if (defined($git_daemon_host_list)) {
110 $git_daemon_host_list = lc($git_daemon_host_list);
111 $git_daemon_host_list =~ s/^\s+//;
112 $git_daemon_host_list =~ s/\s+$//;
113 $git_daemon_host_list = undef if $git_daemon_host_list eq "";
115 $mirror || $push or
116 die "Girocco::Config: neither \$mirror nor \$push is set?!";
117 !$push || ($pushurl || $httpspushurl || $gitpullurl || $httppullurl) or
118 die "Girocco::Config: no pull URL is set";
119 !$push || ($pushurl || $httpspushurl) or
120 die "Girocco::Config: \$push set but \$pushurl and \$httpspushurl are undef";
121 !$mirror || $mirror_user or
122 die "Girocco::Config: \$mirror set but \$mirror_user is undef";
123 $TLSHost = $TLSHost ? 1 : '';
124 $manage_users = $manage_users ? 1 : 0;
125 $chrooted = $chrooted ? 1 : 0;
126 $manage_users == $chrooted or
127 die "Girocco::Config: \$manage_users and \$chrooted must be set to the same value";
128 !$chrooted || uc($permission_control) ne 'ACL' or
129 die "Girocco::Config: resolving uids for ACL not supported when using chroot";
130 defined($permission_control) or $permission_control = '';
131 $permission_control = ucfirst(lc($permission_control));
132 (grep { $permission_control eq $_ } qw(Group Hooks)) or
133 die "Girocco::Config: \$permission_control must be set to Group or Hooks";
134 $chrooted || !$mob or
135 die "Girocco::Config: mob user supported only in the chrooted mode";
136 !$httpspushurl || $httpsdnsname or
137 die "Girocco::Config: \$httpspushurl invalid does not start with https://domainname";
138 !$svn_log_window_size || $svn_log_window_size =~ /^[1-9][0-9]*$/ or
139 die "Girocco::Config: \$svn_log_window_size must be undef or numeric";
140 defined($max_file_size512) && !$max_file_size512 and $max_file_size512 = undef;
141 !defined($max_file_size512) || $max_file_size512 =~ /^[1-9][0-9]*$/ && $max_file_size512 <= 2147483647 or
142 die "Girocco::Config: \$max_file_size512 must be undef or a positive integer <= 2147483647";
143 defined($max_clone_objects) && !$max_clone_objects and $max_clone_objects = undef;
144 !defined($max_clone_objects) || $max_clone_objects =~ /^[1-9][0-9]*$/ or
145 die "Girocco::Config: \$max_clone_objects must be undef or a positive integer";
146 !defined($posix_sh_bin) || $posix_sh_bin !~ /\s/ or
147 die "Girocco::Config: \$posix_sh_bin must not contain any whitespace";
148 !defined($perl_bin) || $perl_bin !~ /\s/ or
149 die "Girocco::Config: \$perl_bin must not contain any whitespace";
150 !$delay_gfi_redelta and $delay_gfi_redelta = undef;
151 !$git_no_mmap and $git_no_mmap = undef;
152 !$suppress_x_girocco and $suppress_x_girocco = undef;
153 !$jgit_compatible_bitmaps and $jgit_compatible_bitmaps = undef;
154 !$autogchack and $autogchack = undef;
155 !$reflogs_lifetime || $reflogs_lifetime !~ /^[1-9][0-9]*$/ and $reflogs_lifetime = 1;
156 $reflogs_lifetime = 0 + $reflogs_lifetime;
157 $reflogs_lifetime >= 0 or $reflogs_lifetime = 1;
158 $reflogs_lifetime <= 30 or $reflogs_lifetime = 30;
159 !defined $upload_pack_window || $upload_pack_window =~ /^[1-9][0-9]*$/ or
160 die "Girocco::Config: \$upload_pack_window must be undef or numeric";
161 !defined $upload_pack_window || (2 <= $upload_pack_window && $upload_pack_window <= 50) or
162 die "Girocco::Config: \$upload_pack_window must be in range 2..50";
163 !defined $max_receive_size || $max_receive_size =~ /^\d+[kKmMgG]?$/ or
164 die "Girocco::Config: \$max_receive_size setting is invalid";
165 defined $git_shared_repository_setting or $git_shared_repository_setting = 2;
166 $git_shared_repository_setting = lc($git_shared_repository_setting);
168 $git_shared_repository_setting =~ /^(?:false|umask|00*)$/ and do {
169 $git_shared_repository_setting = 0;
170 $var_umask = '0177';
171 $var_umask_ug = $var_umask;
172 last;
174 $git_shared_repository_setting =~ /^(?:true|group|1|00*1)$/ and do {
175 $git_shared_repository_setting = 1;
176 $var_umask = '0117';
177 $var_umask_ug = $var_umask;
178 last;
180 $git_shared_repository_setting =~ /^(?:all|world|everybody|2|00*2)$/ and do {
181 $git_shared_repository_setting = 2;
182 $var_umask = '0113';
183 $var_umask_ug = '0117';
184 last;
186 $git_shared_repository_setting =~ /^0[0-7]{1,3}$/ and do {
187 my $p = oct($git_shared_repository_setting);
188 $p &= ~0111;
189 $p |= 0600;
190 $git_shared_repository_setting = sprintf("0%03o", $p);
191 $var_umask = sprintf("0%03o", $p ^ 0777);
192 $var_umask_ug = sprintf("0%03o", ($p ^ 0777) | 007);
193 last;
195 die "Invalid \$Girocco::Config::git_shared_repository_setting setting ($git_shared_repository_setting)\n";
197 $var_umask_perm = $permission_control eq 'Group' ? $var_umask : '0';
198 defined($ENV{'SENDMAIL_PL_HOST'}) and eval 'our $sendmail_pl_host = $ENV{"SENDMAIL_PL_HOST"}';
199 defined($ENV{'SENDMAIL_PL_PORT'}) and eval 'our $sendmail_pl_port = $ENV{"SENDMAIL_PL_PORT"}';
200 defined($ENV{'SENDMAIL_PL_NCBIN'}) and eval 'our $sendmail_pl_ncbin = $ENV{"SENDMAIL_PL_NCBIN"}';
201 defined($ENV{'SENDMAIL_PL_NCOPT'}) and eval 'our $sendmail_pl_ncopt = $ENV{"SENDMAIL_PL_NCOPT"}';
202 defined($ENV{'PYTHON'}) and eval 'our $python = $ENV{"PYTHON"}';
204 # jailreporoot MUST NOT be absolute
205 defined($jailreporoot) && substr($jailreporoot, 0, 1) ne "/" or
206 die "Girocco::Config: \$jailreporoot MUST NOT be an absolute path\n";
208 # webreporoot can be undef
209 !defined($webreporoot) || substr($webreporoot, 0, 1) eq "/" or
210 die "Girocco::Config: \$webreporoot MUST be an absolute path if not undef\n";
212 # All these MUST be absolute paths
214 no strict 'refs';
215 defined(${$_}) && substr(${$_}, 0, 1) eq "/" or
216 die "Girocco::Config: \$$_ MUST be an absolute path\n"
217 foreach qw(basedir certsdir reporoot chroot webroot cgiroot projlist_cache_dir);
220 # Make sure Git has a consistent and reproducible environment
222 $ENV{'XDG_CONFIG_HOME'} = $chroot.'/var/empty';
223 $ENV{'HOME'} = $chroot.'/etc/girocco';
224 $ENV{'TMPDIR'} = '/tmp';
225 $ENV{'GIT_CONFIG_NOSYSTEM'} = 1;
226 $ENV{'GIT_ATTR_NOSYSTEM'} = 1;
227 $ENV{'GIT_NO_REPLACE_OBJECTS'} = 1;
228 $ENV{'GIT_TERMINAL_PROMPT'} = 0;
229 $ENV{'GIT_ASKPASS'} = $basedir.'/bin/git-askpass-password';
230 delete $ENV{'GIT_USER_AGENT'};
231 $ENV{'GIT_USER_AGENT'} = $git_client_ua if defined($git_client_ua);
232 delete $ENV{'GIT_HTTP_USER_AGENT'};
233 delete $ENV{'GIT_CONFIG_PARAMETERS'};
234 delete $ENV{'GIT_ALTERNATE_OBJECT_DIRECTORIES'};
235 delete $ENV{'GIT_CONFIG'};
236 delete $ENV{'GIT_DIR'};
237 delete $ENV{'GIT_GRAFT_FILE'};
238 delete $ENV{'GIT_INDEX_FILE'};
239 delete $ENV{'GIT_OBJECT_DIRECTORY'};
240 delete $ENV{'GIT_NAMESPACE'};
242 # Guarantee a sane umask for Girocco
244 umask(umask() & ~0770);