Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400] [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]
1 <?php 2 /** 3 * Library for CSV serialization. 4 * 5 * This is used by the csv/proxy driver and is the CacheExecute() 6 * serialization format. 7 * 8 * This file is part of ADOdb, a Database Abstraction Layer library for PHP. 9 * 10 * @package ADOdb 11 * @link https://adodb.org Project's web site and documentation 12 * @link https://github.com/ADOdb/ADOdb Source code and issue tracker 13 * 14 * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause 15 * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, 16 * any later version. This means you can use it in proprietary products. 17 * See the LICENSE.md file distributed with this source code for details. 18 * @license BSD-3-Clause 19 * @license LGPL-2.1-or-later 20 * 21 * @copyright 2000-2013 John Lim 22 * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community 23 */ 24 25 // security - hide paths 26 if (!defined('ADODB_DIR')) die(); 27 28 global $ADODB_INCLUDED_CSV; 29 $ADODB_INCLUDED_CSV = 1; 30 31 /** 32 * convert a recordset into special format 33 * 34 * @param rs the recordset 35 * 36 * @return the CSV formatted data 37 */ 38 function _rs2serialize(&$rs,$conn=false,$sql='') 39 { 40 $max = ($rs) ? $rs->FieldCount() : 0; 41 42 if ($sql) $sql = urlencode($sql); 43 // metadata setup 44 45 if ($max <= 0 || $rs->dataProvider == 'empty') { // is insert/update/delete 46 if (is_object($conn)) { 47 $sql .= ','.$conn->Affected_Rows(); 48 $sql .= ','.$conn->Insert_ID(); 49 } else 50 $sql .= ',,'; 51 52 $text = "====-1,0,$sql\n"; 53 return $text; 54 } 55 $tt = ($rs->timeCreated) ? $rs->timeCreated : time(); 56 57 ## changed format from ====0 to ====1 58 $line = "====1,$tt,$sql\n"; 59 60 if ($rs->databaseType == 'array') { 61 $rows = $rs->_array; 62 } else { 63 $rows = array(); 64 while (!$rs->EOF) { 65 $rows[] = $rs->fields; 66 $rs->MoveNext(); 67 } 68 } 69 70 for($i=0; $i < $max; $i++) { 71 $o = $rs->FetchField($i); 72 $flds[] = $o; 73 } 74 75 $savefetch = isset($rs->adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode; 76 $class = $rs->connection->arrayClass; 77 $rs2 = new $class(); 78 $rs2->timeCreated = $rs->timeCreated; # memcache fix 79 $rs2->sql = $rs->sql; 80 $rs2->oldProvider = $rs->dataProvider; 81 $rs2->InitArrayFields($rows,$flds); 82 $rs2->fetchMode = $savefetch; 83 return $line.serialize($rs2); 84 } 85 86 87 /** 88 * Open CSV file and convert it into Data. 89 * 90 * @param url file/ftp/http url 91 * @param err returns the error message 92 * @param timeout dispose if recordset has been alive for $timeout secs 93 * 94 * @return recordset, or false if error occurred. If no 95 * error occurred in sql INSERT/UPDATE/DELETE, 96 * empty recordset is returned 97 */ 98 function csv2rs($url,&$err,$timeout=0, $rsclass='ADORecordSet_array') 99 { 100 $false = false; 101 $err = false; 102 $fp = @fopen($url,'rb'); 103 if (!$fp) { 104 $err = $url.' file/URL not found'; 105 return $false; 106 } 107 @flock($fp, LOCK_SH); 108 $arr = array(); 109 $ttl = 0; 110 111 if ($meta = fgetcsv($fp, 32000, ",")) { 112 // check if error message 113 if (strncmp($meta[0],'****',4) === 0) { 114 $err = trim(substr($meta[0],4,1024)); 115 fclose($fp); 116 return $false; 117 } 118 // check for meta data 119 // $meta[0] is -1 means return an empty recordset 120 // $meta[1] contains a time 121 122 if (strncmp($meta[0], '====',4) === 0) { 123 124 if ($meta[0] == "====-1") { 125 if (sizeof($meta) < 5) { 126 $err = "Corrupt first line for format -1"; 127 fclose($fp); 128 return $false; 129 } 130 fclose($fp); 131 132 if ($timeout > 0) { 133 $err = " Illegal Timeout $timeout "; 134 return $false; 135 } 136 137 $rs = new $rsclass($val=true); 138 $rs->fields = array(); 139 $rs->timeCreated = $meta[1]; 140 $rs->EOF = true; 141 $rs->_numOfFields = 0; 142 $rs->sql = urldecode($meta[2]); 143 $rs->affectedrows = (integer)$meta[3]; 144 $rs->insertid = $meta[4]; 145 return $rs; 146 } 147 # Under high volume loads, we want only 1 thread/process to _write_file 148 # so that we don't have 50 processes queueing to write the same data. 149 # We use probabilistic timeout, ahead of time. 150 # 151 # -4 sec before timeout, give processes 1/32 chance of timing out 152 # -2 sec before timeout, give processes 1/16 chance of timing out 153 # -1 sec after timeout give processes 1/4 chance of timing out 154 # +0 sec after timeout, give processes 100% chance of timing out 155 if (sizeof($meta) > 1) { 156 if($timeout >0){ 157 $tdiff = (integer)( $meta[1]+$timeout - time()); 158 if ($tdiff <= 2) { 159 switch($tdiff) { 160 case 4: 161 case 3: 162 if ((rand() & 31) == 0) { 163 fclose($fp); 164 $err = "Timeout 3"; 165 return $false; 166 } 167 break; 168 case 2: 169 if ((rand() & 15) == 0) { 170 fclose($fp); 171 $err = "Timeout 2"; 172 return $false; 173 } 174 break; 175 case 1: 176 if ((rand() & 3) == 0) { 177 fclose($fp); 178 $err = "Timeout 1"; 179 return $false; 180 } 181 break; 182 default: 183 fclose($fp); 184 $err = "Timeout 0"; 185 return $false; 186 } // switch 187 188 } // if check flush cache 189 }// (timeout>0) 190 $ttl = $meta[1]; 191 } 192 //================================================ 193 // new cache format - use serialize extensively... 194 if ($meta[0] === '====1') { 195 // slurp in the data 196 $MAXSIZE = 128000; 197 198 $text = fread($fp,$MAXSIZE); 199 if (strlen($text)) { 200 while ($txt = fread($fp,$MAXSIZE)) { 201 $text .= $txt; 202 } 203 } 204 fclose($fp); 205 $rs = unserialize($text); 206 if (is_object($rs)) $rs->timeCreated = $ttl; 207 else { 208 $err = "Unable to unserialize recordset"; 209 //echo htmlspecialchars($text),' !--END--!<p>'; 210 } 211 return $rs; 212 } 213 214 $meta = false; 215 $meta = fgetcsv($fp, 32000, ","); 216 if (!$meta) { 217 fclose($fp); 218 $err = "Unexpected EOF 1"; 219 return $false; 220 } 221 } 222 223 // Get Column definitions 224 $flds = array(); 225 foreach($meta as $o) { 226 $o2 = explode(':',$o); 227 if (sizeof($o2)!=3) { 228 $arr[] = $meta; 229 $flds = false; 230 break; 231 } 232 $fld = new ADOFieldObject(); 233 $fld->name = urldecode($o2[0]); 234 $fld->type = $o2[1]; 235 $fld->max_length = $o2[2]; 236 $flds[] = $fld; 237 } 238 } else { 239 fclose($fp); 240 $err = "Recordset had unexpected EOF 2"; 241 return $false; 242 } 243 244 // slurp in the data 245 $MAXSIZE = 128000; 246 247 $text = ''; 248 while ($txt = fread($fp,$MAXSIZE)) { 249 $text .= $txt; 250 } 251 252 fclose($fp); 253 @$arr = unserialize($text); 254 if (!is_array($arr)) { 255 $err = "Recordset had unexpected EOF (in serialized recordset)"; 256 return $false; 257 } 258 $rs = new $rsclass(); 259 $rs->timeCreated = $ttl; 260 $rs->InitArrayFields($arr,$flds); 261 return $rs; 262 } 263 264 265 /** 266 * Save a file $filename and its $contents (normally for caching) with file locking 267 * Returns true if ok, false if fopen/fwrite error, 0 if rename error (eg. file is locked) 268 */ 269 function adodb_write_file($filename, $contents,$debug=false) 270 { 271 # http://www.php.net/bugs.php?id=9203 Bug that flock fails on Windows 272 # So to simulate locking, we assume that rename is an atomic operation. 273 # First we delete $filename, then we create a $tempfile write to it and 274 # rename to the desired $filename. If the rename works, then we successfully 275 # modified the file exclusively. 276 # What a stupid need - having to simulate locking. 277 # Risks: 278 # 1. $tempfile name is not unique -- very very low 279 # 2. unlink($filename) fails -- ok, rename will fail 280 # 3. adodb reads stale file because unlink fails -- ok, $rs timeout occurs 281 # 4. another process creates $filename between unlink() and rename() -- ok, rename() fails and cache updated 282 if (strncmp(PHP_OS,'WIN',3) === 0) { 283 // skip the decimal place 284 $mtime = substr(str_replace(' ','_',microtime()),2); 285 // getmypid() actually returns 0 on Win98 - never mind! 286 $tmpname = $filename.uniqid($mtime).getmypid(); 287 if (!($fd = @fopen($tmpname,'w'))) return false; 288 if (fwrite($fd,$contents)) $ok = true; 289 else $ok = false; 290 fclose($fd); 291 292 if ($ok) { 293 @chmod($tmpname,0644); 294 // the tricky moment 295 @unlink($filename); 296 if (!@rename($tmpname,$filename)) { 297 @unlink($tmpname); 298 $ok = 0; 299 } 300 if (!$ok) { 301 if ($debug) ADOConnection::outp( " Rename $tmpname ".($ok? 'ok' : 'failed')); 302 } 303 } 304 return $ok; 305 } 306 if (!($fd = @fopen($filename, 'a'))) return false; 307 if (flock($fd, LOCK_EX) && ftruncate($fd, 0)) { 308 if (fwrite( $fd, $contents )) $ok = true; 309 else $ok = false; 310 fclose($fd); 311 @chmod($filename,0644); 312 }else { 313 fclose($fd); 314 if ($debug)ADOConnection::outp( " Failed acquiring lock for $filename<br>\n"); 315 $ok = false; 316 } 317 318 return $ok; 319 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body