GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (4873)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/common/backend/BackendCVS.class.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Copyright (c) Xerox Corporation, Codendi Team, 2001-2009. All rights reserved
4
 * Copyright (c) Enalean, 2015. All Rights Reserved.
5
 *
6
 * Tuleap is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * Tuleap is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with Tuleap; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
21
class BackendCVS extends Backend {
22
23
    protected $CVSRootListNeedUpdate;
24
    protected $UseCVSNT;
25
26
    /**
27
     * Return an instance of ServiceDao
28
     *
29
     * @return ServiceDao
30
     */
31
    function _getServiceDao() {
32
        return new ServiceDao(CodendiDataAccess::instance());
33
    }
34
35
36
    /**
37
     * Return true if server uses CVS NT, or false if it uses GNU CVS
38
     *
39
     * @return Boolean
40
     */
41
    function useCVSNT() {
42
        if (isset($this->UseCVSNT)) {
43
            return $this->UseCVSNT;
44
        }
45
        if (is_file("/usr/bin/cvsnt")) {
46
            $this->UseCVSNT=true;
47
        } else {
48
            $this->UseCVSNT=false;
49
        }
50
        return $this->UseCVSNT;
51
    }
52
53
    /**
54
     * Check if repository of given project exists
55
     *
56
     * @param Project $project Project for wich repository will be checked
57
     *
58
     * @return true is repository already exists, false otherwise
59
     */
60
    function repositoryExists($project) {
61
        $unix_group_name=$project->getUnixName(false); // May contain upper-case letters
62
        $cvs_dir=$GLOBALS['cvs_prefix']."/".$unix_group_name;
63
        if (is_dir($cvs_dir)) {
64
            return true;
65
        } else {
66
            return false;
67
        }
68
    }
69
70
    /**
71
     * Create project CVS repository
72
     * If the directory already exists, nothing is done.
73
     *
74
     * @param Integer $group_id project id for wic CVS repository will be created
75
     *
76
     * @return true if repo is successfully created, false otherwise
77
     */
78
    public function createProjectCVS($group_id) {
79
        $project = $this->getProjectManager()->getProject($group_id);
80
        if (!$project) {
81
            return false;
82
        }
83
84
        $unix_group_name = $project->getUnixName(false);
85
        $cvs_dir         = $GLOBALS['cvs_prefix']."/".$unix_group_name;
86
87
        if (! is_dir($cvs_dir)) {
88
            // Let's create a CVS repository for this group
89
            if (! mkdir($cvs_dir)) {
90
                $this->log("Can't create project CVS dir: $cvs_dir", Backend::LOG_ERROR);
91
                return false;
92
            }
93
94
            $return_code = 0;
95
            $output      = '';
96
            $cvs_command = $GLOBALS['cvs_cmd'];
97
98
            if (! file_exists($cvs_command)) {
99
                $this->log("CVS command not found", Backend::LOG_ERROR);
100
                return false;
101
            }
102
103
            if ($this->useCVSNT()) {
104
                // Tell cvsnt not to update /etc/cvsnt/PServer: this is done later by this the script.
105
                $output = $this->system("$cvs_command -d$cvs_dir init -n ", $return_code);
106
            } else {
107
                $output = $this->system("$cvs_command -d$cvs_dir init", $return_code);
108
            }
109
110
            if ($return_code > 0) {
111
                $this->log("CVS init command return: $output", Backend::LOG_ERROR);
112
                return false;
113
            }
114
115
            if (! is_dir("$cvs_dir/CVSROOT")) {
116
                $this->log("Folder $cvs_dir/CVSROOT does not exist", Backend::LOG_ERROR);
117
                return false;
118
            }
119
120
            // Turn off pserver writers, on anonymous readers
121
            // See CVS writers update below. Just create an
122
            // empty writers file so that we can set up the appropriate
123
            // ownership right below. We will put names in writers
124
            // later in the script
125
126
            $return_code_turn_off = 0;
127
128
            $output_turn_off = $this->system("echo '' > $cvs_dir/CVSROOT/writers", $return_code_turn_off);
129
130
            if ($return_code_turn_off > 0) {
131
               $this->log("Echo in /CVSROOT/writers returns: $output_turn_off", Backend::LOG_ERROR);
132
               return false;
133
            }
134
135
            if (! $this->useCVSNT()) {
136
                // But to allow checkout/update to registered users we
137
                // need to setup a world writable directory for CVS lock files
138
                $lockdir=$GLOBALS['cvslock_prefix']."/$unix_group_name";
139
                $filename= "$cvs_dir/CVSROOT/config";
140
                $this->_RcsCheckout($filename);
141
                $this->system("echo  >> $filename");
142
                $this->system("echo '# !!! Codendi Specific !!! DO NOT REMOVE' >> $filename");
143
                $this->system("echo '# Put all CVS lock files in a single directory world writable' >> $filename");
144
                $this->system("echo '# directory so that any registered user can checkout/update' >> $filename");
145
                $this->system("echo '# without having write permission on the entire cvs tree.' >> $filename");
146
                $this->system("echo 'LockDir=$lockdir' >> $filename");
147
                // commit changes to config file (directly with RCS)
148
                $this->_RcsCommit($filename);
149
150
                // Create lock dir
151
                $this->createLockDirIfMissing($project);
152
            }
153
154
            // put an empty line in in the valid tag cache (means no tag yet)
155
            // (this file is not under version control so don't check it in)
156
            $this->system("echo \"\" > $cvs_dir/CVSROOT/val-tags");
157
            $this->system("chmod 0664 $cvs_dir/CVSROOT/val-tags");
158
159
            // set group ownership, http user
160
            $this->changeRepoOwnership($cvs_dir, $unix_group_name);
161
            $this->recursiveSgidOnDirectories($cvs_dir);
162
        }
163
164
        // Create writer file
165
        if (! $this->updateCVSwriters($group_id)) {
166
            $this->log("Error while updating CVS Writers", Backend::LOG_ERROR);
167
            return false;
168
        }
169
170
        // history was deleted (or not created)? Recreate it.
171
        if ($this->useCVSNT()) {
172
            // Create history file (not created by default by cvsnt)
173
            $this->system("touch $cvs_dir/CVSROOT/history");
174
            // Must be writable
175
            $this->system("chmod 0666 $cvs_dir/CVSROOT/history");
176
            $this->recurseChownChgrp($cvs_dir."/CVSROOT", $this->getHTTPUser(), $unix_group_name);
177
        }
178
179
        // Update post-commit hooks
180
        if (! $this->updatePostCommit($project)) {
181
            return false;
182
        }
183
184
        // Update watch mode
185
        if (! $this->updateCVSWatchMode($group_id)) {
186
            return false;
187
        }
188
189
        return true;
190
    }
191
192
    protected function recursiveSgidOnDirectories($root) {
193
        $this->system('find '.$root.' -type d -exec chmod g+rws {} \;');
194
    }
195
    
196
    /**
197
     * Create lock dir if missing
198
     *
199
     * @param Project $project project for wich the lock dir will be created
200
     *
201
     * @return Boolean
202
     */
203
    public function createLockDirIfMissing($project) {
204
        // Lockdir does not exist? (Re)create it.
205
        if (!$this->useCVSNT()) {
206
            $lockdir=$GLOBALS['cvslock_prefix']."/".$project->getUnixName(false);
207
            if (! is_dir($lockdir)) {
208
                if (!mkdir("$lockdir",02777)) {
209
                    $this->log("Can't create project CVS lock dir: $lockdir", Backend::LOG_ERROR);
210
                    return false;
211
                }
212
                $this->system("chmod 02777 $lockdir"); // overwrite umask value
213
            }
214
        }
215
        return true;
216
    }
217
218
    /**
219
     * Update post-commit hooks
220
     *
221
     * @param Project $project project for wich post-commit hooks will be updated
222
     *
223
     * @return Boolean
224
     */
225
    public function updatePostCommit($project) {
226
        $unix_group_name=$project->getUnixName(false); // May contain upper-case letters
227
        $cvs_dir=$GLOBALS['cvs_prefix']."/".$unix_group_name;
228
        if ($project->isCVSTracked()) {
229
            // hook for commit tracking in cvs loginfo file
230
            $filename = "$cvs_dir/CVSROOT/loginfo";
231
            $file_array=file($filename);
232
            if (!in_array($this->block_marker_start, $file_array)) {
233
                if ($this->useCVSNT()) {
234
                    $command = "ALL ".$GLOBALS['codendi_bin_prefix']."/log_accum -T $unix_group_name -C $unix_group_name -s %{sVv}";
235
                } else {
236
                    $command = "ALL (".$GLOBALS['codendi_bin_prefix']."/log_accum -T $unix_group_name -C $unix_group_name -s %{sVv})>/dev/null 2>&1";
237
                }
238
                $this->_RcsCheckout($filename);
239
                $this->addBlock($filename, $command);
240
                $this->_RcsCommit($filename);
241
                $this->recurseChownChgrp($cvs_dir."/CVSROOT", $this->getHTTPUser(), $unix_group_name);
242
            }
243
244
245
            // hook for commit tracking in cvs commitinfo file
246
            $filename = "$cvs_dir/CVSROOT/commitinfo";
247
            $file_array=file($filename);
248
            if (!in_array($this->block_marker_start, $file_array)) {
249
                $this->_RcsCheckout($filename);
250
                $this->addBlock($filename, "ALL ".$GLOBALS['codendi_bin_prefix']."/commit_prep -T $unix_group_name -r");
251
                $this->_RcsCommit($filename);
252
                $this->recurseChownChgrp($cvs_dir."/CVSROOT", $this->getHTTPUser(), $unix_group_name);
253
            }
254
        } else {
255
            // Remove Codendi blocks if needed
256
            $filename = "$cvs_dir/CVSROOT/loginfo";
257
            $file_array=file($filename);
258
            if (in_array($this->block_marker_start, $file_array)) {
259
                $this->removeBlock($filename);
260
            }
261
            $filename = "$cvs_dir/CVSROOT/commitinfo";
262
            $file_array=file($filename);
263
            if (in_array($this->block_marker_start, $file_array)) {
264
                $this->removeBlock($filename);
265
            }
266
        }
267
        return true;
268
    }
269
270
    /**
271
     * Update (or create) file CVSROOT/writers that should contain project members
272
     *
273
     * On Codendi writers go through pserver as well so put
274
     * group members in writers file. Do not write anything
275
     * in the CVS passwd file. The pserver protocol will fallback
276
     * on /etc/passwd (or NSS) for user authentication
277
     *
278
     * @param Integer $group_id Project id for which committers will be updated
279
     *
280
     * @return Boolean
281
     */
282
    public function updateCVSwriters($group_id) {
283
        $project = $this->getProjectManager()->getProject($group_id);
284
        if (! $project) {
285
            return false;
286
        }
287
288
        $unix_group_name = $project->getUnixName(false); // May contain upper-case letters
289
        $cvs_dir         = $GLOBALS['cvs_prefix']."/".$unix_group_name;
290
        $cvswriters_file = "$cvs_dir/CVSROOT/writers";
291
292
        // Get list of project members (Unix names)
293
        $members_id_array   = $project->getMembersUserNames();
294
        $members_name_array = array();
295
        foreach ($members_id_array as $member) {
296
            $members_name_array[] = strtolower($member['user_name'])."\n";
297
        }
298
299
        return $this->writeArrayToFile($members_name_array, $cvswriters_file);
300
    }
301
    /**
302
     * Update CVS writers into all projects that given user belongs to
303
     *
304
     * @param PFUser $user member to add as committer
305
     *
306
     * @return Boolean
307
     */
308
    public function updateCVSWritersForGivenMember($user) {
309
        $projects = $user->getProjects();
310
        if (isset($projects)) {
311
            $pm = $this->getProjectManager();
312
            foreach ($projects as $groupId) {
313
                $project = $pm->getProject($groupId);
314
                if ($this->repositoryExists($project)) {
315
                    if (!$this->updateCVSwriters($groupId)) {
316
                        return false;
317
                    }
318
                }
319
            }
320
        }
321
        return true;
322
    }
323
324
325
    /**
326
     * Update CVS Watch Mode
327
     *
328
     * @param Integer $group_id Project id for wich watch mode will be updated
329
     *
330
     * @return Boolean
331
     */
332
    public function updateCVSWatchMode($group_id) {
333
        $project=$this->getProjectManager()->getProject($group_id);
334
        if (!$project) {
335
            $this->log("Project not found: $group_id", Backend::LOG_ERROR);
336
            return false;
337
        }
338
339
        $unix_group_name=$project->getUnixName(false); // May contain upper-case letters
340
        $cvs_dir=$GLOBALS['cvs_prefix']."/".$unix_group_name;
341
        $filename = "$cvs_dir/CVSROOT/notify";
342
        //If notify file does not exist, we should raise error in log
343
        //and return false
344
        if (!file_exists($filename)) {
345
            $this->log("No such file: $filename", Backend::LOG_ERROR);
346
            return false;
347
        }
348
        $file_array=file($filename);
349
350
        // Add notify command if cvs_watch_mode is on
351
        if ($project->getCVSWatchMode()) {
352
            if (!in_array($this->block_marker_start, $file_array)) {
353
                $this->_RcsCheckout($filename);
354
                $this->addBlock($filename, 'ALL mail %s -s "CVS notification"');
355
                $this->_RcsCommit($filename);
356
357
                // Apply cvs watch on only if cvs_watch_mode changed to on
358
                $this->CVSWatch($cvs_dir, $unix_group_name, 1);
359
                $this->changeRepoOwnership($cvs_dir, $unix_group_name);
360
                $this->system("chmod g+rws $cvs_dir");
361
            }
362
        } else {
363
            // Remove notify command if cvs_watch_mode is off.
364
            if (in_array($this->block_marker_start, $file_array)) {
365
                // Switch to cvs watch off
366
                $this->_RcsCheckout($filename);
367
                $this->removeBlock($filename);
368
                $this->_RcsCommit($filename);
369
                $this->recurseChownChgrp($cvs_dir."/CVSROOT", $this->getHTTPUser(), $unix_group_name);
370
                $this->CVSWatch($cvs_dir, $unix_group_name, 0);
371
            }
372
        }
373
        return true;
374
    }
375
376
    /**
377
     * Setup the watch mode on the CVS repository
378
     *
379
     * @param String  $cvs_dir         CVS root directory
380
     * @param String  $unix_group_name name of the project
381
     * @param Integer $watch_mode      defines the watch mode
382
     *
383
     * @return Boolean
384
     */
385
    function CVSWatch($cvs_dir, $unix_group_name, $watch_mode) {
386
        $sandbox_dir =  $GLOBALS['tmp_dir']."/".$unix_group_name.".cvs_watch_sandbox";
387
        if (is_dir($sandbox_dir)) {
388
            return false;
389
        } else {
390
            mkdir("$sandbox_dir", 0700);
391
            $this->system("chmod 0700 $sandbox_dir"); // overwrite umask value
392
        }
393
        if ($watch_mode == 1) {
394
            $this->system("cd $sandbox_dir;cvs -d$cvs_dir co . 2>/dev/null 1>&2;cvs -d$cvs_dir watch on 2>/dev/null 1>&2;");
395
        } else {
396
            $this->system("cd $sandbox_dir;cvs -d$cvs_dir co . 2>/dev/null 1>&2;cvs -d$cvs_dir watch off 2>/dev/null 1>&2;");
397
        }
398
        $this->system("rm -rf $sandbox_dir;");
399
        return true;
400
    }
401
402
    /**
403
     * Checkout the file
404
     *
405
     * @param File $file file to checkout
406
     *
407
     * @return void
408
     */
409
    function _RcsCheckout($file, &$output='') {
410
        $rcode = 0;
411
        $output = $this->system("co -q -l $file", $rcode);
412
        return $rcode;
413
    }
414
415
    /**
416
     * Commit the file
417
     *
418
     * @param File $file file to be committed
419
     *
420
     * @return void
421
     */
422
    function _RcsCommit($file, &$output='') {
423
        $rcode  = 0;
424
        $output = $this->system("/usr/bin/rcs -q -l $file; ci -q -m\"Codendi modification\" $file; co -q $file", $rcode);
425
        return $rcode;
426
    }
427
428
    /**
429
     * Archive CVS repository: stores a tgz in temp dir, and remove the directory
430
     *
431
     * @param Integer $group_id id of the project for which CVS repository will be archived
432
     *
433
     * @return Boolean
434
     */
435
    public function archiveProjectCVS($group_id) {
436
        $project=$this->getProjectManager()->getProject($group_id);
437
        if (!$project) {
438
            return false;
439
        }
440
        $mydir=$GLOBALS['cvs_prefix']."/".$project->getUnixName(false);
441
        $backupfile=ForgeConfig::get('sys_project_backup_path')."/".$project->getUnixName(false)."-cvs.tgz";
442
443
        if (is_dir($mydir)) {
444
            $this->system("cd ".$GLOBALS['cvs_prefix']."; tar cfz $backupfile ".$project->getUnixName(false));
445
            chmod($backupfile, 0600);
446
            $this->recurseDeleteInDir($mydir);
447
            rmdir($mydir);
448
        }
449
        return true;
450
    }
451
452
    /**
453
     * Update the "cvs_root_allow" file that contains the list of authorised CVS repositories
454
     *
455
     * @return Boolean
456
     */
457
    public function CVSRootListUpdate() {
458
        $cvs_root_allow_array = array();
459
        $projlist = array();
460
        $repolist = array();
461
462
        $service_dao = $this->_getServiceDao();
463
        $dar = $service_dao->searchActiveUnixGroupByUsedService('cvs');
464
        foreach ($dar as $row) {
465
            $repolist[]="/cvsroot/".$row['unix_group_name'];
466
        }
467
468
469
        if ($this->useCVSNT()) {
470
            $config_file=$GLOBALS['cvsnt_config_file'];
471
            $cvsnt_marker="DON'T EDIT THIS LINE - END OF CODENDI BLOCK";
472
        } else {
473
            $config_file=$GLOBALS['cvs_root_allow_file'];
474
        }
475
        $config_file_old=$config_file.".old";
476
        $config_file_new=$config_file.".new";
477
478
        if (is_file($config_file)) {
479
            $cvs_config_array = file($config_file);
480
        }
481
482
        $fp = fopen($config_file_new, 'w');
483
484
        if ($this->useCVSNT()) {
485
            fwrite($fp, "# Codendi CVSROOT directory list: do not edit this list!\n");
486
487
            $num=0;
488
            foreach ($repolist as $reponame) {
489
                fwrite($fp, "Repository$num=$reponame\n");
490
                $num++;
491
            }
492
            fwrite($fp, "# End of Codendi CVSROOT directory list: you may change options below $cvsnt_marker\n");
493
494
            // and recopy other configuration instructions
495
            $configlines=0;
496
            foreach ($cvs_config_array as $line) {
497
                if ($configlines) {
498
                    fwrite($fp, $line);
499
                }
500
                if (strpos($line, $cvsnt_marker)) {
501
                    $configlines=1;
502
                }
503
            }
504
        } else {
505
            // CVS: simple list of allowed CVS roots
506
            foreach ($repolist as $reponame) {
507
                fwrite($fp, "$reponame\n");
508
            }
509
        }
510
        fclose($fp);
511
512
        // Backup existing file and install new one if they are different
513
        $this->installNewFileVersion($config_file_new, $config_file, $config_file_old);
514
515
        return true;
516
    }
517
518
    /**
519
     * set whether CVS root need to be updated or not
520
     *
521
     * @return void
522
     */
523
    public function setCVSRootListNeedUpdate() {
524
        $this->CVSRootListNeedUpdate=true;
525
    }
526
527
    /**
528
     * Check if CVS root need update
529
     *
530
     * @return Boolean
531
     */
532
    public function getCVSRootListNeedUpdate() {
533
        return $this->CVSRootListNeedUpdate;
534
    }
535
536
    /**
537
     * Make the cvs repository of the project private or public
538
     *
539
     * @param Project $project    project for which project privacy is set
540
     * @param boolean $is_private true if the repository is private
541
     *
542
     * @return boolean true if success
543
     */
544
    public function setCVSPrivacy($project, $is_private) {
545
        $perms = $is_private ? 02770 : 02775;
546
        $cvsroot = $GLOBALS['cvs_prefix'] . '/' . $project->getUnixName(false);
547
        return is_dir($cvsroot) && $this->chmod($cvsroot, $perms);
548
    }
549
550
551
    /**
552
     * Check ownership/mode/privacy of repository
553
     *
554
     * @param Project $project The project to work on
555
     *
556
     * @return boolean true if success
557
     */
558
    public function checkCVSMode($project) {
559
        $unix_group_name =  $project->getUnixName(false);
560
        $cvsroot = $GLOBALS['cvs_prefix'] . '/' . $unix_group_name;
561
        $is_private = !$project->isPublic() || $project->isCVSPrivate();
562
        if ($is_private) {
563
            $perms = fileperms($cvsroot);
564
            // 'others' should have no right on the repository
565
            if (($perms & 0x0004) || ($perms & 0x0002) || ($perms & 0x0001) || ($perms & 0x0200)) {
566
                $this->log("Restoring privacy on CVS dir: $cvsroot", Backend::LOG_WARNING);
567
                $this->setCVSPrivacy($project, $is_private);
568
            }
569
        }
570
        // Sometimes, there might be a bad ownership on file (e.g. chmod failed, maintenance done as root...)
571
        $files_to_check=array('CVSROOT/loginfo', 'CVSROOT/commitinfo', 'CVSROOT/config');
572
        $need_owner_update = false;
573
        foreach ($files_to_check as $file) {
574
            if (file_exists($cvsroot.'/'.$file)) {
575
                // Get file stat
576
                $stat = stat("$cvsroot/$file");
577
                if ($stat) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $stat of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
578
                    if ( ($stat['uid'] != $this->getHTTPUserUID()) || ($stat['gid'] != $project->getUnixGID()) ) {
579
                        $need_owner_update = true;
580
                    }
581
                }
582
            } else {
583
                $this->log("File not found in cvsroot: $cvsroot/$file", Backend::LOG_WARNING);
584
            }
585
        }
586
        if ($need_owner_update) {
587
            $this->log("Restoring ownership on CVS dir: $cvsroot", Backend::LOG_INFO);
588
            $this->changeRepoOwnership($cvsroot, $unix_group_name);
589
            $this->system('chmod g+rws '.$cvsroot);
590
        }
591
592
        return true;
593
    }
