xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
Commit e771f072b8b8393b8e40283ee87c663025407d70

Big (bulk) update: fetch/push by http(s)
Author: Catalin(ux) M. BOIE
Author date (UTC): 2016-09-17 10:22
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2016-09-17 10:22
Parent(s): f7db12862aa048feba85411fd64a2a97403c2e66
Signing key:
Tree: d59b841ae0194729033a5a9d020bbf5a8a950114
File Lines added Lines deleted
Compare.txt 26 23
Makefile.in 14 9
README 7 0
TODO 72 20
debian/control.in 1 1
docker/Dockerfile-postgresql.tmpl 1 1
docker/build.sh 1 1
hooks/post-receive 1 1
hooks/pre-commit 1 1
hooks/pre-receive 9 8
hooks/update 4 2
inc/fixes.inc.php 4 4
inc/git.inc.php 59 6
inc/init.inc.php 5 3
inc/log.inc.php 6 23
inc/repo.inc.php 204 8
inc/rights.inc.php 1 1
inc/user.inc.php 257 22
inc/util.inc.php 53 26
inc/wh/build.inc.php 3 3
rocketgit.spec.in 10 8
root/index.php 11 13
root/themes/default/hints/repo/clone_git.html 1 1
root/themes/default/hints/repo/clone_owner.html 3 3
root/themes/default/hints/repo/clone_ssh.html 1 1
samples/config.php 6 6
samples/cron 1 3
samples/php-fpm.conf 107 0
samples/pool.conf 414 0
samples/rg.conf 8 5
samples/systemd.service 21 0
scripts/cache.php 1 3
scripts/cron.php 0 11
scripts/events.php 1 2
scripts/remote.php 16 127
scripts/worker.php 3 4
spell_check.sh 1 1
tests/config.php 2 3
File Compare.txt changed (mode: 100644) (index d3ecc1d..6ef73b2)
1 RocketGit Gitlab GitHub Gitorious unfuddle.com gitolite
1 RocketGit Gitlab GitHub Gitorious unfuddle.com gitolite Pagure.io
2 2
3 License Affero GPLv3+ OpenCore? Proprietary ?open ? ?
3 License Affero GPLv3+ OpenCore? Proprietary ?open ? ? ?
4 Needs CLA? No Yes! n/a ? ? ? ?
4 5
5 6 [Features] [Features]
6 Easy installation Yes No Yes? No! ? Yes
7 SELinux friendly Yes ? ? ? ? ?
8 Distro friendly Yes No (see 2) No (see 2) No ? Yes
9 Bug tracker Yes Yes Yes No ? No
10 CLI commands (SSH) Yes ? ? ? ? ?
11 API HTTP(S) ? Yes ? ? ?
12 Anonymous push Yes ? No ? ? ?
13 Languages 1 ? ? ? ? ?
14 IPv6 Yes ? ? ? ? ?
15 Submodules ? ? ? ? ? ?
16 Usable with lynx ? ? ? ? ? ?
17 2fa Yes ? Yes (see 1) ? ? ?
18 Web Hooks Yes Yes Yes ? ? No
19 Web Hooks - client certs Yes No No ? ? n/a
20 Web Hooks - auth server (CA cert) Yes No No ? ? n/a
7 Easy installation Yes No Yes? No! ? Yes No
8 SELinux friendly Yes ? ? ? ? ? ?
9 Distro friendly Yes No (see 2) No (see 2) No ? Yes No (see 2)
10 Bug tracker Yes Yes Yes No ? No ?
11 CLI commands (SSH) Yes ? ? ? ? ? ?
12 API Yes ? Yes ? ? ? ?
13 Anonymous push Yes ? No ? ? ? ?
14 Languages 1 ? ? ? ? ? ?
15 IPv6 Yes ? ? ? ? ? ?
16 Submodules ? ? ? ? ? ? ?
17 Usable with lynx ? ? ? ? ? ? ?
18 2fa Yes ? Yes (see 1) ? ? ? ?
19 Web Hooks Yes Yes Yes ? ? No ?
20 Web Hooks - client certs Yes No No ? ? n/a ?
21 Web Hooks - auth server (CA cert) Yes No No ? ? n/a ?
21 22
22 23 [Rights] [Rights]
23 Path control Yes ? ? ? ? ?
24 Refs control Yes ? ? ? ? ?
25 IP control Yes ? ? ? ? ?
24 Path control Yes ? ? ? ? ? ?
25 Refs control Yes ? ? ? ? ? ?
26 IP control Yes ? ? ? ? ? ?
26 27
27 28
28 29 [Details] [Details]
29 Language PHP Ruby+Perl Ruby Ruby ? Perl
30 Cache Custom Redis ? ? ? No
30 Language PHP Ruby+Perl Ruby Ruby ? Perl Python
31 Cache Custom Redis ? ? ? No ?
32 Database Postgres MySQL ? ? ? ? ?
33 Webserver Apache Nginx ? ? ? ? ?
31 34
32 35
33 36 1) Seems is not really secure: if key is leaking, the attacker can push. 1) Seems is not really secure: if key is leaking, the attacker can push.
34 2) They have a distro inside a distro; so, upgrading distro does not update the software.
37 2) They have a distro inside a distro; so, upgrading distro does not update the software (pip, gem etc.).
File Makefile.in changed (mode: 100644) (index 2a3b938..3bb352d)
... ... tests:
23 23 install: all install: all
24 24 @mkdir -pv $(I_USR_SHARE)/$(PRJ) @mkdir -pv $(I_USR_SHARE)/$(PRJ)
25 25 cp -vdr inc hooks root scripts $(I_USR_SHARE)/$(PRJ) cp -vdr inc hooks root scripts $(I_USR_SHARE)/$(PRJ)
26 @
27 @echo "Installing configs..."
26 28 @mkdir -pv $(I_ETC)/xinetd.d @mkdir -pv $(I_ETC)/xinetd.d
27 29 cp -vd --no-clobber samples/rg $(I_ETC)/xinetd.d/$(PRJ) cp -vd --no-clobber samples/rg $(I_ETC)/xinetd.d/$(PRJ)
28 30 @mkdir -pv $(I_ETC)/cron.d @mkdir -pv $(I_ETC)/cron.d
 
... ... install: all
32 34 @mkdir -pv $(I_ETC)/$(PRJ) @mkdir -pv $(I_ETC)/$(PRJ)
33 35 cp -vd --no-clobber samples/config.php $(I_ETC)/$(PRJ)/ cp -vd --no-clobber samples/config.php $(I_ETC)/$(PRJ)/
34 36 cp -vd samples/config.php $(I_ETC)/$(PRJ)/config.php.sample cp -vd samples/config.php $(I_ETC)/$(PRJ)/config.php.sample
37 cp -vd --no-clobber samples/php-fpm.conf $(I_ETC)/$(PRJ)/
38 cp -vd --no-clobber samples/pool.conf $(I_ETC)/$(PRJ)/
35 39 @mkdir -pv $(I_ETC)/logrotate.d @mkdir -pv $(I_ETC)/logrotate.d
36 40 cp -vd samples/logrotate $(I_ETC)/logrotate.d/$(PRJ) cp -vd samples/logrotate $(I_ETC)/logrotate.d/$(PRJ)
41 @mkdir -pv $(I_USR)/lib/systemd/system/
42 cp -vd samples/systemd.service $(I_USR)/lib/systemd/system/rocketgit-fpm.service
37 43 @ @
38 44 @echo "Installing tools..." @echo "Installing tools..."
39 45 @mkdir -pv $(I_USR_SBIN) @mkdir -pv $(I_USR_SBIN)
 
... ... install: all
43 49 @echo "Installing log stuff..." @echo "Installing log stuff..."
44 50 @mkdir -pv $(I_VAR_LOG)/$(PRJ) @mkdir -pv $(I_VAR_LOG)/$(PRJ)
45 51 @-chown -R rocketgit:rocketgit $(I_VAR_LOG)/$(PRJ) @-chown -R rocketgit:rocketgit $(I_VAR_LOG)/$(PRJ)
46 @-find $(I_VAR_LOG)/$(PRJ) -type d -exec chmod -R 0755 {} \;
52 @-find $(I_VAR_LOG)/$(PRJ) -type d -exec chmod -R 0700 {} \;
47 53 @-find $(I_VAR_LOG)/$(PRJ) -type f -exec chmod -R 0600 {} \; @-find $(I_VAR_LOG)/$(PRJ) -type f -exec chmod -R 0600 {} \;
48 54 @ @
49 @mkdir -pv $(I_VAR_LOG)/$(PRJ)-web
50 @-chown -R apache:apache $(I_VAR_LOG)/$(PRJ)-web
51 @-find $(I_VAR_LOG)/$(PRJ)-web -type d -exec chmod -R 0755 {} \;
52 @-find $(I_VAR_LOG)/$(PRJ)-web -type f -exec chmod -R 0600 {} \;
53 @
54 55 @echo "Installing varlib stuff..." @echo "Installing varlib stuff..."
55 56 @mkdir -pv $(I_VAR_LIB)/$(PRJ) @mkdir -pv $(I_VAR_LIB)/$(PRJ)
56 57 @mkdir -pv $(I_VAR_LIB)/$(PRJ)/locks @mkdir -pv $(I_VAR_LIB)/$(PRJ)/locks
 
