Rev Author Line No. Line
4988 kaklik 1 <?php
2 // WebSVN - Subversion repository viewing via the web using PHP
3 // Copyright (C) 2004-2006 Tim Armes
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 //
19 // --
20 //
21 // configclass.php
22 //
23 // General class for handling configuration options
24  
25 require_once 'include/command.php';
26 require_once 'include/authz.php';
27 require_once 'include/version.php';
28  
29 // Auxillary functions used to sort repositories by name/group
30  
31 // {{{ cmpReps($a, $b)
32  
33 function cmpReps($a, $b) {
34 // First, sort by group
35 $g = strcasecmp((string) $a->group, (string) $b->group);
36 if ($g) return $g;
37  
38 // Same group? Sort by name
39 return strcasecmp($a->name, $b->name);
40 }
41  
42 // }}}
43  
44 // {{{ cmpGroups($a, $b)
45  
46 function cmpGroups($a, $b) {
47 $g = strcasecmp((string) $a->group, (string) $b->group);
48 if ($g) return $g;
49  
50 return 0;
51 }
52  
53 // }}}
54  
55 // {{{ mergesort(&$array, [$cmp_function])
56  
57 function mergesort(&$array, $cmp_function = 'strcmp') {
58 // Arrays of size < 2 require no action
59  
60 if (count($array) < 2) return;
61  
62 // Split the array in half
63 $halfway = count($array) / 2;
64 $array1 = array_slice($array, 0, $halfway);
65 $array2 = array_slice($array, $halfway);
66  
67 // Recurse to sort the two halves
68 mergesort($array1, $cmp_function);
69 mergesort($array2, $cmp_function);
70  
71 // If all of $array1 is <= all of $array2, just append them.
72 if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) {
73 $array = array_merge($array1, $array2);
74 return;
75 }
76  
77 // Merge the two sorted arrays into a single sorted array
78 $array = array();
79 $array1count = count($array1);
80 $array2count = count($array2);
81 $ptr1 = 0;
82 $ptr2 = 0;
83 while ($ptr1 < $array1count && $ptr2 < $array2count) {
84 if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) {
85 $array[] = $array1[$ptr1++];
86 } else {
87 $array[] = $array2[$ptr2++];
88 }
89 }
90  
91 // Merge the remainder
92 while ($ptr1 < $array1count) $array[] = $array1[$ptr1++];
93 while ($ptr2 < $array2count) $array[] = $array2[$ptr2++];
94  
95 return;
96 }
97  
98 // }}}
99  
100 // A Repository parent path configuration class
101  
102 class ParentPath {
103 // {{{ Properties
104  
105 var $path;
106 var $group;
107 var $pattern;
108 var $skipAlreadyAdded;
109 var $clientRootURL;
110  
111 // }}}
112  
113 // {{{ __construct($path [, $group [, $pattern [, $skipAlreadyAdded [, $clientRootURL]]]])
114 function __construct($path, $group = null, $pattern = false, $skipAlreadyAdded = true, $clientRootURL = '') {
115 $this->path = $path;
116 $this->group = $group;
117 $this->pattern = $pattern;
118 $this->skipAlreadyAdded = $skipAlreadyAdded;
119 $this->clientRootURL = rtrim($clientRootURL, '/');
120 }
121 // }}}
122  
123 // {{{ findRepository($name)
124 // look for a repository with $name
125 function &findRepository($name) {
126 global $config;
127 if ($this->group != null) {
128 $prefix = $this->group.'.';
129 if (substr($name, 0, strlen($prefix)) == $prefix) {
130 $name = substr($name, strlen($prefix));
131 } else {
132 $null = null;
133 return $null;
134 }
135 }
136 // is there a directory named $name?
137 $fullpath = $this->path.DIRECTORY_SEPARATOR.$name;
138 if (is_dir($fullpath) && is_readable($fullpath)) {
139 // And that contains a db directory (in an attempt to not include non svn repositories.
140 $dbfullpath = $fullpath.DIRECTORY_SEPARATOR.'db';
141 if (is_dir($dbfullpath) && is_readable($dbfullpath)) {
142 // And matches the pattern if specified
143 if ($this->pattern === false || preg_match($this->pattern, $name)) {
144 $url = $config->fileUrlPrefix.$fullpath;
145 $url = str_replace(DIRECTORY_SEPARATOR, '/', $url);
146 if ($url[ strlen($url) - 1 ] == '/') {
147 $url = substr($url, 0, -1);
148 }
149  
150 if (!in_array($url, $config->_excluded, true)) {
151 $clientRootURL = ($this->clientRootURL) ? $this->clientRootURL.'/'.$name : '';
152 $rep = new Repository($name, $name, $url, $this->group, null, null, null, $clientRootURL);
153 return $rep;
154 }
155 }
156 }
157 }
158 $null = null;
159 return $null;
160 }
161 // }}}
162  
163 // {{{ getRepositories()
164 // return all repositories in the parent path matching pattern
165 function &getRepositories() {
166 global $config;
167 $repos = array();
168 $handle = @opendir($this->path);
169  
170 if (!$handle) return $repos;
171  
172 // For each file...
173 while (false !== ($name = readdir($handle))) {
174 $fullpath = $this->path.DIRECTORY_SEPARATOR.$name;
175 if ($name[0] != '.' && is_dir($fullpath) && is_readable($fullpath)) {
176 // And that contains a db directory (in an attempt to not include non svn repositories.
177 $dbfullpath = $fullpath.DIRECTORY_SEPARATOR.'db';
178 if (is_dir($dbfullpath) && is_readable($dbfullpath)) {
179 // And matches the pattern if specified
180 if ($this->pattern === false || preg_match($this->pattern, $name)) {
181 $url = $config->fileUrlPrefix.$fullpath;
182 $url = str_replace(DIRECTORY_SEPARATOR, '/', $url);
183 if ($url[strlen($url) - 1] == '/') {
184 $url = substr($url, 0, -1);
185 }
186 $clientRootURL = ($this->clientRootURL) ? $this->clientRootURL.'/'.$name : '';
187 $repos[] = new Repository($name, $name, $url, $this->group, null, null, null, $clientRootURL);
188 }
189 }
190 }
191 }
192 closedir($handle);
193  
194 // Sort the repositories into alphabetical order
195 if (!empty($repos)) {
196 usort($repos, 'cmpReps');
197 }
198  
199 return $repos;
200 }
201 // }}}
202  
203 // {{{ getSkipAlreadyAdded()
204 // Return if we should skip already added repos for this parent path.
205 function getSkipAlreadyAdded() {
206 return $this->skipAlreadyAdded;
207 }
208 // }}}
209 }
210  
211 // A Repository configuration class
212  
213 class Repository {
214 // {{{ Properties
215  
216 var $name;
217 var $svnName;
218 var $path;
219 var $subpath;
220 var $group;
221 var $username = null;
222 var $password = null;
223 var $clientRootURL;
224  
225 // Local configuration options must start off unset
226  
227 var $allowDownload;
228 var $minDownloadLevel;
229 var $allowedExceptions = array();
230 var $disallowedExceptions = array();
231 var $logsShowChanges;
232 var $rss;
233 var $rssCaching;
234 var $rssMaxEntries;
235 var $spaces;
236 var $ignoreSvnMimeTypes;
237 var $ignoreWebSVNContentTypes;
238 var $bugtraq;
239 var $bugtraqProperties;
240 var $authz = null;
241 var $templatePath = false;
242  
243 // }}}
244  
245 // {{{ __construct($name, $svnName, $serverRootURL [, $group [, $username [, $password [, $clientRootURL]]]])
246  
247 function __construct($name, $svnName, $serverRootURL, $group = null, $username = null, $password = null, $subpath = null, $clientRootURL = null) {
248 $this->name = $name;
249 $this->svnName = $svnName;
250 $this->path = $serverRootURL;
251 $this->subpath = $subpath;
252 $this->group = $group;
253 $this->username = $username;
254 $this->password = $password;
255 $this->clientRootURL = rtrim($clientRootURL, '/');
256 }
257  
258 // }}}
259  
260 // {{{ getDisplayName()
261  
262 function getDisplayName() {
263 if (!empty($this->group)) {
264 return $this->group.'.'.$this->name;
265 }
266  
267 return $this->name;
268 }
269  
270 // }}}
271  
272 // {{{ svnCredentials
273  
274 function svnCredentials() {
275 $params = '';
276 if ($this->username !== null && $this->username !== '') {
277 $params .= ' --username '.quote($this->username);
278 }
279 if ($this->password !== null) {
280 $params .= ' --password '.quote($this->password);
281 }
282 return $params;
283 }
284  
285 // }}}
286  
287 // Local configuration accessors
288  
289 function setLogsShowChanges($enabled = true) {
290 $this->logsShowChanges = $enabled;
291 }
292  
293 function logsShowChanges() {
294 global $config;
295  
296 if (isset($this->logsShowChanges))
297 return $this->logsShowChanges;
298 else
299 return $config->logsShowChanges();
300 }
301  
302 // {{{ RSS Feed
303  
304 function setRssEnabled($enabled) {
305 $this->rss = $enabled;
306 }
307  
308 function isRssEnabled() {
309 global $config;
310  
311 if (isset($this->rss))
312 return $this->rss;
313 else
314 return $config->isRssEnabled();
315 }
316  
317 function setRssCachingEnabled($enabled = true) {
318 $this->rssCaching = $enabled;
319 }
320  
321 function isRssCachingEnabled() {
322 global $config;
323  
324 if (isset($this->rssCaching))
325 return $this->rssCaching;
326 else
327 return $config->isRssCachingEnabled();
328 }
329  
330 function setRssMaxEntries($max) {
331 $this->rssMaxEntries = $max;
332 }
333  
334 function getRssMaxEntries() {
335 global $config;
336  
337 if (isset($this->rssMaxEntries))
338 return $this->rssMaxEntries;
339 else
340 return $config->getRssMaxEntries();
341 }
342  
343 // }}}
344  
345 // {{{ Download
346  
347 function allowDownload() {
348 $this->allowDownload = true;
349 }
350  
351 function disallowDownload() {
352 $this->allowDownload = false;
353 }
354  
355 function getAllowDownload() {
356 global $config;
357  
358 if (isset($this->allowDownload)) {
359 return $this->allowDownload;
360 }
361  
362 return $config->getAllowDownload();
363 }
364  
365 function setMinDownloadLevel($level) {
366 $this->minDownloadLevel = $level;
367 }
368  
369 function getMinDownloadLevel() {
370 global $config;
371  
372 if (isset($this->minDownloadLevel)) {
373 return $this->minDownloadLevel;
374 }
375  
376 return $config->getMinDownloadLevel();
377 }
378  
379 function addAllowedDownloadException($path) {
380 if ($path[strlen($path) - 1] != '/') $path .= '/';
381  
382 $this->allowedExceptions[] = $path;
383 }
384  
385 function addDisallowedDownloadException($path) {
386 if ($path[strlen($path) - 1] != '/') $path .= '/';
387  
388 $this->disallowedExceptions[] = $path;
389 }
390  
391 function isDownloadAllowed($path) {
392 global $config;
393  
394 // Check global download option
395 if (!$this->getAllowDownload()) {
396 return false;
397 }
398  
399 // Check with access module
400 if (!$this->hasUnrestrictedReadAccess($path)) {
401 return false;
402 }
403  
404 $subs = explode('/', $path);
405 $level = count($subs) - 2;
406 if ($level >= $this->getMinDownloadLevel()) {
407 // Level OK, search for disallowed exceptions
408  
409 if ($config->findException($path, $this->disallowedExceptions)) {
410 return false;
411 }
412  
413 if ($config->findException($path, $config->disallowedExceptions)) {
414 return false;
415 }
416  
417 return true;
418  
419 } else {
420 // Level not OK, search for disallowed exceptions
421  
422 if ($config->findException($path, $this->allowedExceptions)) {
423 return true;
424 }
425  
426 if ($config->findException($path, $config->allowedExceptions)) {
427 return true;
428 }
429  
430 return false;
431 }
432 }
433  
434 // }}}
435  
436 // {{{ Templates
437  
438 function setTemplatePath($path) {
439 $this->templatePath = $path;
440 }
441  
442 function getTemplatePath() {
443 global $config;
444 if (!empty($this->templatePath)) {
445 return $this->templatePath;
446 }
447  
448 return $config->getTemplatePath();
449 }
450  
451 // }}}
452  
453 // {{{ Tab expansion
454  
455 function expandTabsBy($sp) {
456 $this->spaces = $sp;
457 }
458  
459 function getExpandTabsBy() {
460 global $config;
461  
462 if (isset($this->spaces)) {
463 return $this->spaces;
464 }
465  
466 return $config->getExpandTabsBy();
467 }
468  
469 // }}}
470  
471 // {{{ MIME-Type Handing
472  
473 function ignoreSvnMimeTypes() {
474 $this->ignoreSvnMimeTypes = true;
475 }
476  
477 function useSvnMimeTypes() {
478 $this->ignoreSvnMimeTypes = false;
479 }
480  
481 function getIgnoreSvnMimeTypes() {
482 global $config;
483  
484 if (isset($this->ignoreSvnMimeTypes)) {
485 return $this->ignoreSvnMimeTypes;
486 }
487  
488 return $config->getIgnoreSvnMimeTypes();
489 }
490  
491 function ignoreWebSVNContentTypes() {
492 $this->ignoreWebSVNContentTypes = true;
493 }
494  
495 function useWebSVNContentTypes() {
496 $this->ignoreWebSVNContentTypes = false;
497 }
498  
499 function getIgnoreWebSVNContentTypes() {
500 global $config;
501  
502 if (isset($this->ignoreWebSVNContentTypes)) {
503 return $this->ignoreWebSVNContentTypes;
504 }
505  
506 return $config->getIgnoreWebSVNContentTypes();
507 }
508  
509 // }}}
510  
511 // {{{ Bugtraq issue tracking
512  
513 function setBugtraqEnabled($enabled) {
514 $this->bugtraq = $enabled;
515 }
516  
517 function isBugtraqEnabled() {
518 global $config;
519  
520 if (isset($this->bugtraq))
521 return $this->bugtraq;
522 else
523 return $config->isBugtraqEnabled();
524 }
525  
526 function setBugtraqProperties($properties) {
527 $this->bugtraqProperties = $properties;
528 }
529  
530 function getBugtraqProperties() {
531 global $config;
532  
533 if (isset($this->bugtraqProperties))
534 return $this->bugtraqProperties;
535 else
536 return $config->getBugtraqProperties();
537 }
538  
539 // }}}
540  
541 // {{{ Authorization
542  
543 function useAccessFile($file) {
544 if (is_readable($file)) {
545 if ($this->authz === null) {
546 $this->authz = new Authorization();
547 }
548 $this->authz->addAccessFile($file);
549 } else {
550 die('Unable to read access file "'.$file.'"');
551 }
552 }
553  
554 function &getAuthz() {
555 global $config;
556  
557 $a = null;
558 if ($this->authz !== null) {
559 $a =& $this->authz;
560 } else {
561 $a =& $config->getAuthz();
562 }
563 return $a;
564 }
565  
566 function _getPathWithSubIf($pathWoSub) {
567 if (!$this->subpath) {
568 return $pathWoSub;
569 }
570  
571 return '/' . $this->subpath . $pathWoSub;
572 }
573  
574 function hasReadAccess($pathWoSub, $checkSubDirs = false) {
575 $path = $this->_getPathWithSubIf($pathWoSub);
576 $a =& $this->getAuthz();
577  
578 if (!empty($a)) {
579 return $a->hasReadAccess($this->svnName, $path, $checkSubDirs);
580 }
581  
582 // No access file - free access...
583 return true;
584 }
585  
586 function hasLogReadAccess($pathWithSub) {
587 $path = $pathWithSub;
588 $a =& $this->getAuthz();
589  
590 if (!empty($a)) {
591 return $a->hasReadAccess($this->svnName, $path, false);
592 }
593  
594 // No access file - free access...
595 return true;
596 }
597  
598 function hasUnrestrictedReadAccess($pathWoSub) {
599 $path = $this->_getPathWithSubIf($pathWoSub);
600 $a =& $this->getAuthz();
601  
602 if (!empty($a)) {
603 return $a->hasUnrestrictedReadAccess($this->svnName, $path);
604 }
605  
606 // No access file - free access...
607 return true;
608 }
609  
610 // }}}
611  
612 }
613  
614 // The general configuration class
615  
616 class WebSvnConfig {
617 // {{{ Properties
618  
619 // Tool path locations
620  
621 var $_svnCommandPath = '';
622 var $_svnConfigDir = '/tmp/websvn';
623 var $_svnTrustServerCert = false;
624 var $svn = 'svn --non-interactive --config-dir /tmp/websvn';
625 var $svnAuthz = 'svnauthz accessof';
626 var $diff = 'diff';
627 var $enscript = 'enscript -q';
628 var $sed = 'sed';
629 var $gzip = 'gzip';
630 var $tar = 'tar';
631 var $zip = 'zip';
632 var $locale = '';
633  
634 // different modes for file and directory download
635  
636 var $defaultFileDlMode = 'plain';
637 var $defaultDirectoryDlMode = 'gzip';
638  
639 var $validFileDlModes = array( 'gzip', 'zip', 'plain' );
640 var $validDirectoryDlModes = array( 'gzip', 'zip' );
641  
642 // Other configuration items
643  
644 var $treeView = true;
645 var $flatIndex = true;
646 var $openTree = false;
647 var $alphabetic = false;
648 var $showLastModInIndex = true;
649 var $showLastModInListing = true;
650 var $showAgeInsteadOfDate = true;
651 var $_showRepositorySelectionForm = true;
652 var $_ignoreWhitespacesInDiff = false;
653 var $serverIsWindows = false;
654 var $multiViews = false;
655 var $multiViewsIndex = 'browse';
656 var $useEnscript = false;
657 var $useEnscriptBefore_1_6_3 = false;
658 var $useGeshi = false;
659 var $geshiScript = 'geshi.php';
660 var $useParsedown = false;
661 var $parsedownScript = 'Parsedown.php';
662 var $inlineMimeTypes = array();
663 var $allowDownload = false;
664 var $tempDir = '';
665 var $minDownloadLevel = 0;
666 var $allowedExceptions = array();
667 var $disallowedExceptions = array();
668 var $logsShowChanges = false;
669 var $rss = true;
670 var $rssCaching = false;
671 var $rssMaxEntries = 40;
672 var $spaces = 8;
673 var $bugtraq = false;
674 var $bugtraqProperties = null;
675 var $authz = null;
676 var $blockRobots = false;
677  
678 var $loadAllRepos = false;
679  
680 var $templatePaths = array();
681 var $userTemplate = false;
682  
683 var $ignoreSvnMimeTypes = false;
684 var $ignoreWebSVNContentTypes = false;
685  
686 var $subversionVersion = '';
687 var $subversionMajorVersion = '';
688 var $subversionMinorVersion = '';
689  
690 var $defaultLanguage = 'en';
691 var $ignoreAcceptedLanguages = false;
692  
693 var $quote = "'";
694 var $pathSeparator = ':';
695 var $fileUrlPrefix = 'file://';
696 var $breadcrumbRepoRootAsRepo = false;
697  
698 var $_repositories = array();
699  
700 var $_parentPaths = array(); // parent paths to load
701  
702 var $_parentPathsLoaded = false;
703  
704 var $_excluded = array();
705  
706 // }}}
707  
708 // {{{ __construct()
709  
710 function __construct() {
711 }
712  
713 // }}}
714  
715 // {{{ Repository configuration
716  
717 function addRepository($name, $serverRootURL, $group = null, $username = null, $password = null, $clientRootURL = null) {
718 $this->addRepositorySubpath($name, $serverRootURL, null, $group, $username, $password, $clientRootURL);
719 }
720  
721 function addRepositorySubpath($name, $serverRootURL, $subpath, $group = null, $username = null, $password = null, $clientRootURL = null) {
722 if (DIRECTORY_SEPARATOR != '/') {
723 $serverRootURL = str_replace(DIRECTORY_SEPARATOR, '/', $serverRootURL);
724 if ($subpath !== null) {
725 $subpath = str_replace(DIRECTORY_SEPARATOR, '/', $subpath);
726 }
727 }
728 $serverRootURL = trim($serverRootURL, '/');
729 $svnName = substr($serverRootURL, strrpos($serverRootURL, '/') + 1);
730 $this->_repositories[] = new Repository($name, $svnName, $serverRootURL, $group, $username, $password, $subpath, $clientRootURL);
731 }
732  
733 // Automatically set up the repositories based on a parent path
734  
735 function parentPath($path, $group = null, $pattern = false, $skipAlreadyAdded = true, $clientRootURL = '') {
736 $this->_parentPaths[] = new ParentPath($path, $group, $pattern, $skipAlreadyAdded, $clientRootURL);
737 }
738  
739 function addExcludedPath($path) {
740 $url = $this->fileUrlPrefix.$path;
741 $url = str_replace(DIRECTORY_SEPARATOR, '/', $url);
742 if ($url[strlen($url) - 1] == '/') {
743 $url = substr($url, 0, -1);
744 }
745 $this->_excluded[] = $url;
746 }
747  
748 function getRepositories() {
749 // lazily load parent paths
750 if ($this->_parentPathsLoaded) return $this->_repositories;
751  
752 $this->_parentPathsLoaded = true;
753  
754 foreach ($this->_parentPaths as $parentPath) {
755 $parentRepos = $parentPath->getRepositories();
756 foreach ($parentRepos as $repo) {
757 if (!$parentPath->getSkipAlreadyAdded()) {
758 $this->_repositories[] = $repo;
759 } else {
760 // we have to check if we already have a repo with the same svn name
761 $duplicate = false;
762 foreach ($this->_repositories as $knownRepos) {
763 if ($knownRepos->path == $repo->path && $knownRepos->subpath == $repo->subpath) {
764 $duplicate = true;
765 break;
766 }
767 }
768  
769 if (!$duplicate && !in_array($repo->path, $this->_excluded, true)) {
770 $this->_repositories[] = $repo;
771 }
772 }
773 }
774 }
775  
776 return $this->_repositories;
777 }
778  
779 function &findRepository($name) {
780 // first look in the "normal repositories"
781 foreach ($this->_repositories as $index => $rep) {
782 if (strcmp($rep->getDisplayName(), $name) == 0) {
783 $repref =& $this->_repositories[$index];
784 return $repref;
785 }
786 }
787  
788 // now if the parent repos have not already been loaded
789 // check them
790 if (!$this->_parentPathsLoaded) {
791 foreach ($this->_parentPaths as $parentPath) {
792 $repref =& $parentPath->findRepository($name);
793 if ($repref != null) {
794 $this->_repositories[] = $repref;
795 return $repref;
796 }
797 }
798 }
799  
800 // Hack to return a string by reference; value retrieved at setup.php:414
801 $str = 'Unable to find repository "'.escape($name).'".';
802 $error =& $str;
803 return $error;
804 }
805  
806 // }}}
807  
808 // {{{ setServerIsWindows
809 //
810 // The server is running on Windows
811  
812 function setServerIsWindows() {
813 $this->serverIsWindows = true;
814  
815 // On Windows machines, use double quotes around command line parameters
816 $this->quote = '"';
817  
818 // On Windows, semicolon separates path entries in a list rather than colon.
819 $this->pathSeparator = ';';
820  
821 $this->fileUrlPrefix = 'file:///';
822 }
823  
824 // }}}
825  
826 // {{{ MultiViews
827  
828 // useMultiViews
829 //
830 // Use MultiViews to access the repository
831  
832 function useMultiViews($multiViewsIndex = 'browse') {
833 $this->multiViews = true;
834 $this->multiViewsIndex = $multiViewsIndex;
835 }
836  
837 function getUseMultiViews() {
838 return $this->multiViews;
839 }
840  
841 function getMultiViewsIndex() {
842 return $this->multiViewsIndex;
843 }
844  
845 // }}}
846  
847 // {{{ Enscript
848  
849 // useEnscript
850 //
851 // Use Enscript to colourise listings
852  
853 function useEnscript($before_1_6_3 = false) {
854 $this->useEnscript = true;
855 $this->useEnscriptBefore_1_6_3 = $before_1_6_3;
856 }
857  
858 function getUseEnscript() {
859 return $this->useEnscript;
860 }
861  
862 function getUseEnscriptBefore_1_6_3() {
863 return $this->useEnscriptBefore_1_6_3;
864 }
865  
866 // }}}
867  
868 // {{{ GeSHi
869  
870 function setGeshiPath($path) {
871 $this->_setPath($this->geshiScript, $path, 'geshi.php');
872 }
873  
874 function getGeshiScript() {
875 return $this->geshiScript;
876 }
877  
878 // useGeshi
879 //
880 // Use GeSHi to colourise listings
881 function useGeshi() {
882 $this->useGeshi = true;
883 }
884  
885 function getUseGeshi() {
886 return $this->useGeshi;
887 }
888  
889 // }}}
890  
891 // {{{ Parsedown
892  
893 function setParsedownPath($path) {
894 $this->_setPath($this->parsedownScript, $path, 'Parsedown.php');
895 }
896  
897 function getParsedownScript() {
898 return $this->parsedownScript;
899 }
900  
901 // useParsedown
902 //
903 // Use Parsedown to render README.md
904 function useParsedown() {
905 $this->useParsedown = true;
906 }
907  
908 function getUseParsedown() {
909 return $this->useParsedown;
910 }
911  
912 // }}}
913  
914 // {{{ Inline MIME Types
915  
916 // inlineMimeTypes
917 //
918 // Specify MIME types to display inline in WebSVN pages
919 function addInlineMimeType($type) {
920 if (!in_array($type, $this->inlineMimeTypes)) {
921 $this->inlineMimeTypes[] = $type;
922 }
923 }
924  
925 // }}}
926  
927 // {{{ Show changed files by default on log.php
928  
929 function setLogsShowChanges($enabled = true, $myrep = 0) {
930 if (empty($myrep)) {
931 $this->logsShowChanges = $enabled;
932 } else {
933 $repo =& $this->findRepository($myrep);
934 $repo->logsShowChanges = $enabled;
935 }
936 }
937  
938 function logsShowChanges() {
939 return $this->logsShowChanges;
940 }
941  
942 // }}}
943  
944 // {{{ RSS
945  
946 function setRssEnabled($enabled = true, $myrep = 0) {
947 if (empty($myrep)) {
948 $this->rss = $enabled;
949 } else {
950 $repo =& $this->findRepository($myrep);
951 $repo->setRssEnabled($enabled);
952 }
953 }
954  
955 function isRssEnabled() {
956 return $this->rss;
957 }
958  
959 function setRssCachingEnabled($enabled = true, $myrep = 0) {
960 if (empty($myrep)) {
961 $this->rssCaching = true;
962 } else {
963 $repo =& $this->findRepository($myrep);
964 $repo->setRssCachingEnabled($enabled);
965 }
966 }
967  
968 function isRssCachingEnabled() {
969 return $this->rssCaching;
970 }
971  
972 // Maximum number of entries in RSS feed
973  
974 function setRssMaxEntries($max, $myrep = 0) {
975 if (empty($myrep)) {
976 $this->rssMaxEntries = $max;
977 } else {
978 $repo =& $this->findRepository($myrep);
979 $repo->setRssMaxEntries($max);
980 }
981 }
982  
983 function getRssMaxEntries() {
984 return $this->rssMaxEntries;
985 }
986  
987 function getHideRSS() {
988 return $this->rss;
989 }
990  
991 // cacheRSS
992 //
993 // Enable caching of RSS feeds
994  
995 function enableRSSCaching($myrep = 0) {
996 if (empty($myrep)) {
997 $this->rssCaching = true;
998 } else {
999 $repo =& $this->findRepository($myrep);
1000 $repo->enableRSSCaching();
1001 }
1002 }
1003  
1004 function getRSSCaching() {
1005 return $this->rssCaching;
1006 }
1007  
1008 // }}}
1009  
1010 // {{{ Downloads
1011  
1012 // allowDownload
1013 //
1014 // Allow download of tarballs
1015  
1016 function allowDownload($myrep = 0) {
1017 if (empty($myrep)) {
1018 $this->allowDownload = true;
1019 } else {
1020 $repo =& $this->findRepository($myrep);
1021 $repo->allowDownload();
1022 }
1023 }
1024  
1025 function disallowDownload($myrep = 0) {
1026 if (empty($myrep)) {
1027 $this->allowDownload = false;
1028 } else {
1029 $repo =& $this->findRepository($myrep);
1030 $repo->disallowDownload();
1031 }
1032 }
1033  
1034 function getAllowDownload() {
1035 return $this->allowDownload;
1036 }
1037  
1038 function setTempDir($tempDir) {
1039 $this->tempDir = $tempDir;
1040 }
1041  
1042 function getTempDir() {
1043 if (empty($this->tempDir)) {
1044 $this->tempDir = sys_get_temp_dir();
1045 }
1046 return $this->tempDir;
1047 }
1048  
1049 function setMinDownloadLevel($level, $myrep = 0) {
1050 if (empty($myrep)) {
1051 $this->minDownloadLevel = $level;
1052 } else {
1053 $repo =& $this->findRepository($myrep);
1054 $repo->setMinDownloadLevel($level);
1055 }
1056 }
1057  
1058 function getMinDownloadLevel() {
1059 return $this->minDownloadLevel;
1060 }
1061  
1062 function addAllowedDownloadException($path, $myrep = 0) {
1063 if ($path[strlen($path) - 1] != '/') {
1064 $path .= '/';
1065 }
1066  
1067 if (empty($myrep)) {
1068 $this->allowedExceptions[] = $path;
1069 } else {
1070 $repo =& $this->findRepository($myrep);
1071 $repo->addAllowedDownloadException($path);
1072 }
1073 }
1074  
1075 function addDisallowedDownloadException($path, $myrep = 0) {
1076 if ($path[strlen($path) - 1] != '/') {
1077 $path .= '/';
1078 }
1079  
1080 if (empty($myrep)) {
1081 $this->disallowedExceptions[] = $path;
1082 } else {
1083 $repo =& $this->findRepository($myrep);
1084 $repo->addDisallowedDownloadException($path);
1085 }
1086 }
1087  
1088 function findException($path, $exceptions) {
1089 foreach ($exceptions as $key => $exc) {
1090 if (strncmp($exc, $path, strlen($exc)) == 0) {
1091 return true;
1092 }
1093 }
1094  
1095 return false;
1096 }
1097  
1098 // }}}
1099  
1100 // {{{ getURL
1101 //
1102 // Get the URL to a path name based on the current config
1103  
1104 function getURL($rep, $path, $op) {
1105 list($base, $params) = $this->getUrlParts($rep, $path, $op);
1106 $url = $base.'?';
1107 foreach ($params as $k => $v) {
1108 $url .= $k.'='.rawurlencode($v).'&amp;';
1109 }
1110 return $url;
1111 }
1112  
1113 // }}}
1114  
1115 // {{{ getUrlParts
1116 //
1117 // Get the URL and parameters for a path name based on the current config
1118  
1119 function getUrlParts($rep, $path, $op) {
1120 $params = array();
1121  
1122 if ($this->multiViews) {
1123 $url = $_SERVER['SCRIPT_NAME'];
1124 if (preg_match('|\.php$|i', $url)) {
1125 // remove the .php extension
1126 $url = substr($url, 0, -4);
1127 }
1128  
1129 if ($path && $path[0] != '/') {
1130 $path = '/'.$path;
1131 }
1132  
1133 if (substr($url, -5) == 'index') {
1134 $url = substr($url, 0, -5).$this->multiViewsIndex;
1135 }
1136  
1137 if ($op == 'index') {
1138 $url .= '/';
1139 } else if (is_object($rep)) {
1140 $url .= '/'.$rep->getDisplayName().str_replace('%2F', '/', rawurlencode($path ?? ''));
1141  
1142 if ($op && $op != 'dir' && $op != 'file') {
1143 $params['op'] = $op;
1144 }
1145 }
1146  
1147 } else {
1148 switch ($op) {
1149 case 'index':
1150 $url = '.';
1151 break;
1152  
1153 case 'dir':
1154 $url = 'listing.php';
1155 break;
1156  
1157 case 'revision':
1158 $url = 'revision.php';
1159 break;
1160  
1161 case 'file':
1162 $url = 'filedetails.php';
1163 break;
1164  
1165 case 'log':
1166 $url = 'log.php';
1167 break;
1168  
1169 case 'diff':
1170 $url = 'diff.php';
1171 break;
1172  
1173 case 'blame':
1174 $url = 'blame.php';
1175 break;
1176  
1177 case 'form':
1178 $url = 'form.php';
1179 break;
1180  
1181 case 'rss':
1182 $url = 'rss.php';
1183 break;
1184  
1185 case 'dl':
1186 $url = 'dl.php';
1187 break;
1188  
1189 case 'comp':
1190 $url = 'comp.php';
1191 break;
1192  
1193 case 'search':
1194 $url = 'search.php';
1195 break;
1196 }
1197  
1198 if (is_object($rep) && $op != 'index') {
1199 $params['repname'] = $rep->getDisplayName();
1200 }
1201 if (!empty($path)) {
1202 $params['path'] = $path;
1203 }
1204 }
1205  
1206 return array($url, $params);
1207 }
1208  
1209 // }}}
1210  
1211 // {{{ Paths and Commands
1212  
1213 // setPath
1214 //
1215 // Set the location of the given path
1216  
1217 function _setPath(&$var, $path, $name, $params = '') {
1218 if ($path == '') {
1219 // Search in system search path. No check for existence possible
1220 $var = $name;
1221 } else {
1222 $lastchar = substr($path, -1, 1);
1223 $isDir = ($lastchar == DIRECTORY_SEPARATOR || $lastchar == '/' || $lastchar == '\\');
1224  
1225 if (!$isDir) $path .= DIRECTORY_SEPARATOR;
1226  
1227 if (($this->serverIsWindows && !file_exists($path.$name.'.exe')) || (!$this->serverIsWindows && !file_exists($path.$name))) {
1228 echo 'Unable to find "'.$name.'" tool at location "'.$path.$name.'"';
1229 exit;
1230 }
1231  
1232 // On a windows machine we need to put quotes around the
1233 // entire command to allow for spaces in the path
1234 if ($this->serverIsWindows) {
1235 $var = '"'.$path.$name.'"';
1236 } else {
1237 $var = $path.$name;
1238 }
1239 }
1240  
1241 // Append parameters
1242 if ($params != '') $var .= ' '.$params;
1243 }
1244  
1245 // Define directory path to use for --config-dir parameter
1246 function setSvnConfigDir($path) {
1247 $this->_svnConfigDir = $path;
1248 $this->_updateSvnCommand();
1249 }
1250  
1251 // Define flag to use --trust-server-cert parameter
1252 function setTrustServerCert() {
1253 $this->_svnTrustServerCert = true;
1254 $this->_updateSvnCommand();
1255 }
1256  
1257 // Define the location of the svn command (e.g. '/usr/bin')
1258 function setSvnCommandPath($path) {
1259 $this->_svnCommandPath = $path;
1260 $this->_updateSvnCommand();
1261 }
1262  
1263 // Define the location of the svnauthz command (e.g. '/usr/bin')
1264 function setSvnAuthzCommandPath($path) {
1265 $this->_setPath($this->svnAuthz, $path, 'svnauthz', 'accessof');
1266 }
1267  
1268 function _updateSvnCommand() {
1269 $this->_setPath($this->svn, $this->_svnCommandPath, 'svn', '--non-interactive --config-dir '.$this->_svnConfigDir.($this->_svnTrustServerCert ? ' --trust-server-cert' : ''));
1270 }
1271  
1272 function getSvnCommand() {
1273 return $this->svn;
1274 }
1275  
1276 function getSvnAuthzCommand() {
1277 return $this->svnAuthz;
1278 }
1279  
1280 // setDiffPath
1281 //
1282 // Define the location of the diff command
1283  
1284 function setDiffPath($path) {
1285 $this->_setPath($this->diff, $path, 'diff');
1286 }
1287  
1288 function getDiffCommand() {
1289 return $this->diff;
1290 }
1291  
1292 // setEnscriptPath
1293 //
1294 // Define the location of the enscript command
1295  
1296 function setEnscriptPath($path) {
1297 $this->_setPath($this->enscript, $path, 'enscript', '-q');
1298 }
1299  
1300 function getEnscriptCommand() {
1301 return $this->enscript;
1302 }
1303  
1304 // setSedPath
1305 //
1306 // Define the location of the sed command
1307  
1308 function setSedPath($path) {
1309 $this->_setPath($this->sed, $path, 'sed');
1310 }
1311  
1312 function getSedCommand() {
1313 return $this->sed;
1314 }
1315  
1316 // setTarPath
1317 //
1318 // Define the location of the tar command
1319  
1320 function setTarPath($path) {
1321 $this->_setPath($this->tar, $path, 'tar');
1322 }
1323  
1324 function getTarCommand() {
1325 return $this->tar;
1326 }
1327  
1328 // setGzipPath
1329 //
1330 // Define the location of the GZip command
1331  
1332 function setGzipPath($path) {
1333 $this->_setPath($this->gzip, $path, 'gzip');
1334 }
1335  
1336 function getGzipCommand() {
1337 return $this->gzip;
1338 }
1339  
1340 // setZipPath
1341 //
1342 // Define the location of the zip command
1343 function setZipPath($path) {
1344 $this->_setPath($this->zip, $path, 'zip');
1345 }
1346  
1347 function getZipPath() {
1348 return $this->zip;
1349 }
1350  
1351 // setLocale
1352 //
1353 // Set the locale for PHP and all spawned processes
1354  
1355 function setLocale($locale) {
1356 $this->locale = $locale;
1357 }
1358  
1359 function getLocale() {
1360 return $this->locale;
1361 }
1362  
1363 // setDefaultFileDlMode
1364 //
1365 // Define the default file download mode - one of [gzip, zip, plain]
1366 function setDefaultFileDlMode($dlmode) {
1367 if (in_array($dlmode, $this->validFileDlModes)) {
1368 $this->defaultFileDlMode = $dlmode;
1369 } else {
1370 echo 'Setting default file download mode to an invalid value "'.$dlmode.'"';
1371 exit;
1372 }
1373 }
1374  
1375 function getDefaultFileDlMode() {
1376 return $this->defaultFileDlMode;
1377 }
1378  
1379 // setDefaultDirectoryDlMode
1380 //
1381 // Define the default directory download mode - one of [gzip, zip]
1382 function setDefaultDirectoryDlMode($dlmode) {
1383 if (in_array($dlmode, $this->validDirectoryDlModes)) {
1384 $this->defaultDirectoryDlMode = $dlmode;
1385 } else {
1386 echo 'Setting default directory download mode to an invalid value "'.$dlmode.'"';
1387 exit;
1388 }
1389 }
1390  
1391 function setDefaultFolderDlMode($dlmode) {
1392 $this->setDefaultDirectoryDlMode($dlmode);
1393 }
1394  
1395 function getDefaultDirectoryDlMode() {
1396 return $this->defaultDirectoryDlMode;
1397 }
1398  
1399 function getDefaultFolderDlMode() {
1400 return $this->getDefaultDirectoryDlMode();
1401 }
1402  
1403 // Templates
1404  
1405 function addTemplatePath($path) {
1406 $lastchar = substr($path, -1, 1);
1407 if ($lastchar != '/' && $lastchar != '\\') {
1408 $path .= DIRECTORY_SEPARATOR;
1409 }
1410  
1411 if (!in_array($path, $this->templatePaths)) {
1412 $this->templatePaths[] = $path;
1413 }
1414 }
1415  
1416 function setTemplatePath($path, $myrep = null) {
1417 $lastchar = substr($path, -1, 1);
1418 if ($lastchar != '/' && $lastchar != '\\') {
1419 $path .= DIRECTORY_SEPARATOR;
1420 }
1421  
1422 if ($myrep !== null) {
1423 // fixed template for specific repository
1424 $repo =& $this->findRepository($myrep);
1425 $repo->setTemplatePath($path);
1426 } else {
1427 // for backward compatibility
1428 if (in_array($path, $this->templatePaths)) {
1429 array_splice($this->templatePaths, array_search($path, $this->templatePaths), 1);
1430 }
1431 array_unshift($this->templatePaths, $path);
1432 }
1433 }
1434  
1435 function getTemplatePath() {
1436 if (count($this->templatePaths) == 0) {
1437 echo 'No template path added in config file';
1438 exit;
1439 }
1440 if ($this->userTemplate !== false)
1441 return $this->userTemplate;
1442 else
1443 return $this->templatePaths[0];
1444 }
1445  
1446 // }}}
1447  
1448 function setDefaultLanguage($language) {
1449 $this->defaultLanguage = $language;
1450 }
1451  
1452 function getDefaultLanguage() {
1453 return $this->defaultLanguage;
1454 }
1455  
1456 function ignoreUserAcceptedLanguages() {
1457 $this->ignoreAcceptedLanguages = true;
1458 }
1459  
1460 function useAcceptedLanguages() {
1461 return !$this->ignoreAcceptedLanguages;
1462 }
1463  
1464 // {{{ Tab expansion functions
1465  
1466 function expandTabsBy($sp, $myrep = 0) {
1467 if (empty($myrep)) {
1468 $this->spaces = $sp;
1469 } else {
1470 $repo =& $this->findRepository($myrep);
1471 $repo->expandTabsBy($sp);
1472 }
1473 }
1474  
1475 function getExpandTabsBy() {
1476 return $this->spaces;
1477 }
1478  
1479 // }}}
1480  
1481 // {{{ Bugtraq issue tracking
1482  
1483 function setBugtraqEnabled($enabled, $myrep = 0) {
1484 if (empty($myrep)) {
1485 $this->bugtraq = $enabled;
1486 } else {
1487 $repo =& $this->findRepository($myrep);
1488 $repo->setBugtraqEnabled($enabled);
1489 }
1490 }
1491  
1492 function isBugtraqEnabled() {
1493 return $this->bugtraq;
1494 }
1495  
1496 function setBugtraqProperties($message, $logregex, $url, $append = true, $myrep = null) {
1497 $properties = array();
1498 $properties['bugtraq:message'] = $message;
1499 $properties['bugtraq:logregex'] = $logregex;
1500 $properties['bugtraq:url'] = $url;
1501 $properties['bugtraq:append'] = (bool)$append;
1502 if ($myrep === null) {
1503 $this->bugtraqProperties = $properties;
1504 } else {
1505 $repo =& $this->findRepository($myrep);
1506 $repo->setBugtraqProperties($properties);
1507 }
1508 }
1509  
1510 function getBugtraqProperties() {
1511 return $this->bugtraqProperties;
1512 }
1513  
1514 // }}}
1515  
1516 // {{{ Misc settings
1517  
1518 function ignoreSvnMimeTypes() {
1519 $this->ignoreSvnMimeTypes = true;
1520 }
1521  
1522 function getIgnoreSvnMimeTypes() {
1523 return $this->ignoreSvnMimeTypes;
1524 }
1525  
1526 function ignoreWebSVNContentTypes() {
1527 $this->ignoreWebSVNContentTypes = true;
1528 }
1529  
1530 function getIgnoreWebSVNContentTypes() {
1531 return $this->ignoreWebSVNContentTypes;
1532 }
1533  
1534 function useAccessFile($file, $myrep = 0) {
1535 if (empty($myrep)) {
1536 if (is_readable($file)) {
1537 if ($this->authz === null) {
1538 $this->authz = new Authorization();
1539 }
1540 $this->authz->addAccessFile($file);
1541 } else {
1542 echo 'Unable to read access file "'.$file.'"';
1543 exit;
1544 }
1545 } else {
1546 $repo =& $this->findRepository($myrep);
1547 $repo->useAccessFile($file);
1548 }
1549 }
1550  
1551 function &getAuthz() {
1552 return $this->authz;
1553 }
1554  
1555 function areRobotsBlocked() {
1556 return $this->blockRobots;
1557 }
1558  
1559 function setBlockRobots($value = true) {
1560 $this->blockRobots = $value;
1561 }
1562  
1563 function useTreeView() {
1564 $this->treeView = true;
1565 }
1566  
1567 function getUseTreeView() {
1568 return $this->treeView;
1569 }
1570  
1571 function useFlatView() {
1572 $this->treeView = false;
1573 }
1574  
1575 function useTreeIndex($open) {
1576 $this->flatIndex = false;
1577 $this->openTree = $open;
1578 }
1579  
1580 function getUseFlatIndex() {
1581 return $this->flatIndex;
1582 }
1583  
1584 function getOpenTree() {
1585 return $this->openTree;
1586 }
1587  
1588 function setLoadAllRepos($flag) {
1589 $this->loadAllRepos = $flag;
1590 }
1591  
1592 function showLoadAllRepos() {
1593 return $this->loadAllRepos;
1594 }
1595  
1596 function setAlphabeticOrder($flag) {
1597 $this->alphabetic = $flag;
1598 }
1599  
1600 function isAlphabeticOrder() {
1601 return $this->alphabetic;
1602 }
1603  
1604 function showLastModInIndex() {
1605 return $this->showLastModInIndex;
1606 }
1607  
1608 function setShowLastModInIndex($show) {
1609 $this->showLastModInIndex = $show;
1610 }
1611  
1612 function showLastModInListing() {
1613 return $this->showLastModInListing;
1614 }
1615  
1616 function setShowLastModInListing($show) {
1617 $this->showLastModInListing = $show;
1618 }
1619  
1620 function showAgeInsteadOfDate() {
1621 return $this->showAgeInsteadOfDate;
1622 }
1623  
1624 function setShowAgeInsteadOfDate($show) {
1625 $this->showAgeInsteadOfDate = $show;
1626 }
1627  
1628 function showRepositorySelectionForm() {
1629 return $this->_showRepositorySelectionForm;
1630 }
1631  
1632 function setShowRepositorySelectionForm($show) {
1633 $this->_showRepositorySelectionForm = $show;
1634 }
1635  
1636 function getIgnoreWhitespacesInDiff() {
1637 return $this->_ignoreWhitespacesInDiff;
1638 }
1639  
1640 function setIgnoreWhitespacesInDiff($ignore) {
1641 $this->_ignoreWhitespacesInDiff = $ignore;
1642 }
1643  
1644 // Methods for storing version information for the command-line svn tool
1645  
1646 function setSubversionVersion($subversionVersion) {
1647 $this->subversionVersion = $subversionVersion;
1648 }
1649  
1650 function getSubversionVersion() {
1651 return $this->subversionVersion;
1652 }
1653  
1654 function setSubversionMajorVersion($subversionMajorVersion) {
1655 $this->subversionMajorVersion = $subversionMajorVersion;
1656 }
1657  
1658 function getSubversionMajorVersion() {
1659 return $this->subversionMajorVersion;
1660 }
1661  
1662 function setSubversionMinorVersion($subversionMinorVersion) {
1663 $this->subversionMinorVersion = $subversionMinorVersion;
1664 }
1665  
1666 function getSubversionMinorVersion() {
1667 return $this->subversionMinorVersion;
1668 }
1669  
1670 // }}}
1671  
1672 // {{{ Sort the repostories
1673 //
1674 // This function sorts the repositories by group name. The contents of the
1675 // group are left in there original order, which will either be sorted if the
1676 // group was added using the parentPath function, or defined for the order in
1677 // which the repositories were included in the user's config file.
1678 //
1679 // Note that as of PHP 4.0.6 the usort command no longer preserves the order
1680 // of items that are considered equal (in our case, part of the same group).
1681 // The mergesort function preserves this order.
1682  
1683 function sortByGroup() {
1684 if (!empty($this->_repositories)) {
1685 mergesort($this->_repositories, 'cmpGroups');
1686 }
1687 }
1688  
1689 // }}}
1690  
1691 // {{{ Change the name of the breadcrumb root-phrase to that of the current repo?
1692  
1693 function setBreadcrumbRepoRootAsRepo($newValue) {
1694 $this->breadcrumbRepoRootAsRepo = $newValue;
1695 }
1696  
1697 function getBreadcrumbRepoRootAsRepo() {
1698 return $this->breadcrumbRepoRootAsRepo;
1699 }
1700  
1701 // }}}
1702 }