Rev 178 Rev 185
Line 1... Line 1...
1 <?php 1 <?php
2 # vim:et:ts=3:sts=3:sw=3:fdm=marker: 2 # vim:et:ts=3:sts=3:sw=3:fdm=marker:
3   3  
4 // WebSVN - Subversion repository viewing via the web using PHP 4 // WebSVN - Subversion repository viewing via the web using PHP
5 // Copyright © 2004-2006 Tim Armes, Matt Sicker 5 // Copyright © 2004-2006 Tim Armes, Matt Sicker
6 // 6 //
7 // This program is free software; you can redistribute it and/or modify 7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by 8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or 9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version. 10 // (at your option) any later version.
11 // 11 //
12 // This program is distributed in the hope that it will be useful, 12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details. 15 // GNU General Public License for more details.
16 // 16 //
17 // You should have received a copy of the GNU General Public License 17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software 18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // 20 //
21 // -- 21 // --
22 // 22 //
23 // utils.inc 23 // utils.inc
24 // 24 //
25 // General utility commands 25 // General utility commands
26   26  
27 #require_once 'php5compat.inc'; 27 // {{{ createDirLinks
28   28 //
29 // {{{ createDirLinks 29 // Create a list of links to the current path that'll be available from the template
30 // 30  
31 // Create a list of links to the current path that'll be available from the template 31 function createDirLinks($rep, $path, $rev, $showchanged)
32   32 {
33 function createDirLinks($rep, $path, $rev, $showchanged) 33 global $vars, $config;
34 { 34
35 global $vars, $config; 35 $subs = explode('/', htmlentities($path));
36 36 $sofar = "";
37 $subs = explode('/', htmlentities($path)); 37 $count = count($subs);
38 $sofar = ""; 38 $vars["curdirlinks"] = "";
39 $count = count($subs); 39
40 $vars["curdirlinks"] = ""; 40 // The number of links depends on the last item. It's empty if
41 41 // we're looing at a directory, and full if it's a file
42 // The number of links depends on the last item. It's empty if 42 if (empty($subs[$count - 1]))
43 // we're looing at a directory, and full if it's a file 43 {
44 if (empty($subs[$count - 1])) 44 $limit = $count - 2;
45 { 45 $dir = true;
46 $limit = $count - 2; 46 }
47 $dir = true; 47 else
48 } 48 {
49 else 49 $limit = $count - 1;
50 { 50 $dir = false;
51 $limit = $count - 1; 51 }
52 $dir = false; 52
53 } 53 for ($n = 0; $n < $limit; $n++)
54 54 {
55 for ($n = 0; $n < $limit; $n++) 55 $sofar .= html_entity_decode($subs[$n])."/";
56 { 56 $sofarurl = $config->getURL($rep, $sofar, "dir");
57 $sofar .= html_entity_decode($subs[$n])."/"; 57 $vars["curdirlinks"] .= "[<a href=\"${sofarurl}rev=$rev&amp;sc=$showchanged\">".$subs[$n]."/]</a> ";
58 $sofarurl = $config->getURL($rep, $sofar, "dir"); 58 }
59 $vars["curdirlinks"] .= "[<a href=\"${sofarurl}rev=$rev&amp;sc=$showchanged\">".$subs[$n]."/]</a> "; 59
60 } 60 if ($dir)
61 61 {
62 if ($dir) 62 $vars["curdirlinks"] .= "[<b>".html_entity_decode($subs[$n])."</b>/]";
63 { 63 }
64 $vars["curdirlinks"] .= "[<b>".html_entity_decode($subs[$n])."</b>/]"; 64 else
65 } 65 {
66 else 66 $vars["curdirlinks"] .= "[<b>".html_entity_decode($subs[$n])."</b>]";
67 { 67 }
68 $vars["curdirlinks"] .= "[<b>".html_entity_decode($subs[$n])."</b>]"; 68 }
69 } 69  
70 } 70 // }}}
71   71  
72 // }}} 72 // {{{ create_anchors
73   73 //
74 // {{{ create_anchors 74 // Create links out of http:// and mailto: tags
75 // 75  
76 // Create links out of http:// and mailto: tags 76 # TODO: the target="_blank" nonsense should be optional (or specified by the template)
77   77 function create_anchors($text)
78 # TODO: the target="_blank" nonsense should be optional (or specified by the template) 78 {
79 function create_anchors($text) 79 $ret = $text;
80 { 80  
81 $ret = $text; 81 // Match correctly formed URLs that aren't already links
82   82 $ret = preg_replace("#\b(?<!href=\")([a-z]+?)://(\S*)([\w/]+)#i",
83 // Match correctly formed URLs that aren't already links 83 "<a href=\"\\1://\\2\\3\" target=\"_blank\">\\1://\\2\\3</a>",
84 $ret = preg_replace("#\b(?<!href=\")([a-z]+?)://(\S*)([\w/]+)#i", 84 $ret);
85 "<a href=\"\\1://\\2\\3\" target=\"_blank\">\\1://\\2\\3</a>", 85
86 $ret); 86 // Now match anything beginning with www, as long as it's not //www since they were matched above
87 87 $ret = preg_replace("#\b(?<!//)www\.(\S*)([\w/]+)#i",
88 // Now match anything beginning with www, as long as it's not //www since they were matched above 88 "<a href=\"http://www.\\1\\2\" target=\"_blank\">www.\\1\\2</a>",
89 $ret = preg_replace("#\b(?<!//)www\.(\S*)([\w/]+)#i", 89 $ret);
90 "<a href=\"http://www.\\1\\2\" target=\"_blank\">www.\\1\\2</a>", 90  
91 $ret); 91 // Match email addresses
92   92 $ret = preg_replace("#\b([\w\-_.]+)@([\w\-.]+)\b#i",
93 // Match email addresses 93 "<a href=\"mailto:\\1@\\2\">\\1@\\2</a>",
94 $ret = preg_replace("#\b([\w\-_.]+)@([\w\-.]+)\b#i", 94 $ret);
95 "<a href=\"mailto:\\1@\\2\">\\1@\\2</a>", 95
96 $ret); 96 return ($ret);
97 97 }
98 return ($ret); 98  
99 } 99 // }}}
100   100  
101 // }}} 101 // {{{ getFullURL
102   102  
103 // {{{ getFullURL 103 function getFullURL($loc)
104   104 {
105 function getFullURL($loc) 105 $protocol = 'http';
106 { 106
107 $protocol = 'http'; 107 if (isset($_SERVER["HTTPS"]) && (strtolower($_SERVER["HTTPS"]) != "off"))
108 108 {
109 if (isset($_SERVER["HTTPS"]) && (strtolower($_SERVER["HTTPS"]) != "off")) 109 $protocol = "https";
110 { 110 }
111 $protocol = "https"; 111
112 } 112 $port = ":".$_SERVER["SERVER_PORT"];
113 113 if ((":80" == $port && "http" == $protocol) ||
114 $port = ":".$_SERVER["SERVER_PORT"]; 114 (":443" == $port && "https" == $protocol))
115 if ((":80" == $port && "http" == $protocol) || 115 {
116 (":443" == $port && "https" == $protocol)) 116 $port = "";
117 { 117 }
118 $port = ""; 118
119 } 119 if (isset($_SERVER["HTTP_HOST"]))
120 120 {
121 if (isset($_SERVER["HTTP_HOST"])) 121 $host = $_SERVER["HTTP_HOST"];
122 { 122 }
123 $host = $_SERVER["HTTP_HOST"]; 123 else if (isset($_SERVER["SERVER_NAME"]))
124 } 124 {
125 else if (isset($_SERVER["SERVER_NAME"])) 125 $host = $_SERVER["SERVER_NAME"].$port;
126 { 126 }
127 $host = $_SERVER["SERVER_NAME"].$port; 127 else if (isset($_SERVER["SERVER_ADDR"]))
128 } 128 {
129 else if (isset($_SERVER["SERVER_ADDR"])) 129 $host = $_SERVER["SERVER_ADDR"].$port;
130 { 130 }
131 $host = $_SERVER["SERVER_ADDR"].$port; 131 else
132 } 132 {
133 else 133 print "Unable to redirect";
134 { 134 exit;
135 print "Unable to redirect"; 135 }
136 exit; 136
137 } 137 $url = $protocol . "://" . $host . $loc;
138 138  
139 $url = $protocol . "://" . $host . $loc; 139 return $url;
140   140 }
141 return $url; 141  
142 } 142 // }}}
143   143  
144 // }}} 144 // {{{ hardspace
145   145 //
146 // {{{ hardspace 146 // Replace the spaces at the front of a line with hard spaces
147 // 147  
148 // Replace the spaces at the front of a line with hard spaces 148 # XXX: this is an unnecessary function; you can prevent whitespace from being
149   149 # trimmed via CSS (use the "white-space: pre;" properties). ~J
150 # XXX: this is an unnecessary function; you can prevent whitespace from being 150 # in the meantime, here's an improved function (does nothing)
151 # trimmed via CSS (use the "white-space: pre;" properties). ~J 151  
152 # in the meantime, here's an improved function (does nothing) 152 function hardspace($s)
153   153 {
154 function hardspace($s) 154 return '<code>' . expandTabs($s) . '</code>';
155 { 155 }
156 return '<code>'.$s.'</code>'; 156  
157 } 157 // }}}
158   158  
159 // }}} 159 // {{{ expandTabs
160   160  
161 // {{{ datetimeFormatDuration 161 /**
162 // 162 * Expands the tabs in a line that may or may not include HTML.
163 // Formats a duration of seconds for display. 163 *
164 // 164 * Enscript generates code with HTML, so we need to take that into account.
165 // $seconds the number of seconds until something 165 *
166 // $nbsp true if spaces should be replaced by nbsp 166 * @param string $s Line of possibly HTML-encoded text to expand
167 // $skipSeconds true if seconds should be omitted 167 * @param int $tabwidth Tab width, -1 to use repository's default, 0 to collapse
168 // 168 * all tabs.
169 // return the formatted duration (e.g. @c "8h 6m 1s") 169 * @return string The expanded line.
170   170 * @since 2.1
171 function datetimeFormatDuration($seconds, $nbsp = false, $skipSeconds = false) 171 */
172 { 172  
173 global $lang; 173 function expandTabs($s, $tabwidth = -1)
174 174 {
175 if ($seconds < 0) 175 global $rep;
176 { 176  
177 $seconds = -$seconds; 177 if ($tabwidth == -1)
178 $neg = true; 178 $tabwidth = $rep->getExpandTabsBy();
179 } 179 $pos = 0;
180 else 180  
181 $neg = false; 181 // Parse the string into chunks that are either 1 of: HTML tag, tab char, run of any other stuff
182   182 $chunks = preg_split("/((?:<.+?>)|(?:&.+?;)|(?:\t))/", $s, -1, PREG_SPLIT_DELIM_CAPTURE);
183 $qty = array(); 183  
184   184 // Count the sizes of the chunks and replace tabs as we go
185 $qty[] = (int)($seconds / (60 * 60 * 24)); 185 for ($i = 0; $i < count($chunks); $i++)
186 $seconds %= 60 * 60 * 24; 186 {
187   187 # make sure we're not dealing with an empty string
188 $qty[] = (int)($seconds / (60 * 60)); 188 if (empty($chunks[$i])) continue;
189 $seconds %= 60 * 60; 189 switch ($chunks[$i]{0})
190   190 {
191 $qty[] = (int)($seconds / 60); 191 case '<': // HTML tag : ignore its width by doing nothing
192 $qty[] = (int)($seconds % 60); 192 break;
193   193  
194 $text = ""; 194 case '&': // HTML entity: count its width as 1 char
195 $names = $lang["DAYLETTER"].$lang["HOURLETTER"].$lang["MINUTELETTER"]; 195 $pos += 1;
196 if (!$skipSeconds) $names .= $lang["SECONDLETTER"]; 196 break;
197   197  
198 $any = false; 198 case "\t": // Tab char: replace it with a run of spaces between length tabwidth and 1
199 for ($i = 0; $i < strlen($names); $i++) 199 $tabsize = $tabwidth - ($pos % $tabwidth);
200 // If a "higher valued" time slot had a value or this time slot 200 $chunks[$i] = str_repeat(' ', $tabsize);
201 // has a value or this is the very last entry (i.e. all values 201 $pos += $tabsize;
202 // are 0 and we still want to print seconds) 202 break;
203 if ($any || $qty[$i] || $i == sizeof($qty) - 1) 203  
204 { 204 default: // Anything else: just keep track of its width
205 $any = true; 205 $pos += strlen($chunks[$i]);
206   206 break;
207 if ($i) 207 }
208 $text .= sprintf("%2d", $qty[$i]); 208 }
209 else 209  
210 $text .= $qty[$i]; 210 // Put the chunks back together and we've got the original line, detabbed.
211   211 return join('', $chunks);
212 $text .= "{$names{$i}} "; 212 }
213 } 213  
214   214 // }}}
215 $text = trim($text); 215  
216 if ($neg) 216 // {{{ datetimeFormatDuration
217 $text = "-$text"; 217 //
218   218 // Formats a duration of seconds for display.
219 return $nbsp ? str_replace(" ", "&nbsp;", $text) : $text; 219 //
220 } 220 // $seconds the number of seconds until something
221   221 // $nbsp true if spaces should be replaced by nbsp
222 // }}} 222 // $skipSeconds true if seconds should be omitted
223   223 //
224 // {{{ getParameterisedSelfUrl 224 // return the formatted duration (e.g. @c "8h 6m 1s")
225 // 225  
226 // Get the relative URL (PHP_SELF) with GET and POST data 226 function datetimeFormatDuration($seconds, $nbsp = false, $skipSeconds = false)
227   227 {
228 function getParameterisedSelfUrl($params = true) 228 global $lang;
229 { 229
230 $url = null; 230 if ($seconds < 0)
231   231 {
232 if ($config->multiViews) 232 $seconds = -$seconds;
233 { 233 $neg = true;
234 // Get rid of the file's name 234 }
235 $url = preg_replace('/\.php/', '', $_SERVER['PHP_SELF'], 1); 235 else
236 } 236 $neg = false;
237 else 237  
238 { 238 $qty = array();
239 $url = basename($_SERVER['PHP_SELF']); 239  
240   240 $qty[] = (int)($seconds / (60 * 60 * 24));
241 // Sometimes the .php isn't on the end. Damn strange... 241 $seconds %= 60 * 60 * 24;
242 if (strchr($url, '.') === false) 242  
243 $url .= '.php'; 243 $qty[] = (int)($seconds / (60 * 60));
244 } 244 $seconds %= 60 * 60;
245   245  
246 if ($params) 246 $qty[] = (int)($seconds / 60);
247 { 247 $qty[] = (int)($seconds % 60);
248 $arr = $_GET + $_POST; 248  
249 # XXX: the point of HTTP POST is that URIs have a set size limit, so POST 249 $text = "";
250 # data is typically too large to bother with; why include it? 250 $names = $lang["DAYLETTER"].$lang["HOURLETTER"].$lang["MINUTELETTER"];
251 $url .= '?'.htmlentities(http_build_query($arr)); 251 if (!$skipSeconds) $names .= $lang["SECONDLETTER"];
252 } 252  
253   253 $any = false;
254 return $url; 254 for ($i = 0; $i < strlen($names); $i++)
255 } 255 // If a "higher valued" time slot had a value or this time slot
256   256 // has a value or this is the very last entry (i.e. all values
257 // }}} 257 // are 0 and we still want to print seconds)
258   258 if ($any || $qty[$i] || $i == sizeof($qty) - 1)
259 ?> 259 {
-   260 $any = true;
-   261  
-   262 if ($i)
-   263 $text .= sprintf("%2d", $qty[$i]);
-   264 else
-   265 $text .= $qty[$i];
-   266  
-   267 $text .= "{$names{$i}} ";
-   268 }
-   269  
-   270 $text = trim($text);
-   271 if ($neg)
-   272 $text = "-$text";
-   273  
-   274 return $nbsp ? str_replace(" ", "&nbsp;", $text) : $text;
-   275 }
-   276  
-   277 // }}}
-   278  
-   279 // {{{ getParameterisedSelfUrl
-   280 //
-   281 // Get the relative URL (PHP_SELF) with GET and POST data
-   282  
-   283 function getParameterisedSelfUrl($params = true)
-   284 {
-   285 global $config;
-   286  
-   287 $url = null;
-   288  
-   289 if ($config->multiViews)
-   290 {
-   291 // Get rid of the file's name
-   292 $url = preg_replace('/\.php/', '', $_SERVER['PHP_SELF'], 1);
-   293 }
-   294 else
-   295 {
-   296 $url = basename($_SERVER['PHP_SELF']);
-   297  
-   298 // Sometimes the .php isn't on the end. Damn strange...
-   299 if (strchr($url, '.') === false)
-   300 $url .= '.php';
-   301 }
-   302  
-   303 if ($params)
-   304 {
-   305 $arr = $_GET + $_POST;
-   306 # XXX: the point of HTTP POST is that URIs have a set size limit, so POST
-   307 # data is typically too large to bother with; why include it?
-   308 $url .= '?'.htmlentities(http_build_query($arr));
-   309 }
-   310  
-   311 return $url;
-   312 }
-   313  
-   314 // }}}
-   315  
-   316 // {{{ getUserLanguage
-   317  
-   318 function getUserLanguage() {
-   319 $languages = !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : 'en';
-   320 if (strpos($languages, ',') === false) return $languages; # only one specified
-   321 # split off the languages into an array of languages and q-values
-   322 $qvals = array();
-   323 $langs = array();
-   324 preg_match_all('#(\S+?)\s*(?:;q=([01](?:\.\d{1,3})?))?\s*,\s*#', $languages, $qvals, PREG_SET_ORDER);
-   325 foreach ($qvals as $q) {
-   326 $langs[] = array (
-   327 $q[1],
-   328 floatval(!empty($q[2]) ? $q[2] : 1.0)
-   329 );
-   330 }
-   331 # XXX: now, we should loop through our available languages and choose an
-   332 # appropriate one for the user
-   333 # note that we shouldn't match the region unless we have a specific region
-   334 # to use (e.g. zh-CN vs. zh-TW)
-   335 # FIXME: see above; otherwise, this function doesn't really do anything
-   336 }
-   337  
-   338 // }}}
-   339  
-   340 ?>