Fix off-by-one in uid/gid assignment
[girocco.git] / cgi / regproj.cgi
blobc6c7ae2dd3fec302a8c1433ae67701470d8783aa
1 #!/usr/bin/perl
2 # (c) Petr Baudis <pasky@suse.cz>
3 # GPLv2
5 use strict;
6 use warnings;
7 use CGI qw(:standard :escapeHTML -nosticky);
8 use CGI::Util qw(unescape);
9 use CGI::Carp qw(fatalsToBrowser);
11 my $cgi = CGI->new;
13 print $cgi->header(-type=>'text/html', -charset => 'utf-8');
15 print "<html><head><title>Git Project Registration</title></head>\n";
16 print "<body><h1>Register Project</h1></body>\n";
18 sub scrypt {
19 crypt(@_, join ('', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]));
22 sub save_proj_data {
23 my ($path, $url, $email) = @_;
24 open F, ">$path/base_url" or die "base_url failed: $!"; print F "$url\n"; close F;
25 open F, ">$path/.admin_contact" or die "admin_contact failed: $!"; print F "$email\n"; close F;
28 sub add_group {
29 my ($name, $pwd, $xtra) = @_;
30 my $gid = 65536;
31 # racy!
32 open F, "/home/repo/j/etc/group" or die "group failed: $!";
33 while (<F>) {
34 my $agid = (split /:/)[2];
35 $gid = $agid + 1 if ($agid >= $gid);
37 close F;
38 open F, ">>/home/repo/j/etc/group" or die "group append failed: $!";
39 print F "$name:".scrypt($pwd).":$gid:$xtra\n";
40 close F;
41 $gid;
44 sub setup_push {
45 my ($name, $pwd, $email, $url) = @_;
46 system("cg-admin-setuprepo -g repo /srv/git/$name.git") or die "cg-admin-setuprepo failed";
47 save_proj_data("/srv/git/$name.git", $url, $email);
48 my $gid = add_group($name, $pwd, '');
49 chown -1, $gid, map { "/srv/git/$name.git/$_" } qw(info refs/heads refs/tags objects);
50 print "<p>";
51 print "Project successfuly set up. ";
52 print "You can <a href=\"p/editproj.pl\">assign users</a> now (use project name as username, admin password as password). ";
53 print "You need to <a href=\"reguser.pl\">register a user</a> first if you have not done so yet. ";
54 print "(One user can have push access to multiple projects and multiple users can have push access to one project.)";
55 print "</p>\n";
56 print "<p>Enjoy yourself!</p>\n";
57 print "</body></html>\n";
60 sub setup_mirror {
61 my ($name, $pwd, $email, $url) = @_;
62 mkdir "/home/repo/repodata/to-clone/$name" or die "mkdir failed: $!";
63 save_proj_data("/home/repo/repodata/to-clone/$name", $url, $email);
64 chmod 0775, "/home/repo/repodata/to-clone/$name" or die "chmod failed: $!";
65 add_group($name, $pwd, ':');
66 print "<p>Initiated mirroring. You will be notified by mail about results.</p>\n";
67 print "</body></html>\n";
70 if ($cgi->param('name')) {
71 # submitted, let's see
72 # FIXME: racy, do a lock
73 my $err = 0;
74 sub err { print "<p style=\"text-color: red\">@_</p>\n"; $err++; }
75 my $name = $cgi->param('name'); $name =~ s/^\s*(.*?)\s*$/$1/;
76 my $email = $cgi->param('email'); $email =~ s/^\s*(.*?)\s*$/$1/;
77 my $url = $cgi->param('url'); $url =~ s/^\s*(.*?)\s*$/$1/;
78 my $pwd = $cgi->param('pwd');
79 $name =~ /^[a-zA-Z0-9_+-]+$/
80 or err "Name contains invalid characters.";
81 (-d "/srv/git/$name.git" or -d "/home/repo/repodata/cloning/$name" or -d "/home/repo/repodata/to-clone/$name")
82 and err "Project with that name already exists.";
83 $url =~ /^http:\/\/[a-zA-Z0-9-.]+\/[_\%a-zA-Z0-9.\/~-]+$/ or
84 $url =~ /^git:\/\/[a-zA-Z0-9-.]+\/[_\%a-zA-Z0-9.\/~-]+$/
85 or err "Invalid URL. Note that only HTTP and Git protocol is supported. If the URL contains funny characters, contact me.";
86 $email =~ /^[a-zA-Z0-9+._-]+@[a-zA-Z0-9-.]+$/
87 or err "Your email sure looks weird...?";
88 if ($err) {
89 print "<p>Registration aborted due to $err errors.</p>\n";
90 } else {
91 if ($cgi->param('mode') eq 'mirror') {
92 setup_mirror($name, $pwd, $email, $url);
93 } elsif ($cgi->param('mode') eq 'push') {
94 setup_push($name, $pwd, $email, $url);
96 exit;
100 print "<p>Here you can register a project. It can be hosted in two modes: mirror mode and push mode. In the first mode, we will check another repository at a given URL each hour and mirror any new updates. In the second mode, registered users with appropriate permissions will be able to push to the repository. You currently cannot switch freely between those two modes; if you want to switch an existing project, please contact the administrator.</p>\n";
101 print "<p>You will need the admin password to adjust project settings later (mirroring URL, list of users allowed to push, project description, ...). Use the project name as the username when asked by the browser.</p>\n";
102 print "<p>By submitting this form, you are confirming that the repository contains only free software and redistributing it does not violate any law of Czech Republic. Have fun!</p>\n";
103 print "<form method=\"post\">\n";
104 print "<p>Project name (w/o the .git suffix): <input type=\"text\" name=\"name\" /></p>\n";
105 print "<p>Admin password: <input type=\"password\" name=\"pwd\" /></p>\n";
106 print "<p>E-mail contact: <input type=\"text\" name=\"email\" /></p>\n";
107 print "<p>Hosting mode:</p><ul>\n";
108 print "<li><input type=\"radio\" name=\"mode\" value=\"mirror\" />Mirror mode. Repository URL: <input type=\"text\" name=\"url\" /></li>\n";
109 print "<li><input type=\"radio\" name=\"mode\" value=\"push\" />Push mode.</li></ul>\n";
110 print "<p><input type=\"submit\" name=\"y0\" value=\"Register\" /></p>\n";
111 print "</form>\n";
112 print "</body></html>\n";