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

Documentation generated by phpDocumentor 1.3.0RC3