594
   
595
    public function changeRepoOwnership($repo_path, $unix_group_name) {
596
            return $this->system("chown -R {$this->getHTTPUser()}:{$unix_group_name} $repo_path");
597
    }
598
    
599
    /**
600
     * Deleting files older than 2 hours in /var/run/log_accum that contain 'files'
601
     * (they have not been deleted due to commit abort)
602
     *
603
     * @return void
604
     */
605
    public function cleanup() {
606
        // TODO: test!
607
        $filelist = shell_exec("/usr/bin/find ".$GLOBALS['cvs_hook_tmp_dir'].' -name "*.files.*" -amin +120;');
608
        $files = explode("\n", $filelist);
609
        // Remove last (empty) element
610
        array_pop($files);
611
612
        foreach ($files as $file) {
613
            unlink($file);
614
        }
615
    }
616
617
    /**
618
     * Check if given name is not used by a repository or a file or a link
619
     *
620
     * @param String $name checked filename
621
     *
622
     * @return false if repository or file  or link already exists, true otherwise
623
     */
624
    function isNameAvailable($name) {
625
        $path = $GLOBALS['cvs_prefix']."/".$name;
626
        return  (!$this->fileExists($path));
627
    }
628
629
630
    /**
631
     * Rename cvs repository (following project unix_name change)
632
     *
633
     * @param Project $project Project to rename
634
     * @param String  $newName New name
635
     *
636
     * @return Boolean
637
     */
