Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

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