1 | 1 | simandl | <?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 | | | // utils.php |
22 | | | // |
23 | | | // General utility commands |
24 | | | |
25 | | | // {{{ createDirLinks |
26 | | | // |
27 | | | // Create a list of links to the current path that'll be available from the template |
28 | | | |
29 | | | function createDirLinks($rep, $path, $rev) { |
30 | | | global $vars, $config; |
31 | | | |
32 | | | $subs = explode('/', htmlentities($path, ENT_QUOTES, 'UTF-8')); |
33 | | | |
34 | | | $sofar = ""; |
35 | | | $count = count($subs); |
36 | | | $vars["curdirlinks"] = ""; |
37 | | | |
38 | | | // The number of links depends on the last item. It's empty if |
39 | | | // we're looing at a directory, and full if it's a file |
40 | | | if (empty($subs[$count - 1])) { |
41 | | | $limit = $count - 2; |
42 | | | $dir = true; |
43 | | | } else { |
44 | | | $limit = $count - 1; |
45 | | | $dir = false; |
46 | | | } |
47 | | | |
48 | | | for ($n = 0; $n < $limit; $n++) { |
49 | | | $sofar .= html_entity_decode($subs[$n])."/"; |
50 | | | $sofarurl = $config->getURL($rep, $sofar, "dir"); |
51 | | | $vars["curdirlinks"] .= "[<a href=\"${sofarurl}rev=$rev\">".$subs[$n]."/</a>] "; |
52 | | | } |
53 | | | |
54 | | | if ($dir) { |
55 | | | $vars["curdirlinks"] .= "[<b>".$subs[$n]."</b>/]"; |
56 | | | } else { |
57 | | | $vars["curdirlinks"] .= "[<b>".$subs[$n]."</b>]"; |
58 | | | } |
59 | | | } |
60 | | | |
61 | | | // }}} |
62 | | | |
63 | | | // {{{ create_anchors |
64 | | | // |
65 | | | // Create links out of http:// and mailto: tags |
66 | | | |
67 | | | // TODO: the target="_blank" nonsense should be optional (or specified by the template) |
68 | | | function create_anchors($text) { |
69 | | | $ret = $text; |
70 | | | |
71 | | | // Match correctly formed URLs that aren't already links |
72 | | | $ret = preg_replace("#\b(?<!href=\")([a-z]+?)://(\S*)([\w/]+)#i", |
73 | | | "<a href=\"\\1://\\2\\3\" target=\"_blank\">\\1://\\2\\3</a>", |
74 | | | $ret); |
75 | | | |
76 | | | // Now match anything beginning with www, as long as it's not //www since they were matched above |
77 | | | $ret = preg_replace("#\b(?<!//)www\.(\S*)([\w/]+)#i", |
78 | | | "<a href=\"http://www.\\1\\2\" target=\"_blank\">www.\\1\\2</a>", |
79 | | | $ret); |
80 | | | |
81 | | | // Match email addresses |
82 | | | $ret = preg_replace("#\b([\w\-_.]+)@([\w\-.]+)\b#i", |
83 | | | "<a href=\"mailto:\\1@\\2\">\\1@\\2</a>", |
84 | | | $ret); |
85 | | | |
86 | | | return $ret; |
87 | | | } |
88 | | | |
89 | | | // }}} |
90 | | | |
91 | | | // {{{ getFullURL |
92 | | | |
93 | | | function getFullURL($loc) { |
94 | | | $protocol = 'http'; |
95 | | | |
96 | | | if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { |
97 | | | $protocol = $_SERVER['HTTP_X_FORWARDED_PROTO']; |
98 | | | } else if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) { |
99 | | | $protocol = 'https'; |
100 | | | } |
101 | | | |
102 | | | $port = ':'.$_SERVER['SERVER_PORT']; |
103 | | | if ((':80' == $port && 'http' == $protocol) || (':443' == $port && 'https' == $protocol)) { |
104 | | | $port = ''; |
105 | | | } |
106 | | | |
107 | | | if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { |
108 | | | $host = $_SERVER['HTTP_X_FORWARDED_HOST']; |
109 | | | } else if (isset($_SERVER['HTTP_HOST'])) { |
110 | | | $host = $_SERVER['HTTP_HOST']; |
111 | | | } else if (isset($_SERVER['SERVER_NAME'])) { |
112 | | | $host = $_SERVER['SERVER_NAME'].$port; |
113 | | | } else if (isset($_SERVER['SERVER_ADDR'])) { |
114 | | | $host = $_SERVER['SERVER_ADDR'].$port; |
115 | | | } else { |
116 | | | print 'Unable to redirect'; |
117 | | | exit; |
118 | | | } |
119 | | | |
120 | | | // make sure we have a directory to go to |
121 | | | if (empty($loc)) { |
122 | | | $loc = '/'; |
123 | | | } else if ($loc{0} != '/') { |
124 | | | $loc = '/'.$loc; |
125 | | | } |
126 | | | |
127 | | | $url = $protocol . '://' . $host . $loc; |
128 | | | |
129 | | | return $url; |
130 | | | } |
131 | | | |
132 | | | // }}} |
133 | | | |
134 | | | // {{{ hardspace |
135 | | | // |
136 | | | // Replace the spaces at the front of a line with hard spaces |
137 | | | |
138 | | | // XXX: this is an unnecessary function; you can prevent whitespace from being |
139 | | | // trimmed via CSS (use the "white-space: pre;" properties). ~J |
140 | | | // in the meantime, here's an improved function (does nothing) |
141 | | | |
142 | | | function hardspace($s) { |
143 | | | return '<code>' . expandTabs($s) . '</code>'; |
144 | | | } |
145 | | | |
146 | | | // }}} |
147 | | | |
148 | | | // {{{ expandTabs |
149 | | | |
150 | | | /** |
151 | | | * Expands the tabs in a line that may or may not include HTML. |
152 | | | * |
153 | | | * Enscript generates code with HTML, so we need to take that into account. |
154 | | | * |
155 | | | * @param string $s Line of possibly HTML-encoded text to expand |
156 | | | * @param int $tabwidth Tab width, -1 to use repository's default, 0 to collapse |
157 | | | * all tabs. |
158 | | | * @return string The expanded line. |
159 | | | * @since 2.1 |
160 | | | */ |
161 | | | |
162 | | | function expandTabs($s, $tabwidth = -1) { |
163 | | | global $rep; |
164 | | | |
165 | | | if ($tabwidth == -1) { |
166 | | | $tabwidth = $rep->getExpandTabsBy(); |
167 | | | } |
168 | | | $pos = 0; |
169 | | | |
170 | | | // Parse the string into chunks that are either 1 of: HTML tag, tab char, run of any other stuff |
171 | | | $chunks = preg_split("/((?:<.+?>)|(?:&.+?;)|(?:\t))/", $s, -1, PREG_SPLIT_DELIM_CAPTURE); |
172 | | | |
173 | | | // Count the sizes of the chunks and replace tabs as we go |
174 | | | for ($i = 0; $i < count($chunks); $i++) { |
175 | | | // make sure we're not dealing with an empty string |
176 | | | if (empty($chunks[$i])) continue; |
177 | | | switch ($chunks[$i]{0}) { |
178 | | | case '<': // HTML tag: ignore its width by doing nothing |
179 | | | break; |
180 | | | |
181 | | | case '&': // HTML entity: count its width as 1 char |
182 | | | $pos += 1; |
183 | | | break; |
184 | | | |
185 | | | case "\t": // Tab char: replace it with a run of spaces between length tabwidth and 1 |
186 | | | $tabsize = $tabwidth - ($pos % $tabwidth); |
187 | | | $chunks[$i] = str_repeat(' ', $tabsize); |
188 | | | $pos += $tabsize; |
189 | | | break; |
190 | | | |
191 | | | default: // Anything else: just keep track of its width |
192 | | | $pos += strlen($chunks[$i]); |
193 | | | break; |
194 | | | } |
195 | | | } |
196 | | | |
197 | | | // Put the chunks back together and we've got the original line, detabbed. |
198 | | | return join('', $chunks); |
199 | | | } |
200 | | | |
201 | | | // }}} |
202 | | | |
203 | | | // {{{ datetimeFormatDuration |
204 | | | // |
205 | | | // Formats a duration of seconds for display. |
206 | | | // |
207 | | | // $seconds the number of seconds until something |
208 | | | // $nbsp true if spaces should be replaced by nbsp |
209 | | | // $skipSeconds true if seconds should be omitted |
210 | | | // |
211 | | | // return the formatted duration (e.g. @c "8h 6m 1s") |
212 | | | |
213 | | | function datetimeFormatDuration($seconds, $nbsp = false, $skipSeconds = false) { |
214 | | | global $lang; |
215 | | | |
216 | | | $neg = false; |
217 | | | if ($seconds < 0) { |
218 | | | $seconds = -$seconds; |
219 | | | $neg = true; |
220 | | | } |
221 | | | |
222 | | | $qty = array(); |
223 | | | $names = array($lang["DAYLETTER"], $lang["HOURLETTER"], $lang["MINUTELETTER"]); |
224 | | | |
225 | | | $qty[] = (int)($seconds / (60 * 60 * 24)); |
226 | | | $seconds %= 60 * 60 * 24; |
227 | | | |
228 | | | $qty[] = (int)($seconds / (60 * 60)); |
229 | | | $seconds %= 60 * 60; |
230 | | | |
231 | | | $qty[] = (int)($seconds / 60); |
232 | | | |
233 | | | if (!$skipSeconds) { |
234 | | | $qty[] = (int)($seconds % 60); |
235 | | | $names[] = $lang["SECONDLETTER"]; |
236 | | | } |
237 | | | |
238 | | | $text = $neg ? '-' : ''; |
239 | | | $any = false; |
240 | | | $count = count($names); |
241 | | | $parts = 0; |
242 | | | for ($i = 0; $i < $count; $i++) { |
243 | | | // If a "higher valued" time slot had a value or this time slot |
244 | | | // has a value or this is the very last entry (i.e. all values |
245 | | | // are 0 and we still want to print seconds) |
246 | | | if ($any || $qty[$i] > 0 || $i == $count - 1) { |
247 | | | if ($any) $text .= $nbsp ? ' ' : ' '; |
248 | | | if ($any && $qty[$i] < 10) $text .= '0'; |
249 | | | $text .= $qty[$i].$names[$i]; |
250 | | | $any = true; |
251 | | | $parts++; |
252 | | | if ($parts >= 2) break; |
253 | | | } |
254 | | | } |
255 | | | return $text; |
256 | | | } |
257 | | | |
258 | | | // }}} |
259 | | | |
260 | | | // {{{ buildQuery |
261 | | | // |
262 | | | // Build parameters for url query part |
263 | | | |
264 | | | function buildQuery($data, $separator = '&', $key = '') { |
265 | | | if (is_object($data)) $data = get_object_vars($data); |
266 | | | $p = array(); |
267 | | | foreach ($data as $k => $v) { |
268 | | | $k = urlencode($k); |
269 | | | if (!empty($key)) $k = $key.'['.$k.']'; |
270 | | | |
271 | | | if (is_array($v) || is_object($v)) { |
272 | | | $p[] = buildQuery($v, $separator, $k); |
273 | | | } else { |
274 | | | $p[] = $k.'='.urlencode($v); |
275 | | | } |
276 | | | } |
277 | | | |
278 | | | return implode($separator, $p); |
279 | | | } |
280 | | | |
281 | | | // }}} |
282 | | | |
283 | | | // {{{ getUserLanguage |
284 | | | |
285 | | | function getUserLanguage($languages, $default, $userchoice) { |
286 | | | $acceptlangs = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : false; |
287 | | | if (!$acceptlangs) return $default; |
288 | | | |
289 | | | $langs = array(); |
290 | | | $sublangs = array(); |
291 | | | |
292 | | | foreach (explode(',', $acceptlangs) as $str) { |
293 | | | $a = explode(';', $str, 2); |
294 | | | $lang = trim($a[0]); |
295 | | | $pos = strpos($lang, '-'); |
296 | | | if ($pos !== false) $sublangs[] = substr($lang, 0, $pos); |
297 | | | $q = 1.0; |
298 | | | |
299 | | | if (sizeof($a) == 2) { |
300 | | | $v = trim($a[1]); |
301 | | | if (substr($v, 0, 2) == 'q=') $q = doubleval(substr($v, 2)); |
302 | | | } |
303 | | | |
304 | | | if ($userchoice) $q *= 0.9; |
305 | | | $langs[$lang] = $q; |
306 | | | } |
307 | | | |
308 | | | foreach ($sublangs as $l) if (!isset($langs[$l])) $langs[$l] = 0.1; |
309 | | | |
310 | | | if ($userchoice) $langs[$userchoice] = 1.0; |
311 | | | |
312 | | | arsort($langs); |
313 | | | |
314 | | | foreach ($langs as $code => $q) { |
315 | | | if (isset($languages[$code])) { |
316 | | | return $code; |
317 | | | } |
318 | | | } |
319 | | | |
320 | | | return $default; |
321 | | | } |
322 | | | |
323 | | | // }}} |