638
    public function renameCVSRepository($project, $newName) {
639
        if (rename($GLOBALS['cvs_prefix'].'/'.$project->getUnixName(false), $GLOBALS['cvs_prefix'].'/'.$newName)) {
640
            $this->renameLockDir($project, $newName);
641
            $this->renameLogInfoFile($project, $newName);
642
            $this->renameCommitInfoFile($project, $newName);
643
            return true;
644
        }
645
        return false;
646
    }
647
648
    /**
649
     * Rename CVS lock dir and corresponding file in repository
650
     *
651
     * @param Project $project Project to rename
652
     * @param String  $newName New name
653
     *
654
     * @return Boolean
655
     */
656
    public function renameLockDir($project, $newName) {
657
        $oldLockDir = $GLOBALS['cvslock_prefix'].'/'.$project->getUnixName(false);
658
        $newLockDir = $GLOBALS['cvslock_prefix'].'/'.$newName;
659
        if (is_dir($oldLockDir)) {
660
            rename($oldLockDir, $newLockDir);
661
        }
662
663
        $filename = $GLOBALS['cvs_prefix'].'/'.$newName.'/CVSROOT/config';
664
        $this->_RcsCheckout($filename);
665
        $file = file_get_contents($filename);
666
        $file = preg_replace('%'.$oldLockDir.'%m', $newLockDir, $file);
667
        file_put_contents($filename, $file);
668
        $this->_RcsCommit($filename);
669
670
        return true;
671
    }
