source: moodle/trunk/fuentes/lib/adodb/adodb-csvlib.inc.php @ 1331

Last change on this file since 1331 was 1331, checked in by jrpelegrina, 3 years ago

Updated to moodle 3.0.3

File size: 8.3 KB
Line 
1<?php
2
3// security - hide paths
4if (!defined('ADODB_DIR')) die();
5
6global $ADODB_INCLUDED_CSV;
7$ADODB_INCLUDED_CSV = 1;
8
9/*
10
11  @version   v5.20.1  06-Dec-2015
12  @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
13  @copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community
14  Released under both BSD license and Lesser GPL library license.
15  Whenever there is any discrepancy between the two licenses,
16  the BSD license will take precedence. See License.txt.
17  Set tabs to 4 for best viewing.
18
19  Latest version is available at http://adodb.sourceforge.net
20
21  Library for CSV serialization. This is used by the csv/proxy driver and is the
22  CacheExecute() serialization format.
23
24  ==== NOTE ====
25  Format documented at http://php.weblogs.com/ADODB_CSV
26  ==============
27*/
28
29        /**
30         * convert a recordset into special format
31         *
32         * @param rs    the recordset
33         *
34         * @return      the CSV formated data
35         */
36        function _rs2serialize(&$rs,$conn=false,$sql='')
37        {
38                $max = ($rs) ? $rs->FieldCount() : 0;
39
40                if ($sql) $sql = urlencode($sql);
41                // metadata setup
42
43                if ($max <= 0 || $rs->dataProvider == 'empty') { // is insert/update/delete
44                        if (is_object($conn)) {
45                                $sql .= ','.$conn->Affected_Rows();
46                                $sql .= ','.$conn->Insert_ID();
47                        } else
48                                $sql .= ',,';
49
50                        $text = "====-1,0,$sql\n";
51                        return $text;
52                }
53                $tt = ($rs->timeCreated) ? $rs->timeCreated : time();
54
55                ## changed format from ====0 to ====1
56                $line = "====1,$tt,$sql\n";
57
58                if ($rs->databaseType == 'array') {
59                        $rows = $rs->_array;
60                } else {
61                        $rows = array();
62                        while (!$rs->EOF) {
63                                $rows[] = $rs->fields;
64                                $rs->MoveNext();
65                        }
66                }
67
68                for($i=0; $i < $max; $i++) {
69                        $o = $rs->FetchField($i);
70                        $flds[] = $o;
71                }
72
73                $savefetch = isset($rs->adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode;
74                $class = $rs->connection->arrayClass;
75                $rs2 = new $class();
76                $rs2->timeCreated = $rs->timeCreated; # memcache fix
77                $rs2->sql = $rs->sql;
78                $rs2->oldProvider = $rs->dataProvider;
79                $rs2->InitArrayFields($rows,$flds);
80                $rs2->fetchMode = $savefetch;
81                return $line.serialize($rs2);
82        }
83
84
85/**
86* Open CSV file and convert it into Data.
87*
88* @param url            file/ftp/http url
89* @param err            returns the error message
90* @param timeout        dispose if recordset has been alive for $timeout secs
91*
92* @return               recordset, or false if error occured. If no
93*                       error occurred in sql INSERT/UPDATE/DELETE,
94*                       empty recordset is returned
95*/
96        function csv2rs($url,&$err,$timeout=0, $rsclass='ADORecordSet_array')
97        {
98                $false = false;
99                $err = false;
100                $fp = @fopen($url,'rb');
101                if (!$fp) {
102                        $err = $url.' file/URL not found';
103                        return $false;
104                }
105                @flock($fp, LOCK_SH);
106                $arr = array();
107                $ttl = 0;
108
109                if ($meta = fgetcsv($fp, 32000, ",")) {
110                        // check if error message
111                        if (strncmp($meta[0],'****',4) === 0) {
112                                $err = trim(substr($meta[0],4,1024));
113                                fclose($fp);
114                                return $false;
115                        }
116                        // check for meta data
117                        // $meta[0] is -1 means return an empty recordset
118                        // $meta[1] contains a time
119
120                        if (strncmp($meta[0], '====',4) === 0) {
121
122                                if ($meta[0] == "====-1") {
123                                        if (sizeof($meta) < 5) {
124                                                $err = "Corrupt first line for format -1";
125                                                fclose($fp);
126                                                return $false;
127                                        }
128                                        fclose($fp);
129
130                                        if ($timeout > 0) {
131                                                $err = " Illegal Timeout $timeout ";
132                                                return $false;
133                                        }
134
135                                        $rs = new $rsclass($val=true);
136                                        $rs->fields = array();
137                                        $rs->timeCreated = $meta[1];
138                                        $rs->EOF = true;
139                                        $rs->_numOfFields = 0;
140                                        $rs->sql = urldecode($meta[2]);
141                                        $rs->affectedrows = (integer)$meta[3];
142                                        $rs->insertid = $meta[4];
143                                        return $rs;
144                                }
145                        # Under high volume loads, we want only 1 thread/process to _write_file
146                        # so that we don't have 50 processes queueing to write the same data.
147                        # We use probabilistic timeout, ahead of time.
148                        #
149                        # -4 sec before timeout, give processes 1/32 chance of timing out
150                        # -2 sec before timeout, give processes 1/16 chance of timing out
151                        # -1 sec after timeout give processes 1/4 chance of timing out
152                        # +0 sec after timeout, give processes 100% chance of timing out
153                                if (sizeof($meta) > 1) {
154                                        if($timeout >0){
155                                                $tdiff = (integer)( $meta[1]+$timeout - time());
156                                                if ($tdiff <= 2) {
157                                                        switch($tdiff) {
158                                                        case 4:
159                                                        case 3:
160                                                                if ((rand() & 31) == 0) {
161                                                                        fclose($fp);
162                                                                        $err = "Timeout 3";
163                                                                        return $false;
164                                                                }
165                                                                break;
166                                                        case 2:
167                                                                if ((rand() & 15) == 0) {
168                                                                        fclose($fp);
169                                                                        $err = "Timeout 2";
170                                                                        return $false;
171                                                                }
172                                                                break;
173                                                        case 1:
174                                                                if ((rand() & 3) == 0) {
175                                                                        fclose($fp);
176                                                                        $err = "Timeout 1";
177                                                                        return $false;
178                                                                }
179                                                                break;
180                                                        default:
181                                                                fclose($fp);
182                                                                $err = "Timeout 0";
183                                                                return $false;
184                                                        } // switch
185
186                                                } // if check flush cache
187                                        }// (timeout>0)
188                                        $ttl = $meta[1];
189                                }
190                                //================================================
191                                // new cache format - use serialize extensively...
192                                if ($meta[0] === '====1') {
193                                        // slurp in the data
194                                        $MAXSIZE = 128000;
195
196                                        $text = fread($fp,$MAXSIZE);
197                                        if (strlen($text)) {
198                                                while ($txt = fread($fp,$MAXSIZE)) {
199                                                        $text .= $txt;
200                                                }
201                                        }
202                                        fclose($fp);
203                                        $rs = unserialize($text);
204                                        if (is_object($rs)) $rs->timeCreated = $ttl;
205                                        else {
206                                                $err = "Unable to unserialize recordset";
207                                                //echo htmlspecialchars($text),' !--END--!<p>';
208                                        }
209                                        return $rs;
210                                }
211
212                                $meta = false;
213                                $meta = fgetcsv($fp, 32000, ",");
214                                if (!$meta) {
215                                        fclose($fp);
216                                        $err = "Unexpected EOF 1";
217                                        return $false;
218                                }
219                        }
220
221                        // Get Column definitions
222                        $flds = array();
223                        foreach($meta as $o) {
224                                $o2 = explode(':',$o);
225                                if (sizeof($o2)!=3) {
226                                        $arr[] = $meta;
227                                        $flds = false;
228                                        break;
229                                }
230                                $fld = new ADOFieldObject();
231                                $fld->name = urldecode($o2[0]);
232                                $fld->type = $o2[1];
233                                $fld->max_length = $o2[2];
234                                $flds[] = $fld;
235                        }
236                } else {
237                        fclose($fp);
238                        $err = "Recordset had unexpected EOF 2";
239                        return $false;
240                }
241
242                // slurp in the data
243                $MAXSIZE = 128000;
244
245                $text = '';
246                while ($txt = fread($fp,$MAXSIZE)) {
247                        $text .= $txt;
248                }
249
250                fclose($fp);
251                @$arr = unserialize($text);
252                //var_dump($arr);
253                if (!is_array($arr)) {
254                        $err = "Recordset had unexpected EOF (in serialized recordset)";
255                        if (get_magic_quotes_runtime()) $err .= ". Magic Quotes Runtime should be disabled!";
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        }
Note: See TracBrowser for help on using the repository browser.