Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

first pass at the site. completely untested and likely broken.

  • Loading branch information...
commit caaed41b5169905b0c3beef432470c478a2292bc 1 parent 2080c2c
Zach Hoeken authored
Showing with 31,060 additions and 0 deletions.
  1. +950 −0 classes/EasySwift.php
  2. +1,388 −0 classes/PEAR/DB.php
  3. +2,157 −0 classes/PEAR/DB/common.php
  4. +1,034 −0 classes/PEAR/DB/mysql.php
  5. +1,097 −0 classes/PEAR/DB/pgsql.php
  6. +504 −0 classes/PEAR/DB/storage.php
  7. +197 −0 classes/PEAR/File/Iterator.php
  8. +159 −0 classes/PEAR/File/Iterator/Factory.php
  9. +1,484 −0 classes/PEAR/HTTP/Request.php
  10. +106 −0 classes/PEAR/HTTP/Request/Listener.php
  11. +431 −0 classes/PEAR/Image/3D.php
  12. +235 −0 classes/PEAR/Image/3D/Color.php
  13. +65 −0 classes/PEAR/Image/3D/Color/Metal.php
  14. +267 −0 classes/PEAR/Image/3D/Coordinate.php
  15. +161 −0 classes/PEAR/Image/3D/Driver.php
  16. +242 −0 classes/PEAR/Image/3D/Driver/ASCII.php
  17. +92 −0 classes/PEAR/Image/3D/Driver/GD.php
  18. +59 −0 classes/PEAR/Image/3D/Driver/ImageCanvas.php
  19. +106 −0 classes/PEAR/Image/3D/Driver/ImageMagick.php
  20. +149 −0 classes/PEAR/Image/3D/Driver/SVG.php
  21. +502 −0 classes/PEAR/Image/3D/Driver/SVGControl.php
  22. +193 −0 classes/PEAR/Image/3D/Driver/ZBuffer.php
  23. +91 −0 classes/PEAR/Image/3D/Enlightenable.php
  24. +190 −0 classes/PEAR/Image/3D/Matrix.php
  25. +57 −0 classes/PEAR/Image/3D/Matrix/Move.php
  26. +57 −0 classes/PEAR/Image/3D/Matrix/Rotation.php
  27. +58 −0 classes/PEAR/Image/3D/Matrix/Scale.php
  28. +41 −0 classes/PEAR/Image/3D/Paintable.php
  29. +89 −0 classes/PEAR/Image/3D/Paintable/Light.php
  30. +63 −0 classes/PEAR/Image/3D/Paintable/Light/Ambient.php
  31. +86 −0 classes/PEAR/Image/3D/Paintable/Light/Point.php
  32. +94 −0 classes/PEAR/Image/3D/Paintable/Light/Spotlight.php
  33. +85 −0 classes/PEAR/Image/3D/Paintable/Object.php
  34. +133 −0 classes/PEAR/Image/3D/Paintable/Object/3ds.php
  35. +281 −0 classes/PEAR/Image/3D/Paintable/Object/3dsChunks.php
  36. +117 −0 classes/PEAR/Image/3D/Paintable/Object/Bezier.php
  37. +35 −0 classes/PEAR/Image/3D/Paintable/Object/Cone.php
  38. +105 −0 classes/PEAR/Image/3D/Paintable/Object/Cube.php
  39. +127 −0 classes/PEAR/Image/3D/Paintable/Object/Map.php
  40. +111 −0 classes/PEAR/Image/3D/Paintable/Object/Pie.php
  41. +60 −0 classes/PEAR/Image/3D/Paintable/Object/Polygon.php
  42. +127 −0 classes/PEAR/Image/3D/Paintable/Object/Sphere.php
  43. +102 −0 classes/PEAR/Image/3D/Paintable/Object/Text.php
  44. +93 −0 classes/PEAR/Image/3D/Paintable/Object/Torus.php
  45. +178 −0 classes/PEAR/Image/3D/Paintable/Polygon.php
  46. +135 −0 classes/PEAR/Image/3D/Point.php
  47. +469 −0 classes/PEAR/Image/3D/Renderer.php
  48. +90 −0 classes/PEAR/Image/3D/Renderer/Isometric.php
  49. +93 −0 classes/PEAR/Image/3D/Renderer/Perspectively.php
  50. +92 −0 classes/PEAR/Image/3D/Vector.php
  51. +114 −0 classes/PEAR/Image/Barcode.php
  52. +304 −0 classes/PEAR/Image/Barcode/Code39.php
  53. +343 −0 classes/PEAR/Image/Barcode/code128.php
  54. +255 −0 classes/PEAR/Image/Barcode/ean13.php
  55. +174 −0 classes/PEAR/Image/Barcode/int25.php
  56. +162 −0 classes/PEAR/Image/Barcode/postnet.php
  57. +324 −0 classes/PEAR/Image/Barcode/upca.php
  58. +858 −0 classes/PEAR/Log.php
  59. +231 −0 classes/PEAR/Log/composite.php
  60. +208 −0 classes/PEAR/Log/console.php
  61. +235 −0 classes/PEAR/Log/daemon.php
  62. +161 −0 classes/PEAR/Log/display.php
  63. +160 −0 classes/PEAR/Log/error_log.php
  64. +316 −0 classes/PEAR/Log/file.php
  65. +214 −0 classes/PEAR/Log/firebug.php
  66. +294 −0 classes/PEAR/Log/mail.php
  67. +170 −0 classes/PEAR/Log/mcal.php
  68. +358 −0 classes/PEAR/Log/mdb2.php
  69. +91 −0 classes/PEAR/Log/null.php
  70. +129 −0 classes/PEAR/Log/observer.php
  71. +294 −0 classes/PEAR/Log/sql.php
  72. +225 −0 classes/PEAR/Log/sqlite.php
  73. +179 −0 classes/PEAR/Log/syslog.php
  74. +269 −0 classes/PEAR/Log/win.php
  75. +528 −0 classes/PEAR/Net/Socket.php
  76. +410 −0 classes/PEAR/Net/URL.php
  77. +1,108 −0 classes/PEAR/PEAR.php
  78. +613 −0 classes/PEAR/PHP/CodeCoverage.php
  79. +71 −0 classes/PEAR/PHP/CodeCoverage/Driver.php
  80. +91 −0 classes/PEAR/PHP/CodeCoverage/Driver/Xdebug.php
  81. +334 −0 classes/PEAR/PHP/CodeCoverage/Filter.php
  82. +467 −0 classes/PEAR/PHP/CodeCoverage/Report/Clover.php
  83. +419 −0 classes/PEAR/PHP/CodeCoverage/Report/HTML.php
  84. +512 −0 classes/PEAR/PHP/CodeCoverage/Report/HTML/Node.php
  85. +430 −0 classes/PEAR/PHP/CodeCoverage/Report/HTML/Node/Directory.php
  86. +916 −0 classes/PEAR/PHP/CodeCoverage/Report/HTML/Node/File.php
  87. +149 −0 classes/PEAR/PHP/CodeCoverage/Report/HTML/Node/Iterator.php
  88. +1,653 −0 classes/PEAR/PHP/CodeCoverage/Report/HTML/Template/RGraph.bar.js
  89. +2,454 −0 classes/PEAR/PHP/CodeCoverage/Report/HTML/Template/RGraph.common.core.js
