]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/adodb/adodb-csvlib.inc.php
Upgrade adodb
[SourceForge/phpwiki.git] / lib / WikiDB / adodb / adodb-csvlib.inc.php
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   V5.18 3 Sep 2012   (c) 2000-2012 John Lim (jlim#natsoft.com). 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->timeCreated = $rs->timeCreated; # memcache fix
75                 $rs2->sql = $rs->sql;
76                 $rs2->oldProvider = $rs->dataProvider; 
77                 $rs2->InitArrayFields($rows,$flds);
78                 $rs2->fetchMode = $savefetch;
79                 return $line.serialize($rs2);
80         }
81
82         
83 /**
84 * Open CSV file and convert it into Data. 
85 *
86 * @param url            file/ftp/http url
87 * @param err            returns the error message
88 * @param timeout        dispose if recordset has been alive for $timeout secs
89 *
90 * @return               recordset, or false if error occured. If no
91 *                       error occurred in sql INSERT/UPDATE/DELETE, 
92 *                       empty recordset is returned
93 */
94         function csv2rs($url,&$err,$timeout=0, $rsclass='ADORecordSet_array')
95         {
96                 $false = false;
97                 $err = false;
98                 $fp = @fopen($url,'rb');
99                 if (!$fp) {
100                         $err = $url.' file/URL not found';
101                         return $false;
102                 }
103                 @flock($fp, LOCK_SH);
104                 $arr = array();
105                 $ttl = 0;
106                 
107                 if ($meta = fgetcsv($fp, 32000, ",")) {
108                         // check if error message
109                         if (strncmp($meta[0],'****',4) === 0) {
110                                 $err = trim(substr($meta[0],4,1024));
111                                 fclose($fp);
112                                 return $false;
113                         }
114                         // check for meta data
115                         // $meta[0] is -1 means return an empty recordset
116                         // $meta[1] contains a time 
117         
118                         if (strncmp($meta[0], '====',4) === 0) {
119                         
120                                 if ($meta[0] == "====-1") {
121                                         if (sizeof($meta) < 5) {
122                                                 $err = "Corrupt first line for format -1";
123                                                 fclose($fp);
124                                                 return $false;
125                                         }
126                                         fclose($fp);
127                                         
128                                         if ($timeout > 0) {
129                                                 $err = " Illegal Timeout $timeout ";
130                                                 return $false;
131                                         }
132                                         
133                                         $rs = new $rsclass($val=true);
134                                         $rs->fields = array();
135                                         $rs->timeCreated = $meta[1];
136                                         $rs->EOF = true;
137                                         $rs->_numOfFields = 0;
138                                         $rs->sql = urldecode($meta[2]);
139                                         $rs->affectedrows = (integer)$meta[3];
140                                         $rs->insertid = $meta[4];       
141                                         return $rs;
142                                 } 
143                         # Under high volume loads, we want only 1 thread/process to _write_file
144                         # so that we don't have 50 processes queueing to write the same data.
145                         # We use probabilistic timeout, ahead of time.
146                         #
147                         # -4 sec before timeout, give processes 1/32 chance of timing out
148                         # -2 sec before timeout, give processes 1/16 chance of timing out
149                         # -1 sec after timeout give processes 1/4 chance of timing out
150                         # +0 sec after timeout, give processes 100% chance of timing out
151                                 if (sizeof($meta) > 1) {
152                                         if($timeout >0){ 
153                                                 $tdiff = (integer)( $meta[1]+$timeout - time());
154                                                 if ($tdiff <= 2) {
155                                                         switch($tdiff) {
156                                                         case 4:
157                                                         case 3:
158                                                                 if ((rand() & 31) == 0) {
159                                                                         fclose($fp);
160                                                                         $err = "Timeout 3";
161                                                                         return $false;
162                                                                 }
163                                                                 break;
164                                                         case 2: 
165                                                                 if ((rand() & 15) == 0) {
166                                                                         fclose($fp);
167                                                                         $err = "Timeout 2";
168                                                                         return $false;
169                                                                 }
170                                                                 break;
171                                                         case 1:
172                                                                 if ((rand() & 3) == 0) {
173                                                                         fclose($fp);
174                                                                         $err = "Timeout 1";
175                                                                         return $false;
176                                                                 }
177                                                                 break;
178                                                         default: 
179                                                                 fclose($fp);
180                                                                 $err = "Timeout 0";
181                                                                 return $false;
182                                                         } // switch
183                                                         
184                                                 } // if check flush cache
185                                         }// (timeout>0)
186                                         $ttl = $meta[1];
187                                 }
188                                 //================================================
189                                 // new cache format - use serialize extensively...
190                                 if ($meta[0] === '====1') {
191                                         // slurp in the data
192                                         $MAXSIZE = 128000;
193                                         
194                                         $text = fread($fp,$MAXSIZE);
195                                         if (strlen($text)) {
196                                                 while ($txt = fread($fp,$MAXSIZE)) {
197                                                         $text .= $txt;
198                                                 }
199                                         }
200                                         fclose($fp);
201                                         $rs = unserialize($text);
202                                         if (is_object($rs)) $rs->timeCreated = $ttl;
203                                         else {
204                                                 $err = "Unable to unserialize recordset";
205                                                 //echo htmlspecialchars($text),' !--END--!<p>';
206                                         }
207                                         return $rs;
208                                 }
209                                 
210                                 $meta = false;
211                                 $meta = fgetcsv($fp, 32000, ",");
212                                 if (!$meta) {
213                                         fclose($fp);
214                                         $err = "Unexpected EOF 1";
215                                         return $false;
216                                 }
217                         }
218
219                         // Get Column definitions
220                         $flds = array();
221                         foreach($meta as $o) {
222                                 $o2 = explode(':',$o);
223                                 if (sizeof($o2)!=3) {
224                                         $arr[] = $meta;
225                                         $flds = false;
226                                         break;
227                                 }
228                                 $fld = new ADOFieldObject();
229                                 $fld->name = urldecode($o2[0]);
230                                 $fld->type = $o2[1];
231                                 $fld->max_length = $o2[2];
232                                 $flds[] = $fld;
233                         }
234                 } else {
235                         fclose($fp);
236                         $err = "Recordset had unexpected EOF 2";
237                         return $false;
238                 }
239                 
240                 // slurp in the data
241                 $MAXSIZE = 128000;
242                 
243                 $text = '';
244                 while ($txt = fread($fp,$MAXSIZE)) {
245                         $text .= $txt;
246                 }
247                         
248                 fclose($fp);
249                 @$arr = unserialize($text);
250                 //var_dump($arr);
251                 if (!is_array($arr)) {
252                         $err = "Recordset had unexpected EOF (in serialized recordset)";
253                         if (get_magic_quotes_runtime()) $err .= ". Magic Quotes Runtime should be disabled!";
254                         return $false;
255                 }
256                 $rs = new $rsclass();
257                 $rs->timeCreated = $ttl;
258                 $rs->InitArrayFields($arr,$flds);
259                 return $rs;
260         }
261         
262
263         /**
264         * Save a file $filename and its $contents (normally for caching) with file locking
265         * Returns true if ok, false if fopen/fwrite error, 0 if rename error (eg. file is locked)
266         */
267         function adodb_write_file($filename, $contents,$debug=false)
268         { 
269         # http://www.php.net/bugs.php?id=9203 Bug that flock fails on Windows
270         # So to simulate locking, we assume that rename is an atomic operation.
271         # First we delete $filename, then we create a $tempfile write to it and 
272         # rename to the desired $filename. If the rename works, then we successfully 
273         # modified the file exclusively.
274         # What a stupid need - having to simulate locking.
275         # Risks:
276         # 1. $tempfile name is not unique -- very very low
277         # 2. unlink($filename) fails -- ok, rename will fail
278         # 3. adodb reads stale file because unlink fails -- ok, $rs timeout occurs
279         # 4. another process creates $filename between unlink() and rename() -- ok, rename() fails and  cache updated
280                 if (strncmp(PHP_OS,'WIN',3) === 0) {
281                         // skip the decimal place
282                         $mtime = substr(str_replace(' ','_',microtime()),2); 
283                         // getmypid() actually returns 0 on Win98 - never mind!
284                         $tmpname = $filename.uniqid($mtime).getmypid();
285                         if (!($fd = @fopen($tmpname,'w'))) return false;
286                         if (fwrite($fd,$contents)) $ok = true;
287                         else $ok = false;
288                         fclose($fd);
289                         
290                         if ($ok) {
291                                 @chmod($tmpname,0644);
292                                 // the tricky moment
293                                 @unlink($filename);
294                                 if (!@rename($tmpname,$filename)) {
295                                         unlink($tmpname);
296                                         $ok = 0;
297                                 }
298                                 if (!$ok) {
299                                         if ($debug) ADOConnection::outp( " Rename $tmpname ".($ok? 'ok' : 'failed'));
300                                 }
301                         }
302                         return $ok;
303                 }
304                 if (!($fd = @fopen($filename, 'a'))) return false;
305                 if (flock($fd, LOCK_EX) && ftruncate($fd, 0)) {
306                         if (fwrite( $fd, $contents )) $ok = true;
307                         else $ok = false;
308                         fclose($fd);
309                         @chmod($filename,0644);
310                 }else {
311                         fclose($fd);
312                         if ($debug)ADOConnection::outp( " Failed acquiring lock for $filename<br>\n");
313                         $ok = false;
314                 }
315         
316                 return $ok;
317         }
318 ?>