... ... install: all
59 60 @mkdir -pv $(I_VAR_LIB)/$(PRJ)/qstats @mkdir -pv $(I_VAR_LIB)/$(PRJ)/qstats
60 61 @mkdir -pv $(I_VAR_LIB)/$(PRJ)/sockets @mkdir -pv $(I_VAR_LIB)/$(PRJ)/sockets
61 62 @mkdir -pv $(I_VAR_LIB)/$(PRJ)/worker @mkdir -pv $(I_VAR_LIB)/$(PRJ)/worker
63 @
62 64 @echo "Fixing rights..." @echo "Fixing rights..."
63 @-find $(I_VAR_LIB)/$(PRJ) -type d -exec chmod 0755 {} \;
64 @-find $(I_VAR_LIB)/$(PRJ) -type f -exec chmod 0600 {} \;
65 @echo "Fixing rights: /var/lib dirs..."
66 @-find $(I_VAR_LIB)/$(PRJ) -mindepth 1 -type d | xargs chmod -c 0700
67 @echo "Fixing rights: /var/lib files..."
68 @-find $(I_VAR_LIB)/$(PRJ) -type f | xargs chmod -c 0600
65 69 @mkdir -pv --mode=0700 $(I_VAR_LIB)/$(PRJ)/tmp @mkdir -pv --mode=0700 $(I_VAR_LIB)/$(PRJ)/tmp
66 70 @-chown -R rocketgit:rocketgit $(I_VAR_LIB)/$(PRJ) @-chown -R rocketgit:rocketgit $(I_VAR_LIB)/$(PRJ)
67 @-chown root:root $(I_VAR_LIB)/$(PRJ)
68 71 @-chown root:root $(I_VAR_LIB)/$(PRJ)/worker @-chown root:root $(I_VAR_LIB)/$(PRJ)/worker
72 @-chown root:root $(I_VAR_LIB)/$(PRJ)
73 @-chmod -c 0755 $(I_VAR_LIB)/$(PRJ)
69 74 @ @
70 75 @echo "Installing SELinux stuff..." @echo "Installing SELinux stuff..."
71 76 @mkdir -pv --mode=0755 $(I_USR_SHARE)/selinux/targeted @mkdir -pv --mode=0755 $(I_USR_SHARE)/selinux/targeted
File README changed (mode: 100644) (index 95543a1..3ee5dbb)
27 27
28 28 . Edit /etc/rocketgit/config.php . Edit /etc/rocketgit/config.php
29 29 . Edit /etc/httpd/conf.d/rocketgit.conf . Edit /etc/httpd/conf.d/rocketgit.conf
30 . Activate php-fpm:
31 systemd based distributions:
32 # systemctl enable rocketgit-fpm
33 # systemctl start rocketgit-fpm
34 RedHat/CentOS/Oracle
35 # chkconfig rocketgit-fpm on
36 # service rocketgit-fpm start
30 37
31 38 . PHP . PHP
32 39 Adjust php.ini to: Adjust php.ini to:
File TODO changed (mode: 100644) (index a8bfdcf..efb1295)
1 1 == Where I stopped last time == == Where I stopped last time ==
2 [ ] I am investigating the switch to php-fpm:
3 - a systemd start file must be provided (also a classic one)
4 - Add the new files to spec
5 - Adapt SELinux file.
6 - Adjust docker/vm build scripts
7 [ ] Better explain why world needs another git hosting repo.
8 [ ] How do we get rid of post-update hook? rpm will auto clean it?
9 Let's see on rocketgit.com.
10 [ ]
2 11
3 12 == BEFORE NEXT RELEASE == == BEFORE NEXT RELEASE ==
13 [ ] use shutdown function for async cache stuff? Maybe other things?
14 I do not think so... Should we have a write ahead log:
15 something like we inform the cache that we need to clean an entry
16 it the connection is broken.
17 [ ] UTF8 with the databse, please check.
18 [ ] main page: add a new way to ear money: add sponsort, directly in the source
19 to be shown on every deployed rocketgit instalation.
20 We can use bidding for the order.
21 [ ] Investigate socket activation for fpm? Cache? Events?
22 [ ] Why do I show info about correct host name in hooks?!
23 Maybe because only in the hook can we output stuff?
24 Also, give correct command to change the url, not only inform the user.
25 [ ] http: do we allow a fetch for a anon user from a private repo? test!
26 Not only http.
27 [ ] If user has push access, why do we create a namespace?!
28 Maybe because I do not know the pushed refs?
29 [ ] 2fa: http is not supported yet!
30 [ ] Now, also the web part can do the db update.
31 [ ] Get rid of rwe?
32 [ ] rg_repo_fetch_push_helper: if git repo is not created, delay the fetch/push?
33 [ ] target_ui => owner_ui?
34 [ ] Consolidate "welcome to rocketgit" messages!
35 [ ] when creating a vm, pass 'rng' device
36 [ ] Allow user to upload GPG keys ids and use them as an authentication
37 witness when pushing signed stuff.
38 [ ] Provide the URL to the pull request
39 [ ] Add custom hooks (example: hooks.d/post-update.d/*)
40 [ ] Disable auto gc and run it one per day, more or less?
41 [ ] Log client version when fetching/pushing?
42 [ ] man git-http-backend:
43 The backend process sets GIT_COMMITTER_NAME to $REMOTE_USER and
44 GIT_COMMITTER_EMAIL to ${REMOTE_USER}@http.${REMOTE_ADDR}, ensuring
45 that any reflogs created by git-receive-pack contain some identifying
46 information of the remote user who performed the push.
47 [ ] Clone/push by HTTP: cannot send the welcome message.
48 Probably, we have to add a patch to git-receive/send-pack.
49 [ ] Add support for nginx and lighttpd.
50 php-fpm comes with files in /etc/nginx! So can we!
51 [ ] At least for http we do not check if host does not matches and warn user
52 to change it.
53 [ ] Get rid of xinetd and run remote.php as a service. With a .service file.
54 The same for all other cron scripts (except cron.php)!
55 [ ] unit test for apikeys
56 [ ] advertise on git mailing list.
57 [ ] git-receive-pack: check certificate stuff!
58 [ ] We may want to use fastcgi_finish_request to continue doing stuff in
59 background.
60 [ ] demo: list pages (and titles) in a text file to not have it hardcoded!
61 [ ] demo: small tutorial on how to contribute to a project on rocketgit
62 [ ] demo: ci1: I did not explain how it works regarding workers/libvirt/etc.
63 [ ] https://libreboot.org/git/#githosting; also why you should not use
64 github/gitlab. We should link to this in a section: "Why we need
65 another git hosting solution?"
66 [ ] build: Instruct user to add qemu-guest-agent package?
67 [ ] demo: contributing to a project - how easy it is.
68 [ ] We have no event for tag push!
69 [ ] Notify user if a repo is created and nothing is pushed.
70 Maybe SSH is a barrier?
71 [ ] wh: add a rsync plugin, with user and pass.
4 72 [ ] build: Document how to start builder.sh (from cron or let it read the conf [ ] build: Document how to start builder.sh (from cron or let it read the conf
5 73 file). Or, never install worker.conf and let an admin to rename file). Or, never install worker.conf and let an admin to rename
6 74 worker.conf.sample into worker.conf worker.conf.sample into worker.conf
 
45 113 firewall-cmd --permanent --add-port=19999/tcp firewall-cmd --permanent --add-port=19999/tcp
46 114 firewall-cmd --reload firewall-cmd --reload
47 115 [ ] Register with freecode.club [ ] Register with freecode.club
48 [ ] build: give error if we cannot install one of the packages.
49 [ ] build: allow user to install some dependencies.
116 [ ] build: allow user to install some dependencies (done).
50 117 Or maybe try to detect from the spec file? Or maybe try to detect from the spec file?
51 We also must specify how to install packages.
52 [ ] wh: we do not have the time of last run!
118 [ ] wh: we do not have the time of last run! Where?
53 119 [ ] build: allow adding environment variables for a job. [ ] build: allow adding environment variables for a job.
54 120 [ ] Somehow, warn the user that no environments are available and instruct [ ] Somehow, warn the user that no environments are available and instruct
55 121 she/him to add workers. she/him to add workers.
56 122 [ ] css: 'mess' class has a 5px top margin. it is not ok (check edit webhook). [ ] css: 'mess' class has a 5px top margin. it is not ok (check edit webhook).
57 [ ] Filter environment (allow only a-zA-Z0-9_.)
123 [ ] Filter environment (allow only a-zA-Z0-9_.). Why?
58 124 [ ] Join builders.inc.php and workers.inc.php? [ ] Join builders.inc.php and workers.inc.php?
59 125 [ ] build: builder.php: we should wait for a notification instead to poll [ ] build: builder.php: we should wait for a notification instead to poll
60 126 the database. the database.
61 [ ] build: enforce a max build time; use cost; use max_workers.
62 [ ] build: If a user has own workers, do not use global ones (of course,
63 arch is taken in consideration).
127 [ ] build: enforce a max build time.
64 128 [ ] build: show user the status of the workers. Also, how much time they [ ] build: show user the status of the workers. Also, how much time they
65 129 were used and what builds they did. were used and what builds they did.
66 130 [ ] build: find a way to reuse machines, so we avoid the startup cost. [ ] build: find a way to reuse machines, so we avoid the startup cost.
67 Take care also about package instalation.
68 131 [ ] build: avoid starting a lot of services. We do not need them! [ ] build: avoid starting a lot of services. We do not need them!
69 132 [ ] Some daemon to synchronize two instances (master standby or just [ ] Some daemon to synchronize two instances (master standby or just
70 133 load balancing)? load balancing)?
 
112 175 [ ] build: allow user to specify some packages to be installed first? [ ] build: allow user to specify some packages to be installed first?
113 176 [ ] Get rid of php-mbstring! It is not in main repo on Oracle Linux! [ ] Get rid of php-mbstring! It is not in main repo on Oracle Linux!
114 177 [ ] Destroy storage for 'build' machines [ ] Destroy storage for 'build' machines
115 [ ] If a user types a wrong e-mail at registration phase, and without
116 confirmation we do not allow access, we have a problem.
117 Add a hint in "Create a new account" page to warn about this.
118 Also, to explain why we need the e-mail address.
119 Maybe, add a permanent warning on the login page
120 that the e-mail is not confirmed and add hide or edit account links.
121 178 [ ] Add a new right: "allow pushes only if they are signed". [ ] Add a new right: "allow pushes only if they are signed".
122 179 As with ss keys, a user may want to add public gpg keys to a list As with ss keys, a user may want to add public gpg keys to a list
123 180 that is allowed to push. Take care: you can sign tags but also that is allowed to push. Take care: you can sign tags but also
 
321 378 execute the hook? The problem is that I have no link between the repo execute the hook? The problem is that I have no link between the repo
322 379 and hooks. Maybe go to the repo and link the hooks? what about and hooks. Maybe go to the repo and link the hooks? what about
323 380 'repo create' hook trigger? 'repo create' hook trigger?
324 [ ] docker: document somewhere that is available and how to use it.
325 381 [ ] wh: Add a link to a "movie" explaining how with one hook you can cover both [ ] wh: Add a link to a "movie" explaining how with one hook you can cover both
326 382 production and evaluation deployments. production and evaluation deployments.
327 383 [ ] wh: notify user when a hook fails. [ ] wh: notify user when a hook fails.
 
834 890 [ ] ssh: Show user the entry that must be added for known_hosts [ ] ssh: Show user the entry that must be added for known_hosts
835 891 [ ] LDAP: http://mageconfig.blogspot.ro/2014/06/configure-gitgerrit-with-open-ldap-for.html [ ] LDAP: http://mageconfig.blogspot.ro/2014/06/configure-gitgerrit-with-open-ldap-for.html
836 892 [ ] Pass only uid to events, we already have it in cache! [ ] Pass only uid to events, we already have it in cache!
837 [ ] 'confirmed' should be built in the event handlers not in callers.
838 It is already checked in rg_mail_template!
839 893 [ ] When we push by ssh, we have the user, so we can give more info about [ ] When we push by ssh, we have the user, so we can give more info about
840 894 why the push failed. Carefull, not too much info. For example: why the push failed. Carefull, not too much info. For example:
841 895 "You have no key uploaded, go to ..." "You have no key uploaded, go to ..."
 
... ... But, we have a problem with the expiration time!
1407 1461 [ ] If the confirmation code is truncated, an internal error is generated [ ] If the confirmation code is truncated, an internal error is generated
1408 1462 instead of a user error! instead of a user error!
1409 1463 [ ] Third option: anybody can create an account but must be validated by admin. [ ] Third option: anybody can create an account but must be validated by admin.
1410 [ ] After creating the account, keep the user logged in and allow login
1411 even if is not confirmed (option in config).
1412 1464 [ ] When I close a bug, seems I add myself to the watch table again! [ ] When I close a bug, seems I add myself to the watch table again!
1413 1465 [ ] Should we load the lables in rg_bug_info? [ ] Should we load the lables in rg_bug_info?
1414 1466 [ ] Do we need a rg_bug_cosmetic for notes/users/repos/etc? [ ] Do we need a rg_bug_cosmetic for notes/users/repos/etc?
File debian/control.in changed (mode: 100644) (index fbc5d65..9f469f4)
... ... Vcs-Browser: https://rocketgit.com/user/catalinux/dupdump
10 10
11 11 Package: @PRJ@ Package: @PRJ@
12 12 Architecture: all Architecture: all
13 Depends: ${shlibs:Depends}, ${misc:Depends}, httpd, mod_ssl, php, php-cli, php-pgsql, php-mbstring, xinetd, git, cronie, util-linux, shadow-utils, postgresql-server
13 Depends: ${shlibs:Depends}, ${misc:Depends}, httpd, mod_ssl, php-fpm, php-cli, php-pgsql, php-mbstring, xinetd, git, cronie, util-linux, shadow-utils, postgresql-server
14 14 Description: @SHORT_DESCRIPTION@ Description: @SHORT_DESCRIPTION@
File docker/Dockerfile-postgresql.tmpl changed (mode: 100644) (index d28d744..f892ef5)
1 FROM fedora:23
1 FROM fedora:24
2 2 MAINTAINER Catalin(ux) M. BOIE <catab-docker@embedromix.ro> MAINTAINER Catalin(ux) M. BOIE <catab-docker@embedromix.ro>
3 3
4 4 VOLUME /var/lib/postgresql/data VOLUME /var/lib/postgresql/data
File docker/build.sh changed (mode: 100755) (index e898e94..47d1146)
... ... set -e
5 5
6 6 . ../duilder.conf . ../duilder.conf
7 7
8 RP_VER="20160319"
8 RP_VER="20160711"
9 9 sed -e "s|@@RP_VER@@|${RP_VER}|" Dockerfile-postgresql.tmpl > Dockerfile-postgresql sed -e "s|@@RP_VER@@|${RP_VER}|" Dockerfile-postgresql.tmpl > Dockerfile-postgresql
10 10 if [ "`docker images -q rocketgit/rocketgit-postgresql:${RP_VER}`" = "" ]; then if [ "`docker images -q rocketgit/rocketgit-postgresql:${RP_VER}`" = "" ]; then
11 11 echo "Building rocketgit-postgresql (${RP_VER})..." echo "Building rocketgit-postgresql (${RP_VER})..."
File hooks/post-receive changed (mode: 100755) (index 582ef11..e39549b)
... ... $repo_path = getenv("ROCKETGIT_REPO_PATH");
39 39 rg_log("Start namespace=$namespace repo_path=$repo_path"); rg_log("Start namespace=$namespace repo_path=$repo_path");
40 40 rg_log("_SERVER: " . rg_array2string($_SERVER)); rg_log("_SERVER: " . rg_array2string($_SERVER));
41 41
42 umask(0022);
42 umask(0077);
43 43
44 44 while (($set = fgets(STDIN))) { while (($set = fgets(STDIN))) {
45 45 $set = trim($set); $set = trim($set);
File hooks/pre-commit changed (mode: 100755) (index 00184a9..5ab9d41)
... ... $repo_path = getenv("ROCKETGIT_REPO_PATH");
28 28 rg_log("Start..."); rg_log("Start...");
29 29 rg_log("_SERVER: " . rg_array2string($_SERVER)); rg_log("_SERVER: " . rg_array2string($_SERVER));
30 30
31 umask(0022);
31 umask(0077);
32 32
33 33
34 34 if (rg_git_rev_ok("HEAD") !== FALSE) if (rg_git_rev_ok("HEAD") !== FALSE)
File hooks/pre-receive changed (mode: 100755) (index 5b6c7d5..fa6a704)
... ... $repo_path = getenv('ROCKETGIT_REPO_PATH');
29 29 $login_uid = getenv('ROCKETGIT_LOGIN_UID'); $login_uid = getenv('ROCKETGIT_LOGIN_UID');
30 30 $ip = getenv('ROCKETGIT_IP'); $ip = getenv('ROCKETGIT_IP');
31 31 $git_host = getenv('ROCKETGIT_HOST'); $git_host = getenv('ROCKETGIT_HOST');
32 $info_show = getenv('ROCKETGIT_INFO_SHOW');
32 $show_info = getenv('ROCKETGIT_SHOW_INFO');
33 33
34 34 rg_log("Start"); rg_log("Start");
35 35 rg_log("_SERVER: " . rg_array2string($_SERVER)); rg_log("_SERVER: " . rg_array2string($_SERVER));
36 36
37 umask(0022);
37 umask(0077);
38 38
39 39
40 if ($info_show == 0) {
41 rg_git_info('== Welcome to RocketGit! ==');
42 rg_git_info('you are connecting from IP ' . $ip . '.');
40 if ($show_info) {
41 rg_git_info('', '== Welcome to RocketGit! ==');
42 rg_git_info('', 'you are connecting from IP ' . $ip . '.');
43 43 } }
44 44
45 45 // If user does not correct to the correct URL, correct them // If user does not correct to the correct URL, correct them
46 if (!empty($git_host) && (strcasecmp($git_host, $rg_git_host) != 0))
47 rg_git_info('Please use ' . $rg_git_host
48 . ' instead of ' . $git_host . '.');
46 // TODO: this is not working for http!
47 //if (!empty($git_host) && (strcasecmp($git_host, $rg_git_host) != 0))
48 // rg_git_info('', 'Please use ' . $rg_git_host
49 // . ' instead of ' . $git_host . '.');
49 50
50 51 exit(0); exit(0);
51 52
File hooks/update changed (mode: 100755) (index ee8f6d9..375d036)
... ... $a['namespace'] = getenv("GIT_NAMESPACE");
45 45 $a['repo_path'] = getenv("ROCKETGIT_REPO_PATH"); $a['repo_path'] = getenv("ROCKETGIT_REPO_PATH");
46 46 $a['repo_name'] = getenv("ROCKETGIT_REPO_NAME"); $a['repo_name'] = getenv("ROCKETGIT_REPO_NAME");
47 47 $a['repo_uid'] = sprintf("%u", getenv("ROCKETGIT_REPO_UID")); $a['repo_uid'] = sprintf("%u", getenv("ROCKETGIT_REPO_UID"));
48 $a['repo_clone_url'] = getenv('ROCKETGIT_REPO_CLONE_URL');
48 $a['repo_clone_url_http'] = getenv('ROCKETGIT_REPO_CLONE_URL');
49 49
50 50 rg_log("Start a=" . rg_array2string($a)); rg_log("Start a=" . rg_array2string($a));
51 51 rg_log("_SERVER: " . rg_array2string($_SERVER)); rg_log("_SERVER: " . rg_array2string($_SERVER));
 
... ... if ($a['login_uid'] > 0) {
64 64 ); );
65 65 } }
66 66
67 umask(0022);
67 umask(0077);
68 68
69 //echo rg_git_pack("\x02Test message on band 2\n");
70 //echo rg_git_pack("\x03Test message on band 3\n");
69 71
70 72 $a['refname'] = rg_git_reference($_SERVER['argv'][1]); $a['refname'] = rg_git_reference($_SERVER['argv'][1]);
71 73 if ($a['refname'] === FALSE) if ($a['refname'] === FALSE)
File inc/fixes.inc.php changed (mode: 100644) (index 33eb417..4bd2ef2)
... ... function rg_fixes_repo_index_by_id_one($uid, $repo_id, $repo_name)
123 123 // we expect to have a folder .../repos/by_id // we expect to have a folder .../repos/by_id
124 124 $by_id = rg_repo_path_by_id($uid, $repo_id); $by_id = rg_repo_path_by_id($uid, $repo_id);
125 125 $p = dirname($by_id); $p = dirname($by_id);
126 if (!is_dir($p) && (mkdir($p, 0755, TRUE) === FALSE)) {
126 if (!is_dir($p) && (mkdir($p, 0700, TRUE) === FALSE)) {
127 127 rg_log("Cannot create [$p] folder!"); rg_log("Cannot create [$p] folder!");
128 128 break; break;
129 129 } }
 
... ... function rg_fixes_repo_index_by_id_one($uid, $repo_id, $repo_name)
131 131 // we expect to have a folder .../repos/by_name // we expect to have a folder .../repos/by_name
132 132 $by_name = rg_repo_path_by_name($uid, $repo_name); $by_name = rg_repo_path_by_name($uid, $repo_name);
133 133 $p = dirname($by_name); $p = dirname($by_name);
134 if (!is_dir($p) && (mkdir($p, 0755, TRUE) === FALSE)) {
134 if (!is_dir($p) && (mkdir($p, 0700, TRUE) === FALSE)) {
135 135 rg_log("Cannot create [$p] folder!"); rg_log("Cannot create [$p] folder!");
136 136 break; break;
137 137 } }
 
... ... function rg_fixes_user_index_by_id_one($uid, $username)
223 223
224 224 // parend dir exits? if not, create it // parend dir exits? if not, create it
225 225 $p = dirname($user_path_uid); $p = dirname($user_path_uid);
226 if (!is_dir($p) && (mkdir($p, 0755, TRUE) === FALSE)) {
226 if (!is_dir($p) && (mkdir($p, 0700, TRUE) === FALSE)) {
227 227 rg_log("cannot create parent dir [$p]"); rg_log("cannot create parent dir [$p]");
228 228 break; break;
229 229 } }
230 230
231 231 // parend dir exits? if not, create it // parend dir exits? if not, create it
232 232 $p = dirname($user_path_name); $p = dirname($user_path_name);
233 if (!is_dir($p) && (mkdir($p, 0755, TRUE) === FALSE)) {
233 if (!is_dir($p) && (mkdir($p, 0700, TRUE) === FALSE)) {
234 234 rg_log("cannot create parent dir [$p]"); rg_log("cannot create parent dir [$p]");
235 235 break; break;
236 236 } }
File inc/git.inc.php changed (mode: 100644) (index 45f72f6..c4a9bb0)
... ... function rg_git_short($ref)
48 48 return $ref; return $ref;
49 49 } }
50 50
51 function rg_git_info($msg)
51 function rg_git_info($band, $msg)
52 52 { {
53 echo $band;
53 54 $x = explode("\n", trim($msg)); $x = explode("\n", trim($msg));
54 55 foreach ($x as $line) { foreach ($x as $line) {
55 56 rg_log("INFO: $line"); rg_log("INFO: $line");
56 echo "RocketGit: Info: $line\n";
57 echo 'RocketGit: Info: ' . $line . "\n";
57 58 } }
58 59 } }
59 60
61 function rg_git_info_pack($band, $msg)
62 {
63 $s = $band;
64 $x = explode("\n", trim($msg));
65 foreach ($x as $line) {
66 rg_log("INFO: $line");
67 $s .= 'RocketGit: Info: ' . $line . "\n";
68 }
69
70 echo rg_git_pack($s);
71 }
72
60 73 /* /*
61 74 * Installs rg hooks instead of original ones, by making a link * Installs rg hooks instead of original ones, by making a link
62 75 */ */
 
... ... function rg_git_init($dst)
123 136 while (1) { while (1) {
124 137 $dir = dirname($dst); $dir = dirname($dst);
125 138 if (!file_exists($dir)) { if (!file_exists($dir)) {
126 $r = @mkdir($dir, 0755, TRUE);
139 $r = @mkdir($dir, 0700, TRUE);
127 140 if ($r === FALSE) { if ($r === FALSE) {
128 141 rg_git_set_error("cannot create dir [$dir] ($php_errormsg)"); rg_git_set_error("cannot create dir [$dir] ($php_errormsg)");
129 142 break; break;
 
... ... function rg_git_clone($src, $dst)
175 188 while (1) { while (1) {
176 189 $dir = dirname($dst); $dir = dirname($dst);
177 190 if (!file_exists($dir)) { if (!file_exists($dir)) {
178 $r = @mkdir($dir, 0755, TRUE);
191 $r = @mkdir($dir, 0700, TRUE);
179 192 if ($r === FALSE) { if ($r === FALSE) {
180 193 rg_git_set_error("cannot create dir [$dir] ($php_errormsg)"); rg_git_set_error("cannot create dir [$dir] ($php_errormsg)");
181 194 break; break;
 
... ... function rg_git_update_branch($db, $a)
1452 1465
1453 1466 $_x = array(); $_x = array();
1454 1467 $msg = rg_template("msg/push_merge_request.txt", $_x, FALSE /*xss*/); $msg = rg_template("msg/push_merge_request.txt", $_x, FALSE /*xss*/);
1455 rg_git_info($a['refname'] . ':' . "\n" . $msg);
1468 rg_git_info('', $a['refname'] . ':' . "\n" . $msg);
1456 1469
1457 1470 $history['history_category'] = REPO_CAT_GIT_BRANCH_ANON_PUSH; $history['history_category'] = REPO_CAT_GIT_BRANCH_ANON_PUSH;
1458 1471 $history['history_message'] = 'Anonymous push to ref ' $history['history_message'] = 'Anonymous push to ref '
 
... ... function rg_git_update_branch($db, $a)
1482 1495 'name' => $a['repo_name'], 'name' => $a['repo_name'],
1483 1496 'url' => rg_base_url() . $a['login_url'] 'url' => rg_base_url() . $a['login_url']
1484 1497 . '/' . $a['repo_name'], . '/' . $a['repo_name'],
1485 'clone_url' => $a['repo_clone_url']
1498 'clone_url' => $a['repo_clone_url_http']
1486 1499 ); );
1487 1500 unset($ev['repo_id']); unset($ev['repo_name']); unset($ev['repo_id']); unset($ev['repo_name']);
1488 1501 $r = rg_event_add($db, $ev); $r = rg_event_add($db, $ev);
 
... ... function rg_git_request_pull($repo_path, $start, $url, $end, $patch)
2038 2051 return $ret; return $ret;
2039 2052 } }
2040 2053
2054 /*
2055 * Prepares a git packet from a string
2056 */
2057 function rg_git_pack($str)
2058 {
2059 return sprintf("%04x", 4 + strlen($str)) . $str;
2060 }
2061
2062 /*
2063 * Prepares a 'flush' packet
2064 */
2065 function rg_git_flush()
2066 {
2067 return '0000';
2068 }
2069
2070 /*
2071 * Callback used by rg_exec to output in band 1
2072 */
2073 function rg_git_band_1($s)
2074 {
2075 echo rg_git_pack("\x01" . $s);
2076 }
2077
2078 /*
2079 * Callback used by rg_exec to output in band 2
2080 */
2081 function rg_git_band_2($s)
2082 {
2083 echo rg_git_pack("\x02" . $s);
2084 }
2085
2086 /*
2087 * Callback used by rg_exec to output in band 3
2088 */
2089 function rg_git_band_3($s)
2090 {
2091 echo rg_git_pack("\x03" . $s);
2092 }
2093
2041 2094 ?> ?>
File inc/init.inc.php changed (mode: 100644) (index 0e96a58..cc354c0)
... ... if (empty($_dt))
12 12 // For escapeshellarg to work with UTF-8, we are forced to set a locale // For escapeshellarg to work with UTF-8, we are forced to set a locale
13 13 setlocale(LC_CTYPE, "en_US.UTF-8"); setlocale(LC_CTYPE, "en_US.UTF-8");
14 14
15 $_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n');
15 $rg['rg_http_host'] = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n');
16 $_t = explode(':', $rg['rg_http_host']);
17 $rg['rg_http_host_no_port'] = $_t[0];
16 18
17 19 if (!isset($rg_ssh_host) || empty($rg_ssh_host)) if (!isset($rg_ssh_host) || empty($rg_ssh_host))
18 $rg_ssh_host = $_host;
20 $rg_ssh_host = $rg['rg_http_host'];
19 21 $rg['rg_ssh_host'] = $rg_ssh_host; $rg['rg_ssh_host'] = $rg_ssh_host;
20 22
21 23 if (!isset($rg_ssh_port) || empty($rg_ssh_port)) if (!isset($rg_ssh_port) || empty($rg_ssh_port))
 
... ... $rg['rg_ssh_port'] = $rg_ssh_port;
24 26
25 27
26 28 if (!isset($rg_git_host) || empty($rg_git_host)) if (!isset($rg_git_host) || empty($rg_git_host))
27 $rg_git_host = $_host;
29 $rg_git_host = $rg['rg_http_host'];
28 30 $rg['rg_git_host'] = $rg_git_host; $rg['rg_git_host'] = $rg_git_host;
29 31
30 32 if (!isset($rg_git_port) || empty($rg_git_port)) if (!isset($rg_git_port) || empty($rg_git_port))
File inc/log.inc.php changed (mode: 100644) (index 502c433..7a79135)
... ... require_once($INC . "/cache.inc.php");
5 5 if (!isset($rg_log_dir)) if (!isset($rg_log_dir))
6 6 $rg_log_dir = "/var/log/rocketgit"; $rg_log_dir = "/var/log/rocketgit";
7 7
8 if (!isset($rg_web_log_dir))
9 $rg_web_log_dir = "/var/log/rocketgit-web";
8 if (!isset($rg_log_file))
9 $rg_log_file = $rg_log_dir . "/fallback.log";
10 10
11 if (!isset($rg_log_file)) {
12 if (isset($_SERVER['REMOTE_ADDR']))
13 $rg_log_file = $rg_web_log_dir . "/fallback.log";
14 else
15 $rg_log_file = $rg_log_dir . "/fallback.log";
16 }
17 11 $rg_log_fd = FALSE; $rg_log_fd = FALSE;
18 12 $rg_log_sid = rg_id(6); $rg_log_sid = rg_id(6);
19 13 $rg_log_buf = ""; $rg_log_buf = "";
 
... ... function rg_log_ml($str)
134 128 $rg_error_core_seen = array(); $rg_error_core_seen = array();
135 129 function rg_error_core($msg) function rg_error_core($msg)
136 130 { {
137 global $rg_web_log_dir;
138 131 global $rg_log_dir; global $rg_log_dir;
139 132 global $rg_admin_email; global $rg_admin_email;
140 133 global $rg_error_core_seen; global $rg_error_core_seen;
 
... ... function rg_error_core($msg)
146 139 $bt = print_r(debug_backtrace(), TRUE); $bt = print_r(debug_backtrace(), TRUE);
147 140 $bt = substr($bt, 0, 1024 * 1024); $bt = substr($bt, 0, 1024 * 1024);
148 141
149 if (isset($_SERVER['REMOTE_ADDR']))
150 $dir = $rg_web_log_dir;
151 else
152 $dir = $rg_log_dir;
142 $dir = $rg_log_dir;
153 143
154 144 $key = md5($msg); $key = md5($msg);
155 145 if (isset($rg_error_core_seen[$key])) if (isset($rg_error_core_seen[$key]))
 
... ... function rg_error_core($msg)
170 160 */ */
171 161 function rg_log_cron() function rg_log_cron()
172 162 { {
173 global $rg_web_log_dir;
174 163 global $rg_log_dir; global $rg_log_dir;
175 164 global $rg_admin_email; global $rg_admin_email;
176 165 global $rg_state_dir; global $rg_state_dir;
177 166
178 $wd = rg_dir_load_pattern($rg_web_log_dir, "err-.*");
179 if ($wd === FALSE)
180 $wcount = "?";
181 else
182 $wcount = count($wd);
183
184 167 $nd = rg_dir_load_pattern($rg_log_dir, "err-.*"); $nd = rg_dir_load_pattern($rg_log_dir, "err-.*");
185 168 if ($nd === FALSE) if ($nd === FALSE)
186 169 $ncount = "?"; $ncount = "?";
187 170 else else
188 171 $ncount = count($nd); $ncount = count($nd);
189 172
190 if ($wcount + $ncount == 0)
173 if ($ncount == 0)
191 174 return; return;
192 175
193 176 // Do not send less than 1 per 4 hours // Do not send less than 1 per 4 hours
 
... ... function rg_log_cron()
199 182 return 0; return 0;
200 183
201 184 mail($rg_admin_email, mail($rg_admin_email,
202 $wcount . ' + ' . $ncount . ' errors are waiting...',
203 'Please forward the content of /var/log/rocketgit*/err-*'
185 $ncount . ' errors are waiting...',
186 'Please forward the content of /var/log/rocketgit/err-*'
204 187 . ' to RocketGit developers at rg-bugs@embedromix.ro.\n\n' . ' to RocketGit developers at rg-bugs@embedromix.ro.\n\n'
205 188 . 'Thank you!\n\n', . 'Thank you!\n\n',
206 189 'Content-Type: text/plain;charset=UTF-8', 'Content-Type: text/plain;charset=UTF-8',
File inc/repo.inc.php changed (mode: 100644) (index 68f6e8b..1355166)
... ... function rg_repo_cosmetic($db, &$row)
106 106 { {
107 107 global $rg_ssh_port, $rg_git_port; global $rg_ssh_port, $rg_git_port;
108 108
109 $row['clone_url'] = '';
110
111 109 // Because this field was added later and the cache may not have it // Because this field was added later and the cache may not have it
112 110 if (!isset($row['template'])) if (!isset($row['template']))
113 111 $row['template'] = ''; $row['template'] = '';
 
... ... function rg_repo_cosmetic($db, &$row)
132 130 $_ui['username'], $row['name']); $_ui['username'], $row['name']);
133 131 $row['clone_url_git'] = rg_re_repo_git($_ui['organization'], $row['clone_url_git'] = rg_re_repo_git($_ui['organization'],
134 132 $_ui['username'], $row['name']); $_ui['username'], $row['name']);
135 if ($rg_ssh_port != 0)
136 $row['clone_url'] = $row['clone_url_ssh'];
137 else
138 $row['clone_url'] = $row['clone_url_git'];
133 $row['clone_url_http'] = rg_re_repo_http($_ui['organization'],
134 $_ui['username'], $row['name']);
139 135 } }
140 136
141 137 $row['master_name'] = '-'; $row['master_name'] = '-';
 
... ... function rg_repo_event_symlink_by_name($db, $e)
573 569 // Create links' parent // Create links' parent
574 570 $new_path_parent = dirname($new_path); $new_path_parent = dirname($new_path);
575 571 if (!is_dir($new_path_parent)) { if (!is_dir($new_path_parent)) {
576 $r = mkdir($new_path_parent, 0755, TRUE);
572 $r = mkdir($new_path_parent, 0700, TRUE);
577 573 if ($r === FALSE) { if ($r === FALSE) {
578 574 rg_repo_set_error("cannot create links' parent"); rg_repo_set_error("cannot create links' parent");
579 575 break; break;
 
... ... function rg_repo_event_storage_create($db, $e)
607 603 while (1) { while (1) {
608 604 $by_id_path = rg_repo_path_by_id($e['ui']['uid'], $e['ri']['repo_id']); $by_id_path = rg_repo_path_by_id($e['ui']['uid'], $e['ri']['repo_id']);
609 605 if (!is_dir($by_id_path)) { if (!is_dir($by_id_path)) {
610 if (mkdir($by_id_path, 0755, TRUE) === FALSE) {
606 if (mkdir($by_id_path, 0700, TRUE) === FALSE) {
611 607 rg_repo_set_error("could not create folder $dst"); rg_repo_set_error("could not create folder $dst");
612 608 break; break;
613 609 } }
 
... ... function rg_repo_api($db, $a)
2402 2398 return $ret; return $ret;
2403 2399 } }
2404 2400
2401 /*
2402 * Helper for SSH/GIT/HTTP(S) fetch/push
2403 * @host - the host name accessed - may be different than the good one
2404 * @ip - from where the connections come
2405 * @cmd: 'git-upload-pack' or 'git-receive-pack'
2406 * @need_namespace_copy - true if we need to clone refs
2407 * TODO: move it to user.inc.php?!
2408 */
2409 function rg_repo_fetch_push_helper($db, $host, $ip, $login_ui, $prefix, $user,
2410 $repo, $cmd, $need_namespace_copy)
2411 {
2412 rg_prof_start('repo_fetch_push_helper');
2413 rg_log_enter('repo_fetch_push_helper: host=' . $host
2414 . ' prefix=' . $prefix . ' user=' . $user
2415 . ' repo=' . $repo . ' cmd=' . $cmd
2416 . ' need_namespace_copy=' . ($need_namespace_copy ? 'yes' : 'no'));
2417
2418 $ret = array('ok' => 0, 'allow' => 1, 'push_allowed' => 1);
2419 while (1) {
2420 // Extracts command and computes permissions
2421 if (strncasecmp($cmd, 'git-upload-pack', 15) == 0) {
2422 $cmd = 'git-upload-pack';
2423 $needed_rights = 'F';
2424 $push = 0;
2425 } else if (strncasecmp($cmd, 'git-receive-pack', 16) == 0) {
2426 $cmd = 'git-receive-pack';
2427 // We need push or anonymous push
2428 $needed_rights = 'P|H';
2429 $push = 1;
2430 } else {
2431 $ret['error'] = 'Unknown command';
2432 break;
2433 }
2434
2435 // Validity/security checks
2436 // Load info about the owner
2437 if (rg_user_ok($user) !== TRUE) {
2438 $ret['error'] = 'User is invalid (' . rg_user_error() . ')';
2439 break;
2440 }
2441 $ret['owner_ui'] = rg_user_info($db, 0, $user, '');
2442 if ($ret['owner_ui']['ok'] != 1) {
2443 $ret['error'] = 'Internal problems; try again later, please';
2444 break;
2445 }
2446 if ($ret['owner_ui']['exists'] != 1) {
2447 $ret['error'] = 'User does not exists';
2448 break;
2449 }
2450
2451 // Loading info about the repository
2452 if (rg_repo_ok($repo) !== TRUE) {
2453 $ret['error'] = 'Repository is invalid ('
2454 . rg_repo_error() . ')';
2455 break;
2456 }
2457 $ret['ri'] = rg_repo_info($db, 0, $ret['owner_ui']['uid'], $repo);
2458 if ($ret['ri']['ok'] != 1) {
2459 $ret['error'] = 'Internal problems; try again later, please';
2460 break;
2461 }
2462 if ($ret['ri']['exists'] != 1) {
2463 $ret['error'] = 'Repository does not exists';
2464 break;
2465 }
2466 if ($ret['ri']['deleted'] == 1) {
2467 $ret['error'] = 'Repository has been deleted';
2468 break;
2469 }
2470
2471 $ls = rg_repo_lock_status($db, $ret['ri']['repo_id']);
2472 if ($ls['ok'] != 1) {
2473 $ret['error'] = 'Could not get lock status: ' . rg_repo_error();
2474 break;
2475 }
2476 if (($ls['status'] == 1) && ($login_ui['uid'] != $ls['uid'])) {
2477 $_u = rg_user_info($db, $ls['uid'], '', '');
2478 if ($_u['exists'] == 1)
2479 $_user = $_u['username'];
2480 else
2481 $_user = '?';
2482 $ret['error'] = 'Repository has been locked user ' . $_user
2483 . ' at ' . gmdate('Y-m-d H:i', $ls['itime']) . ' UTC.'
2484 . ' Reason: ' . $ls['reason'];
2485 break;
2486 }
2487
2488 $repo_path = rg_repo_path_by_id($ret['owner_ui']['uid'],
2489 $ret['ri']['repo_id']);
2490 $ret['repo_path'] = $repo_path;
2491 rg_log('DEBUG: repo_path=' . $repo_path);
2492
2493 // TODO: signal user that the repo moved and provide a hint how to follow
2494
2495 $x = array();
2496 $x['obj_id'] = $ret['ri']['repo_id'];
2497 $x['type'] = 'repo_refs';
2498 $x['owner'] = $ret['ri']['uid'];
2499 $x['uid'] = $login_ui['uid'];
2500 $x['username'] = $login_ui['uid'] == 0 ? '' : $login_ui['username'];
2501 $x['needed_rights'] = $needed_rights;
2502 $x['ip'] = $ip;
2503 $x['misc'] = '';
2504 $r = rg_rights_allow($db, $x);
2505 if ($r !== TRUE) {
2506 $ret['error'] = 'You have no rights to access this repo';
2507 $ret['allow'] = 0;
2508 break;
2509 }
2510
2511 // We need to know if Push (and not anon) is allowed, so we can
2512 // give the user a chance to authenticate.
2513 // TODO: change rg_rights_allow to return what rights are
2514 // allowed and use it.
2515 $x['needed_rights'] = 'P';
2516 $r = rg_rights_allow($db, $x);
2517 if ($r !== TRUE)
2518 $ret['push_allowed'] = 0;
2519
2520 // If we are enrolled, ask for login token
2521 // For push we always ask for it, for fetch only if repo is
2522 // NOT public. And we can ask only if we have a ssh connection.
2523 // For git protocol we cannot because we do not have the
2524 // username/uid of the connecting user.
2525 if (isset($_SERVER['SSH_CONNECTION'])) {
2526 if (($ret['ri']['public'] == 0) || ($push == 1)) {
2527 $r = rg_totp_verify_ip($db, $login_ui['uid'],
2528 $ip);
2529 if (($r['ok'] == 0) && (empty($r['list']))) {
2530 $ret['error'] = rg_totp_error();
2531 break;
2532 }
2533 }
2534 }
2535
2536 // TODO: limit per connection
2537 // TODO: limit time and/or cpu
2538 // TODO: limit cpuset
2539 // TODO: limit io
2540 // TODO: put process in a cgroup?
2541
2542 if (($push == 1)
2543 && rg_user_over_limit($db, $ret['owner_ui'], $max)) {
2544 // TODO: be aware that a push may mean a delete =>
2545 // free space?!
2546 // We should mark the repo over limit when we compute
2547 // the disk space - same problem
2548 $ret['error'] = 'Cannot push: user is over limit'
2549 . ' (' . $ret['owner_ui']['disk_used_mb'] . 'MiB >= '
2550 . $max . 'MiB)';
2551 break;
2552 }
2553
2554 // Put in environment all we need
2555 putenv('ROCKETGIT_LOGIN_UID=' . $login_ui['uid']);
2556 putenv('ROCKETGIT_LOGIN_URL=' . rg_re_userpage($login_ui));
2557 putenv('ROCKETGIT_REPO_ID=' . $ret['ri']['repo_id']);
2558 putenv('ROCKETGIT_REPO_PATH=' . $repo_path);
2559 putenv('ROCKETGIT_REPO_NAME=' . $ret['ri']['name']);
2560 putenv('ROCKETGIT_REPO_UID=' . $ret['ri']['uid']);
2561 putenv('ROCKETGIT_REPO_CLONE_URL=' . $ret['ri']['clone_url_http']);
2562 putenv('ROCKETGIT_IP=' . $ip);
2563 putenv('ROCKETGIT_ITIME=' . microtime(TRUE));
2564 putenv('ROCKETGIT_HOST=' . $host);
2565 if (($push == 1) && $need_namespace_copy) {
2566 $namespace = 'rg_' . rg_id(8);
2567 rg_log('namespace is ' . $namespace);
2568 putenv('GIT_NAMESPACE=' . $namespace);
2569
2570 // Prepare refs to avoid the following message:
2571 // 'No refs in common and none specified; doing nothing.
2572 // Perhaps you should specify a branch such as 'master'.'
2573 // TODO: cannot we copy only the pushed branch?!
2574 $dst = $repo_path . '/refs/namespaces/' . $namespace . '/refs';
2575 $r = rg_copy_tree($repo_path . '/refs/heads', $dst . '/heads/', 0700);
2576 if ($r !== TRUE) {
2577 $ret['error'] = 'Internal error (cannot copy heads)';
2578 break;
2579 }
2580 $r = rg_copy_tree($repo_path . '/refs/tags',
2581 $dst . '/tags/', 0700);
2582 if ($r !== TRUE) {
2583 $ret['error'] =
2584 'Internal error (cannot copy tags)';
2585 break;
2586 }
2587 }
2588
2589 // TODO: we may want to call here the git-shell cmd and remove
2590 // it from remote.php?
2591
2592 $ret['ok'] = 1;
2593 break;
2594 }
2595
2596 rg_log_exit();
2597 rg_prof_end('repo_fetch_push_helper');
2598 return $ret;
2599 }
2600
2405 2601 ?> ?>
File inc/rights.inc.php changed (mode: 100644) (index 1f54bc7..da35d7d)
... ... function rg_rights_test($list, $needed_rights, $ip, $misc)
663 663
664 664 rg_log_enter("rights_test: needed_rights=$needed_rights ip=$ip" rg_log_enter("rights_test: needed_rights=$needed_rights ip=$ip"
665 665 . " misc=" . $misc); . " misc=" . $misc);
666 rg_log_ml('DEBUG list: ' . print_r($list, TRUE));
666 //rg_log_ml('DEBUG list: ' . print_r($list, TRUE));
667 667
668 668 $ret = FALSE; $ret = FALSE;
669 669 while (1) { while (1) {
File inc/user.inc.php changed (mode: 100644) (index a47e1c6..083d64a)
... ... function rg_user_event_rename($db, $event)
142 142 return $ret; return $ret;
143 143 } }
144 144
145 /*
146 * Empty user data
147 */
148 function rg_user_empty()
149 {
150 return array(
151 'ok' => 0,
152 'uid' => 0,
153 'is_admin' => 0,
154 'rights' => '',
155 'homepage' => '',
156 'username' => '',
157 'exists' => 0,
158 'organization' => 0,
159 'confirmed' => 0
160 );
161 }
162
145 163 /* /*
146 164 * Cosmetic function for 'user' info * Cosmetic function for 'user' info
147 165 */ */
 
... ... function rg_user_link_by_name($db, $event)
169 187 rg_log("user_link_by_name: event=" . rg_array2string($event)); rg_log("user_link_by_name: event=" . rg_array2string($event));
170 188
171 189 $by_id = rg_user_path_by_id($event['ui']['uid']); $by_id = rg_user_path_by_id($event['ui']['uid']);
172 if (!is_dir($by_id) && (mkdir($by_id, 0755, TRUE) === FALSE)) {
190 if (!is_dir($by_id) && (mkdir($by_id, 0700, TRUE) === FALSE)) {
173 191 rg_user_set_error("cannot mkdir by_id=$by_id ($php_errormsg)"); rg_user_set_error("cannot mkdir by_id=$by_id ($php_errormsg)");
174 192 return FALSE; return FALSE;
175 193 } }
176 194
177 195 $by_name = rg_user_path_by_name($event['ui']['username']); $by_name = rg_user_path_by_name($event['ui']['username']);
178 196 $by_name_parent = dirname($by_name); $by_name_parent = dirname($by_name);
179 if (!is_dir($by_name_parent) && (mkdir($by_name_parent, 0755, TRUE) === FALSE)) {
197 if (!is_dir($by_name_parent)
198 && (mkdir($by_name_parent, 0700, TRUE) === FALSE)) {
180 199 rg_user_set_error("cannot mkdir by_name_parent=$by_name_parent ($php_errmsg)"); rg_user_set_error("cannot mkdir by_name_parent=$by_name_parent ($php_errmsg)");
181 200 return FALSE; return FALSE;
182 201 } }
 
... ... function rg_user_info($db, $uid, $user, $email)
655 674 rg_prof_start("user_info"); rg_prof_start("user_info");
656 675 rg_log_enter("user_info: uid=$uid user=$user email=$email"); rg_log_enter("user_info: uid=$uid user=$user email=$email");
657 676
658 $ret = array();
659 $ret['ok'] = 0;
660 $ret['exists'] = 0;
661 $ret['uid'] = 0;
662 $ret['is_admin'] = 0;
663 $ret['rights'] = '';
664 $ret['homepage'] = '';
677 $ret = rg_user_empty();
665 678 while (1) { while (1) {
666 679 $params = array("uid" => $uid, $params = array("uid" => $uid,
667 680 "user" => $user, "user" => $user,
 
... ... function rg_user_info($db, $uid, $user, $email)
682 695
683 696 $sql = "SELECT * FROM users WHERE uid = @@uid@@"; $sql = "SELECT * FROM users WHERE uid = @@uid@@";
684 697 } else if (!empty($user)) { } else if (!empty($user)) {
685 if (rg_user_ok($user) !== TRUE)
698 if (rg_user_ok($user) !== TRUE) {
699 // cannot exists
700 $ret['ok'] = 1;
686 701 break; break;
702 }
687 703
688 704 $c = rg_cache_get("username_to_uid::" . $user); $c = rg_cache_get("username_to_uid::" . $user);
689 705 if ($c !== FALSE) { if ($c !== FALSE) {
 
... ... function rg_user_info($db, $uid, $user, $email)
701 717
702 718 $sql = "SELECT * FROM users WHERE email = @@email@@"; $sql = "SELECT * FROM users WHERE email = @@email@@";
703 719 } else { } else {
704 rg_user_set_error("invalid user");
720 $ret['ok'] = 1;
705 721 break; break;
706 722 } }
707 723
 
... ... function rg_user_login_by_sid($db, &$rg)
784 800 rg_log_enter("user_login_by_sid: sid=" . $rg['sid']); rg_log_enter("user_login_by_sid: sid=" . $rg['sid']);
785 801
786 802 // Make sure it is not passed by client // Make sure it is not passed by client
787 $rg['login_ui'] = array();
788 $rg['login_ui']['uid'] = 0;
789 $rg['login_ui']['is_admin'] = 0;
790 $rg['login_ui']['rights'] = "";
791 $rg['login_ui']['username'] = "";
792 $rg['login_ui']['organization'] = 0;
793 $rg['login_ui']['confirmed'] = 0;
803 $rg['login_ui'] = rg_user_empty();
794 804
795 805 $ret = FALSE; $ret = FALSE;
796 806 while (1) { while (1) {
 
... ... function rg_user_login_by_user_pass($db, $user, $pass, $login_token, $lock_ip,
925 935 rg_log_enter("user_login_by_user_pass: user=$user" rg_log_enter("user_login_by_user_pass: user=$user"
926 936 . " login_token=$login_token lock_ip=$lock_ip"); . " login_token=$login_token lock_ip=$lock_ip");
927 937
928 $ui = array();
929 $ui['uid'] = 0;
930 $ui['is_admin'] = 0;
931 $ui['rights'] = "";
938 $ui = rg_user_empty();
932 939
933 940 $ret = FALSE; $ret = FALSE;
934 941 while (1) { while (1) {
 
... ... function rg_user_list_to_full_info($db, $list)
1820 1827 return $ret; return $ret;
1821 1828 } }
1822 1829
1830 /*
1831 * Deals with push/fetch by HTTP(S)
1832 */
1833 function rg_user_http_git($db, $rg, $paras)
1834 {
1835 rg_prof_start('user_http_git');
1836 rg_log_enter('user_http_git');
1837
1838 rg_log('DEBUG: ct=' . $rg['ct']);
1839 if (strcasecmp($rg['ct'], 'application/x-git-upload-pack-request') == 0)
1840 $service = 'git-upload-pack';
1841 else if (strcasecmp($rg['ct'], 'application/x-git-receive-pack-request') == 0)
1842 $service = 'git-receive-pack';
1843 else
1844 $service = isset($_REQUEST['service']) ? $_REQUEST['service'] : '';
1845 rg_log('DEBUG: service=' . $service);
1846
1847 $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
1848
1849 $ret = FALSE;
1850 while (1) {
1851 if (empty($service))
1852 break;
1853
1854 $ret = TRUE;
1855
1856 set_time_limit(3600);
1857
1858 rg_log_ml('paras: ' . print_r($paras, TRUE));
1859
1860 if (count($paras) < 2) {
1861 //TODO
1862 }
1863
1864 $prefix = array_shift($paras);
1865 if (strcmp($prefix, 'user') != 0) {
1866 $user = $prefix;
1867 $prefix = '';
1868 } else {
1869 $user = array_shift($paras);
1870 }
1871 $repo = array_shift($paras);
1872 $file = implode('/', $paras);
1873 rg_log('DEBUG: file=' . $file);
1874
1875 header('Expires: Fri, 01 Jan 1980 00:00:00 GMT');
1876 header('Pragma: no-cache');
1877 header('Cache-Control: no-cache, max-age=0, must-revalidate');
1878
1879 // if user is valid, retry auth
1880 // if user is not valid, consider anonymous
1881 $authd = FALSE;
1882 $u = '';
1883 $empty_user = TRUE;
1884 $auth_ui = rg_user_empty();
1885 while (isset($_SERVER['PHP_AUTH_USER'])
1886 && isset($_SERVER['PHP_AUTH_PW'])) {
1887 $u = $_SERVER['PHP_AUTH_USER'];
1888 $p = $_SERVER['PHP_AUTH_PW'];
1889 $empty_user = FALSE;
1890 rg_log('DEBUG: HTTP auth: u=' . $u);
1891
1892 if (empty($u))
1893 break;
1894
1895 $auth_ui = rg_user_info($db, 0, $u, '');
1896 if ($auth_ui['ok'] !== 1) {
1897 rg_log('DEBUG: set errror (500): ' . rg_user_error());
1898 header('X-Rocketgit-Error: ' . rg_user_error());
1899 header($protocol . ' 500 Internal server error');
1900 break;
1901 }
1902 $authd = rg_user_login_by_user_pass($db, $u, $p,
1903 '' /*login_token*/, TRUE /*lock IP*/,
1904 $rg['login_ui']);
1905 break;
1906 }
1907
1908 $host = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
1909 $need_namespace_copy = strcmp($file, 'info/refs');
1910 $r = rg_repo_fetch_push_helper($db, $host, $rg['ip'],
1911 $rg['login_ui'], $prefix, $user, $repo, $service,
1912 $need_namespace_copy);
1913 //rg_log_ml('DEBUG: repo_fetch_push_helper: ' . print_r($r, TRUE));
1914 if ($r['ok'] !== 1) {
1915 rg_log('DEBUG: set errror: ' . $r['error']);
1916 header('X-Rocketgit-Error: ' . $r['error']);
1917
1918 if (isset($r['owner_ui'])) {
1919 if ($r['owner_ui']['ok'] != 1) {
1920 header($protocol . ' 500 Internal server error');
1921 break;
1922 }
1923
1924 if ($r['owner_ui']['exists'] != 1) {
1925 header($protocol . ' 404 Not found');
1926 break;
1927 }
1928 }
1929
1930 if (isset($r['ri'])) {
1931 if ($r['ri']['ok'] != 1) {
1932 header($protocol . ' 500 Internal server error');
1933 break;
1934 }
1935
1936 if ($r['ri']['exists'] != 1) {
1937 header($protocol . ' 404 Not found');
1938 break;
1939 }
1940 }
1941
1942 header($protocol . ' 500 Internal server error');
1943 break;
1944 }
1945 $repo_path = $r['repo_path'];
1946
1947 if ($r['allow'] !== 1) {
1948 rg_log('DEBUG: allow != 1 => 401');
1949 // Connecting user has no rights to push, not even anon.
1950 // The user be authed at this point, but may try another
1951 // user/pass combination.
1952 header($protocol . ' 401 Unauthorized status');
1953 header('WWW-Authenticate: Basic'
1954 . ' realm="Use empty user if you have no account"');
1955 break;
1956 }
1957
1958 rg_log('DEBUG: push_allowed=' . $r['push_allowed']
1959 . ' empty_user=' . ($empty_user ? 'yes' : 'no')
1960 . ' authd=' . ($authd === TRUE ? 'yes' : 'no')
1961 . ' exists=' . $auth_ui['exists']);
1962 if ($r['push_allowed'] !== 1) {
1963 // We have only anon push rights at this point.
1964 // If user is correct, but password not, we will ask
1965 // the user to try again. If user is not correct,
1966 // we will go on with anon push access.
1967 if ($empty_user
1968 || (($authd === FALSE) && ($auth_ui['exists'] == 1))) {
1969 rg_log('DEBUG: send 401');
1970 header($protocol . ' 401 Unauthorized status');
1971 header('WWW-Authenticate: Basic'
1972 . ' realm="Use empty user if you have no account"');
1973 break;
1974 }
1975 } else {
1976 rg_log('DEBUG: user has full push rights');
1977 }
1978
1979 if (strcmp($file, 'info/refs') == 0) {
1980 rg_log('DEBUG: info/refs');
1981 // TODO: we should allow this only if the connecting user has
1982 // fetch rights!
1983 header('Content-Type: application/x-'
1984 . $service . '-advertisement');
1985
1986 echo rg_git_pack('# service=' . $service . "\n");
1987 echo rg_git_flush();
1988
1989 $run = '/usr/libexec/git-core/' . $service
1990 . ' --stateless-rpc --advertise-refs'
1991 . ' ' . escapeshellarg($repo_path);
1992 $e = rg_exec($run, '', 'rg_echo', 'rg_git_band_2');
1993 if ($e['code'] != 0)
1994 rg_log('Error executing command: ' . $e['errmsg']);
1995 } else if (strcasecmp($rg['ct'], 'application/x-git-upload-pack-request') == 0) {
1996 rg_log('DEBUG: git-upload-pack...');
1997
1998 header('Content-Type: application/x-git-upload-pack-result');
1999
2000 // TODO: seems I cannot do this here -
2001 // seems remote receive-pack expects ACK/NAK first:
2002 // fatal: git fetch_pack: expected ACK/NAK, got '...
2003 /*
2004 rg_git_info_pack("\x02", '== Welcome to RocketGit! ==');
2005 rg_git_info_pack("\x02", 'you are connecting from IP '
2006 . $rg['ip'] . '.');
2007 // If user does not correct to the correct URL, correct them
2008 if (!empty($host) && (strcasecmp($host, $rg['rg_http_host_no_port']) != 0))
2009 rg_git_info_pack("\x02", 'Please use ' . $rg['rg_http_host_no_port']
2010 . ' instead of ' . $host . '.');
2011 putenv('ROCKETGIT_SHOW_INFO=0');
2012 */
2013
2014 $run = '/usr/libexec/git-core/git-upload-pack'
2015 . ' --stateless-rpc'
2016 . ' ' . escapeshellarg($repo_path);
2017
2018 $data_in = @file_get_contents('php://input');
2019 $e = rg_exec($run, $data_in, 'rg_echo', 'rg_git_band_2');
2020 if ($e['code'] != 0)
2021 rg_log('Error executing command: ' . $e['errmsg']);
2022 } else if (strcasecmp($rg['ct'], 'application/x-git-receive-pack-request') == 0) {
2023 rg_log('DEBUG: git-receive-pack...');
2024
2025 header('Content-Type: application/x-git-receive-pack-result');
2026
2027 rg_git_info_pack("\x02", '== Welcome to RocketGit! ==');
2028 rg_git_info_pack("\x02", 'you are connecting from IP '
2029 . $rg['ip'] . '.');
2030 // If user does not correct to the correct URL, correct them
2031 if (!empty($host) && (strcasecmp($host, $rg['rg_http_host_no_port']) != 0))
2032 rg_git_info_pack("\x02", 'Please use ' . $rg['rg_http_host_no_port']
2033 . ' instead of ' . $host . '.');
2034 putenv('ROCKETGIT_SHOW_INFO=0');
2035
2036 $run = '/usr/libexec/git-core/git-receive-pack'
2037 . ' --stateless-rpc'
2038 . ' ' . escapeshellarg($repo_path);
2039
2040 $data_in = @file_get_contents('php://input');
2041 //rg_log('DEBUG: data_in=' . $data_in);
2042 file_put_contents('/tmp/data_in', $data_in);
2043 $e = rg_exec($run, $data_in, 'rg_echo', 'rg_echo');
2044 if ($e['code'] != 0)
2045 rg_log('Error executing command: ' . $e['errmsg']);
2046 } else {
2047 rg_log('Unknown service!');
2048 }
2049
2050 break;
2051 }
2052
2053 rg_log_exit();
2054 rg_prof_end('user_http_git');
2055 return $ret;
2056 }
2057
1823 2058 ?> ?>
File inc/util.inc.php changed (mode: 100644) (index 4689c32..dc9b8cf)
... ... function rg_lock($file)
127 127
128 128 $f = @fopen($rg_lock_dir . "/" . $file, "w"); $f = @fopen($rg_lock_dir . "/" . $file, "w");
129 129 if ($f === FALSE) { if ($f === FALSE) {
130 rg_internal_error("Cannot open lock $file ($php_errormsg).");
130 rg_internal_error('Cannot open lock [' . $rg_lock_dir
131 . '/' . $file . '] (' . $php_errormsg . ').');
131 132 return FALSE; return FALSE;
132 133 } }
133 134
 
... ... function rg_re_url($area)
189 190
190 191 function rg_re_userpage($ui) function rg_re_userpage($ui)
191 192 { {
193 if (isset($ui['uid']) && ($ui['uid'] == 0))
194 return '';
195
192 196 if (!isset($ui['organization'])) { if (!isset($ui['organization'])) {
193 197 rg_internal_error("rg_re_userpage called with wrong ui (no org)!"); rg_internal_error("rg_re_userpage called with wrong ui (no org)!");
194 198 rg_log("ui: " . print_r($ui, TRUE)); rg_log("ui: " . print_r($ui, TRUE));
 
... ... function rg_re_repo_git($organization, $user, $repo)
276 280 . $prefix . "/" . rawurlencode($user) . "/" . rawurlencode($repo); . $prefix . "/" . rawurlencode($user) . "/" . rawurlencode($repo);
277 281 } }
278 282
283 function rg_re_repo_http($organization, $user, $repo)
284 {
285 $prefix = '';
286 if ($organization == 0)
287 $prefix = '/user';
288
289 return rg_base_url() . $prefix . "/"
290 . rawurlencode($user) . "/" . rawurlencode($repo);
291 }
292
279 293 function rg_var_get($name) function rg_var_get($name)
280 294 { {
281 295 if (isset($_SERVER[$name])) if (isset($_SERVER[$name]))
 
... ... function rg_var_a2s($var)
386 400 */ */
387 401 function rg_chars_allow($name, $allowed_regexp, &$invalid) function rg_chars_allow($name, $allowed_regexp, &$invalid)
388 402 { {
389 if (preg_match('/^[' . $allowed_regexp . ']*$/uUD', $name) !== 1) {
403 // Modifiers: u = UTF8, D = PCRE_DOLLAR_ENDONLY
404 // http://php.net/manual/en/reference.pcre.pattern.modifiers.php
405 if (preg_match('/^[' . $allowed_regexp . ']*$/uD', $name) !== 1) {
390 406 $invalid = preg_replace('/[' . $allowed_regexp . ']/', '', $name); $invalid = preg_replace('/[' . $allowed_regexp . ']/', '', $name);
391 407 rg_log("chars_allow: [$name] does not match [$allowed_regexp]"); rg_log("chars_allow: [$name] does not match [$allowed_regexp]");
392 408 return FALSE; return FALSE;
 
... ... function rg_ok($msg)
966 982 */ */
967 983 function rg_exec($cmd, $input, $cb_stdout, $cb_stderr) function rg_exec($cmd, $input, $cb_stdout, $cb_stderr)
968 984 { {
969 rg_prof_start("exec");
970 rg_log_enter("Executing [$cmd]...");
985 rg_prof_start('exec');
986 rg_log_enter('Executing [' . $cmd . ']');
971 987
972 988 $ret = array(); $ret = array();
973 989 $ret['ok'] = 0; $ret['ok'] = 0;
974 $ret['errmsg'] = "";
990 $ret['errmsg'] = '';
975 991 $ret['code'] = 65000; // fake code $ret['code'] = 65000; // fake code
992 $ret['data'] = '';
993 $ret['stderr'] = '';
976 994 while (1) { while (1) {
977 995 $desc = array( $desc = array(
978 996 0 => array("pipe", "r"), 0 => array("pipe", "r"),
 
... ... function rg_exec($cmd, $input, $cb_stdout, $cb_stderr)
989 1007
990 1008 //rg_log_ml('DEBUG: proc_open pipes: ' . print_r($pipes, TRUE)); //rg_log_ml('DEBUG: proc_open pipes: ' . print_r($pipes, TRUE));
991 1009
992 $stderr = "";
993 $ret['data'] = "";
994 1010 $rx = array($pipes[1], $pipes[2]); $rx = array($pipes[1], $pipes[2]);
995 1011 $wx = array(); $wx = array();
996 1012 if (!empty($input)) if (!empty($input))
 
... ... function rg_exec($cmd, $input, $cb_stdout, $cb_stderr)
1014 1030
1015 1031 //rg_log('DEBUG: write event on fd ' . $fd . '!'); //rg_log('DEBUG: write event on fd ' . $fd . '!');
1016 1032
1017 //rg_log('DEBUG: Writing [' . $input . ']...');
1033 //rg_log('DEBUG: Writing to fd ' . $fd
1034 // . ' [' . $input . ']...');
1018 1035 $r = @fwrite($fd, $input); $r = @fwrite($fd, $input);
1019 1036 if ($r === FALSE) { if ($r === FALSE) {
1020 1037 $ret['ermsg'] = 'cannot write'; $ret['ermsg'] = 'cannot write';
 
... ... function rg_exec($cmd, $input, $cb_stdout, $cb_stderr)
1048 1065 continue; continue;
1049 1066 } }
1050 1067
1051 rg_log('DEBUG: got data from fd ' . $fd
1052 . ': ' . $_d);
1053 1068 if ($fd === $pipes[2]) { if ($fd === $pipes[2]) {
1054 1069 if ($cb_stderr === FALSE) { if ($cb_stderr === FALSE) {
1055 rg_log('DEBUG: fd is pipes[2], append to stderr var');
1056 $stderr .= $_d;
1070 //rg_log('DEBUG: fd is pipes[2], append to stderr var: ' . $_d);
1071 $ret['stderr'] .= $_d;
1057 1072 } else { } else {
1058 rg_log('DEBUG: fd is pipes[2], call stdout cb');
1059 cb_stderr($_d);
1073 //rg_log('DEBUG: fd is pipes[2], call stdout cb:' . $_d);
1074 $cb_stderr($_d);
1060 1075 } }
1061 1076 } else if ($fd === $pipes[1]) { } else if ($fd === $pipes[1]) {
1062 1077 if ($cb_stdout === FALSE) { if ($cb_stdout === FALSE) {
1063 rg_log('Stream data to stdout using echo.');
1078 //rg_log('DEBUG: fd is pipes[1], append to stdout var: ' . $_d);
1064 1079 $ret['data'] .= $_d; $ret['data'] .= $_d;
1065 1080 } else { } else {
1066 rg_log('DEBUG: fd is pipes[1], call stdout cb');
1067 cb_stdout($_d);
1081 //rg_log('DEBUG: fd is pipes[1], call stdout cb: ' . $_d);
1082 $cb_stdout($_d);
1068 1083 } }
1084 } else {
1085 rg_internal_error('invalid fd');
1069 1086 } }
1070 1087 } }
1071 1088
1072 1089 if (!empty($ret['errmsg'])) if (!empty($ret['errmsg']))
1073 1090 break; break;
1074 1091 } }
1075 $stderr = trim($stderr);
1092 $ret['stderr'] = trim($ret['stderr']);
1076 1093 $ret['data'] = trim($ret['data']); $ret['data'] = trim($ret['data']);
1077 1094
1078 1095 for ($i = 0; $i < 3; $i++) for ($i = 0; $i < 3; $i++)
 
... ... function rg_exec($cmd, $input, $cb_stdout, $cb_stderr)
1081 1098
1082 1099 $err = proc_close($a); $err = proc_close($a);
1083 1100 if ($err != 0) { if ($err != 0) {
1101 rg_log('DEBUG: exec returned ' . $err);
1084 1102 $ret['code'] = $err; $ret['code'] = $err;
1085 $ret['errmsg'] = "code " . $err . ": " . $stderr;
1086 }
1087
1088 if (empty($ret['errmsg'])) {
1089 $ret['code'] = 0;
1090 $ret['ok'] = 1;
1103 $ret['errmsg'] = 'task returned code ' . $err
1104 . ' (' . $ret['stderr'] . ')';
1105 break;
1091 1106 } }
1092 1107
1108 //rg_log('DEBUG: exec returned ok');
1109 $ret['code'] = 0;
1110 $ret['ok'] = 1;
1093 1111 break; break;
1094 1112 } }
1095 1113
 
... ... function rg_copy_tree($src, $dst, $mask)
1230 1248 global $php_errormsg; global $php_errormsg;
1231 1249
1232 1250 rg_prof_start("copy_tree"); rg_prof_start("copy_tree");
1233 rg_log_enter("copy_tree($src, $dst, $mask)");
1251 rg_log_enter("copy_tree($src, $dst, mask=$mask)");
1234 1252
1235 1253 $ret = FALSE; $ret = FALSE;
1236 1254 while (1) { while (1) {
 
... ... function rg_socket($path, $buf, $timeout, $tries, $flags)
1555 1573 break; break;
1556 1574 } }
1557 1575 if ($r === FALSE) { if ($r === FALSE) {
1558 rg_log("Could not connect the socket (" . socket_strerror(socket_last_error()) . ")!");
1576 rg_log('Could not connect the socket [' . $path . ']'
1577 . '(' . socket_strerror(socket_last_error()) . ')!');
1559 1578 break; break;
1560 1579 } }
1561 1580 rg_prof_end('socket-connect'); rg_prof_end('socket-connect');
 
... ... function rg_force_alphanum($s)
1736 1755 return preg_replace('/[^A-Za-z0-9_]/', '', $s); return preg_replace('/[^A-Za-z0-9_]/', '', $s);
1737 1756 } }
1738 1757
1758 /*
1759 * Dummy function to be used in rg_exec callback
1760 */
1761 function rg_echo($s)
1762 {
1763 echo $s;
1764 }
1765
1739 1766 ?> ?>
File inc/wh/build.inc.php changed (mode: 100644) (index decb485..8f4c9b7)
... ... function rg_wh_build_job_done($db, $ev)
40 40
41 41 $out .= "\n\n" . 'Command[' $out .= "\n\n" . 'Command['
42 42 . $ev['job']['cmds'][$index]['cmd'] . ']: ' . $ev['job']['cmds'][$index]['cmd'] . ']: '
43 . "\n" . $i['log'];
43 . "\n" . trim($i['log']);
44 44 } }
45 45
46 46 rg_wh_set_last_output($db, $ev['ui']['uid'], rg_wh_set_last_output($db, $ev['ui']['uid'],
 
... ... function rg_wh_build_send_one($db, $event)
74 74 $a['hook_id'] = $wh['id']; $a['hook_id'] = $wh['id'];
75 75 $a['uid'] = $event['ui']['uid']; $a['uid'] = $event['ui']['uid'];
76 76 $a['flags'] = $wh['flags']; $a['flags'] = $wh['flags'];
77 $a['url'] = $event['ri']['clone_url'];
77 $a['url'] = $event['ri']['clone_url_ssh'];
78 78 $a['head'] = $event['new_rev']; $a['head'] = $event['new_rev'];
79 79 $a['env'] = $event['env']; $a['env'] = $event['env'];
80 80 $a['packages'] = $event['packages']; $a['packages'] = $event['packages'];
 
... ... function rg_wh_build_default_paras(&$rg)
333 333
334 334 $rg_wh_plugins['build'] = array( $rg_wh_plugins['build'] = array(
335 335 'htype' => 'build', 'htype' => 'build',
336 'description' => 'Clone, builds and test',
336 'description' => 'Clones, builds and tests (Continuous Integration)',
337 337 'cosmetic' => 'rg_wh_build_cosmetic', 'cosmetic' => 'rg_wh_build_cosmetic',
338 338 'fill_vars' => 'rg_wh_build_fill_vars', 'fill_vars' => 'rg_wh_build_fill_vars',
339 339 'validate_vars' => 'rg_wh_build_validate_vars', 'validate_vars' => 'rg_wh_build_validate_vars',
File rocketgit.spec.in changed (mode: 100644) (index 8486d6d..e60363b)
... ... Source: http://kernel.embedromix.ro/us/rocketgit/%{name}-%{version}.tar.gz
13 13 URL: https://rocketgit.com/ URL: https://rocketgit.com/
14 14 BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
15 15 BuildArch: noarch BuildArch: noarch
16 Requires: httpd, mod_ssl, php, php-cli, php-pgsql, xinetd
16 Requires: httpd, mod_ssl, php-fpm, php-cli, php-pgsql, xinetd
17 17 Requires: git, cronie, postgresql-server Requires: git, cronie, postgresql-server
18 18 Requires: util-linux Requires: util-linux
19 19 # SELinux stuff # SELinux stuff
 
... ... rm -rf ${RPM_BUILD_ROOT}
81 81 %defattr (-,root,root,0755) %defattr (-,root,root,0755)
82 82 %dir @USR_SHARE@/@PRJ@ %dir @USR_SHARE@/@PRJ@
83 83 %doc README LICENSE Changelog TODO selinux/@PRJ@.* %doc README LICENSE Changelog TODO selinux/@PRJ@.*
84 %dir @ETC@/@PRJ@
84 %attr(0700,rocketgit,rocketgit) %dir @ETC@/@PRJ@
85 85 @ETC@/@PRJ@/config.php.sample @ETC@/@PRJ@/config.php.sample
86 86 @ETC@/logrotate.d/rocketgit @ETC@/logrotate.d/rocketgit
87 87 %config(noreplace) @ETC@/@PRJ@/config.php %config(noreplace) @ETC@/@PRJ@/config.php
88 %config(noreplace) @ETC@/@PRJ@/php-fpm.conf
89 %config(noreplace) @ETC@/@PRJ@/pool.conf
88 90 %config(noreplace) @ETC@/cron.d/rocketgit %config(noreplace) @ETC@/cron.d/rocketgit
89 91 %config(noreplace) @ETC@/xinetd.d/rocketgit %config(noreplace) @ETC@/xinetd.d/rocketgit
90 92 %config(noreplace) @ETC@/httpd/conf.d/rocketgit.conf %config(noreplace) @ETC@/httpd/conf.d/rocketgit.conf
91 %attr(0755,rocketgit,rocketgit) %dir @VAR_LOG@/@PRJ@
92 %attr(0755,apache,apache) %dir @VAR_LOG@/@PRJ@-web
93 %attr(0700,rocketgit,rocketgit) %dir @VAR_LOG@/@PRJ@
93 94 %attr(0755,root,root) %dir @VAR_LIB@/@PRJ@ %attr(0755,root,root) %dir @VAR_LIB@/@PRJ@
94 %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/locks
95 %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/repos
96 %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/q_merge_requests
97 %attr(0755,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/sockets
95 %attr(0700,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/locks
96 %attr(0700,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/repos
97 %attr(0700,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/q_merge_requests
98 %attr(0700,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/sockets
98 99 %attr(0700,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/tmp %attr(0700,rocketgit,rocketgit) %dir @VAR_LIB@/@PRJ@/tmp
99 100 %attr(0700,root,root) %dir @VAR_LIB@/@PRJ@/worker %attr(0700,root,root) %dir @VAR_LIB@/@PRJ@/worker
100 101 %attr(0700,root,root) @USR_SBIN@/* %attr(0700,root,root) @USR_SBIN@/*
101 102 @USR_SHARE@/@PRJ@/* @USR_SHARE@/@PRJ@/*
102 103 @USR_SHARE@/selinux/*/@PRJ@.pp @USR_SHARE@/selinux/*/@PRJ@.pp
104 @USR@/lib/systemd/system/*
103 105
104 106 %changelog %changelog
105 107 * Wed Oct 17 2012 Catalin(ux) M. BOIE <catab at embedromix dot ro> 0.10 * Wed Oct 17 2012 Catalin(ux) M. BOIE <catab at embedromix dot ro> 0.10
File root/index.php changed (mode: 100644) (index d59feb4..76863ed)
... ... include_once($INC . "/ver.php");
30 30
31 31 rg_prof_start("MAIN"); rg_prof_start("MAIN");
32 32
33 rg_log_set_file($rg_web_log_dir . "/main.log");
33 rg_log_set_file($rg_log_dir . "/web.log");
34 34
35 35 // database connection // database connection
36 36 rg_sql_app("rg-web"); rg_sql_app("rg-web");
 
... ... $rg['rg_account_allow_creation'] = $rg_account_allow_creation;
50 50 $THEME_URL = "/themes/" . $rg_theme; $THEME_URL = "/themes/" . $rg_theme;
51 51 $rg['rg_redirect_html'] = 0; $rg['rg_redirect_html'] = 0;
52 52 $rg['rg_theme_url'] = $THEME_URL; $rg['rg_theme_url'] = $THEME_URL;
53 $rg['login_ui'] = array();
53 $rg['login_ui'] = rg_user_empty();
54 54 $rg['target_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0); $rg['target_ui'] = array("ok" => 1, "exists" => 0, "uid" => 0);
55 55 $rg['ri'] = array("repo_id" => 0, "uid" => 0); $rg['ri'] = array("repo_id" => 0, "uid" => 0);
56 56 $rg['bug'] = array("bug_id" => 0); $rg['bug'] = array("bug_id" => 0);
 
... ... rg_log("DEBUG: _REQUEST: " . rg_array2string($req));
93 93 rg_log("DEBUG: _COOKIE: " . rg_array2string($_COOKIE)); rg_log("DEBUG: _COOKIE: " . rg_array2string($_COOKIE));
94 94 rg_log($rg['ip'] . " ver=$rocketgit_version"); rg_log($rg['ip'] . " ver=$rocketgit_version");
95 95
96 $service = isset($_REQUEST['service']) ? $_REQUEST['service'] : "";
97 rg_log("service=$service");
96 // Try to detect if we cloning by http(s)
97 rg_log_ml('_SERVER: ' . print_r($_SERVER, TRUE));
98 $rg['ct'] = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '';
98 99
99 100
100 101 $good = 0; $good = 0;
 
... ... if ($good == 0) {
122 123 exit(0); exit(0);
123 124 } }
124 125
125 if (0 && strcmp($service, "git-upload-packXXX") == 0) {
126 rg_log("We have a fetch by http!");
127 // TODO: settimelimit to a resonable value
128 putenv("GIT_HTTP_EXPORT_ALL=1");
129 $run = "/usr/libexec/git-core/git-http-backend";
130 rg_log("Running $run...");
131 passthru($run, $ret);
132 rg_log("returned $ret");
126 // Is it a http push/fetch?
127 $r = rg_user_http_git($db, $rg, $paras);
128 if ($r === TRUE) {
129 rg_prof_end("MAIN");
130 rg_prof_log();
133 131 exit(0); exit(0);
134 132 } }
135 133
 
... ... if ($r === FALSE) {
220 218 if ($rg['login_ui']['uid'] > 0) { if ($rg['login_ui']['uid'] > 0) {
221 219 $rg['logout_token'] = rg_token_get($db, $rg, 'logout'); $rg['logout_token'] = rg_token_get($db, $rg, 'logout');
222 220 } else { } else {
223 $rg['login_ui']['username'] = '';
224 221 $rg['logout_token'] = ''; $rg['logout_token'] = '';
225 222 } }
226 223
 
... ... if ($rg['login_ui']['uid'] > 0) {
228 225 $rg['HTML:rg_body'] = $body; $rg['HTML:rg_body'] = $body;
229 226 $_c = rg_template("index.html", $rg, TRUE /* xss */); $_c = rg_template("index.html", $rg, TRUE /* xss */);
230 227
228 // TODO: really?!
231 229 header('Cache-Control: private, no-cache'); header('Cache-Control: private, no-cache');
232 230
233 231 // Caching // Caching
File root/themes/default/hints/repo/clone_git.html changed (mode: 100644) (index 5acd961..e6f6040)
1 1 <br /> <br />
2 2 Clone this repository using git:<br /> Clone this repository using git:<br />
3 3 <div class="xcode"> <div class="xcode">
4 git clone @@git@@ local_dir<br />
4 git clone @@ri::clone_url_git@@ local_dir<br />
5 5 cd local_dir<br /> cd local_dir<br />
6 6 </div> </div>
File root/themes/default/hints/repo/clone_owner.html changed (mode: 100644) (index 8ba93af..8d5e790)
... ... If you have the project locally, but not versioned with Git:<br />
3 3 <div class="xcode"> <div class="xcode">
4 4 cd local_project_dir<br /> cd local_project_dir<br />
5 5 git init<br /> git init<br />
6 git remote add origin @@ssh@@<br />
6 git remote add origin @@ri::clone_url_ssh@@<br />
7 7 # commit something<br /> # commit something<br />
8 8 git push origin --all<br /> git push origin --all<br />
9 9 git push origin --tags<br /> git push origin --tags<br />
 
... ... git push origin --tags<br />
13 13 If you are switching from another Git hosting provider:<br /> If you are switching from another Git hosting provider:<br />
14 14 <div class="xcode"> <div class="xcode">
15 15 cd local_project_dir<br /> cd local_project_dir<br />
16 git remote change origin @@ssh@@<br />
16 git remote change origin @@ri::clone_url_ssh@@<br />
17 17 git push origin --all<br /> git push origin --all<br />
18 18 git push origin --tags<br /> git push origin --tags<br />
19 19 </div> </div>
 
... ... git push origin --tags<br />
21 21
22 22 If you do not have the project locally, and want to clone it:<br /> If you do not have the project locally, and want to clone it:<br />
23 23 <div class="xcode"> <div class="xcode">
24 git clone @@ssh@@ local_project_dir<br />
24 git clone @@ri::clone_url_ssh@@ local_project_dir<br />
25 25 cd local_project_dir cd local_project_dir
26 26 </div> </div>
File root/themes/default/hints/repo/clone_ssh.html changed (mode: 100644) (index a6b4ab2..12cfec8)
1 1 <br /> <br />
2 2 Clone this repository using ssh (do not forget to upload a key first):<br /> Clone this repository using ssh (do not forget to upload a key first):<br />
3 3 <div class="xcode"> <div class="xcode">
4 git clone @@ssh@@ local_dir<br />
4 git clone @@ri::clone_url_ssh@@ local_dir<br />
5 5 cd local_dir<br /> cd local_dir<br />
6 6 </div> </div>
File samples/config.php changed (mode: 100644) (index 5b85335..73b0a8a)
... ... $rg_keys_file = $rg_base . "/.ssh/authorized_keys";
18 18 $rg_scripts = "/usr/share/rocketgit"; $rg_scripts = "/usr/share/rocketgit";
19 19
20 20 // Allowed repo names (regular expression) // Allowed repo names (regular expression)
21 $rg_repo_allow = '\pL\pN\pP';
21 // M = Mark, L = Letter, N = Number
22 $rg_repo_allow = '-\p{L}\p{N}._+=*&';
22 23
23 24 // Allowed repo name length // Allowed repo name length
24 25 $rg_repo_min_len = 2; $rg_repo_min_len = 2;
25 26 $rg_repo_max_len = 64; $rg_repo_max_len = 64;
26 27
27 28 // Allowed user names (negated regular expression) // Allowed user names (negated regular expression)
28 $rg_user_allow = '\pL\pN\pP';
29 $rg_user_allow = '-\p{L}\p{N}._+=*&';
29 30
30 31 // Allowed user name length // Allowed user name length
31 32 $rg_user_min_len = 3; $rg_user_min_len = 3;
 
... ... $rg_account_email_confirm = 1;
48 49 // Maximum number of keys per user // Maximum number of keys per user
49 50 $rg_max_ssh_keys = 10; $rg_max_ssh_keys = 10;
50 51
51 // log dirs
52 // log dir
52 53 $rg_log_dir = "/var/log/rocketgit"; $rg_log_dir = "/var/log/rocketgit";
53 $rg_web_log_dir = "/var/log/rocketgit-web";
54 54
55 55 // state dir // state dir
56 56 $rg_state_dir = "/var/lib/rocketgit"; $rg_state_dir = "/var/lib/rocketgit";
 
... ... $rg_git_port = 9418;
82 82
83 83 // HTTP(S) host name and port (some scripts could not detect this) // HTTP(S) host name and port (some scripts could not detect this)
84 84 // Format: http[s]://host_name[:port] // Format: http[s]://host_name[:port]
85 // No '/' in the end
85 // No '/' in the end.
86 86 $rg_web_url = ''; $rg_web_url = '';
87 87
88 // How many days to keep the log files? Put 0 to not delete it.
88 // How many days to keep the log files? Put 0 to not delete them.
89 89 $rg_logs_lifetime = 31; $rg_logs_lifetime = 31;
90 90
91 91 // addr/port to bind/listen for build workers // addr/port to bind/listen for build workers
File samples/cron changed (mode: 100644) (index 1a51bc0..36ed0d0)
1 * * * * * apache /usr/share/rocketgit/scripts/cron.sh apache
2
3 * * * * * rocketgit /usr/share/rocketgit/scripts/cron.sh rocketgit
1 * * * * * rocketgit /usr/share/rocketgit/scripts/cron.sh
4 2 * * * * * rocketgit /usr/share/rocketgit/scripts/events.sh * * * * * rocketgit /usr/share/rocketgit/scripts/events.sh
5 3 * * * * * rocketgit /usr/share/rocketgit/scripts/cache.sh * * * * * rocketgit /usr/share/rocketgit/scripts/cache.sh
6 4
File samples/php-fpm.conf added (mode: 100644) (index 0000000..9b95e2e)
1 ;;;;;;;;;;;;;;;;;;;;;
2 ; FPM Configuration ;
3 ;;;;;;;;;;;;;;;;;;;;;
4
5 ; All relative paths in this configuration file are relative to PHP's install
6 ; prefix.
7
8 ; Include one or more files. If glob(3) exists, it is used to include a bunch of
9 ; files from a glob(3) pattern. This directive can be used everywhere in the
10 ; file.
11 include=/etc/rocketgit/pool.conf
12
13 ;;;;;;;;;;;;;;;;;;
14 ; Global Options ;
15 ;;;;;;;;;;;;;;;;;;
16
17 [global]
18 ; Pid file
19 ; Default Value: none
20 pid = /run/php-fpm/rocketgit.pid
21
22 ; Error log file
23 ; If it's set to "syslog", log is sent to syslogd instead of being written
24 ; in a local file.
25 ; Default Value: /var/log/php-fpm.log
26 error_log = /var/log/php-fpm/rocketgit.log
27
28 ; syslog_facility is used to specify what type of program is logging the
29 ; message. This lets syslogd specify that messages from different facilities
30 ; will be handled differently.
31 ; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON)
32 ; Default Value: daemon
33 ;syslog.facility = daemon
34
35 ; syslog_ident is prepended to every message. If you have multiple FPM
36 ; instances running on the same server, you can change the default value
37 ; which must suit common needs.
38 ; Default Value: php-fpm
39 ;syslog.ident = php-fpm
40
41 ; Log level
42 ; Possible Values: alert, error, warning, notice, debug
43 ; Default Value: notice
44 ;log_level = notice
45
46 ; If this number of child processes exit with SIGSEGV or SIGBUS within the time
47 ; interval set by emergency_restart_interval then FPM will restart. A value
48 ; of '0' means 'Off'.
49 ; Default Value: 0
50 ;emergency_restart_threshold = 0
51
52 ; Interval of time used by emergency_restart_interval to determine when
53 ; a graceful restart will be initiated. This can be useful to work around
54 ; accidental corruptions in an accelerator's shared memory.
55 ; Available Units: s(econds), m(inutes), h(ours), or d(ays)
56 ; Default Unit: seconds
57 ; Default Value: 0
58 ;emergency_restart_interval = 0
59
60 ; Time limit for child processes to wait for a reaction on signals from master.
61 ; Available units: s(econds), m(inutes), h(ours), or d(ays)
62 ; Default Unit: seconds
63 ; Default Value: 0
64 ;process_control_timeout = 0
65
66 ; The maximum number of processes FPM will fork. This has been design to control
67 ; the global number of processes when using dynamic PM within a lot of pools.
68 ; Use it with caution.
69 ; Note: A value of 0 indicates no limit
70 ; Default Value: 0
71 ;process.max = 128
72
73 ; Specify the nice(2) priority to apply to the master process (only if set)
74 ; The value can vary from -19 (highest priority) to 20 (lower priority)
75 ; Note: - It will only work if the FPM master process is launched as root
76 ; - The pool process will inherit the master process priority
77 ; unless it specified otherwise
78 ; Default Value: no set
79 ;process.priority = -19
80
81 ; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
82 ; Default Value: yes
83 daemonize = no
84
85 ; Set open file descriptor rlimit for the master process.
86 ; Default Value: system defined value
87 ;rlimit_files = 1024
88
89 ; Set max core size rlimit for the master process.
90 ; Possible Values: 'unlimited' or an integer greater or equal to 0
91 ; Default Value: system defined value
92 ;rlimit_core = 0
93
94 ; Specify the event mechanism FPM will use. The following is available:
95 ; - select (any POSIX os)
96 ; - poll (any POSIX os)
97 ; - epoll (linux >= 2.5.44)
98 ; Default Value: not set (auto detection)
99 ;events.mechanism = epoll
100
101 ; When FPM is build with systemd integration, specify the interval,
102 ; in second, between health report notification to systemd.
103 ; Set to 0 to disable.
104 ; Available Units: s(econds), m(inutes), h(ours)
105 ; Default Unit: seconds
106 ; Default value: 10
107 ;systemd_interval = 10
File samples/pool.conf added (mode: 100644) (index 0000000..b3bb360)
1 ; Start a new pool named 'rocketgit'.
2 ; the variable $pool can we used in any directive and will be replaced by the
3 ; pool name ('rocketgit' here)
4 [rocketgit]
5
6 ; Per pool prefix
7 ; It only applies on the following directives:
8 ; - 'slowlog'
9 ; - 'listen' (unixsocket)
10 ; - 'chroot'
11 ; - 'chdir'
12 ; - 'php_values'
13 ; - 'php_admin_values'
14 ; When not set, the global prefix (or @php_fpm_prefix@) applies instead.
15 ; Note: This directive can also be relative to the global prefix.
16 ; Default Value: none
17 ;prefix = /path/to/pools/$pool
18
19 ; Unix user/group of processes
20 ; Note: The user is mandatory. If the group is not set, the default user's group
21 ; will be used.
22 ; RPM: apache Choosed to be able to access some dir as httpd
23 user = rocketgit
24 ; RPM: Keep a group allowed to write in log dir.
25 group = rocketgit
26
27 ; The address on which to accept FastCGI requests.
28 ; Valid syntaxes are:
29 ; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on
30 ; a specific port;
31 ; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
32 ; a specific port;
33 ; 'port' - to listen on a TCP socket to all IPv4 addresses on a
34 ; specific port;
35 ; '[::]:port' - to listen on a TCP socket to all addresses
36 ; (IPv6 and IPv4-mapped) on a specific port;
37 ; '/path/to/unix/socket' - to listen on a unix socket.
38 ; Note: This value is mandatory.
39 listen = /run/php-fpm/rocketgit.sock
40
41 ; Set listen(2) backlog.
42 ; Default Value: 65535
43 ;listen.backlog = 65535
44
45 ; Set permissions for unix socket, if one is used. In Linux, read/write
46 ; permissions must be set in order to allow connections from a web server.
47 ; Default Values: user and group are set as the running user
48 ; mode is set to 0660
49 ;listen.owner = nobody
50 ;listen.group = nobody
51 ;listen.mode = 0660
52
53 ; When POSIX Access Control Lists are supported you can set them using
54 ; these options, value is a comma separated list of user/group names.
55 ; When set, listen.owner and listen.group are ignored
56 listen.acl_users = apache,nginx
57 ;listen.acl_groups =
58
59 ; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect.
60 ; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
61 ; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
62 ; must be separated by a comma. If this value is left blank, connections will be
63 ; accepted from any ip address.
64 ; Default Value: any
65 listen.allowed_clients = 127.0.0.1
66
67 ; Specify the nice(2) priority to apply to the pool processes (only if set)
68 ; The value can vary from -19 (highest priority) to 20 (lower priority)
69 ; Note: - It will only work if the FPM master process is launched as root
70 ; - The pool processes will inherit the master process priority
71 ; unless it specified otherwise
72 ; Default Value: no set
73 ; process.priority = -19
74
75 ; Choose how the process manager will control the number of child processes.
76 ; Possible Values:
77 ; static - a fixed number (pm.max_children) of child processes;
78 ; dynamic - the number of child processes are set dynamically based on the
79 ; following directives. With this process management, there will be
80 ; always at least 1 children.
81 ; pm.max_children - the maximum number of children that can
82 ; be alive at the same time.
83 ; pm.start_servers - the number of children created on startup.
84 ; pm.min_spare_servers - the minimum number of children in 'idle'
85 ; state (waiting to process). If the number
86 ; of 'idle' processes is less than this
87 ; number then some children will be created.
88 ; pm.max_spare_servers - the maximum number of children in 'idle'
89 ; state (waiting to process). If the number
90 ; of 'idle' processes is greater than this
91 ; number then some children will be killed.
92 ; ondemand - no children are created at startup. Children will be forked when
93 ; new requests will connect. The following parameter are used:
94 ; pm.max_children - the maximum number of children that
95 ; can be alive at the same time.
96 ; pm.process_idle_timeout - The number of seconds after which
97 ; an idle process will be killed.
98 ; Note: This value is mandatory.
99 pm = dynamic
100
101 ; The number of child processes to be created when pm is set to 'static' and the
102 ; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
103 ; This value sets the limit on the number of simultaneous requests that will be
104 ; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
105 ; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
106 ; CGI. The below defaults are based on a server without much resources. Don't
107 ; forget to tweak pm.* to fit your needs.
108 ; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
109 ; Note: This value is mandatory.
110 pm.max_children = 50
111
112 ; The number of child processes created on startup.
113 ; Note: Used only when pm is set to 'dynamic'
114 ; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
115 pm.start_servers = 5
116
117 ; The desired minimum number of idle server processes.
118 ; Note: Used only when pm is set to 'dynamic'
119 ; Note: Mandatory when pm is set to 'dynamic'
120 pm.min_spare_servers = 5
121
122 ; The desired maximum number of idle server processes.
123 ; Note: Used only when pm is set to 'dynamic'
124 ; Note: Mandatory when pm is set to 'dynamic'
125 pm.max_spare_servers = 10
126
127 ; The number of seconds after which an idle process will be killed.
128 ; Note: Used only when pm is set to 'ondemand'
129 ; Default Value: 10s
130 ;pm.process_idle_timeout = 10s;
131 pm.process_idle_timeout = 30s;
132
133 ; The number of requests each child process should execute before respawning.
134 ; This can be useful to work around memory leaks in 3rd party libraries. For
135 ; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
136 ; Default Value: 0
137 ;pm.max_requests = 500
138
139 ; The URI to view the FPM status page. If this value is not set, no URI will be
140 ; recognized as a status page. It shows the following informations:
141 ; pool - the name of the pool;
142 ; process manager - static, dynamic or ondemand;
143 ; start time - the date and time FPM has started;
144 ; start since - number of seconds since FPM has started;
145 ; accepted conn - the number of request accepted by the pool;
146 ; listen queue - the number of request in the queue of pending
147 ; connections (see backlog in listen(2));
148 ; max listen queue - the maximum number of requests in the queue
149 ; of pending connections since FPM has started;
150 ; listen queue len - the size of the socket queue of pending connections;
151 ; idle processes - the number of idle processes;
152 ; active processes - the number of active processes;
153 ; total processes - the number of idle + active processes;
154 ; max active processes - the maximum number of active processes since FPM
155 ; has started;
156 ; max children reached - number of times, the process limit has been reached,
157 ; when pm tries to start more children (works only for
158 ; pm 'dynamic' and 'ondemand');
159 ; Value are updated in real time.
160 ; Example output:
161 ; pool: www
162 ; process manager: static
163 ; start time: 01/Jul/2011:17:53:49 +0200
164 ; start since: 62636
165 ; accepted conn: 190460
166 ; listen queue: 0
167 ; max listen queue: 1
168 ; listen queue len: 42
169 ; idle processes: 4
170 ; active processes: 11
171 ; total processes: 15
172 ; max active processes: 12
173 ; max children reached: 0
174 ;
175 ; By default the status page output is formatted as text/plain. Passing either
176 ; 'html', 'xml' or 'json' in the query string will return the corresponding
177 ; output syntax. Example:
178 ; http://www.foo.bar/status
179 ; http://www.foo.bar/status?json
180 ; http://www.foo.bar/status?html
181 ; http://www.foo.bar/status?xml
182 ;
183 ; By default the status page only outputs short status. Passing 'full' in the
184 ; query string will also return status for each pool process.
185 ; Example:
186 ; http://www.foo.bar/status?full
187 ; http://www.foo.bar/status?json&full
188 ; http://www.foo.bar/status?html&full
189 ; http://www.foo.bar/status?xml&full
190 ; The Full status returns for each process:
191 ; pid - the PID of the process;
192 ; state - the state of the process (Idle, Running, ...);
193 ; start time - the date and time the process has started;
194 ; start since - the number of seconds since the process has started;
195 ; requests - the number of requests the process has served;
196 ; request duration - the duration in µs of the requests;
197 ; request method - the request method (GET, POST, ...);
198 ; request URI - the request URI with the query string;
199 ; content length - the content length of the request (only with POST);
200 ; user - the user (PHP_AUTH_USER) (or '-' if not set);
201 ; script - the main script called (or '-' if not set);
202 ; last request cpu - the %cpu the last request consumed
203 ; it's always 0 if the process is not in Idle state
204 ; because CPU calculation is done when the request
205 ; processing has terminated;
206 ; last request memory - the max amount of memory the last request consumed
207 ; it's always 0 if the process is not in Idle state
208 ; because memory calculation is done when the request
209 ; processing has terminated;
210 ; If the process is in Idle state, then informations are related to the
211 ; last request the process has served. Otherwise informations are related to
212 ; the current request being served.
213 ; Example output:
214 ; ************************
215 ; pid: 31330
216 ; state: Running
217 ; start time: 01/Jul/2011:17:53:49 +0200
218 ; start since: 63087
219 ; requests: 12808
220 ; request duration: 1250261
221 ; request method: GET
222 ; request URI: /test_mem.php?N=10000
223 ; content length: 0
224 ; user: -
225 ; script: /home/fat/web/docs/php/test_mem.php
226 ; last request cpu: 0.00
227 ; last request memory: 0
228 ;
229 ; Note: There is a real-time FPM status monitoring sample web page available
230 ; It's available in: @EXPANDED_DATADIR@/fpm/status.html
231 ;
232 ; Note: The value must start with a leading slash (/). The value can be
233 ; anything, but it may not be a good idea to use the .php extension or it
234 ; may conflict with a real PHP file.
235 ; Default Value: not set
236 ;pm.status_path = /status
237
238 ; The ping URI to call the monitoring page of FPM. If this value is not set, no
239 ; URI will be recognized as a ping page. This could be used to test from outside
240 ; that FPM is alive and responding, or to
241 ; - create a graph of FPM availability (rrd or such);
242 ; - remove a server from a group if it is not responding (load balancing);
243 ; - trigger alerts for the operating team (24/7).
244 ; Note: The value must start with a leading slash (/). The value can be
245 ; anything, but it may not be a good idea to use the .php extension or it
246 ; may conflict with a real PHP file.
247 ; Default Value: not set
248 ;ping.path = /ping
249
250 ; This directive may be used to customize the response of a ping request. The
251 ; response is formatted as text/plain with a 200 response code.
252 ; Default Value: pong
253 ;ping.response = pong
254
255 ; The access log file
256 ; Default: not set
257 ;access.log = log/$pool.access.log
258
259 ; The access log format.
260 ; The following syntax is allowed
261 ; %%: the '%' character
262 ; %C: %CPU used by the request
263 ; it can accept the following format:
264 ; - %{user}C for user CPU only
265 ; - %{system}C for system CPU only
266 ; - %{total}C for user + system CPU (default)
267 ; %d: time taken to serve the request
268 ; it can accept the following format:
269 ; - %{seconds}d (default)
270 ; - %{miliseconds}d
271 ; - %{mili}d
272 ; - %{microseconds}d
273 ; - %{micro}d
274 ; %e: an environment variable (same as $_ENV or $_SERVER)
275 ; it must be associated with embraces to specify the name of the env
276 ; variable. Some exemples:
277 ; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e
278 ; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e
279 ; %f: script filename
280 ; %l: content-length of the request (for POST request only)
281 ; %m: request method
282 ; %M: peak of memory allocated by PHP
283 ; it can accept the following format:
284 ; - %{bytes}M (default)
285 ; - %{kilobytes}M
286 ; - %{kilo}M
287 ; - %{megabytes}M
288 ; - %{mega}M
289 ; %n: pool name
290 ; %o: output header
291 ; it must be associated with embraces to specify the name of the header:
292 ; - %{Content-Type}o
293 ; - %{X-Powered-By}o
294 ; - %{Transfert-Encoding}o
295 ; - ....
296 ; %p: PID of the child that serviced the request
297 ; %P: PID of the parent of the child that serviced the request
298 ; %q: the query string
299 ; %Q: the '?' character if query string exists
300 ; %r: the request URI (without the query string, see %q and %Q)
301 ; %R: remote IP address
302 ; %s: status (response code)
303 ; %t: server time the request was received
304 ; it can accept a strftime(3) format:
305 ; %d/%b/%Y:%H:%M:%S %z (default)
306 ; %T: time the log has been written (the request has finished)
307 ; it can accept a strftime(3) format:
308 ; %d/%b/%Y:%H:%M:%S %z (default)
309 ; %u: remote user
310 ;
311 ; Default: "%R - %u %t \"%m %r\" %s"
312 ;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
313
314 ; The log file for slow requests
315 ; Default Value: not set
316 ; Note: slowlog is mandatory if request_slowlog_timeout is set
317 slowlog = /var/log/php-fpm/rocketgit-slow.log
318
319 ; The timeout for serving a single request after which a PHP backtrace will be
320 ; dumped to the 'slowlog' file. A value of '0s' means 'off'.
321 ; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
322 ; Default Value: 0
323 ;request_slowlog_timeout = 0
324 request_slowlog_timeout = 2s
325
326 ; The timeout for serving a single request after which the worker process will
327 ; be killed. This option should be used when the 'max_execution_time' ini option
328 ; does not stop script execution for some reason. A value of '0' means 'off'.
329 ; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
330 ; Default Value: 0
331 ;request_terminate_timeout = 0
332
333 ; Set open file descriptor rlimit.
334 ; Default Value: system defined value
335 ;rlimit_files = 1024
336
337 ; Set max core size rlimit.
338 ; Possible Values: 'unlimited' or an integer greater or equal to 0
339 ; Default Value: system defined value
340 ;rlimit_core = 0
341
342 ; Chroot to this directory at the start. This value must be defined as an
343 ; absolute path. When this value is not set, chroot is not used.
344 ; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
345 ; of its subdirectories. If the pool prefix is not set, the global prefix
346 ; will be used instead.
347 ; Note: chrooting is a great security feature and should be used whenever
348 ; possible. However, all PHP paths will be relative to the chroot
349 ; (error_log, sessions.save_path, ...).
350 ; Default Value: not set
351 ;chroot =
352
353 ; Chdir to this directory at the start.
354 ; Note: relative path can be used.
355 ; Default Value: current directory or / when chroot
356 ;chdir = /var/www
357
358 ; Redirect worker stdout and stderr into main error log. If not set, stdout and
359 ; stderr will be redirected to /dev/null according to FastCGI specs.
360 ; Note: on highloaded environement, this can cause some delay in the page
361 ; process time (several ms).
362 ; Default Value: no
363 ;catch_workers_output = yes
364
365 ; Clear environment in FPM workers
366 ; Prevents arbitrary environment variables from reaching FPM worker processes
367 ; by clearing the environment in workers before env vars specified in this
368 ; pool configuration are added.
369 ; Setting to "no" will make all environment variables available to PHP code
370 ; via getenv(), $_ENV and $_SERVER.
371 ; Default Value: yes
372 ;clear_env = no
373
374 ; Limits the extensions of the main script FPM will allow to parse. This can
375 ; prevent configuration mistakes on the web server side. You should only limit
376 ; FPM to .php extensions to prevent malicious users to use other extensions to
377 ; exectute php code.
378 ; Note: set an empty value to allow all extensions.
379 ; Default Value: .php
380 ;security.limit_extensions = .php .php3 .php4 .php5
381
382 ; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
383 ; the current environment.
384 ; Default Value: clean env
385 ;env[HOSTNAME] = $HOSTNAME
386 ;env[PATH] = /usr/local/bin:/usr/bin:/bin
387 ;env[TMP] = /tmp
388 ;env[TMPDIR] = /tmp
389 ;env[TEMP] = /tmp
390
391 ; Additional php.ini defines, specific to this pool of workers. These settings
392 ; overwrite the values previously defined in the php.ini. The directives are the
393 ; same as the PHP SAPI:
394 ; php_value/php_flag - you can set classic ini defines which can
395 ; be overwritten from PHP call 'ini_set'.
396 ; php_admin_value/php_admin_flag - these directives won't be overwritten by
397 ; PHP call 'ini_set'
398 ; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.
399
400 ; Defining 'extension' will load the corresponding shared extension from
401 ; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
402 ; overwrite previously defined php.ini values, but will append the new value
403 ; instead.
404
405 ; Note: path INI options can be relative and will be expanded with the prefix
406 ; (pool, global or @prefix@)
407
408 ; Default Value: nothing is defined by default except the values in php.ini and
409 ; specified at startup with the -d argument
410 ;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
411 ;php_flag[display_errors] = off
412 php_admin_value[error_log] = /var/log/rocketgit/pool-error.log
413 php_admin_flag[log_errors] = on
414 php_admin_value[memory_limit] = 32M
File samples/rg.conf changed (mode: 100644) (index 871746f..7552fe2)
11 11 </IfModule> </IfModule>
12 12
13 13 # Cache at will # Cache at will
14 <FilesMatch "(?i)^.*\.(ico|flv|jpg|jpeg|png|gif|js|css|swf)$">
14 <FilesMatch "(?i)^.*\.(ico|jpg|jpeg|png|gif|js|css)$">
15 15 FileETag MTime Size FileETag MTime Size
16 16 </FilesMatch> </FilesMatch>
17 17
 
37 37 MaxKeepAliveRequests 1000 MaxKeepAliveRequests 1000
38 38 KeepAliveTimeout 10 KeepAliveTimeout 10
39 39
40
40 41 RewriteEngine On RewriteEngine On
41 #RewriteLog /var/log/httpd/rg-Rewrite.log
42 #RewriteLogLevel 3
43 42
44 43 # If you do not want HTTPS, comment the following lines and the HTTPS # If you do not want HTTPS, comment the following lines and the HTTPS
45 44 # virtual host, below. # virtual host, below.
 
66 65 </VirtualHost> </VirtualHost>
67 66
68 67 <VirtualHost *:443> <VirtualHost *:443>
68 #LogLevel debug #rewrite:trace8
69
69 70 DocumentRoot /usr/share/rocketgit/root/ DocumentRoot /usr/share/rocketgit/root/
70 71
71 72 ErrorLog logs/rocketgit-ssl_error_log ErrorLog logs/rocketgit-ssl_error_log
 
78 79 KeepAliveTimeout 10 KeepAliveTimeout 10
79 80
80 81 RewriteEngine On RewriteEngine On
81 #RewriteLog /var/log/httpd/rg-Rewrite.log
82 #RewriteLogLevel 3
83 82
84 83 # Allow .ico, 'themes' folder and robots.txt # Allow .ico, 'themes' folder and robots.txt
85 84 RewriteCond %{REQUEST_URI} ^/(favicon\.ico|themes/.*|robots\.txt)$ RewriteCond %{REQUEST_URI} ^/(favicon\.ico|themes/.*|robots\.txt)$
 
111 110 # Compress # Compress
112 111 AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/x-javascript
113 112 DeflateBufferSize 81920 DeflateBufferSize 81920
113
114 <FilesMatch "\.php$">
115 SetHandler "proxy:unix:/run/php-fpm/rocketgit.sock|fcgi://localhost"
116 </FilesMatch>
114 117 </VirtualHost> </VirtualHost>
File samples/systemd.service added (mode: 100644) (index 0000000..e0eee46)
1 # It's not recommended to modify this file in-place, because it will be
2 # overwritten during package upgrades.
3
4 # To alter the FPM environment, drop a file with the suffix
5 # .conf in /etc/systemd/system/rocketgit.service.d, with
6 # [Service]
7 # Environment=FOO=bar
8
9 [Unit]
10 Description=The PHP FastCGI Process Manager (Rocketgit)
11 After=syslog.target network.target
12
13 [Service]
14 Type=notify
15 PIDFile=/run/php-fpm/rocketgit-fpm.pid
16 ExecStart=/usr/sbin/php-fpm --fpm-config /etc/rocketgit/php-fpm.conf
17 ExecReload=/bin/kill -USR2 $MAINPID
18 PrivateTmp=true
19
20 [Install]
21 WantedBy=multi-user.target
File scripts/cache.php changed (mode: 100644) (index f100e84..16fe053)
... ... if ($r === FALSE) {
326 326
327 327 socket_set_nonblock($master); socket_set_nonblock($master);
328 328
329 // Allow apache (at least) to connect to socket
330 // TODO: this is a security hole. Take care. Hm. How?!
331 $r = chmod($rg_cache_socket, 0666);
329 $r = chmod($rg_cache_socket, 0600);
332 330 if ($r === FALSE) { if ($r === FALSE) {
333 331 rg_internal_error("Cannot set rights on cache socket!"); rg_internal_error("Cannot set rights on cache socket!");
334 332 exit(1); exit(1);
File scripts/cron.php changed (mode: 100644) (index a2d78cc..93281e6)
... ... require_once($INC . "/admin.inc.php");
19 19 require_once($INC . "/ver.php"); require_once($INC . "/ver.php");
20 20
21 21 $now = time(); $now = time();
22 $user = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : "rocketgit";
23
24 if (strcmp($user, "apache") == 0) {
25 rg_log_set_file($rg_web_log_dir . "/cron.log");
26 rg_log_set_sid("000000"); // to spread the logs
27
28 if (gmdate("Hi") == "0310")
29 rg_clean_logs('/var/log/rocketgit-web');
30
31 exit(0);
32 }
33 22
34 23 rg_log_set_file($rg_log_dir . "/cron.log"); rg_log_set_file($rg_log_dir . "/cron.log");
35 24 rg_log_set_sid("000000"); // to spread the logs rg_log_set_sid("000000"); // to spread the logs
File scripts/events.php changed (mode: 100644) (index 9d38aa2..939f33b)
... ... if ($r === FALSE) {
99 99
100 100 socket_set_nonblock($socket); socket_set_nonblock($socket);
101 101
102 // Allow apache to connect to socket
103 $r = chmod($rg_event_socket, 0666);
102 $r = chmod($rg_event_socket, 0600);
104 103 if ($r === FALSE) { if ($r === FALSE) {
105 104 rg_internal_error("Cannot set rights on event socket!"); rg_internal_error("Cannot set rights on event socket!");
106 105 exit(1); exit(1);
File scripts/remote.php changed (mode: 100644) (index b03344f..3b8d13c)
... ... rg_prof_start("remote.php");
23 23
24 24 rg_log_set_file($rg_log_dir . "/remote.log"); rg_log_set_file($rg_log_dir . "/remote.log");
25 25
26 function git_output($str)
27 {
28 echo sprintf("%04x", 4 + 4 + strlen($str)) . 'ERR ' . $str;
29 }
30
31 26 function info($str) function info($str)
32 27 { {
33 28 rg_log("Sending: " . $str); rg_log("Sending: " . $str);
 
... ... function fatal($str)
53 48 // But, keep in mind that at least git archive --remote // But, keep in mind that at least git archive --remote
54 49 // expects a 4 byte len! // expects a 4 byte len!
55 50 //echo "\n" . $str2; //echo "\n" . $str2;
56 git_output($str2);
51 echo rg_git_pack('ERR ' . $str2);
57 52 } }
58 53 exit(1); exit(1);
59 54 } }
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
110 105 info('== Welcome to RocketGit! =='); info('== Welcome to RocketGit! ==');
111 106 info('you are connecting from IP ' . $ip . '.'); info('you are connecting from IP ' . $ip . '.');
112 107
113 $conn_ui = rg_user_info($db, $login_uid, '', '');
114 if ($conn_ui['exists'] != 1)
108 $login_ui = rg_user_info($db, $login_uid, '', '');
109 if ($login_ui['exists'] != 1)
115 110 fatal("User does not exists (conn)."); fatal("User does not exists (conn).");
116 info('you are connecting as user \'' . $conn_ui['username'] . '\'.');
111 info('you are connecting as user \'' . $login_ui['username'] . '\'.');
117 112
118 putenv('ROCKETGIT_INFO_SHOW=1');
113 putenv('ROCKETGIT_SHOW_INFO=0');
119 114
120 115 // Only normal keys can execute some commands // Only normal keys can execute some commands
121 116 if (strstr($flags, 'N')) if (strstr($flags, 'N'))
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
128 123 // We do this operation after dispatch to not impact the latency. // We do this operation after dispatch to not impact the latency.
129 124 // TODO: This should be put in a queue for performance reasons // TODO: This should be put in a queue for performance reasons
130 125 // At the same time, update stats? events? // At the same time, update stats? events?
131 $_r = rg_keys_update_use($db, $conn_ui['uid'], $key_id, $ip,
126 $_r = rg_keys_update_use($db, $login_ui['uid'], $key_id, $ip,
132 127 $cmd_repo); $cmd_repo);
133 128 if ($_r !== TRUE) if ($_r !== TRUE)
134 129 rg_internal_error("Cannot update key last_use!"); rg_internal_error("Cannot update key last_use!");
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
146 141 $login_uid = 0; $login_uid = 0;
147 142 $key_id = 0; $key_id = 0;
148 143 $flags = ''; $flags = '';
149 $conn_ui = array('uid' => 0,
144 $login_ui = array('uid' => 0,
150 145 'username' => 'anonymous user', 'username' => 'anonymous user',
151 146 'organization' => 0); 'organization' => 0);
152 147
 
... ... if (isset($_SERVER['SSH_CONNECTION'])) {
170 165 $ip = rg_fix_ip(getenv("REMOTE_HOST")); $ip = rg_fix_ip(getenv("REMOTE_HOST"));
171 166 } }
172 167
173 // Extracts command and computes permissions
174 168 if (strncasecmp($cmd_repo, "git-upload-pack", 15) == 0) { if (strncasecmp($cmd_repo, "git-upload-pack", 15) == 0) {
175 $cmd = "git-upload-pack";
176 $needed_rights = "F";
177 $push = 0;
178 } else if (strncasecmp($cmd_repo, "git-receive-pack", 16) == 0) {
179 $cmd = "git-receive-pack";
180 // We need push or anonymous push
181 $needed_rights = "P|H";
182 $push = 1;
169 $cmd = 'git-upload-pack';
170 } else if (strncasecmp($cmd_repo ', "git-receive-pack', 16) == 0) {
171 $cmd = 'git-receive-pack';
183 172 } else { } else {
184 rg_log("Unknown command [$cmd_repo]");
185 fatal("Unknown command!");
173 $cmd = $cmd_repo;
186 174 } }
187 175
188 176 // extract repository name // extract repository name
 
... ... if (strstr($flags, 'W')) {
209 197 fatal('A worker can only clone!'); fatal('A worker can only clone!');
210 198 } }
211 199
212 // validity/security checks
213 // Load info about the owner
214 if (rg_user_ok($user) !== TRUE)
215 fatal("User [$user] is invalid (" . rg_user_error() . ")!");
216 $owner_ui = rg_user_info($db, 0, $user, "");
217 if ($owner_ui['ok'] != 1)
218 fatal("Internal problems. Try again later, please.");
219 if ($owner_ui['exists'] != 1)
220 fatal("User does not exists.");
221
222 // Loading info about the repository
223 if (rg_repo_ok($repo) !== TRUE)
224 fatal("Repo is invalid (" . rg_repo_error() . ")");
225 $ri = rg_repo_info($db, 0, $owner_ui['uid'], $repo);
226 if ($ri['ok'] != 1)
227 fatal("Internal problems. Try again later, please.");
228 if ($ri['exists'] != 1)
229 fatal("Repo does not exists.");
230 if ($ri['deleted'] == 1)
231 fatal("Repo has been deleted!");
232
233 $ls = rg_repo_lock_status($db, $ri['repo_id']);
234 if ($ls['ok'] != 1)
235 fatal('Could not get lock status: ' . rg_repo_error());
236 if (($ls['status'] == 1) && ($conn_ui['uid'] != $ls['uid'])) {
237 $_u = rg_user_info($db, $ls['uid'], '', '');
238 if ($_u['exists'] == 1)
239 $_user = $_u['username'];
240 else
241 $_user = '?';
242 fatal('Repository has been locked user ' . $_user
243 . ' at ' . gmdate('Y-m-d H:i', $ls['itime']) . ' UTC.'
244 . ' Reason: ' . $ls['reason']);
245 }
246
247 $repo_path = rg_repo_path_by_id($owner_ui['uid'], $ri['repo_id']);
248 rg_log("repo_path=$repo_path.");
249
250 // TODO: signal user that the repo moved and provide a hint how to follow
251
252 $x = array();
253 $x['obj_id'] = $ri['repo_id'];
254 $x['type'] = 'repo_refs';
255 $x['owner'] = $ri['uid'];
256 $x['uid'] = $conn_ui['uid'];
257 $x['username'] = $conn_ui['username'];
258 $x['needed_rights'] = $needed_rights;
259 $x['ip'] = $ip;
260 $x['misc'] = '';
261 $ret = rg_rights_allow($db, $x);
262 if ($ret !== TRUE)
263 fatal("You have no rights to access this repo!");
264
265 // If we are enrolled, ask for login token
266 // For push we always ask for it, for fetch only if repo is NOT public
267 // And we can ask only if we have a ssh connection. For git protocol we cannot
268 // because we do not have the username/uid of the connecting user.
269 if (isset($_SERVER['SSH_CONNECTION'])) {
270 if (($ri['public'] == 0) || ($push == 1)) {
271 $r = rg_totp_verify_ip($db, $conn_ui['uid'], $ip);
272 if (($r['ok'] == 0) && (empty($r['list'])))
273 fatal(rg_totp_error() . '.');
274 }
275 }
276
277 // TODO: limit per connection
278 // TODO: limit time and/or cpu
279 // TODO: limit cpuset
280 // TODO: limit io
281 // TODO: put process in a cgroup?
282
283
284 if (($push == 1) && rg_user_over_limit($db, $owner_ui, $max))
285 fatal("Cannot push: user is over limit"
286 . " (" . $owner_ui['disk_used_mb']. "MiB >= " . $max . "MiB)");
287
288 // Put in environment all we need
289 putenv("ROCKETGIT_LOGIN_UID=" . $login_uid);
290 putenv("ROCKETGIT_LOGIN_URL=" . rg_re_userpage($conn_ui));
291 putenv("ROCKETGIT_KEY_ID=" . $key_id);
292 putenv("ROCKETGIT_REPO_ID=" . $ri['repo_id']);
293 putenv("ROCKETGIT_REPO_PATH=" . $repo_path);
294 putenv("ROCKETGIT_REPO_NAME=" . $ri['name']);
295 putenv("ROCKETGIT_REPO_UID=" . $ri['uid']);
296 putenv("ROCKETGIT_REPO_CLONE_URL=" . $ri['clone_url']);
297 putenv("ROCKETGIT_IP=$ip");
298 putenv("ROCKETGIT_ITIME=" . microtime(TRUE));
299 putenv("ROCKETGIT_HOST=" . $host);
300 if ($push == 1) {
301 $namespace = "rg_" . rg_id(8);
302 rg_log("namespace is $namespace.");
303 putenv("GIT_NAMESPACE=" . $namespace);
304
305 // Prepare refs to avoid the following message:
306 // "No refs in common and none specified; doing nothing.
307 // Perhaps you should specify a branch such as 'master'."
308 $dst = $repo_path . '/refs/namespaces/' . $namespace . '/refs';
309 $r = rg_copy_tree($repo_path . '/refs/heads', $dst . '/heads/', 0755);
310 if ($r !== TRUE)
311 fatal("Internal error (cannot copy heads)");
312 $r = rg_copy_tree($repo_path . '/refs/tags', $dst . '/tags/', 0755);
313 if ($r !== TRUE)
314 fatal("Internal error (cannot copy tags)");
315 }
200 $r = rg_repo_fetch_push_helper($db, $host, $ip, $login_ui, $prefix, $user,
201 $repo, $cmd, TRUE /*need_namespace_copy*/);
202 if ($r['ok'] != 1)
203 fatal($r['error']);
316 204
317 205 $run = "git-shell -c \"" . $cmd . " " . escapeshellarg($repo_path) . "\""; $run = "git-shell -c \"" . $cmd . " " . escapeshellarg($repo_path) . "\"";
318 206 $run = $cmd . ' ' . escapeshellarg($repo_path); $run = $cmd . ' ' . escapeshellarg($repo_path);
319 207 rg_log("Running [$run]..."); rg_log("Running [$run]...");
320 208 rg_prof_start($cmd); rg_prof_start($cmd);
209 // TODO: shouldn't we use rg_exec to capture stderr?
321 210 passthru($run, $ret); passthru($run, $ret);
322 211 rg_prof_end($cmd); rg_prof_end($cmd);
323 212 rg_log("[$run] returned $ret."); rg_log("[$run] returned $ret.");
File scripts/worker.php changed (mode: 100644) (index 022ccf6..60086e3)
... ... function start_worker($job)
144 144 break; break;
145 145 } }
146 146
147 $r = @mkdir($job['main'], 0755);
147 $r = @mkdir($job['main'], 0700);
148 148 if ($r === FALSE) { if ($r === FALSE) {
149 149 rg_log('Cannot create main dir (' . $job['main'] . '):' rg_log('Cannot create main dir (' . $job['main'] . '):'
150 150 . ' ' . $php_errormsg . '!'); . ' ' . $php_errormsg . '!');
 
... ... function start_worker($job)
256 256 $reason = 'cannot store build commands!'; $reason = 'cannot store build commands!';
257 257 break; break;
258 258 } }
259 $r = @chmod($job['main'] . '/root/build.sh', 0755);
259 $r = @chmod($job['main'] . '/root/build.sh', 0700);
260 260 if ($r === FALSE) { if ($r === FALSE) {
261 261 $reason = 'cannot to chmod on build.sh!'; $reason = 'cannot to chmod on build.sh!';
262 262 break; break;
 
... ... function start_worker($job)
296 296 $reason = 'cannot store commands!'; $reason = 'cannot store commands!';
297 297 break; break;
298 298 } }
299 $r = @chmod($job['main'] . '/root/rg.sh', 0755);
299 $r = @chmod($job['main'] . '/root/rg.sh', 0700);
300 300 if ($r === FALSE) { if ($r === FALSE) {
301 301 $reason = 'cannot to chmod on rg.sh!'; $reason = 'cannot to chmod on rg.sh!';
302 302 break; break;
 
... ... function start_worker($job)
309 309 } }
310 310 $do_umount = FALSE; $do_umount = FALSE;
311 311
312 // . ' --console pty,target_type=virtio'
313 312 // . ' --noautoconsole' // . ' --noautoconsole'
314 313 // . ' --security type=dynamic,relabel=yes' // . ' --security type=dynamic,relabel=yes'
315 314 // . ' --filesystem source=' . $emain . '/root') // . ' --filesystem source=' . $emain . '/root')
File spell_check.sh changed (mode: 100755) (index bfcfb00..462ccd1)
... ... find . \
11 11 -o -name '*.spec.in' \ -o -name '*.spec.in' \
12 12 -o -name README \ -o -name README \
13 13 | while read f; do | while read f; do
14 aspell check "${f}" </dev/tty &>/dev/tty
14 aspell --dont-backup check "${f}" </dev/tty &>/dev/tty
15 15 done done
File tests/config.php changed (mode: 100644) (index a202ae1..65889d2)
... ... $rg_sql_debug = 1;
7 7 $rg_session_time = 3600; $rg_session_time = 3600;
8 8 $rg_keys_file = "afile.txt"; $rg_keys_file = "afile.txt";
9 9 $rg_scripts = dirname(dirname(__FILE__)); $rg_scripts = dirname(dirname(__FILE__));
10 $rg_repo_allow = '\pL\pN\pP_<>';
10 $rg_repo_allow = '-\p{L}\p{N}._+=*&<>';
11 11 $rg_repo_min_len = 1; $rg_repo_min_len = 1;
12 12 $rg_repo_max_len = 100; $rg_repo_max_len = 100;
13 $rg_user_allow = '\pL\pN\pP_<>';
13 $rg_user_allow = '-\p{L}\p{N}._+=*&<>';
14 14 $rg_user_min_len = 1; $rg_user_min_len = 1;
15 15 $rg_user_max_len = 50; $rg_user_max_len = 50;
16 16 $rg_ssh_paras = "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty"; $rg_ssh_paras = "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty";
 
... ... $rg_account_allow_creation = 1;
20 20 $rg_account_email_confirm = 0; $rg_account_email_confirm = 0;
21 21 $rg_max_ssh_keys = 10; $rg_max_ssh_keys = 10;
22 22 $rg_log_dir = dirname(__FILE__); $rg_log_dir = dirname(__FILE__);
23 $rg_web_log_dir = dirname(__FILE__);
24 23 $rg_state_dir = dirname(__FILE__); $rg_state_dir = dirname(__FILE__);
25 24 $rg_lock_dir = dirname(__FILE__); $rg_lock_dir = dirname(__FILE__);
26 25 $rg_repos = "base"; $rg_repos = "base";
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master