Source for file file-defs.php

Documentation is available at file-defs.php

  1. <?php
  2. /* ******************************************************************** */
  3. /* CATALYST PHP Source Code */
  4. /* -------------------------------------------------------------------- */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or */
  8. /* (at your option) any later version. */
  9. /* */
  10. /* This program is distributed in the hope that it will be useful, */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  13. /* GNU General Public License for more details. */
  14. /* */
  15. /* You should have received a copy of the GNU General Public License */
  16. /* along with this program; if not, write to: */
  17. /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
  18. /* Boston, MA 02111-1307 USA */
  19. /* -------------------------------------------------------------------- */
  20. /* */
  21. /* Filename: file-defs.php */
  22. /* Author: Paul Waite */
  23. /* Description: Definitions for filesystem access. */
  24. /* */
  25. /* ******************************************************************** */
  26. /** @package file */// Definitions
  27. /** Save the file on close */
  28. ("SAVE_FILE", 0);
  29. /** Abandon file on close */
  30. ("ABANDON_FILE", 1);
  31.  
  32. // ----------------------------------------------------------------------
  33. /**
  34. * Return a random unique filename, with optional prefix and an optional
  35. * extension. The filename is composed from an md5 of microtime(), plus
  36. * the prefix and extension if given.
  37. *
  38. * @param string $prefix Optional fixed prefix required.
  39. * @param string $extn Optional fixed extension required.
  40. * @return string Unique filename string
  41. */
  42. function unique_filename($prefix="", $extn="") {
  43. $fname = md5( $prefix . microtime() . $extn );
  44. $fname = $prefix . $fname;
  45. if ($extn != "") {
  46. $fname .= ".$extn";
  47. }
  48. return $fname;
  49. } // unique_filename
  50. // ----------------------------------------------------------------------
  51.  
  52. /**
  53. * Make sure path exists
  54. * A utility function which makes sure a given directory path
  55. * is made, using mkdir as required. This function assumes
  56. * that permissions are all as needed.
  57. * @param string $path The directory path which must exist
  58. */
  59. function mkpath($path) {
  60. if (substr($path, 0, 2) != "./" && substr($path, 0, 1) != "/") {
  61. $path = "./" . $path;
  62. }
  63. $result = true;
  64. clearstatcache();
  65. if (!is_dir($path)) {
  66. $dirs = explode("/", $path);
  67. $testpath = "";
  68. foreach ($dirs as $dir) {
  69. if ($dir == "") $testpath = "/";
  70. elseif ($dir == ".") $testpath = realpath($dir);
  71. else $testpath .= "/$dir";
  72. if (!is_dir($testpath)) {
  73. if (!mkdir($testpath)) {
  74. $result = false;
  75. break;
  76. }
  77. }
  78. }
  79. }
  80. return $result;
  81. } // mkpath
  82. // ----------------------------------------------------------------------
  83.  
  84. /**
  85. * Return the file extension from a filepath.
  86. */
  87. function get_file_extn($path){
  88. $extn = "";
  89. if ($path != "") {
  90. $fname = basename($path);
  91. $bits = explode(".", $fname);
  92. $extn = strtolower(trim($bits[ count($bits) - 1 ]));
  93. }
  94. return $extn;
  95. } // get_file_extn
  96.  
  97. /**
  98. * Return the file stem (name without extn) from a filepath.
  99. */
  100. function get_file_stem($path){
  101. $stem = "";
  102. if ($path != "") {
  103. $fname = basename($path);
  104. $bits = explode(".", $fname);
  105. $stem = strtolower(trim($bits[ 0 ]));
  106. }
  107. return $stem;
  108. } // get_file_stem
  109. // ----------------------------------------------------------------------
  110.  
  111. /**
  112. * Returns an array containing full paths to the files in the directory
  113. * given by the path. This can be optionally recursive, in which case we will
  114. * end up with a long list of path/filenames which comprise the whole
  115. * tree, minus the special files '.' and '..'
  116. * @param string $path Path to the directory containing the files to list
  117. * @param boolean $recurse Whether to recurse the tree listing files in subdirs
  118. * @param $regex Full regular expression filename must match, eg: '/^.*?\.jpg$/i'
  119. * @return array List of full paths that comprise files in the directory, or tree
  120. */
  121. function get_dirlist($path, $recurse=false, $regex="") {
  122. $dirlist = array();
  123. if ($dirH = opendir($path)) {
  124. while (false !== ($filename = readdir($dirH))) {
  125. if ($filename != "." && $filename != "..") {
  126. $filetype = filetype("$path/$filename");
  127. $valid = ($regex == "" || $filetype == "dir" ? true : preg_match($regex, $filename));
  128. if ($valid) {
  129. if ($filetype == "dir") {
  130. if ($recurse) {
  131. $dirlist += get_dirlist("$path/$filename", $recurse, $regex);
  132. }
  133. else {
  134. $dirlist[] = "$path/$filename";
  135. }
  136. }
  137. else {
  138. $dirlist[] = "$path/$filename";
  139. }
  140. }
  141. }
  142. } // while
  143. closedir($dirH);
  144. }
  145. // Return array of paths..
  146. return $dirlist;
  147. } // get_dirlist
  148. // ----------------------------------------------------------------------
  149.  
  150. /**
  151. * The inputfile class manages files for input. It opens, reads and closes
  152. * files in input-only mode.
  153. * @package file
  154. */
  155. class inputfile {
  156. // Public
  157. /** The file name */
  158.  
  159. var $name = "";
  160. /** The directory prefix (if any) of the file */
  161.  
  162. var $dir = "";
  163. /** The full path to the file */
  164.  
  165. var $datafname = "";
  166. /** True if file was opened */
  167.  
  168. var $opened = false;
  169. /** Size of opened file in bytes */
  170.  
  171. var $filesize = 0;
  172. /** Content of file after readall() */
  173.  
  174. var $content = "";
  175. // Private
  176. /** The file pointer
  177. @access private */
  178. var $fp;
  179. // ....................................................................
  180. /**
  181. * Constructor
  182. * Open the given file for input.
  183. * @param string $name The name of the file
  184. * @param string $dir The directory the file is in
  185. * @return boolean True if file was opened, else false
  186. */
  187. function inputfile($name, $dir="") {
  188. $this->opened = false;
  189. if ($dir != "") {
  190. // Separate filename and directory..
  191. $this->name = $name;
  192. $this->dir = $dir;
  193. }
  194. else {
  195. // Combined path/filename..
  196. $this->dir = dirname($name);
  197. $this->name = basename($name);
  198. }
  199.  
  200. // Full pathnames..
  201. $this->datafname = $this->dir . "/" . $this->name;
  202. clearstatcache();
  203. if (file_exists($this->datafname) && is_file($this->datafname)) {
  204. $this->fp = fopen($this->datafname, "r");
  205. if ($this->fp === false) {
  206. $this->opened = false;
  207. }
  208. else {
  209. $this->opened = true;
  210. $this->filesize = filesize($this->datafname);
  211. }
  212. }
  213. return $this->opened;
  214. } // inputfile
  215. // ....................................................................
  216. /**
  217. * Reads all of the file contents into class variable $content.
  218. * @return boolean True if the content was successfully read
  219. */
  220. function readall() {
  221. if ($this->opened) {
  222. $this->content = fread($this->fp, $this->filesize);
  223. return $this->content;
  224. }
  225. else return false;
  226. }
  227. // ....................................................................
  228. /**
  229. * Reads the next line of the file, up to max chars specified.
  230. * @param integer $maxchars Maximum chars per line to read
  231. * @return mixed A string containing the line, or false if failed
  232. */
  233. function readln($maxchars=4096) {
  234. if ($this->opened && !$this->eof()) {
  235. $buf = fgets($this->fp, $maxchars);
  236. return rtrim($buf);
  237. }
  238. else return false;
  239. }
  240. // ....................................................................
  241. /** Return true if at end-of-file or not opened, else false */
  242.  
  243. function eof() {
  244. $eof = true;
  245. if ($this->opened) {
  246. $eof = feof($this->fp);
  247. }
  248. return $eof;
  249. }
  250. // ....................................................................
  251. /** Close the file */
  252.  
  253. function closefile() {
  254. if ($this->opened) {
  255. fclose($this->fp);
  256. }
  257. }
  258. } // inputfile class
  259. // ----------------------------------------------------------------------
  260.  
  261. /**
  262. * CSV Inputfile class
  263. * Manage CSV-formatted files for input.
  264. * Open, close and read CSV formatted files for input.
  265. * @package file
  266. */
  267. class csv_inputfile extends inputfile {
  268. /**
  269. * Constructor
  270. * Open the given CSV formatted file for input.
  271. * @param string $name The name of the file
  272. * @param string $dir The directory the file is in
  273. * @return boolean True if file was opened, else false
  274. */
  275. function csv_inputfile($name, $dir="") {
  276. return $this->inputfile($name, $dir);
  277. }
  278. // ....................................................................
  279. /**
  280. * Reads the next line of the file in the form of an array of
  281. * fields as delimited by the given charater. Lines can be of
  282. * a length up to the specified maximum no. of chars.
  283. * NB: This properly handles double-quoted elements which
  284. * contain the delimiter character.
  285. * @param string $delimiter CSV delimiter character, default ","
  286. * @param integer $maxchars Maximum chars per line to read
  287. * @return array An array of the CSV fields read in
  288. */
  289. function readln($delimiter=",", $maxchars=4096) {
  290. if ($this->opened && !feof($this->fp)) {
  291. $csvarray = fgetcsv($this->fp, $maxchars, $delimiter);
  292. return $csvarray;
  293. }
  294. else return false;
  295. }
  296. } // csv_inputfile class
  297. // ----------------------------------------------------------------------
  298.  
  299. /**
  300. * Open a file which contains a stylesheet and read in the style
  301. * settings. This is a special case of inputfile.
  302. * @package file
  303. */
  304. class stylesheet extends inputfile {
  305. /** @access private */
  306. var $class;
  307. // ....................................................................
  308. /**
  309. * Constructor
  310. * Open the given stylesheet file for input.
  311. * @param string $name The name of the file
  312. * @param string $dir The directory the file is in
  313. * @return boolean True if file was opened, else false
  314. */
  315. function stylesheet($sspath, $dir="") {
  316. if ($this->inputfile($sspath, $dir)) {
  317. // We support the DIY readln() and readall() which
  318. // are provided by inputfile, but we also read the
  319. // stylesheet into our special structure, so that
  320. // styles are easily accessible..
  321. $this->class = array();
  322. $this->readstyles();
  323. }
  324. }
  325. // ....................................................................
  326. /**
  327. * Read in the styles from stylesheet. We have repeated
  328. * entries of the form: classlist { attrib: def; attrib: def; }
  329. * NB: this does not, as yet, cope with 'complex' stylesheets
  330. * which have inheritance in the name definitions.
  331. * @access private
  332. */
  333. function readstyles() {
  334. if ($this->opened) {
  335. if ($this->readall()) {
  336. // Remove comments, normalise case..
  337. $content = strtolower(preg_replace("/\/\*.*?\*\//", "", $this->content));
  338. $entries = explode("}", $content);
  339. foreach ($entries as $entry) {
  340. $entrybits = explode("{", $entry);
  341. $classlist = trim($entrybits[0]);
  342. $classes = explode(",", $classlist);
  343. foreach ($classes as $classname) {
  344. $classname = trim($classname);
  345. if ($classname != "") {
  346. if (substr($classname, 0, 1) == ".") {
  347. $classname = substr($classname, 1);
  348. }
  349. if (isset($this->class[$classname])) {
  350. $classattr = $this->class[$classname];
  351. //debugbr("ADDING TO CLASS $classname");
  352. }
  353. else {
  354. $classattr = array();
  355. //debugbr("FIRST TIME FOR CLASS $classname");
  356. }
  357. $classdefs = explode(";", $entrybits[1]);
  358. foreach($classdefs as $classdef) {
  359. $defbits = explode(":", $classdef);
  360. $name = trim($defbits[0]);
  361. $setting = trim($defbits[1]);
  362. if ($name != "") {
  363. $classattr[$name] = $setting;
  364. //debugbr("[$classname][$name] -> [$setting]");
  365. }
  366. }
  367. // Store this class away..
  368. $this->class[$classname] = $classattr;
  369. //debugbr("CLASS: [$classname]");
  370. }
  371. } // foreach classname
  372. } // foreach entry
  373. } // if readall
  374. $this->closefile();
  375. } // if opened
  376. } // readstyles
  377. // ....................................................................
  378. /**
  379. * Return a style setting(s) for given class name in the list format:
  380. * "attrib:def;attrib:def; ..."
  381. * Also allow specification of a particular attribute within the class
  382. * to return the style setting for.
  383. * @param string $classname The name of the class
  384. * @param string $attrname The name of the class attribute
  385. * @return boolean True if file was opened, else false
  386. */
  387. function style($classname, $attrname="") {
  388. $style = "";
  389. $classname = strtolower($classname);
  390. $attrname = strtolower($attrname);
  391. if (isset($this->class[$classname])) {
  392. $class = $this->class[$classname];
  393. if ($attrname != "") {
  394. if (isset($class[$attrname])) {
  395. $style = $class[$attrname];
  396. }
  397. }
  398. else {
  399. while (list($name, $setting) = each($class)) {
  400. $style .= "$name:$setting;";
  401. }
  402. }
  403. }
  404. return $style;
  405. }
  406. } // stylesheet class
  407. // ----------------------------------------------------------------------
  408.  
  409. /**
  410. * The outputfile class manages files for outputting content. This includes
  411. * both appending to an existing file, and creating new files. The method
  412. * used in both cases is to write to a temporary file, and then rename/move
  413. * it onto the final file path when closefile() is called.
  414. * @package file
  415. */
  416. class outputfile {
  417. // Public
  418. /** The file name */
  419.  
  420. var $name = "";
  421. /** The directory prefix (if any) of the file */
  422.  
  423. var $dir = "";
  424. /** The full path to the file */
  425.  
  426. var $datafname = "";
  427. /** Type of file 'text' or 'templated' */
  428.  
  429. var $filetype = "text";
  430. /** True if file was sucessfully opened */
  431.  
  432. var $opened = false;
  433. /** How to save: default "overwrite", or "append" to append. */
  434.  
  435. var $savehow = "overwrite";
  436.  
  437. // Private
  438. /** Full pathname of template file
  439. @access private */
  440. var $template_fname = "";
  441. /** Content of template file when read in
  442. @access private */
  443. var $template_contents = "";
  444. /** Full pathname of destination (temporary) file
  445. @access private */
  446. var $tempfname = "";
  447. /** File pointer
  448. @access private */
  449. var $fp;
  450. /** File pointer
  451. @access private */
  452. var $template_fp;
  453. // ....................................................................
  454. /**
  455. * Constructor
  456. * Note that we open a temporary file, write to this file, and only move
  457. * it to the destination when closed. This means it is less prone to
  458. * interferring with external processes which might be accessing it when
  459. * in the process of being built.
  460. * @param string $name The name of the file
  461. * @param string $dir The directory the file is in
  462. * @param string $savehow "overwrite" (default), or "append"
  463. * @return boolean True if file was opened, else false
  464. */
  465. function outputfile($name, $dir="", $savehow="overwrite") {
  466. if ($dir != "") {
  467. // Separate filename and directory..
  468. $this->name = $name;
  469. $this->dir = $dir;
  470. }
  471. else {
  472. // Combined path/filename..
  473. $this->dir = dirname($name);
  474. $this->name = basename($name);
  475. }
  476.  
  477. // Make sure directory is there..
  478. if ($this->dir != "") {
  479. if (!file_exists($this->dir)) {
  480. mkdir($this->dir, 0755);
  481. if (!file_exists($this->dir)) {
  482. die("");
  483. }
  484. }
  485. }
  486.  
  487. // Whether to append content on close, or overwrite (default)
  488. $this->savehow = $savehow;
  489.  
  490. // Full pathnames..
  491. $this->datafname = $this->dir . "/" . $this->name;
  492. $this->tempfname = tempnam("/tmp", APP_PREFIX);
  493. if ($this->tempfname != "") {
  494. $this->fp = fopen($this->tempfname, "w");
  495. if (!$this->fp) $this->opened = false;
  496. else $this->opened = true;
  497. }
  498. else {
  499. $this->opened = false;
  500. }
  501.  
  502. // Return status..
  503. return $this->opened;
  504. } // outputfile
  505. // ....................................................................
  506. /**
  507. * Set the file type. Possible types include 'text' (default), 'html',
  508. * and 'templated'.
  509. * @param string $type The file type
  510. */
  511. function type($type) {
  512. $this->filetype = $type;
  513. } // type
  514. // ....................................................................
  515. /**
  516. * This defines a template for the file content and flags the
  517. * file as being of "templated" type. The template is expected to
  518. * be at the $path specified. The template is opened and the entire
  519. * file contents are put into $this->content.
  520. * @param string $path The path to the template file
  521. */
  522. function template($path) {
  523. $this->filetype = "templated";
  524. $this->template_fname = $path;
  525. $this->template_fp = fopen($this->template_fname, "r");
  526. if ($this->template_fp) {
  527. $this->template_contents = fread($this->template_fp, filesize($this->template_fname));
  528. fclose ($this->template_fp);
  529. }
  530. return $this;
  531. } // template
  532. // ....................................................................
  533. /**
  534. * Replace a pattern in the current $this->content with replacement
  535. * string. This allows us to work on a template, replacing bits of
  536. * it that represent our dynamic content.
  537. * @param string $tag The pattern in the template to replace
  538. * @param string $newstuff The replacement content
  539. */
  540. function replace($tag, $newstuff) {
  541. $tmp = str_replace($tag, $newstuff, $this->template_contents);
  542. $this->template_contents = $tmp;
  543. return $this;
  544. } // replace
  545. // ....................................................................
  546. /**
  547. * Flush any buffered content to the stream.
  548. * @return boolean True if stream was flushed, else false
  549. */
  550. function flushbuffer() {
  551. $flushed = false;
  552. if ($this->opened) {
  553. $flushed = fflush($this->fp);
  554. }
  555. return $flushed;
  556. } // flushbuffer
  557. // ....................................................................
  558. /**
  559. * Close the file. We move the temporary file that has been built to
  560. * the actual file path contained in 'datafname'. If this is called with
  561. * no argument, then the default mode SAVE_MODE is assumed and the file
  562. * is saved. However if the argument is set to the constant ABANDON_FILE
  563. * then nothing will be saved/created.
  564. * @param integer $mode How to save: SAVE_FILE or ABANDON_FILE
  565. * @return boolean True if file was saved and closed successfully.
  566. */
  567. function closefile($mode=SAVE_FILE) {
  568. $ok = false;
  569. if ($this->opened) {
  570. switch ($this->filetype) {
  571. case "html":
  572. // Finish off the HTML file..
  573. $this->writeln("</body>");
  574. $this->writeln("</html>");
  575. break;
  576. case "templated":
  577. // Write the templated contents out..
  578. $this->write($this->template_contents);
  579. break;
  580. default:
  581. // Text files leave as-is
  582. } // switch
  583.  
  584. fclose($this->fp);
  585. if ($mode == SAVE_FILE) {
  586. switch ($this->savehow) {
  587. case "append":
  588. if (PHP_VERSION >= 4.3) {
  589. $s = file_get_contents($this->tempfname);
  590. }
  591. else {
  592. $lines = file($this->tempfname);
  593. $s = implode("", $lines);
  594. }
  595. $ofp = fopen($this->datafname, "a");
  596. $wrote = fwrite($ofp, $s);
  597. fclose($ofp);
  598. $ok = ($wrote == strlen($s));
  599. break;
  600. default:
  601. $ok = copy($this->tempfname, $this->datafname);
  602. } // switch
  603. }
  604. else {
  605. $ok = true;
  606. }
  607. // Remove temporary workfile..
  608. unlink($this->tempfname);
  609. // Flag as closed..
  610. $this->opened = false;
  611. }
  612. return $ok;
  613. } // closefile
  614. // ....................................................................
  615. /**
  616. * Write to file
  617. * Write the given string to the output file.
  618. * @param string $s The string to write to the file
  619. * @return bool True if write was successful
  620. */
  621. function write($s) {
  622. $res = fwrite($this->fp, $s);
  623. return ($res != -1);
  624. } // write
  625. // ....................................................................
  626. /**
  627. * Write line to file
  628. * Write the given string to the output file as a line.
  629. * @param string $s The string to write as a line to the file
  630. * @return bool True if writeln was successful
  631. */
  632. function writeln($s) {
  633. return $this->write($s . "\n");
  634. } // writeln
  635.  
  636. } // outputfile class
  637. // ----------------------------------------------------------------------
  638.  
  639. /**
  640. * This is a derived class from outputfile and is a quick way of creating
  641. * a file with content in a single hit. You can check the $created
  642. * property afterwards to determine success/failure.
  643. * @package file
  644. */
  645. class quickfile extends outputfile {
  646. /** True if quickfile was created successfully */
  647.  
  648. var $created = false;
  649. /**
  650. * Creates a file containing given content quickly.
  651. * @param $path Path to file to create
  652. * @param $content Optional content to put in the file
  653. */
  654. function quickfile($path, $content="") {
  655. $this->outputfile($path);
  656. if ($this->opened) {
  657. if ($this->write($content)) {
  658. $this->created = $this->closefile();
  659. }
  660. }
  661. } // quickfile
  662.  
  663. } // quickfile class
  664. // ----------------------------------------------------------------------
  665. // FILEUPLOAD CLASS
  666.  
  667.  
  668.  
  669. /** Error code: All ok, no errors */
  670. ("UPLOAD_E_OK", 0);
  671. /** Failed to move file, filesys error (perms?) */
  672. ("UPLOAD_E_MOV", 100);
  673. /** Uploaded file exceeded the given maximum size */
  674. ("UPLOAD_E_MAXSIZ", 101);
  675. /** Uploaded file was not of an allowed mime type */
  676. ("UPLOAD_E_BADTYP", 102);
  677. /** Attempt to move a non-uploaded file. Hacking. */
  678. ("UPLOAD_E_HACK", 103);
  679. /** Destination directory access problem */
  680. ("UPLOAD_E_ACCESS", 104);
  681.  
  682. /**
  683. * Fileupload class.
  684. * This is a class for handling file uploads. It assumes that one or
  685. * more files have been uploaded and are being actioned by the current
  686. * Php script which instantiates this object.
  687. * @package file
  688. */
  689. class fileupload {
  690. /** Array of info on uploaded files */
  691.  
  692. var $uploaded;
  693. /** No. of files uploaded */
  694.  
  695. var $uploaded_count = 0;
  696. /** True if some files were uploaded */
  697.  
  698. var $hasfiles = false;
  699. /** Destination dir to put files */
  700.  
  701. var $destination_dir = ".";
  702. /** Max filesize, else delete (0 = any size) */
  703.  
  704. var $max_size = 0;
  705. /** Array of allowed mimetypes (unset = any types) */
  706.  
  707. var $allowed_types;
  708. /** Upload field name */
  709.  
  710. var $fieldname = "";
  711. /** Original filename */
  712.  
  713. var $filename = "";
  714. /** Mime type of the the file */
  715.  
  716. var $mimetype = "";
  717. /** Physical size of the file (bytes) */
  718.  
  719. var $filesize = 0;
  720. /** Upload path to the file on the server */
  721.  
  722. var $filepath = "";
  723. /** Error code. Check to see if error occurred. */
  724.  
  725. var $errcode = UPLOAD_E_OK;
  726. /** Error message array, goes with errcode. */
  727.  
  728. var $errmsg = array();
  729. // ....................................................................
  730. /**
  731. * Constructor. On instantiation this class checks the global
  732. * variable space for uploaded file info and pre-processes it.
  733. * NB: You may specify a filesize limit with $maxsize. If you
  734. * do then we do not take notice of the MAX_FILE_SIZE submitted
  735. * from the form. This is recommended, since the form value
  736. * can easily be hacked..
  737. * @param integer $maxsize The maximum filesize in bytes
  738. * @return boolean Status, true if all ok, else false.
  739. */
  740. function fileupload($maxsize=0) {
  741. global $MAX_FILE_SIZE;
  742. // Over-ride max size with possible submitted form value..
  743. if (isset($MAX_FILE_SIZE)) $this->max_size = $maxsize;
  744. // Over-ride with locally-coded value (safest)..
  745. if (isset($maxsize)) $this->max_size = $maxsize;
  746. $this->errcode = UPLOAD_E_OK;
  747.  
  748. // Always check for uploaded files..
  749. if (isset($_FILES) && version_compare(phpversion(), "4.1.0", "ge")) {
  750. $this->uploaded = $this->unpackinfo($_FILES);
  751. }
  752. else {
  753. global $HTTP_POST_FILES;
  754. if (isset($HTTP_POST_FILES)) {
  755. $this->uploaded = $this->unpackinfo($HTTP_POST_FILES);
  756. }
  757. }
  758. // Set the statuses, get current file info..
  759. if (isset($this->uploaded)) {
  760. $this->uploaded_count = count($this->uploaded);
  761. if ($this->uploaded_count > 0) {
  762. $this->hasfiles = true;
  763. $this->get_first();
  764. }
  765. }
  766.  
  767. // Return status so far..
  768. return ($this->errcode == UPLOAD_E_OK);
  769. } // fileupload
  770. // ....................................................................
  771. /**
  772. * Set the maximum filesize allowed
  773. * @param integer $maxsize The maximum filesize in bytes
  774. */
  775. function set_maxsize($maxsize=0) {
  776. $this->max_size = $maxsize;
  777. } // set_maxsize
  778. // ....................................................................
  779. /**
  780. * Set the allowed list of filetypes. This is specified as a
  781. * comma-delimited list, and replaces any already defined.
  782. * @param string $types The list of allowed mimetypes
  783. */
  784. function set_allowed_types($types="") {
  785. if (isset($this->allowed_types)) {
  786. unset($this->allowed_types);
  787. }
  788. if ($types != "") {
  789. $this->allowed_types = explode(",", strtolower(trim($types)));
  790. }
  791. } // set_allowed_types
  792. // ....................................................................
  793. /**
  794. * Unpacks the array variable which holds the uploaded file info. We
  795. * also deal with the special case where the user has uploaded a
  796. * set of multiple files, using the special array syntax for naming
  797. * the form control.
  798. * @param array $rawinfo The raw file info details from the upload
  799. * @access private
  800. */
  801. function unpackinfo($rawinfo) {
  802. $allinfo = array();
  803. while (list($fieldname, $info) = each($rawinfo)) {
  804. $repeatcount = count($info["name"]);
  805. if (is_array($info["name"])) {
  806. for ($ix=0; $ix < $repeatcount; $ix++) {
  807. if ($info["name"][$ix] != "") {
  808. $tmpinfo["fname"] = $fieldname;
  809. $tmpinfo["name"] = $info["name"][$ix];
  810. $tmpinfo["type"] = $info["type"][$ix];
  811. $tmpinfo["size"] = $info["size"][$ix];
  812. $tmpinfo["tmp_name"] = $info["tmp_name"][$ix];
  813. $allinfo[] = $tmpinfo;
  814. }
  815. }
  816. }
  817. else {
  818. if ($info["name"] != "") {
  819. $tmpinfo["fname"] = $fieldname;
  820. $tmpinfo["name"] = $info["name"];
  821. $tmpinfo["type"] = $info["type"];
  822. $tmpinfo["size"] = $info["size"];
  823. $tmpinfo["tmp_name"] = $info["tmp_name"];
  824. $allinfo[] = $tmpinfo;
  825. }
  826. }
  827. }
  828. return $allinfo;
  829. }
  830. // ....................................................................
  831. /**
  832. * Acquire the details on the current upload file. This includes the
  833. * original filename, its mimetype, its size and the full path on
  834. * the webserver to which the file was uploaded. The details are
  835. * populated in class variables:
  836. * $this->fieldname
  837. * $this->filename
  838. * $this->mimetype
  839. * $this->filesize
  840. * $this->filepath
  841. * And these variables are then available to be read/used by the
  842. * calling application code.
  843. * @return boolean True if info was obtained
  844. */
  845. function get_current() {
  846. if ($this->hasfiles) {
  847. $info = current($this->uploaded);
  848. if ($info) {
  849. $this->fieldname = $info["fname"];
  850. $this->filename = $info["name"];
  851. $this->mimetype = strtolower($info["type"]);
  852. $this->filesize = $info["size"];
  853. $this->filepath = $info["tmp_name"];
  854. return true;
  855. }
  856. }
  857. return false;
  858. } // get_current
  859. // ....................................................................
  860. /**
  861. * Acquire the details on the first upload file.
  862. * @see get_current
  863. * @return boolean True if info was obtained
  864. */
  865. function get_first() {
  866. if ($this->hasfiles) {
  867. reset($this->uploaded);
  868. return $this->get_current();
  869. }
  870. return false;
  871. } // get_first
  872. // ....................................................................
  873. /**
  874. * Get details on the next file which was uploaded. If there are no
  875. * more, then this function returns false.
  876. * @see get_current
  877. * @return boolean True if info was obtained
  878. */
  879. function get_next() {
  880. if ($this->hasfiles) {
  881. if (next($this->uploaded)) {
  882. return $this->get_current();
  883. }
  884. }
  885. return false;
  886. } // get_next
  887. // ....................................................................
  888. /**
  889. * Get details on the previous file which was uploaded. If there are no
  890. * more, then this function returns false.
  891. * @see get_current
  892. * @return boolean True if info was obtained
  893. */
  894. function get_previous() {
  895. if ($this->hasfiles) {
  896. if (previous($this->uploaded)) {
  897. return $this->get_current();
  898. }
  899. }
  900. return false;
  901. } // get_previous
  902. // ....................................................................
  903. /**
  904. * Get details on the last file which was uploaded. If there are no
  905. * more, then this function returns false.
  906. * @see get_current
  907. * @return boolean True if info was obtained
  908. */
  909. function get_last() {
  910. if ($this->hasfiles) {
  911. if (last($this->uploaded)) {
  912. return $this->get_current();
  913. }
  914. }
  915. return false;
  916. } // get_last
  917. // ....................................................................
  918. /**
  919. * Fatal error ocurred. Log messages, and delete upload file.
  920. * @param integer $code Error code
  921. * @param string $msg Error message text
  922. * @access private
  923. */
  924. function fatal_error($code, $msg) {
  925. $emsg = "UPLOAD ERROR[$code]: $msg";
  926. $this->errmsg[] = $emsg;
  927. $this->errcode = $code;
  928. debugbr($emsg);
  929. log_sys($emsg);
  930. if (file_exists($this->filepath)) {
  931. unlink($this->filepath);
  932. }
  933. } // fatal_error
  934. // ....................................................................
  935. /**
  936. * Return any error message(s).
  937. * @return string Error message text, or nullstring if no error.
  938. */
  939. function error_message() {
  940. $s = "";
  941. foreach ($this->errmsg as $emsg) { $s .= "$emsg "; }
  942. return $s;
  943. } // error_message
  944. // ....................................................................
  945. /**
  946. * Store the current upload file. Optionally specify a destination
  947. * dir, and a filename. This is useful if you want to process each
  948. * file separately, and need to store the uploaded file in a
  949. * particular place.
  950. * @param string $destdir Destination directory path
  951. * @param string $filename Destination filename (or default to uploaded filename)
  952. * @return boolean True if all was ok, store succeeded
  953. */
  954. function store($destdir="", $filename="") {
  955. if ($destdir != "") {
  956. if ( realpath($destdir) !== FALSE ) {
  957. $this->destination_dir = realpath($destdir);
  958. } else {
  959. $this->destination_dir = $destdir;
  960. }
  961. }
  962.  
  963. if ($filename != "") $this->filename = basename($filename);
  964. if ($this->hasfiles) {
  965. if (is_writable($this->destination_dir)) {
  966. if (is_uploaded_file($this->filepath)) {
  967. if ($this->max_size == 0 || $this->filesize <= $this->max_size) {
  968. if (!isset($this->allowed_types) || in_array($this->mimetype, $this->allowed_types)) {
  969. $dest = "$this->destination_dir/$this->filename";
  970. if (!move_uploaded_file($this->filepath, $dest)) {
  971. $this->fatal_error(UPLOAD_E_MOV, "failed to move upload file: '$this->filepath' to '$dest'");
  972. }
  973. else {
  974. // Change mode..
  975. chmod($dest, 0755);
  976. }
  977. }
  978. else {
  979. // File didn't have the correct type, so remove..
  980. $this->fatal_error(UPLOAD_E_BADTYP, "deleted file of incorrect type $this->mimetype: '$this->filename'");
  981. }
  982. }
  983. else {
  984. // File was too big, so just delete it..
  985. $this->fatal_error(UPLOAD_E_MAXSIZ, "deleted file bigger than $this->max_size: '$this->filename'");
  986. }
  987. }
  988. else {
  989. // Naughty - an attempt to hack maybe..
  990. $this->fatal_error(UPLOAD_E_HACK, "attempt to move a non-upload file: '$this->filepath'");
  991. }
  992. }
  993. else {
  994. // Destination directory is read-only..
  995. $this->fatal_error(UPLOAD_E_ACCESS, "destination directory not writable: '$this->destination_dir'");
  996. }
  997. }
  998. // Return status so far..
  999. return ($this->errcode == UPLOAD_E_OK);
  1000. } // store
  1001. // ....................................................................
  1002. /**
  1003. * Store all files away at destination dir. We use the original
  1004. * names by default.
  1005. * @param string $destdir Destination directory path
  1006. * @return boolean True if all was ok, store succeeded
  1007. */
  1008. function storeall($destdir="") {
  1009. if ($destdir != "") $this->destination_dir = realpath($destdir);
  1010. if ($this->hasfiles) {
  1011. $this->get_first();
  1012. do {
  1013. $this->store();
  1014. } while ($this->get_next());
  1015. }
  1016. // Return status so far..
  1017. return ($this->errcode == UPLOAD_E_OK);
  1018. } // storeall
  1019.  
  1020. } // fileupload class
  1021. // ----------------------------------------------------------------------
  1022.  
  1023. ?>

Documentation generated by phpDocumentor 1.3.0RC3