XOOPS Cube Legacy base repository
Revisão | 124799f35f1abe41e3d38a44e71c4459e1d86a7f (tree) |
---|---|
Hora | 2013-04-20 15:36:15 |
Autor | Mumin Cacao <mumincacao@gmai...> |
Commiter | Mumin Cacao |
Replace MySQL API to mysqli.
@@ -32,8 +32,8 @@ | ||
32 | 32 | * @package kernel |
33 | 33 | * @subpackage database |
34 | 34 | * |
35 | - * @author Kazumi Ono <onokazu@xoops.org> | |
36 | - * @copyright copyright (c) 2000-2003 XOOPS.org | |
35 | + * @author Kazumi Ono <onokazu@xoops.org> | |
36 | + * @copyright copyright (c) 2000-2003 XOOPS.org | |
37 | 37 | */ |
38 | 38 | |
39 | 39 | if (!defined('XOOPS_ROOT_PATH')) exit(); |
@@ -43,10 +43,6 @@ if (!defined('XOOPS_ROOT_PATH')) exit(); | ||
43 | 43 | */ |
44 | 44 | include_once XOOPS_ROOT_PATH.'/class/database/database.php'; |
45 | 45 | |
46 | -if (!defined('MYSQL_CLIENT_FOUND_ROWS')) { | |
47 | - define('MYSQL_CLIENT_FOUND_ROWS', 2); | |
48 | -} | |
49 | - | |
50 | 46 | /** |
51 | 47 | * connection to a mysql database |
52 | 48 | * |
@@ -60,79 +56,79 @@ if (!defined('MYSQL_CLIENT_FOUND_ROWS')) { | ||
60 | 56 | */ |
61 | 57 | class XoopsMySQLDatabase extends XoopsDatabase |
62 | 58 | { |
63 | - /** | |
64 | - * Database connection | |
65 | - * @var resource | |
66 | - */ | |
67 | - var $conn; | |
68 | - | |
69 | - /** | |
70 | - * String for Emulation prepare | |
71 | - * @var string | |
72 | - */ | |
73 | - var $mPrepareQuery=null; | |
74 | - | |
75 | - /** | |
76 | - * connect to the database | |
77 | - * | |
59 | + /** | |
60 | + * Database connection | |
61 | + * @var mysqli | |
62 | + */ | |
63 | + var $conn; | |
64 | + | |
65 | + /** | |
66 | + * String for Emulation prepare | |
67 | + * @var string | |
68 | + */ | |
69 | + var $mPrepareQuery=null; | |
70 | + | |
71 | + /** | |
72 | + * connect to the database | |
73 | + * | |
78 | 74 | * @param bool $selectdb select the database now? |
79 | 75 | * @return bool successful? |
80 | - */ | |
81 | - function connect($selectdb = true) | |
82 | - { | |
83 | - if (XOOPS_DB_PCONNECT == 1) { | |
84 | - $this->conn = @mysql_pconnect(XOOPS_DB_HOST, XOOPS_DB_USER, XOOPS_DB_PASS, false, MYSQL_CLIENT_FOUND_ROWS); | |
85 | - } else { | |
86 | - $this->conn = @mysql_connect(XOOPS_DB_HOST, XOOPS_DB_USER, XOOPS_DB_PASS, false, MYSQL_CLIENT_FOUND_ROWS); | |
87 | - } | |
88 | - | |
89 | - if (!$this->conn) { | |
90 | - $this->logger->addQuery('', $this->error(), $this->errno()); | |
91 | - return false; | |
92 | - } | |
93 | - | |
94 | - if($selectdb != false){ | |
95 | - if (!mysql_select_db(XOOPS_DB_NAME)) { | |
96 | - $this->logger->addQuery('', $this->error(), $this->errno()); | |
97 | - return false; | |
98 | - } | |
99 | - } | |
100 | - return true; | |
101 | - } | |
102 | - | |
103 | - /** | |
104 | - * generate an ID for a new row | |
76 | + */ | |
77 | + function connect($selectdb = true) | |
78 | + { | |
79 | + $host = (XOOPS_DB_PCONNECT == 1 ? 'p:' : '') . XOOPS_DB_HOST; | |
80 | + $this->conn = mysqli_init(); | |
81 | + if(!$this->conn->real_connect($host, XOOPS_DB_USER, XOOPS_DB_PASS, null, null, null, MYSQLI_CLIENT_FOUND_ROWS)) | |
82 | + { | |
83 | + $this->logger->addQuery('', $this->error(), $this->errno()); | |
84 | + return false; | |
85 | + } | |
86 | + | |
87 | + if($selectdb) | |
88 | + { | |
89 | + if(!$this->conn->select_db(XOOPS_DB_NAME)) | |
90 | + { | |
91 | + $this->logger->addQuery('', $this->error(), $this->errno()); | |
92 | + return false; | |
93 | + } | |
94 | + } | |
95 | + | |
96 | + return true; | |
97 | + } | |
98 | + | |
99 | + /** | |
100 | + * generate an ID for a new row | |
105 | 101 | * |
106 | 102 | * This is for compatibility only. Will always return 0, because MySQL supports |
107 | 103 | * autoincrement for primary keys. |
108 | 104 | * |
109 | 105 | * @param string $sequence name of the sequence from which to get the next ID |
110 | 106 | * @return int always 0, because mysql has support for autoincrement |
111 | - */ | |
112 | - function genId($sequence) | |
113 | - { | |
114 | - return 0; // will use auto_increment | |
115 | - } | |
116 | - | |
117 | - /** | |
118 | - * Get a result row as an enumerated array | |
119 | - * | |
120 | - * @param resource $result | |
107 | + */ | |
108 | + function genId($sequence) | |
109 | + { | |
110 | + return 0; // will use auto_increment | |
111 | + } | |
112 | + | |
113 | + /** | |
114 | + * Get a result row as an enumerated array | |
115 | + * | |
116 | + * @param mysqli_result $result | |
121 | 117 | * @return array |
122 | - */ | |
123 | - function fetchRow($result) | |
124 | - { | |
125 | - return @mysql_fetch_row($result); | |
126 | - } | |
127 | - | |
128 | - /** | |
129 | - * Fetch a result row as an associative array | |
130 | - * | |
118 | + */ | |
119 | + function fetchRow($result) | |
120 | + { | |
121 | + return $result->fetch_row(); | |
122 | + } | |
123 | + | |
124 | + /** | |
125 | + * Fetch a result row as an associative array | |
126 | + * | |
131 | 127 | * @return array |
132 | - */ | |
133 | - function fetchArray($result) | |
128 | + */ | |
129 | + function fetchArray($result) | |
134 | 130 | { |
135 | - return @mysql_fetch_assoc( $result ); | |
131 | + return $result->fetch_assoc(); | |
136 | 132 | } |
137 | 133 | |
138 | 134 | /** |
@@ -142,79 +138,79 @@ class XoopsMySQLDatabase extends XoopsDatabase | ||
142 | 138 | */ |
143 | 139 | function fetchBoth($result) |
144 | 140 | { |
145 | - return @mysql_fetch_array( $result, MYSQL_BOTH ); | |
141 | + return $result->fetch_array(MYSQLI_BOTH); | |
146 | 142 | } |
147 | 143 | |
148 | - /** | |
149 | - * Get the ID generated from the previous INSERT operation | |
150 | - * | |
144 | + /** | |
145 | + * Get the ID generated from the previous INSERT operation | |
146 | + * | |
151 | 147 | * @return int |
152 | - */ | |
153 | - function getInsertId() | |
154 | - { | |
155 | - return mysql_insert_id($this->conn); | |
156 | - } | |
157 | - | |
158 | - /** | |
159 | - * Get number of rows in result | |
160 | - * | |
148 | + */ | |
149 | + function getInsertId() | |
150 | + { | |
151 | + return $this->conn->insert_id; | |
152 | + } | |
153 | + | |
154 | + /** | |
155 | + * Get number of rows in result | |
156 | + * | |
161 | 157 | * @param resource query result |
162 | 158 | * @return int |
163 | - */ | |
164 | - function getRowsNum($result) | |
165 | - { | |
166 | - return @mysql_num_rows($result); | |
167 | - } | |
168 | - | |
169 | - /** | |
170 | - * Get number of affected rows | |
171 | - * | |
159 | + */ | |
160 | + function getRowsNum($result) | |
161 | + { | |
162 | + return $result->num_rows; | |
163 | + } | |
164 | + | |
165 | + /** | |
166 | + * Get number of affected rows | |
167 | + * | |
172 | 168 | * @return int |
173 | - */ | |
174 | - function getAffectedRows() | |
175 | - { | |
176 | - return mysql_affected_rows($this->conn); | |
177 | - } | |
178 | - | |
179 | - /** | |
180 | - * Close MySQL connection | |
181 | - * | |
182 | - */ | |
183 | - function close() | |
184 | - { | |
185 | - mysql_close($this->conn); | |
186 | - } | |
187 | - | |
188 | - /** | |
189 | - * will free all memory associated with the result identifier result. | |
190 | - * | |
169 | + */ | |
170 | + function getAffectedRows() | |
171 | + { | |
172 | + return $this->conn->affected_rows; | |
173 | + } | |
174 | + | |
175 | + /** | |
176 | + * Close MySQL connection | |
177 | + * | |
178 | + */ | |
179 | + function close() | |
180 | + { | |
181 | + $this->conn->close(); | |
182 | + } | |
183 | + | |
184 | + /** | |
185 | + * will free all memory associated with the result identifier result. | |
186 | + * | |
191 | 187 | * @param resource query result |
192 | 188 | * @return bool TRUE on success or FALSE on failure. |
193 | - */ | |
194 | - function freeRecordSet($result) | |
195 | - { | |
196 | - return mysql_free_result($result); | |
197 | - } | |
198 | - | |
199 | - /** | |
200 | - * Returns the text of the error message from previous MySQL operation | |
201 | - * | |
189 | + */ | |
190 | + function freeRecordSet($result) | |
191 | + { | |
192 | + return $result->free(); | |
193 | + } | |
194 | + | |
195 | + /** | |
196 | + * Returns the text of the error message from previous MySQL operation | |
197 | + * | |
202 | 198 | * @return bool Returns the error text from the last MySQL function, or '' (the empty string) if no error occurred. |
203 | - */ | |
204 | - function error() | |
205 | - { | |
206 | - return @mysql_error(); | |
207 | - } | |
208 | - | |
209 | - /** | |
210 | - * Returns the numerical value of the error message from previous MySQL operation | |
211 | - * | |
199 | + */ | |
200 | + function error() | |
201 | + { | |
202 | + return $this->conn->error; | |
203 | + } | |
204 | + | |
205 | + /** | |
206 | + * Returns the numerical value of the error message from previous MySQL operation | |
207 | + * | |
212 | 208 | * @return int Returns the error number from the last MySQL function, or 0 (zero) if no error occurred. |
213 | - */ | |
214 | - function errno() | |
215 | - { | |
216 | - return @mysql_errno(); | |
217 | - } | |
209 | + */ | |
210 | + function errno() | |
211 | + { | |
212 | + return $this->conn->errno; | |
213 | + } | |
218 | 214 | |
219 | 215 | /** |
220 | 216 | * Returns escaped string text with single quotes around it to be safely stored in database |
@@ -224,7 +220,7 @@ class XoopsMySQLDatabase extends XoopsDatabase | ||
224 | 220 | */ |
225 | 221 | function quoteString($str) |
226 | 222 | { |
227 | - $str = '\''.mysql_real_escape_string($str, $this->conn).'\''; | |
223 | + $str = "'" . $this->conn->real_escape_string($str) . "'"; | |
228 | 224 | return $str; |
229 | 225 | } |
230 | 226 |
@@ -238,54 +234,54 @@ class XoopsMySQLDatabase extends XoopsDatabase | ||
238 | 234 | * or TRUE if successful and no result |
239 | 235 | */ |
240 | 236 | function &queryF($sql, $limit=0, $start=0) |
241 | - { | |
242 | - if ( !empty($limit) ) { | |
243 | - if (empty($start)) { | |
237 | + { | |
238 | + if ( !empty($limit) ) { | |
239 | + if (empty($start)) { | |
244 | 240 | $sql .= ' LIMIT ' . (int)$limit; |
245 | - } | |
241 | + } | |
246 | 242 | else |
247 | 243 | { |
248 | 244 | $sql = $sql. ' LIMIT '.(int)$start.', '.(int)$limit; |
249 | 245 | } |
250 | - } | |
251 | - $result = mysql_query($sql, $this->conn); | |
252 | - if ( $result ) { | |
253 | - $this->logger->addQuery($sql); | |
254 | - return $result; | |
246 | + } | |
247 | + $result = $this->conn->query($sql); | |
248 | + if ( $result ) { | |
249 | + $this->logger->addQuery($sql); | |
250 | + return $result; | |
255 | 251 | } else { |
256 | - $this->logger->addQuery($sql, $this->error(), $this->errno()); | |
252 | + $this->logger->addQuery($sql, $this->error(), $this->errno()); | |
257 | 253 | $ret = false; |
258 | 254 | return $ret; |
259 | 255 | } |
260 | 256 | } |
261 | 257 | |
262 | - /** | |
263 | - * perform a query | |
258 | + /** | |
259 | + * perform a query | |
264 | 260 | * |
265 | 261 | * This method is empty and does nothing! It should therefore only be |
266 | 262 | * used if nothing is exactly what you want done! ;-) |
267 | - * | |
263 | + * | |
268 | 264 | * @param string $sql a valid MySQL query |
269 | 265 | * @param int $limit number of records to return |
270 | 266 | * @param int $start offset of first record to return |
271 | 267 | * |
272 | 268 | * @abstract |
273 | - */ | |
274 | - function &query($sql, $limit=0, $start=0) | |
275 | - { | |
269 | + */ | |
270 | + function &query($sql, $limit=0, $start=0) | |
271 | + { | |
276 | 272 | |
277 | 273 | } |
278 | 274 | |
279 | 275 | /** |
280 | - * perform queries from SQL dump file in a batch | |
281 | - * | |
276 | + * perform queries from SQL dump file in a batch | |
277 | + * | |
282 | 278 | * @param string $file file path to an SQL dump file |
283 | 279 | * |
284 | 280 | * @return bool FALSE if failed reading SQL file or TRUE if the file has been read and queries executed |
285 | - */ | |
286 | - function queryFromFile($file){ | |
281 | + */ | |
282 | + function queryFromFile($file){ | |
287 | 283 | if (false !== ($fp = fopen($file, 'r'))) { |
288 | - include_once XOOPS_ROOT_PATH.'/class/database/sqlutility.php'; | |
284 | + include_once XOOPS_ROOT_PATH.'/class/database/sqlutility.php'; | |
289 | 285 | $sql_queries = trim(fread($fp, filesize($file))); |
290 | 286 | SqlUtility::splitMySqlFile($pieces, $sql_queries); |
291 | 287 | foreach ($pieces as $query) { |
@@ -302,120 +298,122 @@ class XoopsMySQLDatabase extends XoopsDatabase | ||
302 | 298 | } |
303 | 299 | |
304 | 300 | /** |
305 | - * Get field name | |
306 | - * | |
301 | + * Get field name | |
302 | + * | |
307 | 303 | * @param resource $result query result |
308 | 304 | * @param int numerical field index |
309 | 305 | * @return string |
310 | - */ | |
311 | - function getFieldName($result, $offset) | |
312 | - { | |
313 | - return mysql_field_name($result, $offset); | |
314 | - } | |
315 | - | |
316 | - /** | |
317 | - * Get field type | |
318 | - * | |
306 | + */ | |
307 | + function getFieldName($result, $offset) | |
308 | + { | |
309 | + $info = $result->fetch_field_direct($offset); | |
310 | + return $info ? $info->name : false; | |
311 | + } | |
312 | + | |
313 | + /** | |
314 | + * Get field type | |
315 | + * | |
319 | 316 | * @param resource $result query result |
320 | 317 | * @param int $offset numerical field index |
321 | 318 | * @return string |
322 | - */ | |
319 | + */ | |
323 | 320 | function getFieldType($result, $offset) |
324 | - { | |
325 | - return mysql_field_type($result, $offset); | |
326 | - } | |
321 | + { | |
322 | + $info = $result->fetch_field_direct($offset); | |
323 | + return $info ? $info->type : false; | |
324 | + } | |
327 | 325 | |
328 | - /** | |
329 | - * Get number of fields in result | |
330 | - * | |
326 | + /** | |
327 | + * Get number of fields in result | |
328 | + * | |
331 | 329 | * @param resource $result query result |
332 | 330 | * @return int |
333 | - */ | |
334 | - function getFieldsNum($result) | |
335 | - { | |
336 | - return mysql_num_fields($result); | |
337 | - } | |
338 | - | |
339 | - /** | |
340 | - * Emulates prepare(), but this is TEST API. | |
341 | - * @remark This is TEST API. This method should be called by only Legacy. | |
342 | - */ | |
343 | - function prepare($query) | |
344 | - { | |
345 | - $count=0; | |
346 | - while(($pos=strpos($query,'?'))!==false) { | |
347 | - $pre=substr($query,0,$pos); | |
348 | - $after=''; | |
349 | - if($pos+1<=strlen($query)) | |
350 | - $after=substr($query,$pos+1); | |
351 | - | |
352 | - $query=$pre.'{'.$count.'}'.$after; | |
353 | - $count++; | |
354 | - } | |
355 | - $this->mPrepareQuery=$query; | |
356 | - } | |
357 | - | |
358 | - /** | |
359 | - * Emulates bind_param(), but this is TEST API. | |
360 | - * @remark This is TEST API. This method should be called by only Legacy. | |
361 | - */ | |
362 | - function bind_param() | |
363 | - { | |
364 | - if(func_num_args()<2) | |
365 | - return; | |
366 | - | |
367 | - $types=func_get_arg(0); | |
368 | - $count=strlen($types); | |
369 | - if(func_num_args()<$count) | |
370 | - return; | |
371 | - | |
372 | - $searches=array(); | |
373 | - $replaces=array(); | |
374 | - for($i=0;$i<$count;$i++) { | |
375 | - $searches[$i]='{'.$i.'}'; | |
376 | - switch(substr($types,$i,1)) { | |
377 | - case 'i': | |
378 | - $replaces[$i]=(int)func_get_arg($i+1); | |
379 | - break; | |
380 | - | |
381 | - case 's': | |
382 | - $replaces[$i]=$this->quoteString(func_get_arg($i+1)); | |
383 | - break; | |
384 | - | |
385 | - case 'd': | |
386 | - $replaces[$i]=doubleval(func_get_arg($i+1)); | |
387 | - break; | |
388 | - | |
389 | - case 'b': | |
390 | - // Exception | |
391 | - die(); | |
392 | - } | |
393 | - } | |
394 | - | |
395 | - $this->mPrepareQuery=str_replace($searches,$replaces,$this->mPrepareQuery); | |
396 | - } | |
397 | - | |
398 | - /** | |
399 | - * Executes prepared SQL with query(), but this is TEST API. | |
400 | - * @remark This is TEST API. This method should be called by only Legacy. | |
401 | - */ | |
402 | - function &execute() | |
403 | - { | |
404 | - $result=&$this->query($this->mPrepareQuery); | |
405 | - $this->mPrepareQuery=null; | |
406 | - return $result; | |
407 | - } | |
408 | - | |
409 | - /** | |
410 | - * Executes prepared SQL with queryF(), but this is TEST API. | |
411 | - * @remark This is TEST API. This method should be called by only Legacy. | |
412 | - */ | |
413 | - function &executeF() | |
414 | - { | |
415 | - $result=&$this->queryF($this->mPrepareQuery); | |
416 | - $this->mPrepareQuery=null; | |
417 | - return $result; | |
418 | - } | |
331 | + */ | |
332 | + function getFieldsNum($result) | |
333 | + { | |
334 | + return $this->conn->field_count; | |
335 | + } | |
336 | + | |
337 | + /** | |
338 | + * Emulates prepare(), but this is TEST API. | |
339 | + * @remark This is TEST API. This method should be called by only Legacy. | |
340 | + */ | |
341 | + function prepare($query) | |
342 | + { | |
343 | + $count=0; | |
344 | + while(($pos=strpos($query,'?'))!==false) { | |
345 | + $pre=substr($query,0,$pos); | |
346 | + $after=''; | |
347 | + if($pos+1<=strlen($query)) | |
348 | + $after=substr($query,$pos+1); | |
349 | + | |
350 | + $query=$pre.'{'.$count.'}'.$after; | |
351 | + $count++; | |
352 | + } | |
353 | + $this->mPrepareQuery=$query; | |
354 | + } | |
355 | + | |
356 | + /** | |
357 | + * Emulates bind_param(), but this is TEST API. | |
358 | + * @remark This is TEST API. This method should be called by only Legacy. | |
359 | + */ | |
360 | + function bind_param() | |
361 | + { | |
362 | + if(func_num_args()<2) | |
363 | + return; | |
364 | + | |
365 | + $types=func_get_arg(0); | |
366 | + $count=strlen($types); | |
367 | + if(func_num_args()<$count) | |
368 | + return; | |
369 | + | |
370 | + $searches=array(); | |
371 | + $replaces=array(); | |
372 | + for($i=0;$i<$count;$i++) { | |
373 | + $searches[$i]='{'.$i.'}'; | |
374 | + switch(substr($types,$i,1)) { | |
375 | + case 'i': | |
376 | + $replaces[$i]=(int)func_get_arg($i+1); | |
377 | + break; | |
378 | + | |
379 | + case 's': | |
380 | + $replaces[$i]=$this->quoteString(func_get_arg($i+1)); | |
381 | + break; | |
382 | + | |
383 | + case 'd': | |
384 | + $replaces[$i]=doubleval(func_get_arg($i+1)); | |
385 | + break; | |
386 | + | |
387 | + case 'b': | |
388 | + // Exception | |
389 | + die(); | |
390 | + } | |
391 | + } | |
392 | + | |
393 | + $this->mPrepareQuery=str_replace($searches,$replaces,$this->mPrepareQuery); | |
394 | + } | |
395 | + | |
396 | + /** | |
397 | + * Executes prepared SQL with query(), but this is TEST API. | |
398 | + * @remark This is TEST API. This method should be called by only Legacy. | |
399 | + */ | |
400 | + function &execute() | |
401 | + { | |
402 | + $result=&$this->query($this->mPrepareQuery); | |
403 | + $this->mPrepareQuery=null; | |
404 | + return $result; | |
405 | + } | |
406 | + | |
407 | + /** | |
408 | + * Executes prepared SQL with queryF(), but this is TEST API. | |
409 | + * @remark This is TEST API. This method should be called by only Legacy. | |
410 | + */ | |
411 | + function &executeF() | |
412 | + { | |
413 | + $result=&$this->queryF($this->mPrepareQuery); | |
414 | + $this->mPrepareQuery=null; | |
415 | + return $result; | |
416 | + } | |
419 | 417 | } |
420 | 418 | |
421 | 419 | /** |
@@ -440,11 +438,11 @@ class XoopsMySQLDatabaseSafe extends XoopsMySQLDatabase | ||
440 | 438 | * @return resource query result or FALSE if successful |
441 | 439 | * or TRUE if successful and no result |
442 | 440 | */ |
443 | - function &query($sql, $limit=0, $start=0) | |
444 | - { | |
445 | - $result =& $this->queryF($sql, $limit, $start); | |
446 | - return $result; | |
447 | - } | |
441 | + function &query($sql, $limit=0, $start=0) | |
442 | + { | |
443 | + $result =& $this->queryF($sql, $limit, $start); | |
444 | + return $result; | |
445 | + } | |
448 | 446 | } |
449 | 447 | |
450 | 448 | /** |
@@ -473,17 +471,17 @@ class XoopsMySQLDatabaseProxy extends XoopsMySQLDatabase | ||
473 | 471 | * @param int $start offset of first record to return |
474 | 472 | * @return resource query result or FALSE if unsuccessful |
475 | 473 | */ |
476 | - function &query($sql, $limit=0, $start=0) | |
477 | - { | |
478 | - $sql = ltrim($sql); | |
479 | - if (preg_match('/^SELECT/i', $sql)) { | |
480 | - $ret = $this->queryF($sql, $limit, $start); | |
481 | - return $ret; | |
482 | - } | |
483 | - $this->logger->addQuery($sql, 'Database update not allowed during processing of a GET request', 0); | |
484 | - | |
485 | - $ret = false; | |
486 | - return $ret; | |
487 | - } | |
474 | + function &query($sql, $limit=0, $start=0) | |
475 | + { | |
476 | + $sql = ltrim($sql); | |
477 | + if (preg_match('/^SELECT/i', $sql)) { | |
478 | + $ret = $this->queryF($sql, $limit, $start); | |
479 | + return $ret; | |
480 | + } | |
481 | + $this->logger->addQuery($sql, 'Database update not allowed during processing of a GET request', 0); | |
482 | + | |
483 | + $ret = false; | |
484 | + return $ret; | |
485 | + } | |
488 | 486 | } |
489 | 487 | ?> |