Rev 7 | Rev 48 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 7 | Rev 11 | ||
---|---|---|---|
1 | <?php |
1 | <?php |
2 | 2 | ||
3 | # |
3 | # |
4 | # VWhois (ViaThinkSoft WHOIS, a fork of generic Whois / gwhois) |
4 | # VGWhoIs (ViaThinkSoft Global WhoIs, a fork of generic Whois / gwhois) |
5 | # Common functions in PHP |
5 | # Common functions in PHP |
6 | # |
6 | # |
7 | # (c) 2011-2013 by Daniel Marschall, ViaThinkSoft <info@daniel-marschall.de> |
7 | # (c) 2011-2013 by Daniel Marschall, ViaThinkSoft <info@daniel-marschall.de> |
8 | # |
8 | # |
9 | # License: https://www.gnu.org/licenses/gpl-2.0.html (GPL version 2) |
9 | # License: https://www.gnu.org/licenses/gpl-2.0.html (GPL version 2) |
10 | # |
10 | # |
11 | 11 | ||
12 | include_once __DIR__ . '/ipv4_functions.inc.php'; |
12 | include_once __DIR__ . '/ipv4_functions.inc.php'; |
13 | include_once __DIR__ . '/ipv6_functions.inc.php'; |
13 | include_once __DIR__ . '/ipv6_functions.inc.php'; |
14 | include_once __DIR__ . '/grep_functions.inc.php'; |
14 | include_once __DIR__ . '/grep_functions.inc.php'; |
15 | include_once __DIR__ . '/gwi_functions.inc.php'; |
15 | include_once __DIR__ . '/gwi_functions.inc.php'; |
16 | 16 | ||
17 | function file_age($filename) { |
17 | function file_age($filename) { |
18 | $m = file_exists($filename) ? filemtime($filename) : 0; |
18 | $m = file_exists($filename) ? filemtime($filename) : 0; |
19 | return time()-$m; |
19 | return time()-$m; |
20 | } |
20 | } |
21 | 21 | ||
22 | function human_timediff($t) { |
22 | function human_timediff($t) { |
23 | if ($t < 60) { |
23 | if ($t < 60) { |
24 | $e = 'seconds'; |
24 | $e = 'seconds'; |
25 | } else if ($t < 60*60) { |
25 | } else if ($t < 60*60) { |
26 | $t /= 60; |
26 | $t /= 60; |
27 | $e = 'minutes'; |
27 | $e = 'minutes'; |
28 | } else if ($t < 24*60*60) { |
28 | } else if ($t < 24*60*60) { |
29 | $t /= 60*60; |
29 | $t /= 60*60; |
30 | $e = 'hours'; |
30 | $e = 'hours'; |
31 | } else if ($t < 30*24*60*60) { |
31 | } else if ($t < 30*24*60*60) { |
32 | $t /= 24*60*60; |
32 | $t /= 24*60*60; |
33 | $e = 'days'; |
33 | $e = 'days'; |
34 | } else if ($t < 365*24*60*60) { |
34 | } else if ($t < 365*24*60*60) { |
35 | $t /= 30*24*60*60; |
35 | $t /= 30*24*60*60; |
36 | $e = 'months'; |
36 | $e = 'months'; |
37 | } else { |
37 | } else { |
38 | $t /= 365*24*60*60; |
38 | $t /= 365*24*60*60; |
39 | $e = 'years'; |
39 | $e = 'years'; |
40 | } |
40 | } |
41 | $t = floor($t); |
41 | $t = floor($t); |
42 | return "$t $e"; |
42 | return "$t $e"; |
43 | } |
43 | } |
44 | 44 | ||
45 | # http://www.phpeasycode.com/whois/ |
45 | # http://www.phpeasycode.com/whois/ |
46 | # TODO: code duplicate in maintenance/pattern-generator/generate_newgtld |
46 | # TODO: code duplicate in maintenance/pattern-generator/generate_newgtld |
47 | function QueryWhoisServer($whoisserver, $domain, $port=43, $timeout=10) { |
47 | function QueryWhoisServer($whoisserver, $domain, $port=43, $timeout=10) { |
48 | $fp = @fsockopen($whoisserver, $port, $errno, $errstr, $timeout) or die("Socket Error " . $errno . " - " . $errstr); |
48 | $fp = @fsockopen($whoisserver, $port, $errno, $errstr, $timeout) or die("Socket Error " . $errno . " - " . $errstr); |
49 | // if ($whoisserver == "whois.verisign-grs.com") $domain = "=$domain"; // whois.verisign-grs.com requires the equals sign ("=") or it returns any result containing the searched string. |
49 | // if ($whoisserver == "whois.verisign-grs.com") $domain = "=$domain"; // whois.verisign-grs.com requires the equals sign ("=") or it returns any result containing the searched string. |
50 | fputs($fp, $domain . "\r\n"); |
50 | fputs($fp, $domain . "\r\n"); |
51 | $out = ""; |
51 | $out = ""; |
52 | while(!feof($fp)){ |
52 | while(!feof($fp)){ |
53 | $out .= fgets($fp); |
53 | $out .= fgets($fp); |
54 | } |
54 | } |
55 | fclose($fp); |
55 | fclose($fp); |
56 | 56 | ||
57 | $res = ""; |
57 | $res = ""; |
58 | if ((strpos(strtolower($out), "error") === FALSE) && (strpos(strtolower($out), "not allocated") === FALSE)) { |
58 | if ((strpos(strtolower($out), "error") === FALSE) && (strpos(strtolower($out), "not allocated") === FALSE)) { |
59 | $rows = explode("\n", $out); |
59 | $rows = explode("\n", $out); |
60 | foreach($rows as $row) { |
60 | foreach($rows as $row) { |
61 | $row = trim($row); |
61 | $row = trim($row); |
62 | if (($row != '') && ($row[0] != '#') && ($row[0] != '%')) { |
62 | if (($row != '') && ($row[0] != '#') && ($row[0] != '%')) { |
63 | $res .= "$row\n"; |
63 | $res .= "$row\n"; |
64 | } |
64 | } |
65 | } |
65 | } |
66 | } |
66 | } |
67 | return $res; |
67 | return $res; |
68 | } |
68 | } |
69 | 69 | ||
70 | # TODO: rename (without "gwitc") |
70 | # TODO: rename (without "gwitc") |
71 | function gwitc_is_port_open($server, $default_port, $timeout=3) { |
71 | function gwitc_is_port_open($server, $default_port, $timeout=3) { |
72 | // TODO: "whois.namecoin.us" will always answer to a port request, because the domain parking service is shit |
72 | // TODO: "whois.namecoin.us" will always answer to a port request, because the domain parking service is shit |
73 | 73 | ||
74 | $x = explode(':', $server, 2); |
74 | $x = explode(':', $server, 2); |
75 | $host = $x[0]; |
75 | $host = $x[0]; |
76 | $port = isset($x[1]) ? $x[1] : $default_port; |
76 | $port = isset($x[1]) ? $x[1] : $default_port; |
77 | 77 | ||
78 | // First try with TOR |
78 | // First try with TOR |
79 | # $cmd = "vtor -- nc -zw$timeout $host $port 2>/dev/null"; |
79 | # $cmd = "vtor -- nc -zw$timeout $host $port 2>/dev/null"; |
80 | # exec($cmd, $out, $code); |
80 | # exec($cmd, $out, $code); |
81 | # if ($code == 0) return true; |
81 | # if ($code == 0) return true; |
82 | 82 | ||
83 | // Try without TOR |
83 | // Try without TOR |
84 | $cmd = "nc -zw$timeout $host $port 2>/dev/null"; |
84 | $cmd = "nc -zw$timeout $host $port 2>/dev/null"; |
85 | exec($cmd, $out, $code); |
85 | exec($cmd, $out, $code); |
86 | return ($code == 0); |
86 | return ($code == 0); |
87 | } |
87 | } |
88 | 88 | ||
89 | function getAllFiles($directory, $recursive = true, $include_dirs = false, $include_files = true) { |
89 | function getAllFiles($directory, $recursive = true, $include_dirs = false, $include_files = true) { |
90 | $result = array(); |
90 | $result = array(); |
91 | $handle = opendir($directory); |
91 | $handle = opendir($directory); |
92 | if (substr($directory, -1) == '/') $directory = substr($directory, 0, strlen($directory)-1); |
92 | if (substr($directory, -1) == '/') $directory = substr($directory, 0, strlen($directory)-1); |
93 | if ($include_dirs) { |
93 | if ($include_dirs) { |
94 | $result[] = $directory; |
94 | $result[] = $directory; |
95 | } |
95 | } |
96 | while ($datei = readdir($handle)) { |
96 | while ($datei = readdir($handle)) { |
97 | if (($datei != '.') && ($datei != '..')) { |
97 | if (($datei != '.') && ($datei != '..')) { |
98 | $file = $directory.'/'.$datei; |
98 | $file = $directory.'/'.$datei; |
99 | if (is_dir($file)) { |
99 | if (is_dir($file)) { |
100 | if ($include_dirs && !$recursive) { |
100 | if ($include_dirs && !$recursive) { |
101 | $result[] = $file; |
101 | $result[] = $file; |
102 | } |
102 | } |
103 | if ($recursive) { |
103 | if ($recursive) { |
104 | $result = array_merge($result, getAllFiles($file, $recursive, $include_dirs, $include_files)); |
104 | $result = array_merge($result, getAllFiles($file, $recursive, $include_dirs, $include_files)); |
105 | } |
105 | } |
106 | } else { |
106 | } else { |
107 | if ($include_files) $result[] = $file; |
107 | if ($include_files) $result[] = $file; |
108 | } |
108 | } |
109 | } |
109 | } |
110 | } |
110 | } |
111 | closedir($handle); |
111 | closedir($handle); |
112 | return $result; |
112 | return $result; |
113 | } |
113 | } |
114 | 114 | ||
115 | // TOR capable |
115 | // TOR capable |
116 | function file_get_contents2($url, $postvalues='', $headers=array()) { |
116 | function file_get_contents2($url, $postvalues='', $headers=array()) { |
117 | # exec ("wget -N -O - -- ".escapeshellarg($url), $out); |
117 | # exec ("wget -N -O - -- ".escapeshellarg($url), $out); |
118 | 118 | ||
119 | $add_cmd = ''; |
119 | $add_cmd = ''; |
120 | foreach ($headers as $name => $h) { |
120 | foreach ($headers as $name => $h) { |
121 | if (is_numeric($name)) { |
121 | if (is_numeric($name)) { |
122 | $add_cmd .= "-H ".escapeshellarg($h)." "; |
122 | $add_cmd .= "-H ".escapeshellarg($h)." "; |
123 | } else { |
123 | } else { |
124 | $add_cmd .= "-H ".escapeshellarg($name.': '.$h)." "; |
124 | $add_cmd .= "-H ".escapeshellarg($name.': '.$h)." "; |
125 | } |
125 | } |
126 | } |
126 | } |
127 | 127 | ||
128 | if ($postvalues != '') { |
128 | if ($postvalues != '') { |
129 | $add_cmd .= "-d ".escapeshellarg($postvalues)." "; |
129 | $add_cmd .= "-d ".escapeshellarg($postvalues)." "; |
130 | } |
130 | } |
131 | 131 | ||
132 | exec("curl --cookie ~/.cookiejar --cookie-jar ~/.cookiejar -s -k -L -A 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0' $add_cmd".escapeshellarg($url), $out); |
132 | exec("curl --cookie ~/.cookiejar --cookie-jar ~/.cookiejar -s -k -L -A 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0' $add_cmd".escapeshellarg($url), $out); |
133 | 133 | ||
134 | return implode("\n", $out); |
134 | return implode("\n", $out); |
135 | } |
135 | } |
136 | 136 | ||
137 | function make_tabs($text, $abstand = 4) { |
137 | function make_tabs($text, $abstand = 4) { |
138 | $ary = explode("\n", $text); |
138 | $ary = explode("\n", $text); |
139 | $longest = 0; |
139 | $longest = 0; |
140 | foreach ($ary as $a) { |
140 | foreach ($ary as $a) { |
141 | $bry = explode(':', $a, 2); |
141 | $bry = explode(':', $a, 2); |
142 | if (count($bry) < 2) continue; |
142 | if (count($bry) < 2) continue; |
143 | $c = strlen($bry[0]); |
143 | $c = strlen($bry[0]); |
144 | if ($c > $longest) $longest = $c; |
144 | if ($c > $longest) $longest = $c; |
145 | } |
145 | } |
146 | foreach ($ary as $n => $a) { |
146 | foreach ($ary as $n => $a) { |
147 | $bry = explode(':', $a, 2); |
147 | $bry = explode(':', $a, 2); |
148 | if (count($bry) < 2) continue; |
148 | if (count($bry) < 2) continue; |
149 | $rep = $longest-strlen($bry[0]) + $abstand; |
149 | $rep = $longest-strlen($bry[0]) + $abstand; |
150 | if ($rep < 1) { |
150 | if ($rep < 1) { |
151 | $wh = ''; |
151 | $wh = ''; |
152 | } else { |
152 | } else { |
153 | $wh = str_repeat(' ', $rep); |
153 | $wh = str_repeat(' ', $rep); |
154 | } |
154 | } |
155 | $ary[$n] = $bry[0].':'.$wh.trim($bry[1]); |
155 | $ary[$n] = $bry[0].':'.$wh.trim($bry[1]); |
156 | } |
156 | } |
157 | $x = implode("\n", $ary); |
157 | $x = implode("\n", $ary); |
158 | return $x; |
158 | return $x; |
159 | } |
159 | } |
160 | 160 | ||
161 | function uc_latin1($str) { |
161 | function uc_latin1($str) { |
162 | # Source: http://de3.php.net/manual/en/function.strtoupper.php#82592 |
162 | # Source: http://de3.php.net/manual/en/function.strtoupper.php#82592 |
163 | $str = strtoupper(strtr($str, "àáâãäåæçèéêëìíîïðñòóôõöøùúûüý", |
163 | $str = strtoupper(strtr($str, "àáâãäåæçèéêëìíîïðñòóôõöøùúûüý", |
164 | "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝ")); |
164 | "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝ")); |
165 | return strtr($str, array("ß" => "SS")); |
165 | return strtr($str, array("ß" => "SS")); |
166 | } |
166 | } |
167 | 167 | ||
168 | /** |
168 | /** |
169 | * Converts tabs to the appropriate amount of spaces while preserving formatting |
169 | * Converts tabs to the appropriate amount of spaces while preserving formatting |
170 | * |
170 | * |
171 | * @author Aidan Lister <aidan@php.net> |
171 | * @author Aidan Lister <aidan@php.net> |
172 | * @version 1.2.0 |
172 | * @version 1.2.0 |
173 | * @link http://aidanlister.com/repos/v/function.tab2space.php |
173 | * @link http://aidanlister.com/repos/v/function.tab2space.php |
174 | * @param string $text The text to convert |
174 | * @param string $text The text to convert |
175 | * @param int $spaces Number of spaces per tab column |
175 | * @param int $spaces Number of spaces per tab column |
176 | * @param boolean $html Output as HTML or not |
176 | * @param boolean $html Output as HTML or not |
177 | * @return string The text with tabs replaced |
177 | * @return string The text with tabs replaced |
178 | */ |
178 | */ |
179 | function tab2space($text, $spaces = 4, $html = false) { |
179 | function tab2space($text, $spaces = 4, $html = false) { |
180 | // Snippet from PHP Share: http://www.phpshare.org/scripts/Convert-Tabs-to-Spaces |
180 | // Snippet from PHP Share: http://www.phpshare.org/scripts/Convert-Tabs-to-Spaces |
181 | // Modified by Daniel Marschall: Added $html param |
181 | // Modified by Daniel Marschall: Added $html param |
182 | 182 | ||
183 | // Explode the text into an array of single lines |
183 | // Explode the text into an array of single lines |
184 | $lines = explode("\n", $text); |
184 | $lines = explode("\n", $text); |
185 | 185 | ||
186 | // Loop through each line |
186 | // Loop through each line |
187 | foreach ($lines as $line) { |
187 | foreach ($lines as $line) { |
188 | // Break out of the loop when there are no more tabs to replace |
188 | // Break out of the loop when there are no more tabs to replace |
189 | while (false !== $tab_pos = strpos($line, "\t")) { |
189 | while (false !== $tab_pos = strpos($line, "\t")) { |
190 | // Break the string apart, insert spaces then concatenate |
190 | // Break the string apart, insert spaces then concatenate |
191 | $start = substr($line, 0, $tab_pos); |
191 | $start = substr($line, 0, $tab_pos); |
192 | $tab = str_repeat($html ? ' ' : '', $spaces - $tab_pos % $spaces); |
192 | $tab = str_repeat($html ? ' ' : '', $spaces - $tab_pos % $spaces); |
193 | $end = substr($line, $tab_pos + 1); |
193 | $end = substr($line, $tab_pos + 1); |
194 | $line = $start . $tab . $end; |
194 | $line = $start . $tab . $end; |
195 | } |
195 | } |
196 | 196 | ||
197 | $result[] = $line; |
197 | $result[] = $line; |
198 | } |
198 | } |
199 | 199 | ||
200 | return implode("\n", $result); |
200 | return implode("\n", $result); |
201 | } |
201 | } |
202 | 202 | ||
203 | function trim_each_line($x) { |
203 | function trim_each_line($x) { |
204 | $res = ''; |
204 | $res = ''; |
205 | foreach (explode("\n", $x) as $y) { |
205 | foreach (explode("\n", $x) as $y) { |
206 | $res .= trim($y)."\n"; |
206 | $res .= trim($y)."\n"; |
207 | } |
207 | } |
208 | return $res; |
208 | return $res; |
209 | } |
209 | } |
210 | 210 | ||
211 | function generateRandomString($length = 10) { |
211 | function generateRandomString($length = 10) { |
212 | $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
212 | $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
213 | $randomString = ''; |
213 | $randomString = ''; |
214 | for ($i = 0; $i < $length; $i++) { |
214 | for ($i = 0; $i < $length; $i++) { |
215 | $randomString .= $characters[rand(0, strlen($characters) - 1)]; |
215 | $randomString .= $characters[rand(0, strlen($characters) - 1)]; |
216 | } |
216 | } |
217 | return $randomString; |
217 | return $randomString; |
218 | } |
218 | } |
219 | 219 | ||
220 | # http://stackoverflow.com/a/9361531 |
220 | # http://stackoverflow.com/a/9361531 |
221 | function _uniord($c) { |
221 | function _uniord($c) { |
222 | if (ord($c{0}) >=0 && ord($c{0}) <= 127) |
222 | if (ord($c{0}) >=0 && ord($c{0}) <= 127) |
223 | return ord($c{0}); |
223 | return ord($c{0}); |
224 | if (ord($c{0}) >= 192 && ord($c{0}) <= 223) |
224 | if (ord($c{0}) >= 192 && ord($c{0}) <= 223) |
225 | return (ord($c{0})-192)*64 + (ord($c{1})-128); |
225 | return (ord($c{0})-192)*64 + (ord($c{1})-128); |
226 | if (ord($c{0}) >= 224 && ord($c{0}) <= 239) |
226 | if (ord($c{0}) >= 224 && ord($c{0}) <= 239) |
227 | return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128); |
227 | return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128); |
228 | if (ord($c{0}) >= 240 && ord($c{0}) <= 247) |
228 | if (ord($c{0}) >= 240 && ord($c{0}) <= 247) |
229 | return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128); |
229 | return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128); |
230 | if (ord($c{0}) >= 248 && ord($c{0}) <= 251) |
230 | if (ord($c{0}) >= 248 && ord($c{0}) <= 251) |
231 | return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128); |
231 | return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128); |
232 | if (ord($c{0}) >= 252 && ord($c{0}) <= 253) |
232 | if (ord($c{0}) >= 252 && ord($c{0}) <= 253) |
233 | return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128); |
233 | return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128); |
234 | if (ord($c{0}) >= 254 && ord($c{0}) <= 255) // error |
234 | if (ord($c{0}) >= 254 && ord($c{0}) <= 255) // error |
235 | return FALSE; |
235 | return FALSE; |
236 | return 0; |
236 | return 0; |
237 | } |
237 | } |
238 | 238 | ||
239 | # urn:OID:2.0999 -> .2.999 |
239 | # urn:OID:2.0999 -> .2.999 |
240 | function normalize_oid($oid, $leading_dot=true) { |
240 | function normalize_oid($oid, $leading_dot=true) { |
241 | # remove urn:oid: and oid: |
241 | # remove urn:oid: and oid: |
242 | $oid = preg_replace('@^(urn:oid:|oid:|)@i', '', $oid); |
242 | $oid = preg_replace('@^(urn:oid:|oid:|)@i', '', $oid); |
243 | 243 | ||
244 | # add leading dot if it does not already exist |
244 | # add leading dot if it does not already exist |
245 | $oid = preg_replace('@^\.@', '', $oid); |
245 | $oid = preg_replace('@^\.@', '', $oid); |
246 | $oid = '.' . $oid; |
246 | $oid = '.' . $oid; |
247 | 247 | ||
248 | # remove leading zeros (requires leading dot) |
248 | # remove leading zeros (requires leading dot) |
249 | $oid = preg_replace('@\.0*([1-9])@', '.$1', $oid); |
249 | $oid = preg_replace('@\.0*([1-9])@', '.$1', $oid); |
250 | 250 | ||
251 | if (!$leading_dot) { |
251 | if (!$leading_dot) { |
252 | $oid = preg_replace('@^\\.@s', '', $oid); |
252 | $oid = preg_replace('@^\\.@s', '', $oid); |
253 | } |
253 | } |
254 | 254 | ||
255 | return $oid; |
255 | return $oid; |
256 | } |
256 | } |
257 | 257 | ||
258 | function generateRandomToken($haystack, $length = 20) { |
258 | function generateRandomToken($haystack, $length = 20) { |
259 | do { |
259 | do { |
260 | $t = generateRandomString($length); |
260 | $t = generateRandomString($length); |
261 | } while (strpos($haystack, $t) !== false); |
261 | } while (strpos($haystack, $t) !== false); |
262 | return $t; |
262 | return $t; |
263 | } |
263 | } |
264 | 264 | ||
265 | function github_commit_count($user, $repo) { |
265 | function github_commit_count($user, $repo) { |
266 | $cont = file_get_contents("https://github.com/$user/$repo"); |
266 | $cont = file_get_contents("https://github.com/$user/$repo"); |
267 | if (preg_match('@>\s*(\d+)\s*</span>\s*commits@smU', $cont, $m)) { |
267 | if (preg_match('@>\s*(\d+)\s*</span>\s*commits@smU', $cont, $m)) { |
268 | return $m[1]; |
268 | return $m[1]; |
269 | } else { |
269 | } else { |
270 | return "?"; |
270 | return "?"; |
271 | } |
271 | } |
272 | } |
272 | } |
273 | 273 |