672
673
    /**
674
     * Rename all project occurrences in the loginfo file
675
     *
676
     * @param Project $project Project to rename
677
     * @param String  $newName New name
678
     *
679
     * @return Boolean
680
     */
681
    public function renameLogInfoFile($project, $newName) {
682
        $filename = $GLOBALS['cvs_prefix'].'/'.$newName.'/CVSROOT/loginfo';
683
        $this->_RcsCheckout($filename);
684
        $file = file_get_contents($filename);
685
        $file = preg_replace('%(\s+)'.$project->getUnixName(false).'(\s+)%m', '$1'.$newName.'$2', $file);
686
        $file = preg_replace('%'.$GLOBALS['cvs_prefix'].'/'.$project->getUnixName(false).'%m', $GLOBALS['cvs_prefix'].'/'.$newName, $file);
687
        file_put_contents($filename, $file);
688
        $this->_RcsCommit($filename);
689
        return true;
690
    }
691
692
    /**
693
     * Rename all project occurrences in the commit file
694
     *
695
     * @param Project $project Project to rename
696
     * @param String  $newName New name
697
     *
698
     * @return Boolean
699
     */
700
    public function renameCommitInfoFile($project, $newName) {
701
        $filename = $GLOBALS['cvs_prefix'].'/'.$newName.'/CVSROOT/commitinfo';
702
        $this->_RcsCheckout($filename);
703
        $file = file_get_contents($filename);
704
        $file = preg_replace('%(\s+)'.$project->getUnixName(false).'(\s+)%m', '$1'.$newName.'$2', $file);
705
        file_put_contents($filename, $file);
706
        $this->_RcsCommit($filename);
707
        return true;
708
    }
709
}
710
711
?>
712