Sorry, we could not display the entire diff because too many files (581) changed.
View
950 classes/EasySwift.php
@@ -0,0 +1,950 @@
+<?php
+
+/**
+ * EasySwift: Swift Mailer Facade
+ * Please read the LICENSE file
+ * @author Chris Corbyn <chris@w3style.co.uk>
+ * @package EasySwift
+ * @version 1.0.3
+ * @license GNU Lesser General Public License
+ */
+
+require_once dirname(__FILE__) . "/Swift/ClassLoader.php";
+Swift_ClassLoader::load("Swift");
+Swift_ClassLoader::load("Swift_Connection_SMTP");
+Swift_ClassLoader::load("Swift_Connection_Sendmail");
+
+//Some constants for backwards compatibility with v2 code
+if (!defined("SWIFT_TLS")) define("SWIFT_TLS", Swift_Connection_SMTP::ENC_TLS);
+if (!defined("SWIFT_SSL")) define("SWIFT_SSL", Swift_Connection_SMTP::ENC_SSL);
+if (!defined("SWIFT_OPEN")) define("SWIFT_OPEN", Swift_Connection_SMTP::ENC_OFF);
+if (!defined("SWIFT_SECURE_PORT")) define("SWIFT_SECURE_PORT", Swift_Connection_SMTP::PORT_SECURE);
+if (!defined("SWIFT_DEFAULT_PORT")) define("SWIFT_DEFAULT_PORT", Swift_Connection_SMTP::PORT_DEFAULT);
+
+/**
+ * EasySwift: Facade for Swift Mailer Version 3.
+ * Provides (most of) the API from older versions of Swift, wrapped around the new version 3 API.
+ * Due to the popularity of the new API, EasySwift will not be around indefinitely.
+ * @package EasySwift
+ * @author Chris Corbyn <chris@w3style.co.uk>
+ * @deprecated
+ */
+class EasySwift
+{
+ /**
+ * The instance of Swift this class wrappers
+ * @var Swift
+ */
+ public $swift = null;
+ /**
+ * This value becomes set to true when Swift fails
+ * @var boolean
+ */
+ public $failed = false;
+ /**
+ * The number of loaded plugins
+ * @var int
+ */
+ protected $pluginCount = 0;
+ /**
+ * An instance of Swift_Message
+ * @var Swift_Message
+ */
+ public $message = null;
+ /**
+ * An address list to send to (Cc, Bcc, To..)
+ * @var Swift_RecipientList
+ */
+ public $recipients = null;
+ /**
+ * If all recipients should get the same copy of the message, including headers
+ * This is already implied if any Cc or Bcc recipients are set
+ * @var boolean
+ */
+ protected $exactCopy = false;
+ /**
+ * If EasySwift should get rid of the message and recipients once it's done sending
+ * @var boolean
+ */
+ protected $autoFlush = true;
+ /**
+ * A list of the IDs of all parts added to the message
+ * @var array
+ */
+ protected $partIds = array();
+ /**
+ * A list of all the IDs of the attachments add to the message
+ * @var array
+ */
+ protected $attachmentIds = array();
+ /**
+ * The last response received from the server
+ * @var string
+ */
+ public $lastResponse = "";
+ /**
+ * The 3 digit code in the last response received from the server
+ * @var int
+ */
+ public $responseCode = 0;
+ /**
+ * The list of errors handled at runtime
+ * @var array
+ */
+ public $errors = array();
+ /**
+ * The last error received
+ * @var string
+ */
+ public $lastError = null;
+
+ /**
+ * Constructor
+ * @param Swift_Connection The connection to use
+ * @param string The domain name of this server (not the SMTP server)
+ */
+ public function __construct(Swift_Connection $connection, $domain=null)
+ {
+ try {
+ $this->swift = new Swift($connection, $domain, Swift::ENABLE_LOGGING);
+ Swift_ClassLoader::load("Swift_Plugin_EasySwiftResponseTracker");
+ $this->swift->attachPlugin(new Swift_Plugin_EasySwiftResponseTracker($this), "_ResponseTracker");
+ } catch (Swift_ConnectionException $e) {
+ $this->failed = true;
+ $this->setError("The connection failed to start. An exception was thrown:<br />" . $e->getMessage());
+ }
+ $this->newMessage();
+ $this->newRecipientList();
+ }
+ /**
+ * Set an error message
+ * @param string Error message
+ */
+ public function setError($msg)
+ {
+ $this->errors[] = ($this->lastError = $msg);
+ }
+ /**
+ * Get the full list of errors
+ * @return array
+ */
+ public function getErrors()
+ {
+ return $this->errors;
+ }
+ /**
+ * Get the last error that occured
+ * @return string
+ */
+ public function getLastError()
+ {
+ return $this->lastError;
+ }
+ /**
+ * Clear the current list of errors
+ */
+ public function flushErrors()
+ {
+ $this->errors = null;
+ $this->errors = array();
+ }
+ /**
+ * Turn automatic flsuhing on or off.
+ * This in ON by deault. It removes the message and all parts after sending.
+ * @param boolean
+ */
+ public function autoFlush($flush=true)
+ {
+ $this->autoFlush = $flush;
+ }
+ /**
+ * Set the maximum size of the log
+ * @param int
+ */
+ public function setMaxLogSize($size)
+ {
+ $log = Swift_LogContainer::getLog();
+ $log->setMaxSize($size);
+ }
+ /**
+ * Turn logging on or off (saves memory)
+ * @param boolean
+ */
+ public function useLogging($use=true)
+ {
+ $log = Swift_LogContainer::getLog();
+ if ($use) $log->setLogLevel(Swift_Log::LOG_NETWORK);
+ else $log->setLogLevel(Swift_Log::LOG_NOTHING);
+ }
+ /**
+ * Enable line resizing (on 1000 by default)
+ * @param int The number of characters allowed on a line
+ */
+ public function useAutoLineResizing($size=1000)
+ {
+ $this->message->setLineWrap($size);
+ }
+ /**
+ * Dump the log contents
+ * @deprecated
+ */
+ public function getTransactions()
+ {
+ return $this->dumpLog();
+ }
+ /**
+ * Dump the contents of the log to the browser
+ * The log contains some &lt; and &gt; characters so you may need to view source
+ * Note that this method dumps data to the browser, it does NOT return anything.
+ */
+ public function dumpLog()
+ {
+ $log = Swift_LogContainer::getLog();
+ $log->dump();
+ }
+ /**
+ * This method should be called if you do not wish to send messages in batch mode (i.e. if all recipients should see each others' addresses)
+ * @param boolean If this mode should be used
+ */
+ public function useExactCopy($bool=true)
+ {
+ $this->exactCopy = $bool;
+ }
+ /**
+ * Reset the current message and start a fresh one
+ */
+ public function newMessage($msg=false)
+ {
+ if (!$msg) $msg = new Swift_Message();
+ $this->message = $msg;
+ $this->partIds = array();
+ $this->attachmentIds = array();
+ }
+ /**
+ * Clear out all message parts
+ * @return boolean
+ */
+ public function flushParts()
+ {
+ $success = true;
+ foreach ($this->partIds as $id)
+ {
+ try {
+ $this->message->detach($id);
+ } catch (Swift_Message_MimeException $e) {
+ $success = false;
+ $this->setError("A MIME part failed to detach due to the error:<br />" . $e->getMessage());
+ }
+ }
+ $this->partIds = array();
+ return $success;
+ }
+ /**
+ * Clear out all attachments
+ * @return boolean
+ */
+ public function flushAttachments()
+ {
+ $success = true;
+ foreach ($this->attachmentIds as $id)
+ {
+ try {
+ $this->message->detach($id);
+ } catch (Swift_Message_MimeException $e) {
+ $success = false;
+ $this->setError("An attachment failed to detach due to the error:<br />" . $e->getMessage());
+ }
+ }
+ $this->attachmentIds = array();
+ return $success;
+ }
+ /**
+ * Clear out all message headers
+ * @deprecated
+ */
+ public function flushHeaders()
+ {
+ $this->newMessage();
+ }
+ /**
+ * Reset the current list of recipients and start a new one
+ */
+ public function newRecipientList($list=false)
+ {
+ if (!$list) $list = new Swift_RecipientList();
+ $this->recipients = $list;
+ }
+ /**
+ * Check if Swift has failed or not
+ * This facade stops processing if so
+ * @return boolean
+ */
+ public function hasFailed()
+ {
+ return $this->failed;
+ }
+ /**
+ * Check if the current connection is open or not
+ * @return boolean
+ */
+ public function isConnected()
+ {
+ return (($this->swift !== null) && $this->swift->connection->isAlive());
+ }
+ /**
+ * Connect to the MTA if not already connected
+ */
+ public function connect()
+ {
+ if (!$this->isConnected())
+ {
+ try {
+ $this->swift->connect();
+ return true;
+ } catch (Swift_ConnectionException $e) {
+ $this->failed = true;
+ $this->setError("Swift failed to run the connection process:<br />" . $e->getMessage());
+ }
+ }
+ return false;
+ }
+ /**
+ * Perform the SMTP greeting process (don't do this unless you understand why you're doing it)
+ */
+ public function handshake()
+ {
+ $this->swift->handshake();
+ }
+ /**
+ * Close the connection to the MTA
+ * @return boolean
+ */
+ public function close()
+ {
+ if ($this->isConnected())
+ {
+ try {
+ $this->swift->disconnect();
+ return true;
+ } catch (Swift_ConnectionException $e) {
+ $this->setError("Disconnect failed:<br />" . $e->getMessage());
+ }
+ }
+ return false;
+ }
+ /**
+ * Send a command to Swift and get a response
+ * @param string The command to send (leave of CRLF)
+ * @return string
+ */
+ public function command($command)
+ {
+ if (substr($command, -2) == "\r\n") $command = substr($command, 0, -2);
+
+ try {
+ $rs = $this->swift->command($command);
+ return $rs->getString();
+ } catch (Swift_ConnectionException $e) {
+ $this->setError("Command failed:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ /**
+ * Add a new plugin to respond to events
+ * @param Swift_Events_Listener The plugin to load
+ * @param string The ID to identify the plugin by if needed
+ * @return string The ID of the plugin
+ */
+ public function loadPlugin(Swift_Events_Listener $plugin, $name=null)
+ {
+ $this->pluginCount++;
+ if (!$name) $name = "p" . $this->pluginCount;
+ $this->swift->attachPlugin($plugin, $name);
+ return $name;
+ }
+ /**
+ * Get a reference to the plugin identified by $name
+ * @param string the ID of the plugin
+ * @return Swift_Events_Listener
+ */
+ public function getPlugin($name)
+ {
+ try {
+ $plugin = $this->swift->getPlugin($name);
+ return $plugin;
+ } catch (Exception $e) {
+ return null;
+ }
+ }
+ /**
+ * Remove the plugin identified by $name
+ * @param string The ID of the plugin
+ * @return boolean
+ */
+ public function removePlugin($name)
+ {
+ try {
+ $this->swift->removePlugin($name);
+ return true;
+ } catch (Exception $e) {
+ return false;
+ }
+ }
+ /**
+ * Load in a new authentication mechanism for SMTP
+ * This needn't be called since Swift will locate any available in Swift/Authenticator/*.php
+ * @param Swift_Authenticator The authentication mechanism to load
+ * @throws Exception If the wrong connection is used
+ */
+ public function loadAuthenticator(Swift_Authenticator $auth)
+ {
+ if (method_exists($this->swift->connection, "attachAuthenticator"))
+ {
+ $this->swift->connection->attachAuthenticator($auth);
+ }
+ else throw new Exception("SMTP authentication cannot be used with connection class '" . get_class($this->connection) . "'. Swift_Connection_SMTP is needed");
+ }
+ /**
+ * Authenticate with SMTP authentication
+ * @param string The SMTP username
+ * @param string The SMTP password
+ * @return boolean
+ * @throws Exception If the wrong connection is used
+ */
+ public function authenticate($username, $password)
+ {
+ if (method_exists($this->swift->connection, "runAuthenticators"))
+ {
+ try {
+ $this->swift->connection->runAuthenticators($username, $password, $this->swift);
+ return true;
+ } catch (Swift_ConnectionException $e) {
+ $this->setError("Authentication failed:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ else throw new Exception("SMTP authentication cannot be used with connection class '" . get_class($this->connection) . "'. Swift_Connection_SMTP is needed");
+ }
+ /**
+ * Turn a string representation of an email address into a Swift_Address object
+ * @paramm string The email address
+ * @return Swift_Address
+ */
+ public function stringToAddress($string)
+ {
+ $name = null;
+ $address = null;
+ // Foo Bar <foo@bar>
+ // or: "Foo Bar" <foo@bar>
+ // or: <foo@bar>
+ Swift_ClassLoader::load("Swift_Message_Encoder");
+ if (preg_match("/^\\s*(\"?)(.*?)\\1 *<(" . Swift_Message_Encoder::CHEAP_ADDRESS_RE . ")>\\s*\$/", $string, $matches))
+ {
+ if (!empty($matches[2])) $name = $matches[2];
+ $address = $matches[3];
+ }
+ elseif (preg_match("/^\\s*" . Swift_Message_Encoder::CHEAP_ADDRESS_RE . "\\s*\$/", $string))
+ {
+ $address = trim($string);
+ }
+ else return false;
+
+ $swift_address = new Swift_Address($address, $name);
+ return $swift_address;
+ }
+ /**
+ * Set the encoding used in the message header
+ * The encoding can be one of Q (quoted-printable) or B (base64)
+ * @param string The encoding to use
+ */
+ public function setHeaderEncoding($mode="B")
+ {
+ switch (strtoupper($mode))
+ {
+ case "Q": case "QP": case "QUOTED-PRINTABLE":
+ $this->message->headers->setEncoding("Q");
+ break;
+ default:
+ $this->message->headers->setEncoding("B");
+ }
+ }
+ /**
+ * Set the return path address (where bounces go to)
+ * @param mixed The address as a string or Swift_Address
+ */
+ public function setReturnPath($address)
+ {
+ return $this->message->setReturnPath($address);
+ }
+ /**
+ * Request for a read recipient to be sent to the reply-to address
+ * @param boolean
+ */
+ public function requestReadReceipt($request=true)
+ {
+ //$this->message->requestReadReceipt(true);
+ }
+ /**
+ * Set the message priority
+ * This is an integer between 1 (high) and 5 (low)
+ * @param int The level of priority to use
+ */
+ public function setPriority($priority)
+ {
+ $this->message->setPriority($priority);
+ }
+ /**
+ * Get the return-path address as a string
+ * @return string
+ */
+ public function getReturnPath()
+ {
+ try {
+ return $this->message->getReturnPath();
+ } catch (Swift_Message_MimeException $e) {
+ return false;
+ }
+ }
+ /**
+ * Set the reply-to header
+ * @param mixed The address replies come to. String, or Swift_Address, or an array of either.
+ */
+ public function setReplyTo($address)
+ {
+ return $this->message->setReplyTo($address);
+ }
+ /**
+ * Get the reply-to address(es) as an array of strings
+ * @return array
+ */
+ public function getReplyTo()
+ {
+ try {
+ return $this->message->getReplyTo();
+ } catch (Swift_Message_MimeException $e) {
+ return false;
+ }
+ }
+ /**
+ * Add To: recipients to the email
+ * @param mixed To address(es)
+ * @return boolean
+ */
+ public function addTo($address)
+ {
+ return $this->addRecipients($address, "To");
+ }
+ /**
+ * Get an array of To addresses
+ * This currently returns an array of Swift_Address objects and may be simplified to an array of strings in later versions
+ * @return array
+ */
+ public function getToAddresses()
+ {
+ return $this->recipients->getTo();
+ }
+ /**
+ * Clear out all To: recipients
+ */
+ public function flushTo()
+ {
+ $this->recipients->flushTo();
+ }
+ /**
+ * Add Cc: recipients to the email
+ * @param mixed Cc address(es)
+ * @return boolean
+ */
+ public function addCc($address)
+ {
+ return $this->addRecipients($address, "Cc");
+ }
+ /**
+ * Get an array of Cc addresses
+ * This currently returns an array of Swift_Address objects and may be simplified to an array of strings in later versions
+ * @return array
+ */
+ public function getCcAddresses()
+ {
+ return $this->recipients->getCc();
+ }
+ /**
+ * Clear out all Cc: recipients
+ */
+ public function flushCc()
+ {
+ $this->recipients->flushCc();
+ }
+ /**
+ * Add Bcc: recipients to the email
+ * @param mixed Bcc address(es)
+ * @return boolean
+ */
+ public function addBcc($address)
+ {
+ return $this->addRecipients($address, "Bcc");
+ }
+ /**
+ * Get an array of Bcc addresses
+ * This currently returns an array of Swift_Address objects and may be simplified to an array of strings in later versions
+ * @return array
+ */
+ public function getBccAddresses()
+ {
+ return $this->recipients->getBcc();
+ }
+ /**
+ * Clear out all Bcc: recipients
+ */
+ public function flushBcc()
+ {
+ $this->recipients->flushBcc();
+ }
+ /**
+ * Add recipients to the email
+ * @param mixed Address(es)
+ * @param string Recipient type (To, Cc, Bcc)
+ * @return boolean
+ */
+ protected function addRecipients($address, $type)
+ {
+ if (!in_array($type, array("To", "Cc", "Bcc"))) return false;
+ $method = "add" . $type;
+
+ if ($address instanceof Swift_Address)
+ {
+ $this->recipients->$method($address);
+ return true;
+ }
+ else
+ {
+ $added = 0;
+ foreach ((array)$address as $addr)
+ {
+ if (is_array($addr))
+ {
+ $addr = array_values($addr);
+ if (count($addr) >= 2)
+ {
+ $this->recipients->$method($addr[0], $addr[1]);
+ $added++;
+ continue;
+ }
+ elseif (count($addr) == 1) $addr = $addr[0];
+ else continue;
+ }
+
+ if (is_string($addr))
+ {
+ $addr = $this->stringToAddress($addr);
+ $this->recipients->$method($addr);
+ $added++;
+ }
+ }
+ return ($added > 0);
+ }
+ }
+ /**
+ * Flush message, recipients and headers
+ */
+ public function flush()
+ {
+ $this->newMessage();
+ $this->newRecipientList();
+ }
+ /**
+ * Get a list of any addresses which have failed since instantiation
+ * @return array
+ */
+ public function getFailedRecipients()
+ {
+ $log = Swift_LogContainer::getLog();
+ return $log->getFailedRecipients();
+ }
+ /**
+ * Set the multipart MIME warning message (only seen by old clients)
+ * @param string The message to show
+ */
+ public function setMimeWarning($text)
+ {
+ $this->message->setMimeWarning($text);
+ }
+ /**
+ * Get the currently set MIME warning (seen by old clients)
+ * @return string
+ */
+ public function getMimeWarning()
+ {
+ return $this->message->getMimeWarning();
+ }
+ /**
+ * Set the charset of the charset to use in the message
+ * @param string The charset (e.g. utf-8, iso-8859-1 etc)
+ * @return boolean
+ */
+ public function setCharset($charset)
+ {
+ try {
+ $this->message->setCharset($charset);
+ return true;
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("Unable to set the message charset:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ /**
+ * Get the charset of the charset to use in the message
+ * @return string
+ */
+ public function getCharset()
+ {
+ return $this->message->getCharset();
+ }
+ /**
+ * Add a new MIME part to the message
+ * @param mixed The part to add. If this is a string it's used as the body. If it's an instance of Swift_Message_Part it's used as the entire part
+ * @param string Content-type, default text/plain
+ * @param string The encoding used (default is to let Swift decide)
+ * @param string The charset to use (default is to let swift decide)
+ */
+ public function addPart($body, $type="text/plain", $encoding=null, $charset=null)
+ {
+ if ($body instanceof Swift_Message_Mime)
+ {
+ try {
+ $this->partIds[] = $this->message->attach($body);
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("A MIME part failed to attach:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ else
+ {
+ try {
+ $this->partIds[] = $this->message->attach(new Swift_Message_Part($body, $type, $encoding, $charset));
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("A MIME part failed to attach:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ }
+ /**
+ * Add a new attachment to the message
+ * @param mixed The attachment to add. If this is a string it's used as the file contents. If it's an instance of Swift_Message_Attachment it's used as the entire part. If it's an instance of Swift_File it's used as the contents.
+ * @param string Filename, optional
+ * @param string Content-type. Default application/octet-stream
+ * @param string The encoding used (default is base64)
+ * @return boolean
+ */
+ public function addAttachment($data, $filename=null, $type="application/octet-stream", $encoding=null)
+ {
+ if ($data instanceof Swift_Message_Mime)
+ {
+ try {
+ $this->attachmentIds[] = $this->message->attach($data);
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ else
+ {
+ try {
+ $this->attachmentIds[] = $this->message->attach(new Swift_Message_Attachment($data, $filename, $type, $encoding));
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("An attachment failed to attach<br />" . $e->getMessage());
+ return false;
+ } catch (Swift_FileException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * Embed an image into the message and get the src attribute for HTML
+ * Returns FALSE on failure
+ * @param mixed The path to the image, a Swift_Message_Image object or a Swift_File object
+ * @return string
+ */
+ public function addImage($input)
+ {
+ $ret = false;
+ if ($input instanceof Swift_Message_Image)
+ {
+ $ret = $this->message->attach($input);
+ $this->attachmentIds[] = $ret;
+ return $ret;
+ }
+ elseif ($input instanceof Swift_File)
+ {
+ try {
+ $ret = $this->message->attach(new Swift_Message_Image($input));
+ $this->attachmentIds[] = $ret;
+ return $ret;
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ } catch (Swift_FileException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ else
+ {
+ try {
+ $ret = $this->message->attach(new Swift_Message_Image(new Swift_File($input)));
+ $this->attachmentIds[] = $ret;
+ return $ret;
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ } catch (Swift_FileException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ }
+ /**
+ * Embed an inline file into the message, such as a Image or MIDI file
+ * @param mixed The file contents, Swift_File object or Swift_Message_EmbeddedFile object
+ * @param string The content-type of the file, optional
+ * @param string The filename to use, optional
+ * @param string the Content-ID to use, optional
+ * @return string
+ */
+ public function embedFile($data, $type="application/octet-stream", $filename=null, $cid=null)
+ {
+ $ret = false;
+ if ($data instanceof Swift_Message_EmbeddedFile)
+ {
+ $ret = $this->message->attach($data);
+ $this->attachmentIds[] = $ret;
+ return $ret;
+ }
+ elseif ($data instanceof Swift_File)
+ {
+ try {
+ $ret = $this->message->attach(new Swift_Message_EmbeddedFile($data, $filename, $type, $cid));
+ $this->attachmentIds[] = $ret;
+ return $ret;
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ } catch (Swift_FileException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ else
+ {
+ try {
+ $ret = $this->message->attach(new Swift_Message_EmbeddedFile($data, $filename, $type, $cid));
+ $this->attachmentIds[] = $ret;
+ return $ret;
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ } catch (Swift_FileException $e) {
+ $this->setError("An attachment failed to attach:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+ }
+ /**
+ * Add headers to the message
+ * @param string The message headers to append, separated by CRLF
+ * @deprecated
+ */
+ public function addHeaders($string)
+ {
+ //Split at the line ending only if it's not followed by LWSP (as in, a full header)
+ $headers = preg_split("~\r?\n(?![ \t])~", $string);
+ foreach ($headers as $header)
+ {
+ if (empty($header)) continue;
+ //Get the bit before the colon
+ $header_name = substr($header, 0, ($c_pos = strpos($header, ": ")));
+ // ... and trim it away
+ $header = substr($header, $c_pos+2);
+ //Try splitting at "; " for attributes
+ $attribute_pairs = preg_split("~\\s*;\\s+~", $header);
+ //The value would always be right after the colon
+ $header_value = $attribute_pairs[0];
+ $this->message->headers->set($header_name, $header_value);
+ unset($attribute_pairs[0]);
+ foreach ($attribute_pairs as $pair)
+ {
+ //Now try finding the attribute name, and it's value (removing quotes)
+ if (preg_match("~^(.*?)=(\"?)(.*?)\\2\\s*\$~", $pair, $matches))
+ {
+ try {
+ $this->message->headers->setAttribute($header_name, $matches[1], $matches[3]);
+ } catch (Swift_Message_MimeException $e) {
+ $this->setError("There was a problem parsing or setting a header attribute:<br />" . $e->getMessage());
+ //Ignored... it's EasySwift... C'mon ;)
+ }
+ }
+ }
+ }
+ }
+ /**
+ * Set a header in the message
+ * @param string The name of the header
+ * @param string The value of the header (without attributes)
+ * @see {addHeaderAttribute}
+ */
+ public function setHeader($name, $value)
+ {
+ $this->message->headers->set($name, $value);
+ }
+ /**
+ * Set an attribute in the message headers
+ * For example charset in Content-Type: text/html; charset=utf-8 set by $swift->setHeaderAttribute("Content-Type", "charset", "utf-8")
+ * @param string The name of the header
+ * @param string The name of the attribute
+ * @param string The value of the attribute
+ */
+ public function setHeaderAttribute($name, $attribute, $value)
+ {
+ if ($this->message->headers->has($name))
+ $this->message->headers->setAttribute($name, $attribute, $value);
+ }
+ /**
+ * Send an email to a number of recipients
+ * Returns the number of successful recipients, or FALSE on failure
+ * @param mixed The recipients to send to. One of string, array, 2-dimensional array or Swift_Address
+ * @param mixed The address to send from. string or Swift_Address
+ * @param string The message subject
+ * @param string The message body, optional
+ * @return int
+ */
+ public function send($recipients, $from, $subject, $body=null)
+ {
+ $this->addTo($recipients);
+
+ $sender = false;
+ if (is_string($from)) $sender = $this->stringToAddress($from);
+ elseif ($from instanceof Swift_Address) $sender = $from;
+ if (!$sender) return false;
+
+ $this->message->setSubject($subject);
+ if ($body) $this->message->setBody($body);
+ try {
+ if (!$this->exactCopy && !$this->recipients->getCc() && !$this->recipients->getBcc())
+ {
+ $sent = $this->swift->batchSend($this->message, $this->recipients, $sender);
+ }
+ else
+ {
+ $sent = $this->swift->send($this->message, $this->recipients, $sender);
+ }
+ if ($this->autoFlush) $this->flush();
+ return $sent;
+ } catch (Swift_ConnectionException $e) {
+ $this->setError("Sending failed:<br />" . $e->getMessage());
+ return false;
+ }
+ }
+}
+?>
View
1,388 classes/PEAR/DB.php
@@ -0,0 +1,1388 @@
+<?php
+
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+
+/**
+ * Database independent query interface
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: This source file is subject to version 3.0 of the PHP license
+ * that is available through the world-wide-web at the following URI:
+ * http://www.php.net/license/3_0.txt. If you did not receive a copy of
+ * the PHP License and are unable to obtain it through the web, please
+ * send a note to license@php.net so we can mail you a copy immediately.
+ *
+ * @category Database
+ * @package DB
+ * @author Stig Bakken <ssb@php.net>
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Daniel Convissor <danielc@php.net>
+ * @copyright 1997-2005 The PHP Group
+ * @license http://www.php.net/license/3_0.txt PHP License 3.0
+ * @version CVS: $Id: DB.php 32 2005-08-01 06:21:02Z dancoulter $
+ * @link http://pear.php.net/package/DB
+ */
+
+/**
+ * Obtain the PEAR class so it can be extended from
+ */
+require_once 'PEAR.php';
+
+
+// {{{ constants
+// {{{ error codes
+
+/**#@+
+ * One of PEAR DB's portable error codes.
+ * @see DB_common::errorCode(), DB::errorMessage()
+ *
+ * {@internal If you add an error code here, make sure you also add a textual
+ * version of it in DB::errorMessage().}}
+ */
+
+/**
+ * The code returned by many methods upon success
+ */
+define('DB_OK', 1);
+
+/**
+ * Unkown error
+ */
+define('DB_ERROR', -1);
+
+/**
+ * Syntax error
+ */
+define('DB_ERROR_SYNTAX', -2);
+
+/**
+ * Tried to insert a duplicate value into a primary or unique index
+ */
+define('DB_ERROR_CONSTRAINT', -3);
+
+/**
+ * An identifier in the query refers to a non-existant object
+ */
+define('DB_ERROR_NOT_FOUND', -4);
+
+/**
+ * Tried to create a duplicate object
+ */
+define('DB_ERROR_ALREADY_EXISTS', -5);
+
+/**
+ * The current driver does not support the action you attempted
+ */
+define('DB_ERROR_UNSUPPORTED', -6);
+
+/**
+ * The number of parameters does not match the number of placeholders
+ */
+define('DB_ERROR_MISMATCH', -7);
+
+/**
+ * A literal submitted did not match the data type expected
+ */
+define('DB_ERROR_INVALID', -8);
+
+/**
+ * The current DBMS does not support the action you attempted
+ */
+define('DB_ERROR_NOT_CAPABLE', -9);
+
+/**
+ * A literal submitted was too long so the end of it was removed
+ */
+define('DB_ERROR_TRUNCATED', -10);
+
+/**
+ * A literal number submitted did not match the data type expected
+ */
+define('DB_ERROR_INVALID_NUMBER', -11);
+
+/**
+ * A literal date submitted did not match the data type expected
+ */
+define('DB_ERROR_INVALID_DATE', -12);
+
+/**
+ * Attempt to divide something by zero
+ */
+define('DB_ERROR_DIVZERO', -13);
+
+/**
+ * A database needs to be selected
+ */
+define('DB_ERROR_NODBSELECTED', -14);
+
+/**
+ * Could not create the object requested
+ */
+define('DB_ERROR_CANNOT_CREATE', -15);
+
+/**
+ * Could not drop the database requested because it does not exist
+ */
+define('DB_ERROR_CANNOT_DROP', -17);
+
+/**
+ * An identifier in the query refers to a non-existant table
+ */
+define('DB_ERROR_NOSUCHTABLE', -18);
+
+/**
+ * An identifier in the query refers to a non-existant column
+ */
+define('DB_ERROR_NOSUCHFIELD', -19);
+
+/**
+ * The data submitted to the method was inappropriate
+ */
+define('DB_ERROR_NEED_MORE_DATA', -20);
+
+/**
+ * The attempt to lock the table failed
+ */
+define('DB_ERROR_NOT_LOCKED', -21);
+
+/**
+ * The number of columns doesn't match the number of values
+ */
+define('DB_ERROR_VALUE_COUNT_ON_ROW', -22);
+
+/**
+ * The DSN submitted has problems
+ */
+define('DB_ERROR_INVALID_DSN', -23);
+
+/**
+ * Could not connect to the database
+ */
+define('DB_ERROR_CONNECT_FAILED', -24);
+
+/**
+ * The PHP extension needed for this DBMS could not be found
+ */
+define('DB_ERROR_EXTENSION_NOT_FOUND',-25);
+
+/**
+ * The present user has inadequate permissions to perform the task requestd
+ */
+define('DB_ERROR_ACCESS_VIOLATION', -26);
+
+/**
+ * The database requested does not exist
+ */
+define('DB_ERROR_NOSUCHDB', -27);
+
+/**
+ * Tried to insert a null value into a column that doesn't allow nulls
+ */
+define('DB_ERROR_CONSTRAINT_NOT_NULL',-29);
+/**#@-*/
+
+
+// }}}
+// {{{ prepared statement-related
+
+
+/**#@+
+ * Identifiers for the placeholders used in prepared statements.
+ * @see DB_common::prepare()
+ */
+
+/**
+ * Indicates a scalar (<kbd>?</kbd>) placeholder was used
+ *
+ * Quote and escape the value as necessary.
+ */
+define('DB_PARAM_SCALAR', 1);
+
+/**
+ * Indicates an opaque (<kbd>&</kbd>) placeholder was used
+ *
+ * The value presented is a file name. Extract the contents of that file
+ * and place them in this column.
+ */
+define('DB_PARAM_OPAQUE', 2);
+
+/**
+ * Indicates a misc (<kbd>!</kbd>) placeholder was used
+ *
+ * The value should not be quoted or escaped.
+ */
+define('DB_PARAM_MISC', 3);
+/**#@-*/
+
+
+// }}}
+// {{{ binary data-related
+
+
+/**#@+
+ * The different ways of returning binary data from queries.
+ */
+
+/**
+ * Sends the fetched data straight through to output
+ */
+define('DB_BINMODE_PASSTHRU', 1);
+
+/**
+ * Lets you return data as usual
+ */
+define('DB_BINMODE_RETURN', 2);
+
+/**
+ * Converts the data to hex format before returning it
+ *
+ * For example the string "123" would become "313233".
+ */
+define('DB_BINMODE_CONVERT', 3);
+/**#@-*/
+
+
+// }}}
+// {{{ fetch modes
+
+
+/**#@+
+ * Fetch Modes.
+ * @see DB_common::setFetchMode()
+ */
+
+/**
+ * Indicates the current default fetch mode should be used
+ * @see DB_common::$fetchmode
+ */
+define('DB_FETCHMODE_DEFAULT', 0);
+
+/**
+ * Column data indexed by numbers, ordered from 0 and up
+ */
+define('DB_FETCHMODE_ORDERED', 1);
+
+/**
+ * Column data indexed by column names
+ */
+define('DB_FETCHMODE_ASSOC', 2);
+
+/**
+ * Column data as object properties
+ */
+define('DB_FETCHMODE_OBJECT', 3);
+
+/**
+ * For multi-dimensional results, make the column name the first level
+ * of the array and put the row number in the second level of the array
+ *
+ * This is flipped from the normal behavior, which puts the row numbers
+ * in the first level of the array and the column names in the second level.
+ */
+define('DB_FETCHMODE_FLIPPED', 4);
+/**#@-*/
+
+/**#@+
+ * Old fetch modes. Left here for compatibility.
+ */
+define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
+define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC);
+define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
+/**#@-*/
+
+
+// }}}
+// {{{ tableInfo() && autoPrepare()-related
+
+
+/**#@+
+ * The type of information to return from the tableInfo() method.
+ *
+ * Bitwised constants, so they can be combined using <kbd>|</kbd>
+ * and removed using <kbd>^</kbd>.
+ *
+ * @see DB_common::tableInfo()
+ *
+ * {@internal Since the TABLEINFO constants are bitwised, if more of them are
+ * added in the future, make sure to adjust DB_TABLEINFO_FULL accordingly.}}
+ */
+define('DB_TABLEINFO_ORDER', 1);
+define('DB_TABLEINFO_ORDERTABLE', 2);
+define('DB_TABLEINFO_FULL', 3);
+/**#@-*/
+
+
+/**#@+
+ * The type of query to create with the automatic query building methods.
+ * @see DB_common::autoPrepare(), DB_common::autoExecute()
+ */
+define('DB_AUTOQUERY_INSERT', 1);
+define('DB_AUTOQUERY_UPDATE', 2);
+/**#@-*/
+
+
+// }}}
+// {{{ portability modes
+
+
+/**#@+
+ * Portability Modes.
+ *
+ * Bitwised constants, so they can be combined using <kbd>|</kbd>
+ * and removed using <kbd>^</kbd>.
+ *
+ * @see DB_common::setOption()
+ *
+ * {@internal Since the PORTABILITY constants are bitwised, if more of them are
+ * added in the future, make sure to adjust DB_PORTABILITY_ALL accordingly.}}
+ */
+
+/**
+ * Turn off all portability features
+ */
+define('DB_PORTABILITY_NONE', 0);
+
+/**
+ * Convert names of tables and fields to lower case
+ * when using the get*(), fetch*() and tableInfo() methods
+ */
+define('DB_PORTABILITY_LOWERCASE', 1);
+
+/**
+ * Right trim the data output by get*() and fetch*()
+ */
+define('DB_PORTABILITY_RTRIM', 2);
+
+/**
+ * Force reporting the number of rows deleted
+ */
+define('DB_PORTABILITY_DELETE_COUNT', 4);
+
+/**
+ * Enable hack that makes numRows() work in Oracle
+ */
+define('DB_PORTABILITY_NUMROWS', 8);
+
+/**
+ * Makes certain error messages in certain drivers compatible
+ * with those from other DBMS's
+ *
+ * + mysql, mysqli: change unique/primary key constraints
+ * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT
+ *
+ * + odbc(access): MS's ODBC driver reports 'no such field' as code
+ * 07001, which means 'too few parameters.' When this option is on
+ * that code gets mapped to DB_ERROR_NOSUCHFIELD.
+ */
+define('DB_PORTABILITY_ERRORS', 16);
+
+/**
+ * Convert null values to empty strings in data output by
+ * get*() and fetch*()
+ */
+define('DB_PORTABILITY_NULL_TO_EMPTY', 32);
+
+/**
+ * Turn on all portability features
+ */
+define('DB_PORTABILITY_ALL', 63);
+/**#@-*/
+
+// }}}
+
+
+// }}}
+// {{{ class DB
+
+/**
+ * Database independent query interface
+ *
+ * The main "DB" class is simply a container class with some static
+ * methods for creating DB objects as well as some utility functions
+ * common to all parts of DB.
+ *
+ * The object model of DB is as follows (indentation means inheritance):
+ * <pre>
+ * DB The main DB class. This is simply a utility class
+ * with some "static" methods for creating DB objects as
+ * well as common utility functions for other DB classes.
+ *
+ * DB_common The base for each DB implementation. Provides default
+ * | implementations (in OO lingo virtual methods) for
+ * | the actual DB implementations as well as a bunch of
+ * | query utility functions.
+ * |
+ * +-DB_mysql The DB implementation for MySQL. Inherits DB_common.
+ * When calling DB::factory or DB::connect for MySQL
+ * connections, the object returned is an instance of this
+ * class.
+ * </pre>
+ *
+ * @category Database
+ * @package DB
+ * @author Stig Bakken <ssb@php.net>
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Daniel Convissor <danielc@php.net>
+ * @copyright 1997-2005 The PHP Group
+ * @license http://www.php.net/license/3_0.txt PHP License 3.0
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/DB
+ */
+class DB
+{
+ // {{{ &factory()
+
+ /**
+ * Create a new DB object for the specified database type but don't
+ * connect to the database
+ *
+ * @param string $type the database type (eg "mysql")
+ * @param array $options an associative array of option names and values
+ *
+ * @return object a new DB object. A DB_Error object on failure.
+ *
+ * @see DB_common::setOption()
+ */
+ function &factory($type, $options = false)
+ {
+ if (!is_array($options)) {
+ $options = array('persistent' => $options);
+ }
+
+ if (isset($options['debug']) && $options['debug'] >= 2) {
+ // expose php errors with sufficient debug level
+ include_once "DB/{$type}.php";
+ } else {
+ @include_once "DB/{$type}.php";
+ }
+
+ $classname = "DB_${type}";
+
+ if (!class_exists($classname)) {
+ $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
+ "Unable to include the DB/{$type}.php"
+ . " file for '$dsn'",
+ 'DB_Error', true);
+ return $tmp;
+ }
+
+ @$obj =& new $classname;
+
+ foreach ($options as $option => $value) {
+ $test = $obj->setOption($option, $value);
+ if (DB::isError($test)) {
+ return $test;
+ }
+ }
+
+ return $obj;
+ }
+
+ // }}}
+ // {{{ &connect()
+
+ /**
+ * Create a new DB object including a connection to the specified database
+ *
+ * Example 1.
+ * <code>
+ * require_once 'DB.php';
+ *
+ * $dsn = 'pgsql://user:password@host/database';
+ * $options = array(
+ * 'debug' => 2,
+ * 'portability' => DB_PORTABILITY_ALL,
+ * );
+ *
+ * $db =& DB::connect($dsn, $options);
+ * if (PEAR::isError($db)) {
+ * die($db->getMessage());
+ * }
+ * </code>
+ *
+ * @param mixed $dsn the string "data source name" or array in the
+ * format returned by DB::parseDSN()
+ * @param array $options an associative array of option names and values
+ *
+ * @return object a new DB object. A DB_Error object on failure.
+ *
+ * @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(),
+ * DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(),
+ * DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(),
+ * DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(),
+ * DB_sybase::connect()
+ *
+ * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError()
+ */
+ function &connect($dsn, $options = array())
+ {
+ $dsninfo = DB::parseDSN($dsn);
+ $type = $dsninfo['phptype'];
+
+ if (!is_array($options)) {
+ /*
+ * For backwards compatibility. $options used to be boolean,
+ * indicating whether the connection should be persistent.
+ */
+ $options = array('persistent' => $options);
+ }
+
+ if (isset($options['debug']) && $options['debug'] >= 2) {
+ // expose php errors with sufficient debug level
+ include_once "DB/${type}.php";
+ } else {
+ @include_once "DB/${type}.php";
+ }
+
+ $classname = "DB_${type}";
+ if (!class_exists($classname)) {
+ $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null,
+ "Unable to include the DB/{$type}.php"
+ . " file for '$dsn'",
+ 'DB_Error', true);
+ return $tmp;
+ }
+
+ @$obj =& new $classname;
+
+ foreach ($options as $option => $value) {
+ $test = $obj->setOption($option, $value);
+ if (DB::isError($test)) {
+ return $test;
+ }
+ }
+
+ $err = $obj->connect($dsninfo, $obj->getOption('persistent'));
+ if (DB::isError($err)) {
+ $err->addUserInfo($dsn);
+ return $err;
+ }
+
+ return $obj;
+ }
+
+ // }}}
+ // {{{ apiVersion()
+
+ /**
+ * Return the DB API version
+ *
+ * @return string the DB API version number
+ */
+ function apiVersion()
+ {
+ return '@package_version@';
+ }
+
+ // }}}
+ // {{{ isError()
+
+ /**
+ * Determines if a variable is a DB_Error object
+ *
+ * @param mixed $value the variable to check
+ *
+ * @return bool whether $value is DB_Error object
+ */
+ function isError($value)
+ {
+ return is_a($value, 'DB_Error');
+ }
+
+ // }}}
+ // {{{ isConnection()
+
+ /**
+ * Determines if a value is a DB_<driver> object
+ *
+ * @param mixed $value the value to test
+ *
+ * @return bool whether $value is a DB_<driver> object
+ */
+ function isConnection($value)
+ {
+ return (is_object($value) &&
+ is_subclass_of($value, 'db_common') &&
+ method_exists($value, 'simpleQuery'));
+ }
+
+ // }}}
+ // {{{ isManip()
+
+ /**
+ * Tell whether a query is a data manipulation or data definition query
+ *
+ * Examples of data manipulation queries are INSERT, UPDATE and DELETE.
+ * Examples of data definition queries are CREATE, DROP, ALTER, GRANT,
+ * REVOKE.
+ *
+ * @param string $query the query
+ *
+ * @return boolean whether $query is a data manipulation query
+ */
+ function isManip($query)
+ {
+ $manips = 'INSERT|UPDATE|DELETE|REPLACE|'
+ . 'CREATE|DROP|'
+ . 'LOAD DATA|SELECT .* INTO|COPY|'
+ . 'ALTER|GRANT|REVOKE|'
+ . 'LOCK|UNLOCK';
+ if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) {
+ return true;
+ }
+ return false;
+ }
+
+ // }}}
+ // {{{ errorMessage()
+
+ /**
+ * Return a textual error message for a DB error code
+ *
+ * @param integer $value the DB error code
+ *
+ * @return string the error message or false if the error code was
+ * not recognized
+ */
+ function errorMessage($value)
+ {
+ static $errorMessages;
+ if (!isset($errorMessages)) {
+ $errorMessages = array(
+ DB_ERROR => 'unknown error',
+ DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions',
+ DB_ERROR_ALREADY_EXISTS => 'already exists',
+ DB_ERROR_CANNOT_CREATE => 'can not create',
+ DB_ERROR_CANNOT_DROP => 'can not drop',
+ DB_ERROR_CONNECT_FAILED => 'connect failed',
+ DB_ERROR_CONSTRAINT => 'constraint violation',
+ DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
+ DB_ERROR_DIVZERO => 'division by zero',
+ DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
+ DB_ERROR_INVALID => 'invalid',
+ DB_ERROR_INVALID_DATE => 'invalid date or time',
+ DB_ERROR_INVALID_DSN => 'invalid DSN',
+ DB_ERROR_INVALID_NUMBER => 'invalid number',
+ DB_ERROR_MISMATCH => 'mismatch',
+ DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied',
+ DB_ERROR_NODBSELECTED => 'no database selected',
+ DB_ERROR_NOSUCHDB => 'no such database',
+ DB_ERROR_NOSUCHFIELD => 'no such field',
+ DB_ERROR_NOSUCHTABLE => 'no such table',
+ DB_ERROR_NOT_CAPABLE => 'DB backend not capable',
+ DB_ERROR_NOT_FOUND => 'not found',
+ DB_ERROR_NOT_LOCKED => 'not locked',
+ DB_ERROR_SYNTAX => 'syntax error',
+ DB_ERROR_UNSUPPORTED => 'not supported',
+ DB_ERROR_TRUNCATED => 'truncated',
+ DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
+ DB_OK => 'no error',
+ );
+ }
+
+ if (DB::isError($value)) {
+ $value = $value->getCode();
+ }
+
+ return isset($errorMessages[$value]) ? $errorMessages[$value]
+ : $errorMessages[DB_ERROR];
+ }
+
+ // }}}
+ // {{{ parseDSN()
+
+ /**
+ * Parse a data source name
+ *
+ * Additional keys can be added by appending a URI query string to the
+ * end of the DSN.
+ *
+ * The format of the supplied DSN is in its fullest form:
+ * <code>
+ * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
+ * </code>
+ *
+ * Most variations are allowed:
+ * <code>
+ * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
+ * phptype://username:password@hostspec/database_name
+ * phptype://username:password@hostspec
+ * phptype://username@hostspec
+ * phptype://hostspec/database
+ * phptype://hostspec
+ * phptype(dbsyntax)
+ * phptype
+ * </code>
+ *
+ * @param string $dsn Data Source Name to be parsed
+ *
+ * @return array an associative array with the following keys:
+ * + phptype: Database backend used in PHP (mysql, odbc etc.)
+ * + dbsyntax: Database used with regards to SQL syntax etc.
+ * + protocol: Communication protocol to use (tcp, unix etc.)
+ * + hostspec: Host specification (hostname[:port])
+ * + database: Database to use on the DBMS server
+ * + username: User name for login
+ * + password: Password for login
+ */
+ function parseDSN($dsn)
+ {
+ $parsed = array(
+ 'phptype' => false,
+ 'dbsyntax' => false,
+ 'username' => false,
+ 'password' => false,
+ 'protocol' => false,
+ 'hostspec' => false,
+ 'port' => false,
+ 'socket' => false,
+ 'database' => false,
+ );
+
+ if (is_array($dsn)) {
+ $dsn = array_merge($parsed, $dsn);
+ if (!$dsn['dbsyntax']) {
+ $dsn['dbsyntax'] = $dsn['phptype'];
+ }
+ return $dsn;
+ }
+
+ // Find phptype and dbsyntax
+ if (($pos = strpos($dsn, '://')) !== false) {
+ $str = substr($dsn, 0, $pos);
+ $dsn = substr($dsn, $pos + 3);
+ } else {
+ $str = $dsn;
+ $dsn = null;
+ }
+
+ // Get phptype and dbsyntax
+ // $str => phptype(dbsyntax)
+ if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
+ $parsed['phptype'] = $arr[1];
+ $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
+ } else {
+ $parsed['phptype'] = $str;
+ $parsed['dbsyntax'] = $str;
+ }
+
+ if (!count($dsn)) {
+ return $parsed;
+ }
+
+ // Get (if found): username and password
+ // $dsn => username:password@protocol+hostspec/database
+ if (($at = strrpos($dsn,'@')) !== false) {
+ $str = substr($dsn, 0, $at);
+ $dsn = substr($dsn, $at + 1);
+ if (($pos = strpos($str, ':')) !== false) {
+ $parsed['username'] = rawurldecode(substr($str, 0, $pos));
+ $parsed['password'] = rawurldecode(substr($str, $pos + 1));
+ } else {
+ $parsed['username'] = rawurldecode($str);
+ }
+ }
+
+ // Find protocol and hostspec
+
+ if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
+ // $dsn => proto(proto_opts)/database
+ $proto = $match[1];
+ $proto_opts = $match[2] ? $match[2] : false;
+ $dsn = $match[3];
+
+ } else {
+ // $dsn => protocol+hostspec/database (old format)
+ if (strpos($dsn, '+') !== false) {
+ list($proto, $dsn) = explode('+', $dsn, 2);
+ }
+ if (strpos($dsn, '/') !== false) {
+ list($proto_opts, $dsn) = explode('/', $dsn, 2);
+ } else {
+ $proto_opts = $dsn;
+ $dsn = null;
+ }
+ }
+
+ // process the different protocol options
+ $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
+ $proto_opts = rawurldecode($proto_opts);
+ if ($parsed['protocol'] == 'tcp') {
+ if (strpos($proto_opts, ':') !== false) {
+ list($parsed['hostspec'],
+ $parsed['port']) = explode(':', $proto_opts);
+ } else {
+ $parsed['hostspec'] = $proto_opts;
+ }
+ } elseif ($parsed['protocol'] == 'unix') {
+ $parsed['socket'] = $proto_opts;
+ }
+
+ // Get dabase if any
+ // $dsn => database
+ if ($dsn) {
+ if (($pos = strpos($dsn, '?')) === false) {
+ // /database
+ $parsed['database'] = rawurldecode($dsn);
+ } else {
+ // /database?param1=value1&param2=value2
+ $parsed['database'] = rawurldecode(substr($dsn, 0, $pos));
+ $dsn = substr($dsn, $pos + 1);
+ if (strpos($dsn, '&') !== false) {
+ $opts = explode('&', $dsn);
+ } else { // database?param1=value1
+ $opts = array($dsn);
+ }
+ foreach ($opts as $opt) {
+ list($key, $value) = explode('=', $opt);
+ if (!isset($parsed[$key])) {
+ // don't allow params overwrite
+ $parsed[$key] = rawurldecode($value);
+ }
+ }
+ }
+ }
+
+ return $parsed;
+ }
+
+ // }}}
+}
+
+// }}}
+// {{{ class DB_Error
+
+/**
+ * DB_Error implements a class for reporting portable database error
+ * messages
+ *
+ * @category Database
+ * @package DB
+ * @author Stig Bakken <ssb@php.net>
+ * @copyright 1997-2005 The PHP Group
+ * @license http://www.php.net/license/3_0.txt PHP License 3.0
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/DB
+ */
+class DB_Error extends PEAR_Error
+{
+ // {{{ constructor
+
+ /**
+ * DB_Error constructor
+ *
+ * @param mixed $code DB error code, or string with error message
+ * @param int $mode what "error mode" to operate in
+ * @param int $level what error level to use for $mode &
+ * PEAR_ERROR_TRIGGER
+ * @param mixed $debuginfo additional debug info, such as the last query
+ *
+ * @see PEAR_Error
+ */
+ function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN,
+ $level = E_USER_NOTICE, $debuginfo = null)
+ {
+ if (is_int($code)) {
+ $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code,
+ $mode, $level, $debuginfo);
+ } else {
+ $this->PEAR_Error("DB Error: $code", DB_ERROR,
+ $mode, $level, $debuginfo);
+ }
+ }
+
+ // }}}
+}
+
+// }}}
+// {{{ class DB_result
+
+/**
+ * This class implements a wrapper for a DB result set
+ *
+ * A new instance of this class will be returned by the DB implementation
+ * after processing a query that returns data.
+ *
+ * @category Database
+ * @package DB
+ * @author Stig Bakken <ssb@php.net>
+ * @copyright 1997-2005 The PHP Group
+ * @license http://www.php.net/license/3_0.txt PHP License 3.0
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/DB
+ */
+class DB_result
+{
+ // {{{ properties
+
+ /**
+ * Should results be freed automatically when there are no more rows?
+ * @var boolean
+ * @see DB_common::$options
+ */
+ var $autofree;
+
+ /**
+ * A reference to the DB_<driver> object
+ * @var object
+ */
+ var $dbh;
+
+ /**
+ * The current default fetch mode
+ * @var integer
+ * @see DB_common::$fetchmode
+ */
+ var $fetchmode;
+
+ /**
+ * The name of the class into which results should be fetched when
+ * DB_FETCHMODE_OBJECT is in effect
+ *
+ * @var string
+ * @see DB_common::$fetchmode_object_class
+ */
+ var $fetchmode_object_class;
+
+ /**
+ * The number of rows to fetch from a limit query
+ * @var integer
+ */
+ var $limit_count = null;
+
+ /**
+ * The row to start fetching from in limit queries
+ * @var integer
+ */
+ var $limit_from = null;
+
+ /**
+ * The execute parameters that created this result
+ * @var array
+ * @since Property available since Release 1.7.0
+ */
+ var $parameters;
+
+ /**
+ * The query string that created this result
+ *
+ * Copied here incase it changes in $dbh, which is referenced
+ *
+ * @var string
+ * @since Property available since Release 1.7.0
+ */
+ var $query;
+
+ /**
+ * The query result resource id created by PHP
+ * @var resource
+ */
+ var $result;
+
+ /**
+ * The present row being dealt with
+ * @var integer
+ */
+ var $row_counter = null;
+
+ /**
+ * The prepared statement resource id created by PHP in $dbh
+ *
+ * This resource is only available when the result set was created using
+ * a driver's native execute() method, not PEAR DB's emulated one.
+ *
+ * Copied here incase it changes in $dbh, which is referenced
+ *
+ * {@internal Mainly here because the InterBase/Firebird API is only
+ * able to retrieve data from result sets if the statemnt handle is
+ * still in scope.}}
+ *
+ * @var resource
+ * @since Property available since Release 1.7.0
+ */
+ var $statement;
+
+
+ // }}}
+ // {{{ constructor
+
+ /**
+ * This constructor sets the object's properties
+ *
+ * @param object &$dbh the DB object reference
+ * @param resource $result the result resource id
+ * @param array $options an associative array with result options
+ *
+ * @return void
+ */
+ function DB_result(&$dbh, $result, $options = array())
+ {
+ $this->autofree = $dbh->options['autofree'];
+ $this->dbh = &$dbh;
+ $this->fetchmode = $dbh->fetchmode;
+ $this->fetchmode_object_class = $dbh->fetchmode_object_class;
+ $this->parameters = $dbh->last_parameters;
+ $this->query = $dbh->last_query;
+ $this->result = $result;
+ $this->statement = empty($dbh->last_stmt) ? null : $dbh->last_stmt;
+ foreach ($options as $key => $value) {
+ $this->setOption($key, $value);
+ }
+ }
+
+ /**
+ * Set options for the DB_result object
+ *
+ * @param string $key the option to set
+ * @param mixed $value the value to set the option to
+ *
+ * @return void
+ */
+ function setOption($key, $value = null)
+ {
+ switch ($key) {
+ case 'limit_from':
+ $this->limit_from = $value;
+ break;
+ case 'limit_count':
+ $this->limit_count = $value;
+ }
+ }
+
+ // }}}
+ // {{{ fetchRow()
+
+ /**
+ * Fetch a row of data and return it by reference into an array
+ *
+ * The type of array returned can be controlled either by setting this
+ * method's <var>$fetchmode</var> parameter or by changing the default
+ * fetch mode setFetchMode() before calling this method.
+ *
+ * There are two options for standardizing the information returned
+ * from databases, ensuring their values are consistent when changing
+ * DBMS's. These portability options can be turned on when creating a
+ * new DB object or by using setOption().
+ *
+ * + <var>DB_PORTABILITY_LOWERCASE</var>
+ * convert names of fields to lower case
+ *
+ * + <var>DB_PORTABILITY_RTRIM</var>
+ * right trim the data
+ *
+ * @param int $fetchmode the constant indicating how to format the data
+ * @param int $rownum the row number to fetch (index starts at 0)
+ *
+ * @return mixed an array or object containing the row's data,
+ * NULL when the end of the result set is reached
+ * or a DB_Error object on failure.
+ *
+ * @see DB_common::setOption(), DB_common::setFetchMode()
+ */
+ function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null)
+ {
+ if ($fetchmode === DB_FETCHMODE_DEFAULT) {
+ $fetchmode = $this->fetchmode;
+ }
+ if ($fetchmode === DB_FETCHMODE_OBJECT) {
+ $fetchmode = DB_FETCHMODE_ASSOC;
+ $object_class = $this->fetchmode_object_class;
+ }
+ if ($this->limit_from !== null) {
+ if ($this->row_counter === null) {
+ $this->row_counter = $this->limit_from;
+ // Skip rows
+ if ($this->dbh->features['limit'] === false) {
+ $i = 0;
+ while ($i++ < $this->limit_from) {
+ $this->dbh->fetchInto($this->result, $arr, $fetchmode);
+ }
+ }
+ }
+ if ($this->row_counter >= ($this->limit_from + $this->limit_count))
+ {
+ if ($this->autofree) {
+ $this->free();
+ }
+ $tmp = null;
+ return $tmp;
+ }
+ if ($this->dbh->features['limit'] === 'emulate') {
+ $rownum = $this->row_counter;
+ }
+ $this->row_counter++;
+ }
+ $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum);
+ if ($res === DB_OK) {
+ if (isset($object_class)) {
+ // The default mode is specified in the
+ // DB_common::fetchmode_object_class property
+ if ($object_class == 'stdClass') {
+ $arr = (object) $arr;
+ } else {
+ $arr = &new $object_class($arr);
+ }
+ }
+ return $arr;
+ }
+ if ($res == null && $this->autofree) {
+ $this->free();
+ }
+ return $res;
+ }
+
+ // }}}
+ // {{{ fetchInto()
+
+ /**
+ * Fetch a row of data into an array which is passed by reference
+ *
+ * The type of array returned can be controlled either by setting this
+ * method's <var>$fetchmode</var> parameter or by changing the default
+ * fetch mode setFetchMode() before calling this method.
+ *
+ * There are two options for standardizing the information returned
+ * from databases, ensuring their values are consistent when changing
+ * DBMS's. These portability options can be turned on when creating a
+ * new DB object or by using setOption().
+ *
+ * + <var>DB_PORTABILITY_LOWERCASE</var>
+ * convert names of fields to lower case
+ *
+ * + <var>DB_PORTABILITY_RTRIM</var>
+ * right trim the data
+ *
+ * @param array &$arr the variable where the data should be placed
+ * @param int $fetchmode the constant indicating how to format the data
+ * @param int $rownum the row number to fetch (index starts at 0)
+ *
+ * @return mixed DB_OK if a row is processed, NULL when the end of the
+ * result set is reached or a DB_Error object on failure
+ *
+ * @see DB_common::setOption(), DB_common::setFetchMode()
+ */
+ function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null)
+ {
+ if ($fetchmode === DB_FETCHMODE_DEFAULT) {
+ $fetchmode = $this->fetchmode;
+ }
+ if ($fetchmode === DB_FETCHMODE_OBJECT) {
+ $fetchmode = DB_FETCHMODE_ASSOC;
+ $object_class = $this->fetchmode_object_class;
+ }
+ if ($this->limit_from !== null) {
+ if ($this->row_counter === null) {
+ $this->row_counter = $this->limit_from;
+ // Skip rows
+ if ($this->dbh->features['limit'] === false) {
+ $i = 0;
+ while ($i++ < $this->limit_from) {
+ $this->dbh->fetchInto($this->result, $arr, $fetchmode);
+ }
+ }
+ }
+ if ($this->row_counter >= (
+ $this->limit_from + $this->limit_count))
+ {
+ if ($this->autofree) {
+ $this->free();
+ }
+ return null;
+ }
+ if ($this->dbh->features['limit'] === 'emulate') {
+ $rownum = $this->row_counter;
+ }
+