Import Horde_Util package from CVS HEAD
authorMichael M Slusarz <slusarz@curecanti.org>
Tue, 9 Jun 2009 21:50:41 +0000 (15:50 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Tue, 9 Jun 2009 23:20:24 +0000 (17:20 -0600)
60 files changed:
framework/Browser/lib/Horde/Browser.php
framework/Cache/lib/Horde/Cache/File.php
framework/Cache/lib/Horde/Cache/Sql.php
framework/Crypt/lib/Horde/Crypt.php
framework/Crypt/lib/Horde/Crypt/Pgp.php
framework/Crypt/lib/Horde/Crypt/Smime.php
framework/Crypt/test/Horde/Crypt/pgp.inc
framework/Crypt/test/Horde/Crypt/smime.inc
framework/Date/lib/Horde/Date/Recurrence.php
framework/Date/test/Horde/Date/RecurrenceTest.php
framework/Editor/lib/Horde/Editor/Xinha.php
framework/Kolab_Server/lib/Horde/Kolab/Server/Ldap.php
framework/Kolab_Session/lib/Horde/Kolab/IMAP/pear.php
framework/Mime/lib/Horde/Mime.php
framework/Mime/lib/Horde/Mime/Address.php
framework/Mime/lib/Horde/Mime/Headers.php
framework/Mime/lib/Horde/Mime/Magic.php
framework/Mime/lib/Horde/Mime/Mail.php
framework/Mime/lib/Horde/Mime/Mdn.php
framework/Mime/lib/Horde/Mime/Part.php
framework/Mime/lib/Horde/Mime/Viewer/Css.php
framework/Mime/lib/Horde/Mime/Viewer/Enriched.php
framework/Mime/lib/Horde/Mime/Viewer/Html.php
framework/Mime/lib/Horde/Mime/Viewer/Ooo.php
framework/Mime/lib/Horde/Mime/Viewer/Php.php
framework/Mime/lib/Horde/Mime/Viewer/Plain.php
framework/Mime/lib/Horde/Mime/Viewer/Rar.php
framework/Mime/lib/Horde/Mime/Viewer/Report.php
framework/Mime/lib/Horde/Mime/Viewer/Richtext.php
framework/Mime/lib/Horde/Mime/Viewer/Srchighlite.php
framework/Mime/lib/Horde/Mime/Viewer/Vcard.php
framework/Mime/lib/Horde/Mime/Viewer/Zip.php
framework/Rpc/lib/Horde/Rpc/Soap.php
framework/Rpc/lib/Horde/Rpc/Webdav.php
framework/Secret/lib/Horde/Secret.php
framework/Serialize/lib/Horde/Serialize.php
framework/SessionHandler/lib/Horde/SessionHandler/None.php
framework/SpellChecker/lib/Horde/SpellChecker.php
framework/SpellChecker/lib/Horde/SpellChecker/Aspell.php
framework/Text_Flowed/lib/Horde/Text/Flowed.php
framework/Token/lib/Horde/Token.php
framework/Token/lib/Horde/Token/File.php
framework/Token/lib/Horde/Token/Sql.php
framework/Util/lib/Horde/Array.php [new file with mode: 0644]
framework/Util/lib/Horde/Array/Sort/Helper.php [new file with mode: 0644]
framework/Util/lib/Horde/String.php [new file with mode: 0644]
framework/Util/lib/Horde/Util.php [new file with mode: 0644]
framework/Util/lib/Horde/Variables.php [new file with mode: 0644]
framework/Util/package.xml [new file with mode: 0644]
framework/Util/test/Horde/Util/Array_sort.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/Variables_remove.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/addParameter.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/case.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/case_php6.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/length.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/pad.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/removeParameter.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/substr.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/utf-8.phpt [new file with mode: 0644]
framework/Util/test/Horde/Util/wordwrap.phpt [new file with mode: 0644]

index bee2d1b..e36f2f5 100644 (file)
@@ -298,20 +298,20 @@ class Horde_Browser
         } else {
             $this->_agent = $userAgent;
         }
-        $this->_lowerAgent = String::lower($this->_agent);
+        $this->_lowerAgent = Horde_String::lower($this->_agent);
 
         // Set our accept string.
         if (is_null($accept)) {
             if (isset($_SERVER['HTTP_ACCEPT'])) {
-                $this->_accept = String::lower(trim($_SERVER['HTTP_ACCEPT']));
+                $this->_accept = Horde_String::lower(trim($_SERVER['HTTP_ACCEPT']));
             }
         } else {
-            $this->_accept = String::lower($accept);
+            $this->_accept = Horde_String::lower($accept);
         }
 
         // Check for UTF support.
         if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
-            $this->setFeature('utf', strpos(String::lower($_SERVER['HTTP_ACCEPT_CHARSET']), 'utf') !== false);
+            $this->setFeature('utf', strpos(Horde_String::lower($_SERVER['HTTP_ACCEPT_CHARSET']), 'utf') !== false);
         }
 
         if (empty($this->_agent)) {
@@ -1063,7 +1063,7 @@ class Horde_Browser
             return true;
         } elseif (($error == UPLOAD_ERR_INI_SIZE) ||
                   ($error == UPLOAD_ERR_FORM_SIZE)) {
-            return PEAR::raiseError(sprintf(_("There was a problem with the file upload: The %s was larger than the maximum allowed size (%d bytes)."), $name, min($uploadSize, Util::getFormData('MAX_FILE_SIZE'))), $error);
+            return PEAR::raiseError(sprintf(_("There was a problem with the file upload: The %s was larger than the maximum allowed size (%d bytes)."), $name, min($uploadSize, Horde_Util::getFormData('MAX_FILE_SIZE'))), $error);
         } elseif ($error == UPLOAD_ERR_PARTIAL) {
             return PEAR::raiseError(sprintf(_("There was a problem with the file upload: The %s was only partially uploaded."), $name), $error);
         }
@@ -1149,7 +1149,7 @@ class Horde_Browser
      */
     public function isViewable($mimetype)
     {
-        $mimetype = String::lower($mimetype);
+        $mimetype = Horde_String::lower($mimetype);
         list($type, $subtype) = explode('/', $mimetype);
 
         if (!empty($this->_accept)) {
index 5968a22..11f45da 100644 (file)
@@ -58,8 +58,7 @@ class Horde_Cache_File extends Horde_Cache_Base
         if (!empty($params['dir']) && @is_dir($params['dir'])) {
             $this->_dir = $params['dir'];
         } else {
-            require_once 'Horde/Util.php';
-            $this->_dir = Util::getTempDir();
+            $this->_dir = Horde_Util::getTempDir();
         }
 
         foreach (array('prefix', 'sub') as $val) {
@@ -153,9 +152,8 @@ class Horde_Cache_File extends Horde_Cache_Base
      */
     public function set($key, $data, $lifetime = null)
     {
-        require_once 'Horde/Util.php';
         $filename = $this->_keyToFile($key, true);
-        $tmp_file = Util::getTempFile('HordeCache', true, $this->_dir);
+        $tmp_file = Horde_Util::getTempFile('HordeCache', true, $this->_dir);
         if (isset($this->_params['umask'])) {
             chmod($tmp_file, 0666 & ~$this->_params['umask']);
         }
index 9b28c78..dab86a0 100644 (file)
@@ -353,8 +353,7 @@ class Horde_Cache_Sql extends Horde_Cache_Base
             return true;
         }
 
-        $result = Util::assertDriverConfig($this->_params, array('phptype'),
-                                           'cache SQL', array('driver' => 'cache'));
+        $result = Horde_Util::assertDriverConfig($this->_params, array('phptype'), 'cache SQL', array('driver' => 'cache'));
         if (is_a($result, 'PEAR_Error')) {
             throw new Horde_Exception($result->getMessage());
         }
index 33fa119..ee4a865 100644 (file)
@@ -136,7 +136,7 @@ class Horde_Crypt
     protected function _createTempFile($descrip = 'horde-crypt',
                                        $delete = true)
     {
-        return Util::getTempFile($descrip, $delete, $this->_tempdir, true);
+        return Horde_Util::getTempFile($descrip, $delete, $this->_tempdir, true);
     }
 
 }
index db13e3a..111b03b 100644 (file)
@@ -127,7 +127,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
      */
     protected function __construct($params = array())
     {
-        $this->_tempdir = Util::createTempDir(true, $params['temp']);
+        $this->_tempdir = Horde_Util::createTempDir(true, $params['temp']);
 
         if (empty($params['program'])) {
             Horde::fatal(new Horde_Exception('The location of the GnuPG binary must be given to the Horde_Crypt_Pgp:: class.'), __FILE__, __LINE__);
@@ -287,7 +287,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
             /* Headers are prefaced with a ':' as the first character on the
                line. */
             if (strpos($line, ':') === 0) {
-                $lowerLine = String::lower($line);
+                $lowerLine = Horde_String::lower($line);
 
                 /* If we have a key (rather than a signature block), get the
                    key's ID */
@@ -450,7 +450,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
      */
     protected function _pgpPrettyKeyFormatter(&$s, $k, $m)
     {
-        $s .= ':' . str_repeat(' ', $m - String::length($s));
+        $s .= ':' . str_repeat(' ', $m - Horde_String::length($s));
     }
 
     /**
@@ -919,7 +919,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
         if ($errno == 0) {
             throw new Horde_Exception(_("Connection refused to the public keyserver."), 'horde.error');
         } else {
-            throw new Horde_Exception(sprintf(_("Connection refused to the public keyserver. Reason: %s (%s)"), String::convertCharset($errstr, NLS::getExternalCharset()), $errno), 'horde.error');
+            throw new Horde_Exception(sprintf(_("Connection refused to the public keyserver. Reason: %s (%s)"), Horde_String::convertCharset($errstr, NLS::getExternalCharset()), $errno), 'horde.error');
         }
     }
 
@@ -1000,7 +1000,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
      */
     protected function _createKeyring($type = 'public')
     {
-        $type = String::lower($type);
+        $type = Horde_String::lower($type);
 
         if ($type === 'public') {
             if (empty($this->_publicKeyring)) {
@@ -1028,7 +1028,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
      */
     protected function _putInKeyring($keys = array(), $type = 'public')
     {
-        $type = String::lower($type);
+        $type = Horde_String::lower($type);
 
         if (!is_array($keys)) {
             $keys = array($keys);
@@ -1377,7 +1377,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
         $pgp_sign->setType('application/pgp-signature');
         $pgp_sign->setCharset($charset);
         $pgp_sign->setDisposition('inline');
-        $pgp_sign->setDescription(String::convertCharset(_("PGP Digital Signature"), NLS::getCharset(), $charset));
+        $pgp_sign->setDescription(Horde_String::convertCharset(_("PGP Digital Signature"), NLS::getCharset(), $charset));
         $pgp_sign->setContents($msg_sign);
 
         /* Get the algorithim information from the signature. Since we are
@@ -1422,7 +1422,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
         $part->setType('multipart/encrypted');
         $part->setCharset($charset);
         $part->setContentTypeParameter('protocol', 'application/pgp-encrypted');
-        $part->setDescription(String::convertCharset(_("PGP Encrypted Data"), NLS::getCharset(), $charset));
+        $part->setDescription(Horde_String::convertCharset(_("PGP Encrypted Data"), NLS::getCharset(), $charset));
         $part->setContents('This message is in MIME format and has been PGP encrypted.' . "\n");
 
         $part1 = new Horde_Mime_Part();
@@ -1466,7 +1466,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
 
         $charset = NLS::getEmailCharset();
         $part->setCharset($charset);
-        $part->setDescription(String::convertCharset(_("PGP Signed/Encrypted Data"), NLS::getCharset(), $charset));
+        $part->setDescription(Horde_String::convertCharset(_("PGP Signed/Encrypted Data"), NLS::getCharset(), $charset));
 
         return $part;
     }
@@ -1485,7 +1485,7 @@ class Horde_Crypt_Pgp extends Horde_Crypt
         $part = new Horde_Mime_Part();
         $part->setType('application/pgp-keys');
         $part->setCharset($charset);
-        $part->setDescription(String::convertCharset(_("PGP Public Key"), NLS::getCharset(), $charset));
+        $part->setDescription(Horde_String::convertCharset(_("PGP Public Key"), NLS::getCharset(), $charset));
         $part->setContents($key);
 
         return $part;
index b7e1d08..55b6deb 100644 (file)
@@ -292,7 +292,7 @@ class Horde_Crypt_Smime extends Horde_Crypt
 
         $msg = new Horde_Mime_Part();
         $msg->setCharset($charset);
-        $msg->setDescription(String::convertCharset(_("S/MIME Encrypted Message"), NLS::getCharset(), $charset));
+        $msg->setDescription(Horde_String::convertCharset(_("S/MIME Encrypted Message"), NLS::getCharset(), $charset));
         $msg->setDisposition('inline');
         $msg->setType('application/pkcs7-mime');
         $msg->setContentTypeParameter('smime-type', 'enveloped-data');
@@ -563,7 +563,7 @@ class Horde_Crypt_Smime extends Horde_Crypt
         $text .= "<strong>" . _("Public Key Info") . ":</strong>\n";
         $text .= sprintf("&nbsp;&nbsp;%s: %s\n", _("Public Key Algorithm"), $certificate['subjectPublicKeyInfo']['algorithm']);
         if ($certificate['subjectPublicKeyInfo']['algorithm'] == 'rsaEncryption') {
-            if (Util::extensionExists('bcmath')) {
+            if (Horde_Util::extensionExists('bcmath')) {
                 $modulus = $certificate['subjectPublicKeyInfo']['subjectPublicKey']['modulus'];
                 $modulus_hex = '';
                 while ($modulus != '0') {
@@ -620,7 +620,7 @@ class Horde_Crypt_Smime extends Horde_Crypt
         $text .= sprintf("&nbsp;&nbsp;%s: %d\n", _("Serial Number"), $certificate['serialNumber']);
 
         foreach ($cert_details['fingerprints'] as $hash => $fingerprint) {
-            $label = sprintf(_("%s Fingerprint"), String::upper($hash));
+            $label = sprintf(_("%s Fingerprint"), Horde_String::upper($hash));
             $fingerprint_str = '';
             for ($i = 0; $i < strlen($fingerprint); $i += 2) {
                 $fingerprint_str .= substr($fingerprint, $i, 2) . ':';
@@ -707,7 +707,7 @@ class Horde_Crypt_Smime extends Horde_Crypt
             if (($val[11] == '-') || ($val[9] == '+')) {
                 // handle time zone offset here
                 $seconds = 0;
-            } elseif (String::upper($val[11]) == 'Z') {
+            } elseif (Horde_String::upper($val[11]) == 'Z') {
                 $seconds = 0;
             } else {
                 $seconds = substr($val, 10, 2);
@@ -946,7 +946,7 @@ class Horde_Crypt_Smime extends Horde_Crypt
                     }
                 } else {
                     /* Method works for arbitrary length integers */
-                    if (Util::extensionExists('bcmath')) {
+                    if (Horde_Util::extensionExists('bcmath')) {
                         for ($i = 0; $i < strlen($integer_data); $i++) {
                             $value = bcadd(bcmul($value, 256), ord($integer_data[$i]));
                         }
@@ -1141,7 +1141,7 @@ class Horde_Crypt_Smime extends Horde_Crypt
      */
     public function checkForOpenSSL()
     {
-        if (!Util::extensionExists('openssl')) {
+        if (!Horde_Util::extensionExists('openssl')) {
             throw new Horde_Exception(_("The openssl module is required for the Horde_Crypt_Smime:: class."));
         }
     }
@@ -1177,7 +1177,7 @@ class Horde_Crypt_Smime extends Horde_Crypt
                     continue;
                 }
                 list($kind, $value) = explode(':', $name, 2);
-                if (String::lower($kind) == 'email') {
+                if (Horde_String::lower($kind) == 'email') {
                     return $value;
                 }
             }
index f294dcd..a259384 100644 (file)
@@ -15,7 +15,7 @@ $browser = &Browser::singleton();
 
 $pgp = Horde_Crypt::factory('Pgp', array(
     'program' => '/usr/bin/gpg',
-    'temp' => Util::getTempDir()
+    'temp' => Horde_Util::getTempDir()
 ));
 
 $pubkey = file_get_contents($filedir . '/fixtures/pgp_public.asc');
index 77de298..9ee6692 100644 (file)
@@ -8,4 +8,4 @@ require 'Horde/String.php';
 require 'Horde/Util.php';
 require dirname(__FILE__) . '/../../../lib/Horde/Crypt.php';
 
-$smime = Horde_Crypt::factory('Smime', array('temp' => Util::getTempDir()));
+$smime = Horde_Crypt::factory('Smime', array('temp' => Horde_Util::getTempDir()));
index 205e5c1..5d42289 100644 (file)
@@ -994,14 +994,14 @@ class Horde_Date_Recurrence
         $parts = explode(';', $rrule);
         foreach ($parts as $part) {
             list($key, $value) = explode('=', $part, 2);
-            $rdata[String::upper($key)] = $value;
+            $rdata[Horde_String::upper($key)] = $value;
         }
 
         if (isset($rdata['FREQ'])) {
             // Always default the recurInterval to 1.
             $this->setRecurInterval(isset($rdata['INTERVAL']) ? $rdata['INTERVAL'] : 1);
 
-            switch (String::upper($rdata['FREQ'])) {
+            switch (Horde_String::upper($rdata['FREQ'])) {
             case 'DAILY':
                 $this->setRecurType(self::RECUR_DAILY);
                 break;
index faa601d..5dc7839 100644 (file)
@@ -8,8 +8,7 @@ class Horde_Date_RecurrenceTest extends PHPUnit_Framework_TestCase
 {
     protected function setUp()
     {
-        require_once 'Horde/String.php';
-        String::setDefaultCharset('UTF-8');
+        Horde_String::setDefaultCharset('UTF-8');
         $this->ical = new Horde_iCalendar();
     }
 
index 5e5672b..9d08f26 100644 (file)
@@ -48,7 +48,7 @@ class Horde_Editor_xinha extends Horde_Editor
         } elseif (isset($GLOBALS['language'])) {
             $language = explode('_', $GLOBALS['language']);
             if (count($language) > 1) {
-                $country = String::lower($language[1]);
+                $country = Horde_String::lower($language[1]);
                 if ($country == $language[0]) {
                     $language = $language[0];
                 } else {
index 4faef08..1caefa0 100644 (file)
@@ -567,9 +567,8 @@ class Horde_Kolab_Server_Ldap extends Horde_Kolab_Server
         if (isset($criteria['field'])) {
             $rhs     = isset($criteria['test']) ? $criteria['test'] : '';
             /* Keep this in for reference as we did not really test servers with different encoding yet */
-            // require_once 'Horde/String.php';
             // require_once 'Horde/NLS.php';
-            //$rhs     = String::convertCharset($criteria['test'], NLS::getCharset(), $this->params['charset']);
+            //$rhs     = Horde_String::convertCharset($criteria['test'], NLS::getCharset(), $this->params['charset']);
             switch ($criteria['op']) {
             case '=':
                 $op = 'equals';
index dbb7181..17368cc 100644 (file)
@@ -216,7 +216,7 @@ class Horde_Kolab_IMAP_pear extends Horde_Kolab_IMAP
     function getMessageHeader($uid, $peek_for_body = true)
     {
         $ret = $this->_imap->cmdUidFetch($uid, 'BODY[HEADER]');
-        if (String::upper($ret['RESPONSE']['CODE']) != 'OK') {
+        if (Horde_String::upper($ret['RESPONSE']['CODE']) != 'OK') {
             return PEAR::raiseError(sprintf(_("Failed fetching headers of IMAP message %s. Error was %s"),
                                             $uid,
                                             $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']));
@@ -243,7 +243,7 @@ class Horde_Kolab_IMAP_pear extends Horde_Kolab_IMAP
     function getMessageBody($uid)
     {
         $ret = $this->_imap->cmdUidFetch($uid, 'BODY[TEXT]');
-        if (String::upper($ret['RESPONSE']['CODE']) != 'OK') {
+        if (Horde_String::upper($ret['RESPONSE']['CODE']) != 'OK') {
             return PEAR::raiseError(sprintf(_("Failed fetching body of IMAP message %s. Error was %s"),
                                             $uid,
                                             $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']));
@@ -270,7 +270,7 @@ class Horde_Kolab_IMAP_pear extends Horde_Kolab_IMAP
     function getMessage($uid)
     {
         $ret = $this->_imap->cmdUidFetch($uid, 'RFC822');
-        if (String::upper($ret['RESPONSE']['CODE']) != 'OK') {
+        if (Horde_String::upper($ret['RESPONSE']['CODE']) != 'OK') {
             return PEAR::raiseError(sprintf(_("Failed fetching IMAP message %s. Error was %s"),
                                             $uid,
                                             $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']));
@@ -419,7 +419,7 @@ class Horde_Kolab_IMAP_pear extends Horde_Kolab_IMAP
     function copyMessage($uid, $new_folder)
     {
         $ret = $this->_imap->cmdUidCopy($uid, $new_folder);
-        if (String::upper($ret['RESPONSE']['CODE']) != 'OK') {
+        if (Horde_String::upper($ret['RESPONSE']['CODE']) != 'OK') {
             return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"),
                                             $uid,
                                             $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']));
@@ -469,7 +469,7 @@ class Horde_Kolab_IMAP_pear extends Horde_Kolab_IMAP
 
         foreach ($uids as $uid) {
             $ret = $this->_imap->cmdUidStore($uid, '+FLAGS.SILENT', '\Deleted');
-            if (String::upper($ret['RESPONSE']['CODE']) != 'OK') {
+            if (Horde_String::upper($ret['RESPONSE']['CODE']) != 'OK') {
                 return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"),
                                                 $uid,
                                                 $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']));
@@ -489,7 +489,7 @@ class Horde_Kolab_IMAP_pear extends Horde_Kolab_IMAP
     function undeleteMessages($uid)
     {
         $ret = $this->_imap->cmdUidStore($uid, '-FLAGS.SILENT', '\Deleted');
-        if (String::upper($ret['RESPONSE']['CODE']) != 'OK') {
+        if (Horde_String::upper($ret['RESPONSE']['CODE']) != 'OK') {
             return PEAR::raiseError(sprintf(_("IMAP error. Message: %s. Error: %s"),
                                             $uid,
                                             $ret['RESPONSE']['CODE'] . ', ' . $ret['RESPONSE']['STR_CODE']));
index 0beb019..583cca7 100644 (file)
@@ -58,7 +58,7 @@ class Horde_Mime
             require_once 'Horde/NLS.php';
             $charset = NLS::getCharset();
         }
-        $charset = String::lower($charset);
+        $charset = Horde_String::lower($charset);
 
         if (($charset == 'us-ascii') || !self::is8bit($text, $charset)) {
             return $text;
@@ -158,7 +158,7 @@ class Horde_Mime
                  (($text[$i + 1] == "\n") || ($text[$i + 1] == "\r"))) ||
                 (($ascii < 32) || ($ascii > 126) || ($ascii === 61))) {
                 $char_len = 3;
-                $char = '=' . String::upper(sprintf('%02s', dechex($ascii)));
+                $char = '=' . Horde_String::upper(sprintf('%02s', dechex($ascii)));
             } else {
                 $char_len = 1;
             }
@@ -289,12 +289,12 @@ class Horde_Mime
         case 'Q':
         case 'q':
             $decoded = preg_replace('/=([0-9a-f]{2})/ie', 'chr(0x\1)', str_replace('_', ' ', $encoded_text));
-            $decoded = String::convertCharset($decoded, $charset, $to_charset);
+            $decoded = Horde_String::convertCharset($decoded, $charset, $to_charset);
             break;
 
         case 'B':
         case 'b':
-            $decoded = String::convertCharset(base64_decode($encoded_text), $charset, $to_charset);
+            $decoded = Horde_String::convertCharset(base64_decode($encoded_text), $charset, $to_charset);
             break;
 
         default:
@@ -356,7 +356,7 @@ class Horde_Mime
         $pre_len = strlen($name) + 2;
 
         if (self::is8bit($val, $charset)) {
-            $string = String::lower($charset) . '\'' . (empty($opts['lang']) ? '' : String::lower($opts['lang'])) . '\'' . rawurlencode($val);
+            $string = Horde_String::lower($charset) . '\'' . (empty($opts['lang']) ? '' : Horde_String::lower($opts['lang'])) . '\'' . rawurlencode($val);
             $encode = true;
             /* Account for trailing '*'. */
             ++$pre_len;
@@ -435,7 +435,7 @@ class Horde_Mime
 
         if (is_array($data)) {
             // Use dummy base values
-            $ret['val'] = (String::lower($type) == 'content-type')
+            $ret['val'] = (Horde_String::lower($type) == 'content-type')
                 ? 'text/plain'
                 : 'attachment';
             $params = $data;
@@ -495,7 +495,7 @@ class Horde_Mime
             /* Ignore language. */
             $quote = strpos($val, "'", $quote + 1);
             substr($val, $quote + 1);
-            $ret['params'][$name] = String::convertCharset(urldecode(substr($val, $quote + 1)), $orig_charset, $charset);
+            $ret['params'][$name] = Horde_String::convertCharset(urldecode(substr($val, $quote + 1)), $orig_charset, $charset);
         }
 
         /* MIME parameters are supposed to be encoded via RFC 2231, but many
index 7a31be2..af50439 100644 (file)
@@ -43,8 +43,8 @@ class Horde_Mime_Address
         $host = ltrim($host, '@');
         if ((!isset($opts['idn']) || !$opts['idn']) &&
             (stripos($host, 'xn--') === 0) &&
-            Util::extensionExists('idn')) {
-            $host = String::convertCharset(idn_to_utf8($host), 'UTF-8');
+            Horde_Util::extensionExists('idn')) {
+            $host = Horde_String::convertCharset(idn_to_utf8($host), 'UTF-8');
         }
 
         $address .= self::encode($mailbox, 'address') . '@' . $host;
@@ -238,7 +238,7 @@ class Horde_Mime_Address
         foreach ($addresses as $addr) {
             $val = self::addrObject2String($addr, $opts);
             if (!empty($val)) {
-                $addrList[String::lower(self::bareAddress($val))] = $val;
+                $addrList[Horde_String::lower(self::bareAddress($val))] = $val;
             }
         }
 
index fd0d9db..294a1c4 100644 (file)
@@ -273,10 +273,8 @@ class Horde_Mime_Headers
      */
     public function addHeader($header, $value, $options = array())
     {
-        require_once 'Horde/String.php';
-
         $header = trim($header);
-        $lcHeader = String::lower($header);
+        $lcHeader = Horde_String::lower($header);
 
         if (!isset($this->_headers[$lcHeader])) {
             $this->_headers[$lcHeader] = array();
@@ -318,8 +316,7 @@ class Horde_Mime_Headers
      */
     public function removeHeader($header)
     {
-        require_once 'Horde/String.php';
-        unset($this->_headers[String::lower(trim($header))]);
+        unset($this->_headers[Horde_String::lower(trim($header))]);
     }
 
     /**
@@ -356,9 +353,7 @@ class Horde_Mime_Headers
      */
     public function setValue($header, $value, $options = array())
     {
-        require_once 'Horde/String.php';
-
-        if (isset($this->_headers[String::lower($header)])) {
+        if (isset($this->_headers[Horde_String::lower($header)])) {
             $this->addHeader($header, $value, $decode);
             return true;
         }
@@ -376,9 +371,7 @@ class Horde_Mime_Headers
      */
     public function getString($header)
     {
-        require_once 'Horde/String.php';
-
-        $lcHeader = String::lower($header);
+        $lcHeader = Horde_String::lower($header);
         return (isset($this->_headers[$lcHeader]))
             ? $this->_headers[$lcHeader]['header']
             : null;
@@ -400,10 +393,8 @@ class Horde_Mime_Headers
      */
     public function getValue($header)
     {
-        require_once 'Horde/String.php';
-
         $entry = null;
-        $header = String::lower($header);
+        $header = Horde_String::lower($header);
 
         if (isset($this->_headers[$header])) {
             $ptr = &$this->_headers[$header];
@@ -550,8 +541,6 @@ class Horde_Mime_Headers
         $mime = self::mimeParamFields();
         $to_process = array();
 
-        require_once 'Horde/String.php';
-
         foreach (explode("\n", $text) as $val) {
             $val = rtrim($val);
             if (empty($val)) {
@@ -562,7 +551,7 @@ class Horde_Mime_Headers
                 $currtext .= ' ' . ltrim($val);
             } else {
                 if (!is_null($currheader)) {
-                    if (in_array(String::lower($currheader), $mime)) {
+                    if (in_array(Horde_String::lower($currheader), $mime)) {
                         $res = Horde_Mime::decodeParam($currheader, $currtext);
                         $to_process[] = array($currheader, $res['val'], array('decode' => true, 'params' => $res['params']));
                     } else {
@@ -582,7 +571,7 @@ class Horde_Mime_Headers
         reset($to_process);
         while (list(,$val) = each($to_process)) {
             if ($eightbit_check && Horde_Mime::is8bit($val[1])) {
-                $val[1] = String::convertCharset($val[1], self::$defaultCharset);
+                $val[1] = Horde_String::convertCharset($val[1], self::$defaultCharset);
             }
             $headers->addHeader($val[0], $val[1], $val[2]);
         }
index 4802cc2..80ff10a 100644 (file)
@@ -1,7 +1,4 @@
 <?php
-
-require_once 'Horde/Util.php';
-
 /**
  * The Horde_Mime_Magic:: class provides an interface to determine a MIME type
  * for various content, if it provided with different levels of information.
@@ -64,7 +61,7 @@ class Horde_Mime_Magic
            return 'application/octet-stream';
         }
 
-        $ext = String::lower($ext);
+        $ext = Horde_String::lower($ext);
         $map = self::_getMimeExtensionMap();
         $pos = 0;
 
@@ -155,7 +152,7 @@ class Horde_Mime_Magic
     static public function analyzeFile($path, $magic_db = null)
     {
         /* If the PHP Mimetype extension is available, use that. */
-        if (Util::extensionExists('fileinfo')) {
+        if (Horde_Util::extensionExists('fileinfo')) {
             $res = empty($magic_db)
                 ? @finfo_open(FILEINFO_MIME)
                 : @finfo_open(FILEINFO_MIME, $magic_db);
@@ -177,7 +174,7 @@ class Horde_Mime_Magic
             }
         }
 
-        if (Util::extensionExists('mime_magic')) {
+        if (Horde_Util::extensionExists('mime_magic')) {
             return trim(mime_content_type($path));
         }
 
@@ -197,7 +194,7 @@ class Horde_Mime_Magic
     static public function analyzeData($data, $magic_db = null)
     {
         /* If the PHP Mimetype extension is available, use that. */
-        if (Util::extensionExists('fileinfo')) {
+        if (Horde_Util::extensionExists('fileinfo')) {
             $res = empty($magic_db)
                 ? @finfo_open(FILEINFO_MIME)
                 : @finfo_open(FILEINFO_MIME, $magic_db);
index 129dda9..4bae1dc 100644 (file)
@@ -1,7 +1,4 @@
 <?php
-
-require_once 'Horde/String.php';
-
 /**
  * The Horde_Mime_Mail:: class wraps around the various MIME library classes
  * to provide a simple interface for creating and sending MIME messages.
@@ -141,7 +138,7 @@ class Horde_Mime_Mail
     public function addHeader($header, $value, $charset = 'iso-8859-1',
                               $overwrite = null)
     {
-        $lc_header = String::lower($header);
+        $lc_header = Horde_String::lower($header);
 
         /* Only encode value if charset is explicitly specified, otherwise
          * the message's charset will be used when building the message. */
@@ -181,7 +178,7 @@ class Horde_Mime_Mail
     {
         $value = $this->_headers->getValue($header);
         $this->_headers->removeHeader($header);
-        if (in_array(String::lower($header), array('to', 'cc', 'bcc'))) {
+        if (in_array(Horde_String::lower($header), array('to', 'cc', 'bcc'))) {
             try {
                 $this->removeRecipients($value);
             } catch (Horde_Mime_Exception $e) {}
@@ -201,7 +198,7 @@ class Horde_Mime_Mail
     public function setBody($body, $charset = 'iso-8859-1', $wrap = false)
     {
         if ($wrap) {
-            $body = String::wrap($body, $wrap === true ? 76 : $wrap, "\n");
+            $body = Horde_String::wrap($body, $wrap === true ? 76 : $wrap, "\n");
         }
         $this->_body = new Horde_Mime_Part();
         $this->_body->setType('text/plain');
index fe8abc8..77f8989 100644 (file)
@@ -94,7 +94,7 @@ class Horde_Mime_Mdn
         }
 
         return ($addr_arr[0]['mailbox'] == $ret_arr[0]['mailbox']) &&
-               (String::lower($addr_arr[0]['host']) == String::lower($ret_arr[0]['host']));
+               (Horde_String::lower($addr_arr[0]['host']) == Horde_String::lower($ret_arr[0]['host']));
     }
 
     /**
index 707cdac..d7d4023 100644 (file)
@@ -1,7 +1,4 @@
 <?php
-
-require_once 'Horde/String.php';
-
 /**
  * The Horde_Mime_Part:: class provides a wrapper around MIME parts and
  * methods for dealing with them.
@@ -187,7 +184,7 @@ class Horde_Mime_Part
      */
     public function setDisposition($disposition)
     {
-        $disposition = String::lower($disposition);
+        $disposition = Horde_String::lower($disposition);
 
         if (in_array($disposition, array('inline', 'attachment'))) {
             $this->_disposition = $disposition;
@@ -381,7 +378,7 @@ class Horde_Mime_Part
             return;
         }
 
-        list($this->_type, $this->_subtype) = explode('/', String::lower($mimetype));
+        list($this->_type, $this->_subtype) = explode('/', Horde_String::lower($mimetype));
 
         /* Known types. */
         $known = array(
@@ -535,7 +532,7 @@ class Horde_Mime_Part
     public function setTransferEncoding($encoding)
     {
         $known = array('7bit', '8bit', 'binary', 'base64', 'quoted-printable');
-        $encoding = String::lower($encoding);
+        $encoding = Horde_String::lower($encoding);
 
         if (in_array($encoding, $known)) {
             $this->_transferEncoding = $encoding;
@@ -963,7 +960,7 @@ class Horde_Mime_Part
         /* Quoted-Printable Encoding: See RFC 2045, section 6.7 */
         case 'quoted-printable':
             $output = Horde_Mime::quotedPrintableEncode($this->_contents, $eol);
-            if (($eollength = String::length($eol)) &&
+            if (($eollength = Horde_String::length($eol)) &&
                 (substr($output, $eollength * -1) == $eol)) {
                 return substr($output, 0, $eollength * -1);
             }
@@ -1062,7 +1059,7 @@ class Horde_Mime_Part
             }
         } else {
             $bytes = ($this->getPrimaryType() == 'text')
-                ? String::length($this->_contents, $this->getCharset())
+                ? Horde_String::length($this->_contents, $this->getCharset())
                 : strlen($this->_contents);
         }
 
@@ -1443,7 +1440,7 @@ class Horde_Mime_Part
         /* Set the default character set. */
         if (($data['subtype'] == 'text') &&
             (self::$defaultCharset != 'us-ascii') &&
-            (String::lower($ob->getCharset()) == 'us-ascii')) {
+            (Horde_String::lower($ob->getCharset()) == 'us-ascii')) {
             $ob->setCharset(self::$defaultCharset);
         }
 
index 782a429..3c487b9 100644 (file)
@@ -73,9 +73,9 @@ class Horde_Mime_Viewer_Css extends Horde_Mime_Viewer_Source
 
         // Need Horde headers for CSS tags.
         reset($ret);
-        $ret[key($ret)]['data'] =  Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') .
+        $ret[key($ret)]['data'] = Horde_Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') .
             $ret[key($ret)]['data'] .
-            Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc');
+            Horde_Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc');
 
         return $ret;
     }
index aadc370..e8c55f7 100644 (file)
@@ -63,7 +63,7 @@ class Horde_Mime_Viewer_Enriched extends Horde_Mime_Viewer_Driver
     {
         return array(
             $this->_mimepart->getMimeId() => array(
-                'data' => String::convertCharset($this->_toHTML(), $this->_mimepart->getCharset()),
+                'data' => Horde_String::convertCharset($this->_toHTML(), $this->_mimepart->getCharset()),
                 'status' => array(),
                 'type' => 'text/html; charset=' . NLS::getCharset()
             )
index dc7e4b0..5d4111c 100644 (file)
@@ -57,7 +57,7 @@ class Horde_Mime_Viewer_html extends Horde_Mime_Viewer_Driver
 
         return array(
             $this->_mimepart->getMimeId() => array(
-                'data' => String::convertCharset($html['data'], $this->_mimepart->getCharset()),
+                'data' => Horde_String::convertCharset($html['data'], $this->_mimepart->getCharset()),
                 'status' => $html['status'],
                 'type' => 'text/html; charset=' . NLS::getCharset()
             )
@@ -169,7 +169,7 @@ class Horde_Mime_Viewer_html extends Horde_Mime_Viewer_Driver
             if (!$inline) {
                 $temp = array();
                 foreach ($phish_warning as $val) {
-                    $temp[] = String::convertCharset($val, NLS::getCharset(), $this->_mimepart->getCharset());
+                    $temp[] = Horde_String::convertCharset($val, NLS::getCharset(), $this->_mimepart->getCharset());
                 }
                 $warning = $temp;
             }
index bd14885..4d4cdaf 100644 (file)
@@ -34,10 +34,10 @@ class Horde_Mime_Viewer_Ooo extends Horde_Mime_Viewer_Driver
      */
     protected function _render()
     {
-        $has_xslt = Util::extensionExists('xslt');
+        $has_xslt = Horde_Util::extensionExists('xslt');
         $has_ssfile = function_exists('domxml_xslt_stylesheet_file');
         if (($use_xslt = $has_xslt || $has_ssfile)) {
-            $tmpdir = Util::createTempDir(true);
+            $tmpdir = Horde_Util::createTempDir(true);
         }
 
         $fnames = array('content.xml', 'styles.xml', 'meta.xml');
@@ -74,7 +74,7 @@ class Horde_Mime_Viewer_Ooo extends Horde_Mime_Viewer_Driver
             }
         }
 
-        if (!Util::extensionExists('xslt')) {
+        if (!Horde_Util::extensionExists('xslt')) {
             return array();
         }
 
index 987f8ab..d807e8f 100644 (file)
@@ -37,9 +37,9 @@ class Horde_Mime_Viewer_Php extends Horde_Mime_Viewer_Source
 
         // Need Horde headers for CSS tags.
         reset($ret);
-        $ret[key($ret)]['data'] =  Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') .
+        $ret[key($ret)]['data'] =  Horde_Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') .
             $ret[key($ret)]['data'] .
-            Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc');
+            Horde_Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc');
 
         return $ret;
     }
index 57ae876..cb1e70c 100644 (file)
@@ -59,7 +59,7 @@ class Horde_Mime_Viewer_Plain extends Horde_Mime_Viewer_Driver
      */
     protected function _renderInline()
     {
-        $text = String::convertCharset($this->_mimepart->getContents(), $this->_mimepart->getCharset());
+        $text = Horde_String::convertCharset($this->_mimepart->getContents(), $this->_mimepart->getCharset());
 
         /* Check for 'flowed' text data. */
         $data = ($this->_mimepart->getContentTypeParameter('format') == 'flowed')
index 261c725..7408d6a 100644 (file)
@@ -73,12 +73,12 @@ class Horde_Mime_Viewer_Rar extends Horde_Mime_Viewer_Driver
             Text::htmlAllSpaces(sprintf(ngettext("File Count: %d file", "File Count: %d files", $fileCount), $fileCount)) .
             "\n\n" .
             Text::htmlAllSpaces(
-                String::pad(_("File Name"), 50, ' ', STR_PAD_RIGHT) .
-                String::pad(_("Attributes"), 10, ' ', STR_PAD_LEFT) .
-                String::pad(_("Size"), 10, ' ', STR_PAD_LEFT) .
-                String::pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) .
-                String::pad(_("Method"), 10, ' ', STR_PAD_LEFT) .
-                String::pad(_("Ratio"), 10, ' ', STR_PAD_LEFT)
+                Horde_String::pad(_("File Name"), 50, ' ', STR_PAD_RIGHT) .
+                Horde_String::pad(_("Attributes"), 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("Size"), 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("Method"), 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("Ratio"), 10, ' ', STR_PAD_LEFT)
             ) . "\n" .
             str_repeat('-', 109) . "\n";
 
@@ -88,12 +88,12 @@ class Horde_Mime_Viewer_Rar extends Horde_Mime_Viewer_Driver
                 : 100 * ($val['csize'] / $val['size']);
 
             $text .= Text::htmlAllSpaces(
-                String::pad($val['name'], 50, ' ', STR_PAD_RIGHT) .
-                String::pad($val['attr'], 10, ' ', STR_PAD_LEFT) .
-                String::pad($val['size'], 10, ' ', STR_PAD_LEFT) .
-                String::pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT) .
-                String::pad($val['method'], 10, ' ', STR_PAD_LEFT) .
-                String::pad(sprintf("%1.1f%%", $ratio), 10, ' ', STR_PAD_LEFT)
+                Horde_String::pad($val['name'], 50, ' ', STR_PAD_RIGHT) .
+                Horde_String::pad($val['attr'], 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad($val['size'], 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT) .
+                Horde_String::pad($val['method'], 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(sprintf("%1.1f%%", $ratio), 10, ' ', STR_PAD_LEFT)
             ) . "\n";
         }
 
index 2b02001..3ec86ce 100644 (file)
@@ -24,7 +24,7 @@ class Horde_Mime_Viewer_Report extends Horde_Mime_Viewer_Driver
             return false;
         }
 
-        $viewer = Horde_Mime_Viewer::factory($this->_mimepart, 'message/' . String::lower($type));
+        $viewer = Horde_Mime_Viewer::factory($this->_mimepart, 'message/' . Horde_String::lower($type));
         if ($viewer) {
             $viewer->setParams($this->_params);
         }
index 4aae86b..7f05964 100644 (file)
@@ -72,7 +72,7 @@ class Horde_Mime_Viewer_Richtext extends Horde_Mime_Viewer_Driver
     {
         return array(
             $this->_mimepart->getMimeId() => array(
-                'data' => String::convertCharset($this->_toHTML(), $this->_mimepart->getCharset()),
+                'data' => Horde_String::convertCharset($this->_toHTML(), $this->_mimepart->getCharset()),
                 'status' => array(),
                 'type' => 'text/html; charset=' . NLS::getCharset()
             )
index af4e77e..6250bc2 100644 (file)
@@ -39,9 +39,9 @@ class Horde_Mime_Viewer_Srchighlite extends Horde_Mime_Viewer_Source
 
         // Need Horde headers for CSS tags.
         reset($ret);
-        $ret[key($ret)]['data'] =  Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') .
+        $ret[key($ret)]['data'] =  Horde_Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') .
             $ret[key($ret)]['data'] .
-            Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc');
+            Horde_Util::bufferOutput('require', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc');
 
         return $ret;
     }
index 70fe970..dbeeb83 100644 (file)
@@ -35,9 +35,9 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
         $ret = $this->_renderInline();
         if (!empty($ret)) {
             reset($ret);
-            $ret[key($ret)]['data'] = Util::bufferOutput('include', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') .
+            $ret[key($ret)]['data'] = Horde_Util::bufferOutput('include', $GLOBALS['registry']->get('templates', 'horde') . '/common-header.inc') .
                 $ret[key($ret)]['data'] .
-                Util::bufferOutput('include', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc');
+                Horde_Util::bufferOutput('include', $GLOBALS['registry']->get('templates', 'horde') . '/common-footer.inc');
         }
         return $ret;
     }
@@ -62,10 +62,10 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
             $notification->push(_("There was an error reading the contact data."), 'horde.error');
         }
 
-        if (Util::getFormData('import') &&
-            Util::getFormData('source') &&
+        if (Horde_Util::getFormData('import') &&
+            Horde_Util::getFormData('source') &&
             $registry->hasMethod('contacts/import')) {
-            $source = Util::getFormData('source');
+            $source = Horde_Util::getFormData('source');
             $count = 0;
             foreach ($iCal->getComponents() as $c) {
                 if (is_a($c, 'Horde_iCalendar_vcard')) {
@@ -125,12 +125,12 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
             $photos = $vc->getAllAttributes('PHOTO');
             foreach ($photos as $photo) {
                 if (isset($photo['params']['VALUE']) &&
-                    String::upper($photo['params']['VALUE']) == 'URI') {
+                    Horde_String::upper($photo['params']['VALUE']) == 'URI') {
                     $html .= $this->_row(_("Photo"),
                                          '<img src="' . htmlspecialchars($photo['value']) . '" />',
                                          false);
                 } elseif (isset($photo['params']['ENCODING']) &&
-                          String::upper($photo['params']['ENCODING']) == 'B' &&
+                          Horde_String::upper($photo['params']['ENCODING']) == 'B' &&
                           isset($photo['params']['TYPE']) &&
                           ($GLOBALS['browser']->hasFeature('datauri') === true ||
                            $GLOBALS['browser']->hasFeature('datauri') >= strlen($photo['value']))) {
@@ -151,7 +151,7 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
                 }
                 $types = array();
                 foreach ($label['params']['TYPE'] as $type) {
-                    switch(String::upper($type)) {
+                    switch(Horde_String::upper($type)) {
                     case 'HOME':
                         $types[] = _("Home Address");
                         break;
@@ -215,7 +215,7 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
                 }
                 $types = array();
                 foreach ($item['params']['TYPE'] as $type) {
-                    switch(String::upper($type)) {
+                    switch(Horde_String::upper($type)) {
                     case 'HOME':
                         $types[] = _("Home Address");
                         break;
@@ -259,7 +259,7 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
                         $number['params']['TYPE'] = array($number['params']['TYPE']);
                     }
                     foreach ($number['params']['TYPE'] as $type) {
-                        $number['params'][String::upper($type)] = true;
+                        $number['params'][Horde_String::upper($type)] = true;
                     }
                 }
                 if (isset($number['params']['FAX'])) {
@@ -289,7 +289,7 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
                         $address['params']['TYPE'] = array($address['params']['TYPE']);
                     }
                     foreach ($address['params']['TYPE'] as $type) {
-                        $address['params'][String::upper($type)] = true;
+                        $address['params'][Horde_String::upper($type)] = true;
                     }
                 }
                 $email = '<a href="';
@@ -350,7 +350,7 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
             $registry->hasMethod('contacts/sources')) {
             $html .= '<tr><td colspan="2" class="smallheader"><form action="'
                 . Horde::selfUrl() . '" method="get" name="vcard_import">'
-                . Util::formInput();
+                . Horde_Util::formInput();
             foreach ($_GET as $key => $val) {
                 $html .= '<input type="hidden" name="' . htmlspecialchars($key)
                     . '" value="' . htmlspecialchars($val) . '" />';
@@ -387,7 +387,7 @@ class Horde_Mime_Viewer_Vcard extends Horde_Mime_Viewer_Driver
 
         return array(
             $this->_mimepart->getMimeId() => array(
-                'data' => Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status')) . $html,
+                'data' => Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status')) . $html,
                 'status' => array(),
                 'type' => 'text/html; charset=' . NLS::getCharset()
             )
index 3dac1c8..2ddfef5 100644 (file)
@@ -103,13 +103,13 @@ class Horde_Mime_Viewer_Zip extends Horde_Mime_Viewer_Driver
                 ' bytes' . "\n" .
                 sprintf(ngettext("File Count: %d file", "File Count: %d files", $fileCount), $fileCount) .
                 "\n\n" .
-                String::pad(_("File Name"), $maxlen, ' ', STR_PAD_RIGHT) .
-                String::pad(_("Attributes"), 10, ' ', STR_PAD_LEFT) .
-                String::pad(_("Size"), 10, ' ', STR_PAD_LEFT) .
-                String::pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) .
-                String::pad(_("Method"), 10, ' ', STR_PAD_LEFT) .
-                String::pad(_("CRC"), 10, ' ', STR_PAD_LEFT) .
-                String::pad(_("Ratio"), 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("File Name"), $maxlen, ' ', STR_PAD_RIGHT) .
+                Horde_String::pad(_("Attributes"), 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("Size"), 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("Modified Date"), 19, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("Method"), 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("CRC"), 10, ' ', STR_PAD_LEFT) .
+                Horde_String::pad(_("Ratio"), 10, ' ', STR_PAD_LEFT) .
                 "\n"
             ) . str_repeat('-', 69 + $maxlen) . "\n";
 
@@ -118,13 +118,13 @@ class Horde_Mime_Viewer_Zip extends Horde_Mime_Viewer_Driver
                 ? 0
                 : 100 * ($val['csize'] / $val['size']);
 
-            $val['name']   = String::pad($val['name'], $maxlen, ' ', STR_PAD_RIGHT);
-            $val['attr']   = String::pad($val['attr'], 10,' ', STR_PAD_LEFT);
-            $val['size']   = String::pad($val['size'], 10, ' ', STR_PAD_LEFT);
-            $val['date']   = String::pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT);
-            $val['method'] = String::pad($val['method'], 10, ' ', STR_PAD_LEFT);
-            $val['crc']    = String::pad($val['crc'], 10, ' ', STR_PAD_LEFT);
-            $val['ratio']  = String::pad(sprintf("%1.1f%%", $ratio), 10, ' ', STR_PAD_LEFT);
+            $val['name']   = Horde_String::pad($val['name'], $maxlen, ' ', STR_PAD_RIGHT);
+            $val['attr']   = Horde_String::pad($val['attr'], 10,' ', STR_PAD_LEFT);
+            $val['size']   = Horde_String::pad($val['size'], 10, ' ', STR_PAD_LEFT);
+            $val['date']   = Horde_String::pad(strftime("%d-%b-%Y %H:%M", $val['date']), 19, ' ', STR_PAD_LEFT);
+            $val['method'] = Horde_String::pad($val['method'], 10, ' ', STR_PAD_LEFT);
+            $val['crc']    = Horde_String::pad($val['crc'], 10, ' ', STR_PAD_LEFT);
+            $val['ratio']  = Horde_String::pad(sprintf("%1.1f%%", $ratio), 10, ' ', STR_PAD_LEFT);
 
             $val = array_map(array('Text', 'htmlAllSpaces'), $val);
             if (!is_null($this->_callback)) {
index c937936..8f53ebd 100644 (file)
@@ -87,7 +87,7 @@ class Horde_RPC_PhpSoap extends Horde_RPC {
             return $handler->getResponse($request);
         }
 
-        /* We can't use Util::bufferOutput() here for some reason. */
+        /* We can't use Horde_Util::bufferOutput() here for some reason. */
         $beginTime = time();
         ob_start();
         $this->_server->handle($request);
index f246b10..ea1d762 100644 (file)
@@ -623,10 +623,10 @@ Horde::logMessage(print_r($list, true), __FILE__, __LINE__, PEAR_LOG_ERR);
             }
             $properties[$prop['xmlns']][$prop['name']] = $prop['name'];
         }
-        
+
         // Handle certain standard properties specially
         if (in_array('displayname', $properties['DAV:'])) {
-            $props[] = $this->mkprop('displayname', String::convertCharset($item['name'], NLS::getCharset(), 'UTF-8'));
+            $props[] = $this->mkprop('displayname', Horde_String::convertCharset($item['name'], NLS::getCharset(), 'UTF-8'));
             unset($properties['DAV:']['displayname']);
         }
         if (in_array('getlastmodified', $properties['DAV:'])) {
index 1a35fcd..a2a8159 100644 (file)
@@ -79,8 +79,7 @@ class Horde_Secret
     {
         $ret = false;
 
-        require_once 'Horde/Util.php';
-        if (Util::extensionExists('mcrypt')) {
+        if (Horde_Util::extensionExists('mcrypt')) {
             $old_error = error_reporting(0);
             $td = mcrypt_module_open(MCRYPT_GOST, '', MCRYPT_MODE_ECB, '');
             if ($td) {
index 38454cf..e4dad11 100644 (file)
@@ -121,10 +121,10 @@ class Horde_Serialize
     {
         switch ($mode) {
         case self::BZIP:
-            return Util::extensionExists('bz2');
+            return Horde_Util::extensionExists('bz2');
 
         case self::WDDX:
-            return Util::extensionExists('wddx');
+            return Horde_Util::extensionExists('wddx');
 
         case self::IMAPUTF7:
             return class_exists('Horde_Imap_Client');
@@ -136,13 +136,13 @@ class Horde_Serialize
         case self::GZ_DEFLATE:
         case self::GZ_COMPRESS:
         case self::GZ_ENCODE:
-            return Util::extensionExists('zlib');
+            return Horde_Util::extensionExists('zlib');
 
         case self::SQLXML:
             return @include_once 'XML/sql2xml.php';
 
         case self::LZF:
-            return Util::extensionExists('lzf');
+            return Horde_Util::extensionExists('lzf');
 
         case self::NONE:
         case self::BASIC:
@@ -198,8 +198,7 @@ class Horde_Serialize
             break;
 
         case self::IMAPUTF7:
-            require_once 'Horde/String.php';
-            $data = Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap(String::convertCharset($data, 'ISO-8859-1', 'UTF-8'));
+            $data = Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap(Horde_String::convertCharset($data, 'ISO-8859-1', 'UTF-8'));
             break;
 
         case self::IMAPUTF8:
@@ -245,8 +244,7 @@ class Horde_Serialize
 
         // $params = Source character set
         case self::UTF7:
-            require_once 'Horde/String.php';
-            $data = String::convertCharset($data, $params, 'UTF-7');
+            $data = Horde_String::convertCharset($data, $params, 'UTF-7');
             break;
 
         // $params = Source character set
@@ -256,9 +254,8 @@ class Horde_Serialize
 
         // $params = Source character set
         case self::JSON:
-            require_once 'Horde/String.php';
             if (!empty($params)) {
-                $data = String::convertCharset($data, $params, 'UTF-8');
+                $data = Horde_String::convertCharset($data, $params, 'UTF-8');
             }
             $data = json_encode($data);
             break;
@@ -315,8 +312,7 @@ class Horde_Serialize
             break;
 
         case self::IMAPUTF7:
-            require_once 'Horde/String.php';
-            $data = String::convertCharset(Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($data), 'UTF-8', 'ISO-8859-1');
+            $data = Horde_String::convertCharset(Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($data), 'UTF-8', 'ISO-8859-1');
             break;
 
         case self::IMAPUTF8:
@@ -347,8 +343,7 @@ class Horde_Serialize
 
         // $params = Output character set
         case self::UTF7:
-            require_once 'Horde/String.php';
-            $data = String::convertCharset($data, 'utf-7', $params);
+            $data = Horde_String::convertCharset($data, 'utf-7', $params);
             break;
 
         // $params = Output character set
index e886f75..52c12bb 100644 (file)
@@ -47,7 +47,7 @@ class Horde_SessionHandler_None extends Horde_SessionHandler
         $sessions = array();
 
         $path = session_save_path();
-        $d = @dir(empty($path) ? Util::getTempDir() : $path);
+        $d = @dir(empty($path) ? Horde_Util::getTempDir() : $path);
         if (!$d) {
             return $sessions;
         }
index a7203fb..4e8b903 100644 (file)
@@ -1,7 +1,4 @@
 <?php
-
-require_once 'Horde/String.php';
-
 /**
  * The Horde_SpellChecker:: class provides a unified spellchecker API.
  *
@@ -70,7 +67,7 @@ abstract class Horde_SpellChecker
      */
     static public function getInstance($driver, $params = array())
     {
-        $class = 'Horde_SpellChecker_' . String::ucfirst(basename($driver));
+        $class = 'Horde_SpellChecker_' . Horde_String::ucfirst(basename($driver));
         if (!class_exists($class)) {
             throw new Exception('Driver ' . $driver . ' not found');
         }
@@ -131,7 +128,7 @@ abstract class Horde_SpellChecker
     {
         return (empty($this->_localDict))
             ? false
-            : in_array(String::lower($word, true), $this->_localDict);
+            : in_array(Horde_String::lower($word, true), $this->_localDict);
     }
 
 }
index 7a0bf6b..4597452 100644 (file)
@@ -51,7 +51,7 @@ class Horde_SpellChecker_Aspell extends Horde_SpellChecker
 
         // Write to stdin.
         if ($this->_encoding) {
-            $input = String::convertCharset($input, $charset, $this->_encoding);
+            $input = Horde_String::convertCharset($input, $charset, $this->_encoding);
         }
 
         // The '^' character tells aspell to spell check the entire line.
@@ -78,13 +78,13 @@ class Horde_SpellChecker_Aspell extends Horde_SpellChecker
 
         if (strlen($out) === 0) {
             if ($this->_encoding) {
-                $err = String::convertCharset($err, $this->_encoding, $charset);
+                $err = Horde_String::convertCharset($err, $this->_encoding, $charset);
             }
             throw Exception('Spellcheck failed. Command line: ', $this->_cmd());
         }
 
         if ($this->_encoding) {
-            $out = String::convertCharset($out, $this->_encoding, $charset);
+            $out = Horde_String::convertCharset($out, $this->_encoding, $charset);
         }
 
         // Parse output.
index 21ebd32..186663d 100644 (file)
@@ -260,7 +260,7 @@ class Horde_Text_Flowed
             if (empty($line)) {
                 /* Line is empty. */
                 $this->_output[] = array('text' => $quotestr, 'level' => $num_quotes);
-            } elseif (empty($this->_maxlength) || ((String::length($line, $this->_charset) + $num_quotes) <= $this->_maxlength)) {
+            } elseif (empty($this->_maxlength) || ((Horde_String::length($line, $this->_charset) + $num_quotes) <= $this->_maxlength)) {
                 /* Line does not require rewrapping. */
                 $this->_output[] = array('text' => $quotestr . $this->_stuff($line, $num_quotes, $toflowed), 'level' => $num_quotes);
             } else {
@@ -270,12 +270,12 @@ class Horde_Text_Flowed
                 while ($line) {
                     /* Stuff and re-quote the line. */
                     $line = $quotestr . $this->_stuff($line, $num_quotes, $toflowed);
-                    $line_length = String::length($line, $this->_charset);
+                    $line_length = Horde_String::length($line, $this->_charset);
                     if ($line_length <= $this->_optlength) {
                         /* Remaining section of line is short enough. */
                         $this->_output[] = array('text' => $line, 'level' => $num_quotes);
                         break;
-                    } elseif ($m = String::regexMatch($line, array('^(.{' . $min . ',' . $opt . '}) (.*)', '^(.{' . $min . ',' . $this->_maxlength . '}) (.*)', '^(.{' . $min . ',})? (.*)'), $this->_charset)) {
+                    } elseif ($m = Horde_String::regexMatch($line, array('^(.{' . $min . ',' . $opt . '}) (.*)', '^(.{' . $min . ',' . $this->_maxlength . '}) (.*)', '^(.{' . $min . ',})? (.*)'), $this->_charset)) {
                         /* We need to wrap text at a certain number of
                          * *characters*, not a certain number of *bytes*;
                          * thus the need for a multibyte capable regex.
@@ -299,8 +299,8 @@ class Horde_Text_Flowed
                          * absolutely sure it does not exceed 998 characters
                          * in length or else we must truncate. */
                         if ($line_length > 998) {
-                            $this->_output[] = array('text' => String::substr($line, 0, 998, $this->_charset), 'level' => $num_quotes);
-                            $line = String::substr($line, 998, null, $this->_charset);
+                            $this->_output[] = array('text' => Horde_String::substr($line, 0, 998, $this->_charset), 'level' => $num_quotes);
+                            $line = Horde_String::substr($line, 998, null, $this->_charset);
                         } else {
                             $this->_output[] = array('text' => $line, 'level' => $num_quotes);
                             break;
index f12df07..cb87a10 100644 (file)
@@ -125,8 +125,7 @@ class Horde_Token
      */
     public function generateId($seed = '')
     {
-        require_once 'Horde/Util.php';
-        return Util::uriB64Encode(pack('H*', sha1(uniqid(mt_rand(), true) . $seed . (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''))));
+        return Horde_Util::uriB64Encode(pack('H*', sha1(uniqid(mt_rand(), true) . $seed . (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''))));
     }
 
     /**
index dfd2cde..6e75967 100644 (file)
@@ -42,7 +42,7 @@ class Horde_Token_File extends Horde_Token
 
         /* Choose the directory to save the stub files. */
         if (!isset($this->_params['token_dir'])) {
-            $this->_params['token_dir'] = Util::getTempDir();
+            $this->_params['token_dir'] = Horde_Util::getTempDir();
         }
 
         /* Set timeout to 24 hours if not specified. */
index 464292d..724d0ae 100644 (file)
@@ -174,8 +174,7 @@ class Horde_Token_Sql extends Horde_Token
             return true;
         }
 
-        $result = Util::assertDriverConfig($this->_params, array('phptype'),
-                                           'token SQL', array('driver' => 'token'));
+        $result = Horde_Util::assertDriverConfig($this->_params, array('phptype'), 'token SQL', array('driver' => 'token'));
         if (is_a($result, 'PEAR_Error')) {
             return $result;
         }
diff --git a/framework/Util/lib/Horde/Array.php b/framework/Util/lib/Horde/Array.php
new file mode 100644 (file)
index 0000000..bdef99f
--- /dev/null
@@ -0,0 +1,230 @@
+<?php
+/**
+ * The Horde_Array:: class provides various methods for array manipulation.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @author  Marko Djukic <marko@oblo.com>
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Util
+ */
+class Horde_Array
+{
+    /**
+     * Prepare a list of addresses for storage.
+     * Namely, trims and lowercases all addresses and then sort.
+     *
+     * @param array $addr  The list of addresses.
+     *
+     * @return array  The list of addresses, prepared for storage.
+     */
+    static public function prepareAddressList($addr)
+    {
+        /* Remove any extra space in the address and make it lowercase. */
+        $addr = array_map(array('String', 'lower'), array_map('trim', $addr));
+
+        /* Remove duplicate entries. */
+        $addr = array_keys(array_flip($addr));
+
+        /* Sort the list. */
+        usort($addr, array('Horde_Array', 'sortAddressList'));
+
+        return $addr;
+    }
+
+    /**
+     * Function used by usort() to sort an address list.
+     *   e.g. usort($foo, array('Horde_Array', 'sortAddressList'));
+     *
+     * @param string $a  Address #1.
+     * @param string $b  Address #2.
+     *
+     * @return integer  -1, 0, or 1.
+     */
+    static public function sortAddressList($a, $b)
+    {
+        $a = explode('@', $a);
+        $b = explode('@', $b);
+
+        /* One of the addresses doesn't have a host name. */
+        if (empty($a[0])) {
+            array_shift($a);
+        }
+        if (empty($b[0])) {
+            array_shift($b);
+        }
+        if (count($a) != count($b)) {
+            return (count($a) > count($b));
+        }
+
+        /* The addresses have different hostname or not hostname and
+         * different mailbox names. */
+        if ($a[(count($a) - 1)] != $b[(count($b) - 1)]) {
+            return strcmp($a[(count($a) - 1)], $b[(count($b) - 1)]);
+        }
+
+        /* Compare mailbox names. */
+        return strcmp($a[0], $b[0]);
+    }
+
+    /**
+     * Sorts an array on a specified key. If the key does not exist,
+     * defaults to the first key of the array.
+     *
+     * @param array &$array   The array to be sorted, passed by reference.
+     * @param string $key     The key by which to sort. If not specified then
+     *                        the first key is used.
+     * @param integer $dir    Sort direction:
+     *                          0 = ascending (default)
+     *                          1 = descending
+     * @param boolean $assoc  Keep key value association?
+     */
+    static public function arraySort(&$array, $key = null, $dir = 0,
+                                     $assoc = true)
+    {
+        /* Return if the array is empty. */
+        if (empty($array)) {
+            return;
+        }
+
+        /* If no key to sort by is specified, use the first key of the
+         * first element. */
+        if (is_null($key)) {
+            reset($array);
+            $key = array_shift(array_keys(current($array)));
+        }
+
+        /* Call the appropriate sort function. */
+        $helper = new Horde_Array_Sort_Helper();
+        $helper->key = $key;
+        $function = $dir ? 'reverseCompare' : 'compare';
+        if ($assoc) {
+            uasort($array, array($helper, $function));
+        } else {
+            usort($array, array($helper, $function));
+        }
+    }
+
+    /**
+     * Given an HTML type array field "example[key1][key2][key3]" breaks up
+     * the keys so that they could be used to reference a regular PHP array.
+     *
+     * @param string $field  The field name to be examined.
+     * @param string &$base  Set to the base element.
+     * @param array &$keys   Set to the list of keys.
+     *
+     * @return boolean  True on sucess, false on error.
+     */
+    static public function getArrayParts($field, &$base, &$keys)
+    {
+        if (!preg_match('|([^\[]*)((\[[^\[\]]*\])+)|', $field, $matches)) {
+            return false;
+        }
+
+        $base = $matches[1];
+        $keys = explode('][', $matches[2]);
+        $keys[0] = substr($keys[0], 1);
+        $keys[count($keys) - 1] = substr($keys[count($keys) - 1], 0, strlen($keys[count($keys) - 1]) - 1);
+        return true;
+    }
+
+    /**
+     * Using an array of keys iterate through the array following the
+     * keys to find the final key value. If a value is passed then set
+     * that value.
+     *
+     * @param array &$array  The array to be used.
+     * @param array &$keys   The key path to follow as an array.
+     * @param array $value   If set the target element will have this value set
+     *                       to it.
+     *
+     * @return mixed  The final value of the key path.
+     */
+    static public function getElement(&$array, &$keys, $value = null)
+    {
+        if (count($keys)) {
+            $key = array_shift($keys);
+            return isset($array[$key])
+                ? self::getElement($array[$key], $keys, $value)
+                : false;
+        }
+
+        if (!is_null($value)) {
+            $array = $value;
+        }
+
+        return $array;
+    }
+
+    /**
+     * Returns a rectangle of a two-dimensional array.
+     *
+     * @param array   $array   The array to extract the rectangle from.
+     * @param integer $row     The start row of the rectangle.
+     * @param integer $col     The start column of the rectangle.
+     * @param integer $height  The height of the rectangle.
+     * @param integer $width   The width of the rectangle.
+     *
+     * @return array  The extracted rectangle.
+     */
+    static public function getRectangle($array, $row, $col, $height, $width)
+    {
+        $rec = array();
+        for ($y = $row; $y < $row + $height; $y++) {
+            $rec[] = array_slice($array[$y], $col, $width);
+        }
+        return $rec;
+    }
+
+    /**
+     * Given an array, returns an associative array with each element key
+     * derived from its value.
+     * For example:
+     *   array(0 => 'foo', 1 => 'bar')
+     * would become:
+     *   array('foo' => 'foo', 'bar' => 'bar')
+     *
+     * @param array $array  An array of values.
+     *
+     * @return array  An array with keys the same as values.
+     */
+    static public function valuesToKeys($array)
+    {
+        if (!$array) {
+            return array();
+        }
+
+        $values = array_values($array);
+        return array_combine($values, $values);
+    }
+
+    /**
+     * Enhanced array_merge_recursive() function.  Main difference from PHP's
+     * stock function is later value always overwrites earlier value (stock
+     * function will instead create an array with all values of key).
+     *
+     * @param array $a1  The old array.
+     * @param array $a2  The new array.
+     *
+     * @return array  The merged array.
+     */
+    static public function array_merge_recursive_overwrite($a1, $a2)
+    {
+        foreach ($a2 as $key => $val) {
+            if (!isset($a1[$key])) {
+                $a1[$key] = array();
+            }
+
+            $a1[$key] = (is_array($val))
+                ? self::array_merge_recursive_overwrite($a1[$key], $val)
+                : $val;
+        }
+
+        return $a1;
+    }
+
+}
diff --git a/framework/Util/lib/Horde/Array/Sort/Helper.php b/framework/Util/lib/Horde/Array/Sort/Helper.php
new file mode 100644 (file)
index 0000000..b8a3653
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Helper class for sorting arrays on arbitrary criteria for usort/uasort.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Michael Slusarz <slusarz@horde.org>
+ * @author  Marko Djukic <marko@oblo.com>
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Util
+ */
+class Horde_Array_Sort_Helper
+{
+    /**
+     * The array key to sort by.
+     *
+     * @var string
+     */
+    public $key;
+
+    /**
+     * Compare two associative arrays by the array key defined in self::$key.
+     *
+     * @param array $a
+     * @param array $b
+     */
+    public function compare($a, $b)
+    {
+        return strcoll(Horde_String::lower($a[$this->key], true), Horde_String::lower($b[$this->key], true));
+    }
+
+    /**
+     * Compare, in reverse order, two associative arrays by the array key
+     * defined in self::$key.
+     *
+     * @param scalar $a  TODO
+     * @param scalar $b  TODO
+     *
+     * @return TODO
+     */
+    public function reverseCompare($a, $b)
+    {
+        return strcoll(Horde_String::lower($b[$this->key], true), Horde_String::lower($a[$this->key], true));
+    }
+
+    /**
+     * Compare array keys case insensitively for uksort.
+     *
+     * @param scalar $a  TODO
+     * @param scalar $b  TODO
+     *
+     * @return TODO
+     */
+    public function compareKeys($a, $b)
+    {
+        return strcoll(Horde_String::lower($a, true), Horde_String::lower($b, true));
+    }
+
+    /**
+     * Compare, in reverse order, array keys case insensitively for uksort.
+     *
+     * @param scalar $a  TODO
+     * @param scalar $b  TODO
+     *
+     * @return TODO
+     */
+    public function reverseCompareKeys($a, $b)
+    {
+        return strcoll(Horde_String::lower($b, true), Horde_String::lower($a, true));
+    }
+}
diff --git a/framework/Util/lib/Horde/String.php b/framework/Util/lib/Horde/String.php
new file mode 100644 (file)
index 0000000..61e9606
--- /dev/null
@@ -0,0 +1,705 @@
+<?php
+/**
+ * The Horde_String:: class provides static methods for charset and locale
+ * safe string manipulation.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Horde_Util
+ */
+class Horde_String
+{
+    /**
+     * Default charset.
+     *
+     * @var string
+     */
+    static protected $_charset = 'iso-8859-1';
+
+    /**
+     * lower() cache.
+     *
+     * @var array
+     */
+    static protected $_lowers = array();
+
+    /**
+     * upper() cache.
+     *
+     * @var array
+     */
+    static protected $_uppers = array();
+
+    /**
+     * Sets a default charset that the methods will use if none is explicitly
+     * specified.
+     *
+     * @param string $charset  The charset to use as the default one.
+     */
+    static public function setDefaultCharset($charset)
+    {
+        self::$_charset = $charset;
+        if (Horde_Util::extensionExists('mbstring')) {
+            $old_error = error_reporting(0);
+            mb_regex_encoding(self::_mbstringCharset($charset));
+            error_reporting($old_error);
+        }
+    }
+
+    /**
+     * Converts a string from one charset to another.
+     *
+     * Works only if either the iconv or the mbstring extension
+     * are present and best if both are available.
+     * The original string is returned if conversion failed or none
+     * of the extensions were available.
+     *
+     * @param mixed $input  The data to be converted. If $input is an an array,
+     *                      the array's values get converted recursively.
+     * @param string $from  The string's current charset.
+     * @param string $to    The charset to convert the string to. If not
+     *                      specified, the global variable $_charset will
+     *                      be used.
+     *
+     * @return mixed  The converted input data.
+     */
+    static public function convertCharset($input, $from, $to = null)
+    {
+        /* Don't bother converting numbers. */
+        if (is_numeric($input)) {
+            return $input;
+        }
+
+        /* Get the user's default character set if none passed in. */
+        if (is_null($to)) {
+            $to = self::$_charset;
+        }
+
+        /* If the from and to character sets are identical, return now. */
+        $from = self::lower($from);
+        $to = self::lower($to);
+        if ($from == $to) {
+            return $input;
+        }
+
+        if (is_array($input)) {
+            $tmp = array();
+            reset($input);
+            while (list($key, $val) = each($input)) {
+                $tmp[self::_convertCharset($key, $from, $to)] = self::convertCharset($val, $from, $to);
+            }
+            return $tmp;
+        }
+
+        if (is_object($input)) {
+            // PEAR_Error objects are almost guaranteed to contain recursion,
+            // which will cause a segfault in PHP.  We should never reach
+            // this line, but add a check and a log message to help the devs
+            // track down and fix this issue.
+            if (is_a($input, 'PEAR_Error')) {
+                Horde::logMessage('Called convertCharset() on a PEAR_Error object. ' . print_r($input, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+                return '';
+            }
+            $vars = get_object_vars($input);
+            while (list($key, $val) = each($vars)) {
+                $input->$key = self::convertCharset($val, $from, $to);
+            }
+            return $input;
+        }
+
+        if (!is_string($input)) {
+            return $input;
+        }
+
+        return self::_convertCharset($input, $from, $to);
+    }
+
+    /**
+     * Internal function used to do charset conversion.
+     *
+     * @param string $input  See self::convertCharset().
+     * @param string $from   See self::convertCharset().
+     * @param string $to     See self::convertCharset().
+     *
+     * @return string  The converted string.
+     */
+    static protected function _convertCharset($input, $from, $to)
+    {
+        /* Use utf8_[en|de]code() if possible and if the string isn't too
+         * large (less than 16 MB = 16 * 1024 * 1024 = 16777216 bytes) - these
+         * functions use more memory. */
+        if ((strlen($input) < 16777216) ||
+            !(Horde_Util::extensionExists('iconv') || Horde_Util::extensionExists('mbstring'))) {
+            if (($to == 'utf-8') &&
+                in_array($from, array('iso-8859-1', 'us-ascii'))) {
+                return utf8_encode($input);
+            }
+
+            if (($from == 'utf-8') &&
+                in_array($to, array('iso-8859-1', 'us-ascii'))) {
+                return utf8_decode($input);
+            }
+        }
+
+        /* Try UTF7-IMAP conversions. */
+        if (($from == 'utf7-imap') || ($to == 'utf7-imap')) {
+            try {
+                if ($from == 'utf7-imap') {
+                    return self::convertCharset(Horde_Imap_Client_Utf7imap::Utf7ImapToUtf8($input), 'UTF-8', $to);
+                } else {
+                    if ($from == 'utf-8') {
+                        $conv = $input;
+                    } else {
+                        $conv = self::convertCharset($input, $from, 'UTF-8');
+                    }
+                    return Horde_Imap_Client_Utf7imap::Utf8ToUtf7Imap($conv);
+                }
+            } catch (Horde_Imap_Client_Exception $e) {
+                return $input;
+            }
+        }
+
+        /* Try iconv with transliteration. */
+        if (Horde_Util::extensionExists('iconv')) {
+            /* We need to tack an extra character temporarily because of a bug
+             * in iconv() if the last character is not a 7 bit ASCII
+             * character. */
+            $oldTrackErrors = ini_set('track_errors', 1);
+            unset($php_errormsg);
+            $out = @iconv($from, $to . '//TRANSLIT', $input . 'x');
+            $errmsg = isset($php_errormsg);
+            ini_set('track_errors', $oldTrackErrors);
+            if (!$errmsg) {
+                return self::substr($out, 0, -1, $to);
+            }
+        }
+
+        /* Try mbstring. */
+        if (Horde_Util::extensionExists('mbstring')) {
+            $old_error = error_reporting(0);
+            $out = mb_convert_encoding($input, $to, self::_mbstringCharset($from));
+            error_reporting($old_error);
+            if (!empty($out)) {
+                return $out;
+            }
+        }
+
+        return $input;
+    }
+
+    /**
+     * Makes a string lowercase.
+     *
+     * @param string $string   The string to be converted.
+     * @param boolean $locale  If true the string will be converted based on
+     *                         a given charset, locale independent else.
+     * @param string $charset  If $locale is true, the charset to use when
+     *                         converting. If not provided the current
+     *                         charset.
+     *
+     * @return string  The string with lowercase characters.
+     */
+    static public function lower($string, $locale = false, $charset = null)
+    {
+        if ($locale) {
+            if (Horde_Util::extensionExists('mbstring')) {
+                if (is_null($charset)) {
+                    $charset = self::$_charset;
+                }
+                $old_error = error_reporting(0);
+                $ret = mb_strtolower($string, self::_mbstringCharset($charset));
+                error_reporting($old_error);
+                if (!empty($ret)) {
+                    return $ret;
+                }
+            }
+            return strtolower($string);
+        }
+
+        if (!isset(self::$_lowers[$string])) {
+            $language = setlocale(LC_CTYPE, 0);
+            setlocale(LC_CTYPE, 'C');
+            self::$_lowers[$string] = strtolower($string);
+            setlocale(LC_CTYPE, $language);
+        }
+
+        return self::$_lowers[$string];
+    }
+
+    /**
+     * Makes a string uppercase.
+     *
+     * @param string $string   The string to be converted.
+     * @param boolean $locale  If true the string will be converted based on a
+     *                         given charset, locale independent else.
+     * @param string $charset  If $locale is true, the charset to use when
+     *                         converting. If not provided the current charset.
+     *
+     * @return string  The string with uppercase characters.
+     */
+    static public function upper($string, $locale = false, $charset = null)
+    {
+        if ($locale) {
+            if (Horde_Util::extensionExists('mbstring')) {
+                if (is_null($charset)) {
+                    $charset = self::$_charset;
+                }
+                $old_error = error_reporting(0);
+                $ret = mb_strtoupper($string, self::_mbstringCharset($charset));
+                error_reporting($old_error);
+                if (!empty($ret)) {
+                    return $ret;
+                }
+            }
+            return strtoupper($string);
+        }
+
+        if (!isset(self::$_uppers[$string])) {
+            $language = setlocale(LC_CTYPE, 0);
+            setlocale(LC_CTYPE, 'C');
+            self::$_uppers[$string] = strtoupper($string);
+            setlocale(LC_CTYPE, $language);
+        }
+
+        return self::$_uppers[$string];
+    }
+
+    /**
+     * Returns a string with the first letter capitalized if it is
+     * alphabetic.
+     *
+     * @param string $string   The string to be capitalized.
+     * @param boolean $locale  If true the string will be converted based on a
+     *                         given charset, locale independent else.
+     * @param string $charset  The charset to use, defaults to current charset.
+     *
+     * @return string  The capitalized string.
+     */
+    static public function ucfirst($string, $locale = false, $charset = null)
+    {
+        if ($locale) {
+            $first = self::substr($string, 0, 1, $charset);
+            if (self::isAlpha($first, $charset)) {
+                $string = self::upper($first, true, $charset) . self::substr($string, 1, null, $charset);
+            }
+        } else {
+            $string = self::upper(substr($string, 0, 1), false) . substr($string, 1);
+        }
+
+        return $string;
+    }
+
+    /**
+     * Returns part of a string.
+     *
+     * @param string $string   The string to be converted.
+     * @param integer $start   The part's start position, zero based.
+     * @param integer $length  The part's length.
+     * @param string $charset  The charset to use when calculating the part's
+     *                         position and length, defaults to current
+     *                         charset.
+     *
+     * @return string  The string's part.
+     */
+    static public function substr($string, $start, $length = null,
+                                  $charset = null)
+    {
+        if (is_null($length)) {
+            $length = self::length($string, $charset) - $start;
+        }
+
+        if ($length == 0) {
+            return '';
+        }
+
+        /* Try iconv. */
+        if (Horde_Util::extensionExists('iconv')) {
+            if (is_null($charset)) {
+                $charset = self::$_charset;
+            }
+
+            $old_error = error_reporting(0);
+            $ret = iconv_substr($string, $start, $length, $charset);
+            error_reporting($old_error);
+
+            /* iconv_substr() returns false on failure. */
+            if ($ret !== false) {
+                return $ret;
+            }
+        }
+
+        /* Try mbstring. */
+        if (Horde_Util::extensionExists('mbstring')) {
+            if (is_null($charset)) {
+                $charset = self::$_charset;
+            }
+            $old_error = error_reporting(0);
+            $ret = mb_substr($string, $start, $length, self::_mbstringCharset($charset));
+            error_reporting($old_error);
+
+            /* mb_substr() returns empty string on failure. */
+            if (strlen($ret)) {
+                return $ret;
+            }
+        }
+
+        return substr($string, $start, $length);
+    }
+
+    /**
+     * Returns the character (not byte) length of a string.
+     *
+     * @param string $string  The string to return the length of.
+     * @param string $charset The charset to use when calculating the string's
+     *                        length.
+     *
+     * @return integer  The string's length.
+     */
+    static public function length($string, $charset = null)
+    {
+        if (is_null($charset)) {
+            $charset = self::$_charset;
+        }
+        $charset = self::lower($charset);
+
+        if ($charset == 'utf-8' || $charset == 'utf8') {
+            return strlen(utf8_decode($string));
+        }
+
+        if (Horde_Util::extensionExists('mbstring')) {
+            $old_error = error_reporting(0);
+            $ret = mb_strlen($string, self::_mbstringCharset($charset));
+            error_reporting($old_error);
+            if (!empty($ret)) {
+                return $ret;
+            }
+        }
+
+        return strlen($string);
+    }
+
+    /**
+     * Returns the numeric position of the first occurrence of $needle
+     * in the $haystack string.
+     *
+     * @param string $haystack  The string to search through.
+     * @param string $needle    The string to search for.
+     * @param integer $offset   Allows to specify which character in haystack
+     *                          to start searching.
+     * @param string $charset   The charset to use when searching for the
+     *                          $needle string.
+     *
+     * @return integer  The position of first occurrence.
+     */
+    static public function pos($haystack, $needle, $offset = 0,
+                               $charset = null)
+    {
+        if (Horde_Util::extensionExists('mbstring')) {
+            if (is_null($charset)) {
+                $charset = self::$_charset;
+            }
+            $track_errors = ini_set('track_errors', 1);
+            $old_error = error_reporting(0);
+            $ret = mb_strpos($haystack, $needle, $offset, self::_mbstringCharset($charset));
+            error_reporting($old_error);
+            ini_set('track_errors', $track_errors);
+            if (!isset($php_errormsg)) {
+                return $ret;
+            }
+        }
+
+        return strpos($haystack, $needle, $offset);
+    }
+
+    /**
+     * Returns a string padded to a certain length with another string.
+     * This method behaves exactly like str_pad() but is multibyte safe.
+     *
+     * @param string $input    The string to be padded.
+     * @param integer $length  The length of the resulting string.
+     * @param string $pad      The string to pad the input string with. Must
+     *                         be in the same charset like the input string.
+     * @param const $type      The padding type. One of STR_PAD_LEFT,
+     *                         STR_PAD_RIGHT, or STR_PAD_BOTH.
+     * @param string $charset  The charset of the input and the padding
+     *                         strings.
+     *
+     * @return string  The padded string.
+     */
+    static public function pad($input, $length, $pad = ' ',
+                               $type = STR_PAD_RIGHT, $charset = null)
+    {
+        $mb_length = self::length($input, $charset);
+        $sb_length = strlen($input);
+        $pad_length = self::length($pad, $charset);
+
+        /* Return if we already have the length. */
+        if ($mb_length >= $length) {
+            return $input;
+        }
+
+        /* Shortcut for single byte strings. */
+        if ($mb_length == $sb_length && $pad_length == strlen($pad)) {
+            return str_pad($input, $length, $pad, $type);
+        }
+
+        switch ($type) {
+        case STR_PAD_LEFT:
+            $left = $length - $mb_length;
+            $output = self::substr(str_repeat($pad, ceil($left / $pad_length)), 0, $left, $charset) . $input;
+            break;
+
+        case STR_PAD_BOTH:
+            $left = floor(($length - $mb_length) / 2);
+            $right = ceil(($length - $mb_length) / 2);
+            $output = self::substr(str_repeat($pad, ceil($left / $pad_length)), 0, $left, $charset) .
+                $input .
+                self::substr(str_repeat($pad, ceil($right / $pad_length)), 0, $right, $charset);
+            break;
+
+        case STR_PAD_RIGHT:
+            $right = $length - $mb_length;
+            $output = $input . self::substr(str_repeat($pad, ceil($right / $pad_length)), 0, $right, $charset);
+            break;
+        }
+
+        return $output;
+    }
+
+    /**
+     * Wraps the text of a message.
+     *
+     * @param string $string         String containing the text to wrap.
+     * @param integer $width         Wrap the string at this number of
+     *                               characters.
+     * @param string $break          Character(s) to use when breaking lines.
+     * @param boolean $cut           Whether to cut inside words if a line
+     *                               can't be wrapped.
+     * @param string $charset        Character set to use when breaking lines.
+     * @param boolean $line_folding  Whether to apply line folding rules per
+     *                               RFC 822 or similar. The correct break
+     *                               characters including leading whitespace
+     *                               have to be specified too.
+     *
+     * @return string  String containing the wrapped text.
+     */
+    static public function wordwrap($string, $width = 75, $break = "\n",
+                                    $cut = false, $charset = null,
+                                    $line_folding = false)
+    {
+        /* Get the user's default character set if none passed in. */
+        if (is_null($charset)) {
+            $charset = self::$_charset;
+        }
+
+        $charset = self::_mbstringCharset($charset);
+        $string = self::convertCharset($string, $charset, 'utf-8');
+        $wrapped = '';
+
+        while (self::length($string, 'utf-8') > $width) {
+            $line = self::substr($string, 0, $width, 'utf-8');
+            $string = self::substr($string, self::length($line, 'utf-8'), null, 'utf-8');
+
+            // Make sure didn't cut a word, unless we want hard breaks anyway.
+            if (!$cut && preg_match('/^(.+?)(\s|\r?\n)/u', $string, $match)) {
+                $line .= $match[1];
+                $string = self::substr($string, self::length($match[1], 'utf-8'), null, 'utf-8');
+            }
+
+            // Wrap at existing line breaks.
+            if (preg_match('/^(.*?)(\r?\n)(.*)$/u', $line, $match)) {
+                $wrapped .= $match[1] . $match[2];
+                $string = $match[3] . $string;
+                continue;
+            }
+
+            // Wrap at the last colon or semicolon followed by a whitespace if
+            // doing line folding.
+            if ($line_folding &&
+                preg_match('/^(.*?)(;|:)(\s+.*)$/u', $line, $match)) {
+                $wrapped .= $match[1] . $match[2] . $break;
+                $string = $match[3] . $string;
+                continue;
+            }
+
+            // Wrap at the last whitespace of $line.
+            $sub = $line_folding
+                ? '(.+[^\s])'
+                : '(.*)';
+
+            if (preg_match('/^' . $sub . '(\s+)(.*)$/u', $line, $match)) {
+                $wrapped .= $match[1] . $break;
+                $string = ($line_folding ? $match[2] : '') . $match[3] . $string;
+                continue;
+            }
+
+            // Hard wrap if necessary.
+            if ($cut) {
+                $wrapped .= self::substr($line, 0, $width, 'utf-8') . $break;
+                $string = self::substr($line, $width, null, 'utf-8') . $string;
+                continue;
+            }
+
+            $wrapped .= $line;
+        }
+
+        return self::convertCharset($wrapped . $string, 'utf-8', $charset);
+    }
+
+    /**
+     * Wraps the text of a message.
+     *
+     * @param string $text        String containing the text to wrap.
+     * @param integer $length     Wrap $text at this number of characters.
+     * @param string $break_char  Character(s) to use when breaking lines.
+     * @param string $charset     Character set to use when breaking lines.
+     * @param boolean $quote      Ignore lines that are wrapped with the '>'
+     *                            character (RFC 2646)? If true, we don't
+     *                            remove any padding whitespace at the end of
+     *                            the string.
+     *
+     * @return string  String containing the wrapped text.
+     */
+    static public function wrap($text, $length = 80, $break_char = "\n",
+                                $charset = null, $quote = false)
+    {
+        $paragraphs = array();
+
+        foreach (preg_split('/\r?\n/', $text) as $input) {
+            if ($quote && (strpos($input, '>') === 0)) {
+                $line = $input;
+            } else {
+                /* We need to handle the Usenet-style signature line
+                 * separately; since the space after the two dashes is
+                 * REQUIRED, we don't want to trim the line. */
+                if ($input != '-- ') {
+                    $input = rtrim($input);
+                }
+                $line = self::wordwrap($input, $length, $break_char, false, $charset);
+            }
+
+            $paragraphs[] = $line;
+        }
+
+        return implode($break_char, $paragraphs);
+    }
+
+    /**
+     * Returns true if the every character in the parameter is an alphabetic
+     * character.
+     *
+     * @param string $string   The string to test.
+     * @param string $charset  The charset to use when testing the string.
+     *
+     * @return boolean  True if the parameter was alphabetic only.
+     */
+    static public function isAlpha($string, $charset = null)
+    {
+        if (!Horde_Util::extensionExists('mbstring')) {
+            return ctype_alpha($string);
+        }
+
+        $charset = self::_mbstringCharset($charset);
+        $old_charset = mb_regex_encoding();
+        $old_error = error_reporting(0);
+
+        if ($charset != $old_charset) {
+            mb_regex_encoding($charset);
+        }
+        $alpha = !mb_ereg_match('[^[:alpha:]]', $string);
+        if ($charset != $old_charset) {
+            mb_regex_encoding($old_charset);
+        }
+
+        error_reporting($old_error);
+
+        return $alpha;
+    }
+
+    /**
+     * Returns true if ever character in the parameter is a lowercase letter in
+     * the current locale.
+     *
+     * @param string $string   The string to test.
+     * @param string $charset  The charset to use when testing the string.
+     *
+     * @return boolean  True if the parameter was lowercase.
+     */
+    static public function isLower($string, $charset = null)
+    {
+        return ((self::lower($string, true, $charset) === $string) &&
+                self::isAlpha($string, $charset));
+    }
+
+    /**
+     * Returns true if every character in the parameter is an uppercase letter
+     * in the current locale.
+     *
+     * @param string $string   The string to test.
+     * @param string $charset  The charset to use when testing the string.
+     *
+     * @return boolean  True if the parameter was uppercase.
+     */
+    static public function isUpper($string, $charset = null)
+    {
+        return ((self::upper($string, true, $charset) === $string) &&
+                self::isAlpha($string, $charset));
+    }
+
+    /**
+     * Performs a multibyte safe regex match search on the text provided.
+     *
+     * @param string $text     The text to search.
+     * @param array $regex     The regular expressions to use, without perl
+     *                         regex delimiters (e.g. '/' or '|').
+     * @param string $charset  The character set of the text.
+     *
+     * @return array  The matches array from the first regex that matches.
+     */
+    static public function regexMatch($text, $regex, $charset = null)
+    {
+        if (!empty($charset)) {
+            $regex = self::convertCharset($regex, $charset, 'utf-8');
+            $text = self::convertCharset($text, $charset, 'utf-8');
+        }
+
+        $matches = array();
+        foreach ($regex as $val) {
+            if (preg_match('/' . $val . '/u', $text, $matches)) {
+                break;
+            }
+        }
+
+        if (!empty($charset)) {
+            $matches = self::convertCharset($matches, 'utf-8', $charset);
+        }
+
+        return $matches;
+    }
+
+    /**
+     * Workaround charsets that don't work with mbstring functions.
+     *
+     * @param string $charset  The original charset.
+     *
+     * @return string  The charset to use with mbstring functions.
+     */
+    static protected function _mbstringCharset($charset)
+    {
+        /* mbstring functions do not handle the 'ks_c_5601-1987' &
+         * 'ks_c_5601-1989' charsets. However, these charsets are used, for
+         * example, by various versions of Outlook to send Korean characters.
+         * Use UHC (CP949) encoding instead. See, e.g.,
+         * http://lists.w3.org/Archives/Public/ietf-charsets/2001AprJun/0030.html */
+        if (in_array(self::lower($charset), array('ks_c_5601-1987', 'ks_c_5601-1989'))) {
+            $charset = 'UHC';
+        }
+
+        return $charset;
+    }
+
+}
diff --git a/framework/Util/lib/Horde/Util.php b/framework/Util/lib/Horde/Util.php
new file mode 100644 (file)
index 0000000..c0f6e46
--- /dev/null
@@ -0,0 +1,938 @@
+<?php
+/**
+ * The Horde_Util:: class provides generally useful methods.
+ *
+ * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @author  Jon Parise <jon@horde.org>
+ * @package Horde_Util
+ */
+class Horde_Util
+{
+    /* Error code for a missing driver configuration. */
+    const HORDE_ERROR_DRIVER_CONFIG_MISSING = 1;
+
+    /* Error code for an incomplete driver configuration. */
+    const HORDE_ERROR_DRIVER_CONFIG = 2;
+
+    /**
+     * A list of random patterns to use for overwriting purposes.
+     * See http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html.
+     * We save the random overwrites for efficiency reasons.
+     *
+     * @var array
+     */
+    static public $patterns = array(
+        "\x55", "\xaa", "\x92\x49\x24", "\x49\x24\x92", "\x24\x92\x49",
+        "\x00", "\x11", "\x22", "\x33", "\x44", "\x55", "\x66", "\x77",
+        "\x88", "\x99", "\xaa", "\xbb", "\xcc", "\xdd", "\xee", "\xff",
+        "\x92\x49\x24", "\x49\x24\x92", "\x24\x92\x49", "\x6d\xb6\xdb",
+        "\xb6\xdb\x6d", "\xdb\x6d\xb6"
+    );
+
+    /**
+     * TODO
+     *
+     * @var array
+     */
+    static public $dateSymbols = array(
+        'a', 'A', 'd', 'D', 'F', 'g', 'G', 'h', 'H', 'i', 'j', 'l', 'm', 'M',
+        'n', 'r', 's', 'T', 'w', 'W', 'y', 'Y', 'z', 'm/d/Y', 'M', "\n",
+        'g:i a', 'G:i', "\t", 'H:i:s', '%'
+    );
+
+    /**
+     * TODO
+     *
+     * @var array
+     */
+    static public $strftimeSymbols = array(
+        '%p', '%p', '%d', '%a', '%B', '%I', '%H', '%I', '%H', '%M', '%e',
+        '%A', '%m', '%b', '%m', '%a, %e %b %Y %T %Z', '%S', '%Z', '%w', '%V',
+        '%y', '%Y', '%j', '%D', '%h', '%n', '%r', '%R', '%t', '%T', '%%'
+    );
+
+    /**
+     * Random number for nocacheUrl().
+     *
+     * @var integer.
+     */
+    static protected $_randnum = null;
+
+    /**
+     * TODO
+     */
+    static protected $_magicquotes = null;
+
+    /**
+     * TODO
+     */
+    static protected $_shutdowndata = array(
+        'dirs' => array(),
+        'files' => array(),
+        'secure' => array()
+    );
+
+    /**
+     * TODO
+     */
+    static protected $_shutdownreg = false;
+
+    /**
+     * Cache for extensionExists().
+     *
+     * @var array
+     */
+    static protected $_cache = array();
+
+    /**
+     * Returns an object's clone.
+     *
+     * @param object &$obj  The object to clone.
+     *
+     * @return object  The cloned object.
+     */
+    static public function &cloneObject(&$obj)
+    {
+        if (!is_object($obj)) {
+            $bt = debug_backtrace();
+            if (isset($bt[1])) {
+                $caller = $bt[1]['function'];
+                if (isset($bt[1]['class'])) {
+                    $caller = $bt[1]['class'].$bt[1]['type'].$caller;
+                }
+            } else {
+                $caller = 'main';
+            }
+
+            $caller .= ' on line ' . $bt[0]['line'] . ' of ' . $bt[0]['file'];
+            Horde::logMessage('Horde_Util::cloneObject called on variable of type ' . gettype($obj) . ' by ' . $caller, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+
+            $ret = $obj;
+            return $ret;
+        }
+
+        $ret = clone($obj);
+        return $ret;
+    }
+
+    /**
+     * Buffers the output from a function call, like readfile() or
+     * highlight_string(), that prints the output directly, so that instead it
+     * can be returned as a string and used.
+     *
+     * @param string $function  The function to run.
+     * @param mixed $arg1       First argument to $function().
+     * @param mixed $arg2       Second argument to $function().
+     * @param mixed $arg...     ...
+     * @param mixed $argN       Nth argument to $function().
+     *
+     * @return string  The output of the function.
+     */
+    static public function bufferOutput()
+    {
+        if (func_num_args() == 0) {
+            return false;
+        }
+
+        $include = false;
+        $args = func_get_args();
+        $function = array_shift($args);
+
+        if (is_array($function)) {
+            if (!is_callable($function)) {
+                return false;
+            }
+        } elseif (($function == 'include') ||
+                  ($function == 'include_once') ||
+                  ($function == 'require') ||
+                  ($function == 'require_once')) {
+            $include = true;
+        } elseif (!function_exists($function)) {
+            return false;
+        }
+
+        ob_start();
+        if ($include) {
+            $file = implode(',', $args);
+            switch ($function) {
+            case 'include':
+                include $file;
+                break;
+
+            case 'include_once':
+                include_once $file;
+                break;
+
+            case 'require':
+                require $file;
+                break;
+
+            case 'require_once':
+                require_once $file;
+                break;
+            }
+        } else {
+            call_user_func_array($function, $args);
+        }
+
+        return ob_get_clean();
+    }
+
+    /**
+     * Checks to see if a value has been set by the script and not by GET,
+     * POST, or cookie input. The value being checked MUST be in the global
+     * scope.
+     *
+     * @param string $varname  The variable name to check.
+     * @param mixed $default   Default value if the variable isn't present
+     *                         or was specified by the user. Defaults to null.
+     *
+     * @return mixed  $default if the var is in user input or not present,
+     *                the variable value otherwise.
+     */
+    static public function nonInputVar($varname, $default = null)
+    {
+        return (isset($_GET[$varname]) || isset($_POST[$varname]) || isset($_COOKIE[$varname]))
+            ? $default
+            : isset($GLOBALS[$varname]) ? $GLOBALS[$varname] : $default;
+    }
+
+    /**
+     * Adds a name=value pair to the end of an URL, taking care of whether
+     * there are existing parameters and whether to use ?, & or &amp; as the
+     * glue.  All data will be urlencoded.
+     *
+     * @param string $url       The URL to modify
+     * @param mixed $parameter  Either the name value -or- an array of
+     *                          name/value pairs.
+     * @param string $value     If specified, the value part ($parameter is
+     *                          then assumed to just be the parameter name).
+     * @param boolean $encode   Encode the argument separator?
+     *
+     * @return string  The modified URL.
+     */
+    static public function addParameter($url, $parameter, $value = null,
+                                        $encode = true)
+    {
+        if (empty($parameter)) {
+            return $url;
+        }
+
+        $add = array();
+        $arg = $encode ? '&amp;' : '&';
+
+        if (strpos($url, '?') !== false) {
+            list($url, $query) = explode('?', $url);
+
+            /* Check if the argument separator has been already
+             * htmlentities-ized in the URL. */
+            if (preg_match('/=.*?&amp;.*?=/', $query)) {
+                $query = html_entity_decode($query);
+                $arg = '&amp;';
+            } elseif (preg_match('/=.*?&.*?=/', $query)) {
+                $arg = '&';
+            }
+            $pairs = explode('&', $query);
+            foreach ($pairs as $pair) {
+                $pair = explode('=', urldecode($pair), 2);
+                $pair_val = (count($pair) == 2) ? $pair[1] : '';
+                if (substr($pair[0], -2) == '[]') {
+                    $name = substr($pair[0], 0, -2);
+                    if (!isset($add[$name])) {
+                        $add[$name] = array();
+                    }
+                    $add[$name][] = $pair_val;
+                } else {
+                    $add[$pair[0]] = $pair_val;
+                }
+            }
+        }
+
+        if (is_array($parameter)) {
+            $add = array_merge($add, $parameter);
+        } else {
+            $add[$parameter] = $value;
+        }
+
+        $url_params = array();
+        foreach ($add as $parameter => $value) {
+            if (is_array($value)) {
+                foreach ($value as $val) {
+                    $url_params[] = urlencode($parameter) . '[]=' . urlencode($val);
+                }
+            } else {
+                $url_params[] = urlencode($parameter) . '=' . urlencode($value);
+            }
+        }
+
+        return count($url_params)
+            ? $url . '?' . implode($arg, $url_params)
+            : $url;
+    }
+
+    /**
+     * Removes name=value pairs from a URL.
+     *
+     * @param string $url    The URL to modify.
+     * @param mixed $remove  Either a single parameter to remove or an array
+     *                       of parameters to remove.
+     *
+     * @return string  The modified URL.
+     */
+    static public function removeParameter($url, $remove)
+    {
+        if (!is_array($remove)) {
+            $remove = array($remove);
+        }
+
+        /* Return immediately if there are no parameters to remove. */
+        if (($pos = strpos($url, '?')) === false) {
+            return $url;
+        }
+
+        $entities = false;
+        list($url, $query) = explode('?', $url, 2);
+
+        /* Check if the argument separator has been already
+         * htmlentities-ized in the URL. */
+        if (preg_match('/=.*?&amp;.*?=/', $query)) {
+            $entities = true;
+            $query = html_entity_decode($query);
+        }
+
+        /* Get the list of parameters. */
+        $pairs = explode('&', $query);
+        $params = array();
+        foreach ($pairs as $pair) {
+            $pair = explode('=', $pair, 2);
+            $params[$pair[0]] = count($pair) == 2 ? $pair[1] : '';
+        }
+
+        /* Remove the parameters. */
+        foreach ($remove as $param) {
+            unset($params[$param]);
+        }
+
+        if (!count($params)) {
+            return $url;
+        }
+
+        /* Flatten arrays.
+         * FIXME: should handle more than one array level somehow. */
+        $add = array();
+        foreach ($params as $key => $val) {
+            if (is_array($val)) {
+                foreach ($val as $v) {
+                    $add[] = $key . '[]=' . $v;
+                }
+            } else {
+                $add[] = $key . '=' . $val;
+            }
+        }
+
+        $query = implode('&', $add);
+        if ($entities) {
+            $query = htmlentities($query);
+        }
+
+        return $url . '?' . $query;
+    }
+
+    /**
+     * Returns a url with the 'nocache' parameter added, if the browser is
+     * buggy and caches old URLs.
+     *
+     * @param string $url      The URL to modify.
+     * @param boolean $encode  Encode the argument separator?
+     *
+     * @return string  The requested URI.
+     */
+    static public function nocacheUrl($url, $encode = true)
+    {
+        /* We may need to set a dummy parameter 'nocache' since some
+         * browsers do not always honor the 'no-cache' header. */
+        $browser = &Horde_Browser::singleton();
+        if ($browser->hasQuirk('cache_same_url')) {
+            if (is_null(self::$randnum)) {
+                self::$_randnum = base_convert(microtime(), 10, 36);
+            }
+            return self::addParameter($url, 'nocache', self::$_randnum, $encode);
+        }
+
+        return $url;
+    }
+
+    /**
+     * Returns a hidden form input containing the session name and id.
+     *
+     * @param boolean $append_session  0 = only if needed, 1 = always.
+     *
+     * @return string  The hidden form input, if needed/requested.
+     */
+    static public function formInput($append_session = 0)
+    {
+        return (($append_session == 1) || !isset($_COOKIE[session_name()]))
+            ? '<input type="hidden" name="' . htmlspecialchars(session_name()) . '" value="' . htmlspecialchars(session_id()) . "\" />\n"
+            : '';
+    }
+
+    /**
+     * Prints a hidden form input containing the session name and id.
+     *
+     * @param boolean $append_session  0 = only if needed, 1 = always.
+     */
+    static public function pformInput($append_session = 0)
+    {
+        echo self::formInput($append_session);
+    }
+
+    /**
+     * If magic_quotes_gpc is in use, run stripslashes() on $var.
+     *
+     * @param string &$var  The string to un-quote, if necessary.
+     *
+     * @return string  $var, minus any magic quotes.
+     */
+    static public function dispelMagicQuotes(&$var)
+    {
+        if (is_null(self::$_magicquotes)) {
+            self::$_magicquotes = get_magic_quotes_gpc();
+        }
+
+        if (self::$_magicquotes) {
+            if (!is_array($var)) {
+                $var = stripslashes($var);
+            } else {
+                array_walk($var, array('Horde_Util', 'dispelMagicQuotes'));
+            }
+        }
+
+        return $var;
+    }
+
+    /**
+     * Gets a form variable from GET or POST data, stripped of magic quotes if
+     * necessary. If the variable is somehow set in both the GET data and the
+     * POST data, the value from the POST data will be returned and the GET
+     * value will be ignored.
+     *
+     * @param string $var      The name of the form variable to look for.
+     * @param string $default  The value to return if the variable is not
+     *                         there.
+     *
+     * @return string  The cleaned form variable, or $default.
+     */
+    static public function getFormData($var, $default = null)
+    {
+        return (($val = self::getPost($var)) !== null)
+            ? $val
+            : self::getGet($var, $default);
+    }
+
+    /**
+     * Gets a form variable from GET data, stripped of magic quotes if
+     * necessary. This function will NOT return a POST variable.
+     *
+     * @param string $var      The name of the form variable to look for.
+     * @param string $default  The value to return if the variable is not
+     *                         there.
+     *
+     * @return string  The cleaned form variable, or $default.
+     */
+    static public function getGet($var, $default = null)
+    {
+        return (isset($_GET[$var]))
+            ? self::dispelMagicQuotes($_GET[$var])
+            : $default;
+    }
+
+    /**
+     * Gets a form variable from POST data, stripped of magic quotes if
+     * necessary. This function will NOT return a GET variable.
+     *
+     * @param string $var      The name of the form variable to look for.
+     * @param string $default  The value to return if the variable is not
+     *                         there.
+     *
+     * @return string  The cleaned form variable, or $default.
+     */
+    static public function getPost($var, $default = null)
+    {
+        return (isset($_POST[$var]))
+            ? self::dispelMagicQuotes($_POST[$var])
+            : $default;
+    }
+
+    /**
+     * Determines the location of the system temporary directory.
+     *
+     * @return string  A directory name which can be used for temp files.
+     *                 Returns false if one could not be found.
+     */
+    static public function getTempDir()
+    {
+        /* First, try PHP's upload_tmp_dir directive. */
+        $tmp = ini_get('upload_tmp_dir');
+
+        /* Otherwise, try to determine the TMPDIR environment
+         * variable. */
+        if (empty($tmp)) {
+            $tmp = getenv('TMPDIR');
+        }
+
+        /* If we still cannot determine a value, then cycle through a
+         * list of preset possibilities. */
+        $tmp_locations = array('/tmp', '/var/tmp', 'c:\WUTemp', 'c:\temp',
+                               'c:\windows\temp', 'c:\winnt\temp');
+        while (empty($tmp) && count($tmp_locations)) {
+            $tmp_check = array_shift($tmp_locations);
+            if (@is_dir($tmp_check)) {
+                $tmp = $tmp_check;
+            }
+        }
+
+        /* If it is still empty, we have failed, so return false;
+         * otherwise return the directory determined. */
+        return empty($tmp) ? false : $tmp;
+    }
+
+    /**
+     * Creates a temporary filename for the lifetime of the script, and
+     * (optionally) register it to be deleted at request shutdown.
+     *
+     * @param string $prefix   Prefix to make the temporary name more
+     *                         recognizable.
+     * @param boolean $delete  Delete the file at the end of the request?
+     * @param string $dir      Directory to create the temporary file in.
+     * @param boolean $secure  If deleting file, should we securely delete the
+     *                         file?
+     *
+     * @return string   Returns the full path-name to the temporary file.
+     *                  Returns false if a temp file could not be created.
+     */
+    static public function getTempFile($prefix = '', $delete = true, $dir = '',
+                                       $secure = false)
+    {
+        $tmp_dir = (empty($dir) || !is_dir($dir))
+            ? self::getTempDir()
+            : $dir;
+
+        if (empty($tmp_dir)) {
+            return false;
+        }
+
+        $tmp_file = tempnam($tmp_dir, $prefix);
+
+        /* If the file was created, then register it for deletion and
+         * return. */
+        if (empty($tmp_file)) {
+            return false;
+        }
+
+        if ($delete) {
+            self::deleteAtShutdown($tmp_file, true, $secure);
+        }
+
+        return $tmp_file;
+    }
+
+    /**
+     * Creates a temporary directory in the system's temporary directory.
+     *
+     * @param boolean $delete   Delete the temporary directory at the end of
+     *                          the request?
+     * @param string $temp_dir  Use this temporary directory as the directory
+     *                          where the temporary directory will be created.
+     *
+     * @return string  The pathname to the new temporary directory.
+     *                 Returns false if directory not created.
+     */
+    static public function createTempDir($delete = true, $temp_dir = null)
+    {
+        if (is_null($temp_dir)) {
+            $temp_dir = self::getTempDir();
+        }
+
+        if (empty($temp_dir)) {
+            return false;
+        }
+
+        /* Get the first 8 characters of a random string to use as a temporary
+           directory name. */
+        do {
+            $new_dir = $temp_dir . '/' . substr(base_convert(mt_rand() . microtime(), 10, 36), 0, 8);
+        } while (file_exists($new_dir));
+
+        $old_umask = umask(0000);
+        if (!mkdir($new_dir, 0700)) {
+            $new_dir = false;
+        } elseif ($delete) {
+            self::deleteAtShutdown($new_dir);
+        }
+        umask($old_umask);
+
+        return $new_dir;
+    }
+
+    /**
+     * Returns the canonical path of the string.  Like PHP's built-in
+     * realpath() except the directory need not exist on the local server.
+     *
+     * Algorithim loosely based on code from the Perl File::Spec::Unix module
+     * (version 1.5).
+     *
+     * @param string $path  A file path.
+     *
+     * @return string  The canonicalized file path.
+     */
+    static public function realPath($path)
+    {
+        /* Standardize on UNIX directory separators. */
+        if (!strncasecmp(PHP_OS, 'WIN', 3)) {
+            $path = str_replace('\\', '/', $path);
+        }
+
+        /* xx////xx -> xx/xx
+         * xx/././xx -> xx/xx */
+        $path = preg_replace(array("|/+|", "@(/\.)+(/|\Z(?!\n))@"), array('/', '/'), $path);
+
+        /* ./xx -> xx */
+        if ($path != './') {
+            $path = preg_replace("|^(\./)+|", '', $path);
+        }
+
+        /* /../../xx -> xx */
+        $path = preg_replace("|^/(\.\./?)+|", '/', $path);
+
+        /* xx/ -> xx */
+        if ($path != '/') {
+            $path = preg_replace("|/\Z(?!\n)|", '', $path);
+        }
+
+        /* /xx/.. -> / */
+        while (strpos($path, '/..') !== false) {
+            $path = preg_replace("|/[^/]+/\.\.|", '', $path);
+        }
+
+        return empty($path) ? '/' : $path;
+    }
+
+    /**
+     * Removes given elements at request shutdown.
+     *
+     * If called with a filename will delete that file at request shutdown; if
+     * called with a directory will remove that directory and all files in that
+     * directory at request shutdown.
+     *
+     * If called with no arguments, return all elements to be deleted (this
+     * should only be done by Horde_Util::_deleteAtShutdown()).
+     *
+     * The first time it is called, it initializes the array and registers
+     * Horde_Util::_deleteAtShutdown() as a shutdown function - no need to do
+     * so manually.
+     *
+     * The second parameter allows the unregistering of previously registered
+     * elements.
+     *
+     * @param string $filename   The filename to be deleted at the end of the
+     *                           request.
+     * @param boolean $register  If true, then register the element for
+     *                           deletion, otherwise, unregister it.
+     * @param boolean $secure    If deleting file, should we securely delete
+     *                           the file?
+     */
+    static public function deleteAtShutdown($filename, $register = true,
+                                            $secure = false)
+    {
+        /* Initialization of variables and shutdown functions. */
+        if (!self::$_shutdownreg) {
+            register_shutdown_function(array('Horde_Util', 'shutdown'));
+            self::$_shutdownreg = true;
+        }
+
+        $ptr = &self::$_shutdowndata;
+        if ($register) {
+            if (@is_dir($filename)) {
+                $ptr['dirs'][$filename] = true;
+            } else {
+                $ptr['files'][$filename] = true;
+            }
+
+            if ($secure) {
+                $ptr['secure'][$filename] = true;
+            }
+        } else {
+            unset($ptr['dirs'][$filename], $ptr['files'][$filename], $ptr['secure'][$filename]);
+        }
+    }
+
+    /**
+     * Deletes registered files at request shutdown.
+     *
+     * This function should never be called manually; it is registered as a
+     * shutdown function by Horde_Util::deleteAtShutdown() and called
+     * automatically at the end of the request.
+     *
+     * Contains code from gpg_functions.php.
+     * Copyright 2002-2003 Braverock Ventures
+     */
+    static public function shutdown()
+    {
+        $ptr = &self::$_shutdowndata;
+
+        foreach ($ptr['files'] as $file => $val) {
+            /* Delete files */
+            if ($val && file_exists($file)) {
+                /* Should we securely delete the file by overwriting the data
+                   with a random string? */
+                if (isset($ptr['secure'][$file])) {
+                    $filesize = filesize($file);
+                    $fp = fopen($file, 'r+');
+                    foreach (self::$patterns as $pattern) {
+                        $pattern = substr(str_repeat($pattern, floor($filesize / strlen($pattern)) + 1), 0, $filesize);
+                        fwrite($fp, $pattern);
+                        fseek($fp, 0);
+                    }
+                    fclose($fp);
+                }
+                @unlink($file);
+            }
+        }
+
+        foreach ($ptr['dirs'] as $dir => $val) {
+            /* Delete directories */
+            if ($val && file_exists($dir)) {
+                /* Make sure directory is empty. */
+                $dir_class = dir($dir);
+                while (false !== ($entry = $dir_class->read())) {
+                    if ($entry != '.' && $entry != '..') {
+                        @unlink($dir . '/' . $entry);
+                    }
+                }
+                $dir_class->close();
+                @rmdir($dir);
+            }
+        }
+    }
+
+    /**
+     * Outputs javascript code to close the current window.
+     *
+     * @param string $code  Any additional javascript code to run before
+     *                      closing the window.
+     */
+    static public function closeWindowJS($code = '')
+    {
+        echo '<script type="text/javascript">//<![CDATA[' . "\n"
+            . $code . 'window.close();' . "\n//]]></script>\n";
+    }
+
+    /**
+     * Caches the result of extension_loaded() calls.
+     *
+     * @param string $ext  The extension name.
+     *
+     * @return boolean  Is the extension loaded?
+     */
+    static public function extensionExists($ext)
+    {
+        if (!isset(self::$_cache[$ext])) {
+            self::$_cache[$ext] = extension_loaded($ext);
+        }
+
+        return self::$_cache[$ext];
+    }
+
+    /**
+     * Tries to load a PHP extension, behaving correctly for all operating
+     * systems.
+     *
+     * @param string $ext  The extension to load.
+     *
+     * @return boolean  True if the extension is now loaded, false if not.
+     *                  True can mean that the extension was already loaded,
+     *                  OR was loaded dynamically.
+     */
+    static public function loadExtension($ext)
+    {
+        /* If $ext is already loaded, our work is done. */
+        if (self::extensionExists($ext)) {
+            return true;
+        }
+
+        /* See if we can call dl() at all, by the current ini settings. */
+        if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
+            return false;
+        }
+
+        if (!strncasecmp(PHP_OS, 'WIN', 3)) {
+            $suffix = 'dll';
+        } else {
+            switch (PHP_OS) {
+            case 'HP-UX':
+                $suffix = 'sl';
+                break;
+
+            case 'AIX':
+                $suffix = 'a';
+                break;
+
+            case 'OSX':
+                $suffix = 'bundle';
+                break;
+
+            default:
+                $suffix = 'so';
+            }
+        }
+
+        return @dl($ext . '.' . $suffix) || @dl('php_' . $ext . '.' . $suffix);
+    }
+
+    /**
+     * Checks if all necessary parameters for a driver's configuration are set
+     * and returns a PEAR_Error if something is missing.
+     *
+     * @param array $params   The configuration array with all parameters.
+     * @param array $fields   An array with mandatory parameter names for this
+     *                        driver.
+     * @param string $name    The clear text name of the driver. If not
+     *                        specified, the application name will be used.
+     * @param array $info     A hash containing detailed information about the
+     *                        driver. Will be passed as the userInfo to the
+     *                        PEAR_Error.
+     */
+    static public function assertDriverConfig($params, $fields, $name,
+                                              $info = array())
+    {
+        $info = array_merge($info, array(
+            'params' => $params,
+            'fields' => $fields,
+            'name' => $name
+        ));
+
+        if (!is_array($params) || !count($params)) {
+            return PEAR::throwError(sprintf(_("No configuration information specified for %s."), $name), self::HORDE_ERROR_DRIVER_CONFIG_MISSING, $info);
+        }
+
+        foreach ($fields as $field) {
+            if (!isset($params[$field])) {
+                return PEAR::throwError(sprintf(_("Required \"%s\" not specified in configuration."), $field, $name), self::HORDE_ERROR_DRIVER_CONFIG, $info);
+            }
+        }
+    }
+
+    /**
+     * Returns a format string to be used by strftime().
+     *
+     * @param string $format  A format string as used by date().
+     *
+     * @return string  A format string as similar as possible to $format.
+     */
+    static public function date2strftime($format)
+    {
+        $result = '';
+
+        for ($pos = 0; $pos < strlen($format);) {
+            for ($symbol = 0, $symcount = count(self::$dateSymbols); $symbol < $symcount; ++$symbol) {
+                if (strpos($format, self::$dateSymbols[$symbol], $pos) === $pos) {
+                    $result .= self::$strftimeSymbols[$symbol];
+                    $pos += strlen(self::$dateSymbols[$symbol]);
+                    continue 2;
+                }
+            }
+            $result .= substr($format, $pos, 1);
+            ++$pos;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Returns a format string to be used by date().
+     *
+     * @param string $format  A format string as used by strftime().
+     *
+     * @return string  A format string as similar as possible to $format.
+     */
+    static public function strftime2date($format)
+    {
+        return str_replace(self::$strftimeSymbols, self::$dateSymbols, $format);
+    }
+
+    /**
+     * Utility function to obtain PATH_INFO information.
+     *
+     * @return string  The PATH_INFO string.
+     */
+    static public function getPathInfo()
+    {
+        if (isset($_SERVER['PATH_INFO']) && strpos($_SERVER['SERVER_SOFTWARE'], 'lighttpd') === false) {
+            return $_SERVER['PATH_INFO'];
+        } elseif (isset($_SERVER['REQUEST_URI']) &&
+                  isset($_SERVER['SCRIPT_NAME'])) {
+            $search = array($_SERVER['SCRIPT_NAME']);
+            $replace = array('');
+            if (!empty($_SERVER['QUERY_STRING'])) {
+                $search[] = '?' . $_SERVER['QUERY_STRING'];
+                $replace[] = '';
+            }
+            return str_replace($search, $replace, $_SERVER['REQUEST_URI']);
+        }
+
+        return '';
+    }
+
+    /**
+     * URL-safe base64 encoding, with trimmed '='.
+     *
+     * @param string $string  String to encode.
+     *
+     * @return string  URL-safe, base64 encoded data.
+     */
+    static public function uriB64Encode($string)
+    {
+        return str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode($string));
+    }
+
+    /**
+     * Decode URL-safe base64 data, dealing with missing '='.
+     *
+     * @param string $string  Encoded data
+     *
+     * @return string  Decoded data.
+     */
+    static public function uriB64Decode($string)
+    {
+        $data = str_replace(array('-', '_'), array('+', '/'), $string);
+        $mod4 = strlen($data) % 4;
+        if ($mod4) {
+            $data .= substr('====', $mod4);
+        }
+        return base64_decode($data);
+    }
+
+}
+
+/* Stand-in functions if gettext is not available. */
+if (!function_exists('_'))
+{
+    function _($string)
+    {
+        return $string;
+    }
+
+    function ngettext($msgid1, $msgid2, $n)
+    {
+        return $n > 1 ? $msgid2 : $msgid1;
+    }
+
+    function bindtextdomain() { }
+
+    function textdomain() { }
+}
diff --git a/framework/Util/lib/Horde/Variables.php b/framework/Util/lib/Horde/Variables.php
new file mode 100644 (file)
index 0000000..f89a42c
--- /dev/null
@@ -0,0 +1,272 @@
+<?php
+/**
+ * Horde_Variables:: class.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author  Robert E. Coyle <robertecoyle@hotmail.com>
+ * @author  Chuck Hagenbuch <chuck@horde.org>
+ * @package Horde_Util
+ */
+class Horde_Variables
+{
+    /**
+     * TODO
+     */
+    protected $_vars;
+
+    /**
+     * TODO
+     */
+    protected $_expectedVariables = array();
+
+    /**
+     * TODO
+     */
+    public function __construct($vars = array())
+    {
+        if (is_null($vars)) {
+            $vars = Horde_Util::dispelMagicQuotes($_REQUEST);
+        }
+
+        if (isset($vars['_formvars'])) {
+            $this->_expectedVariables = @unserialize($vars['_formvars']);
+            unset($vars['_formvars']);
+        }
+
+        $this->_vars = $vars;
+    }
+
+    /**
+     * TODO
+     */
+    public function &getDefaultVariables()
+    {
+        $vars = new Variables(null);
+        return $vars;
+    }
+
+    /**
+     * TODO
+     */
+    public function count()
+    {
+        return count($this->_vars);
+    }
+
+    /**
+     * TODO
+     */
+    public function exists($varname)
+    {
+        return $this->__isset($varname);
+    }
+
+    /**
+     * TODO
+     */
+    public function __isset($varname)
+    {
+        if (count($this->_expectedVariables) &&
+            $this->_exists($this->_expectedVariables, $varname, false)) {
+            return true;
+        }
+
+        return $this->_exists($this->_vars, $varname, false);
+    }
+
+    /**
+     * TODO
+     */
+    public function get($varname)
+    {
+        return $this->__get($varname);
+    }
+
+    /**
+     * TODO
+     */
+    public function __get($varname)
+    {
+        $this->_getExists($this->_vars, $varname, $value);
+        return $value;
+    }
+
+    /**
+     * TODO
+     */
+    public function getExists($varname, &$exists)
+    {
+        $exists = $this->_getExists($this->_vars, $varname, $value);
+        return $value;
+    }
+
+    /**
+     * TODO
+     */
+    public function set($varname, $value)
+    {
+        return $this->__set($varname, $value);
+    }
+
+    /**
+     * TODO
+     */
+    public function __set($varname, $value)
+    {
+        $keys = array();
+        if (!Horde_Array::getArrayParts($varname, $base, $keys)) {
+            $this->_vars[$varname] = $value;
+        } else {
+            array_unshift($keys, $base);
+            $place = &$this->_vars;
+
+            while (count($keys)) {
+                $key = array_shift($keys);
+                if (!isset($place[$key])) {
+                    $place[$key] = array();
+                }
+                $place = &$place[$key];
+            }
+
+            $place = $value;
+        }
+    }
+
+    /**
+     * TODO
+     */
+    public function remove($varname)
+    {
+        return $this->__unset($varname);
+    }
+
+    /**
+     * TODO
+     */
+    public function __unset($varname)
+    {
+        Horde_Array::getArrayParts($varname, $base, $keys);
+        if (!is_null($base)) {
+            $ptr = &$this->_vars[$base];
+            $end = count($keys) - 1;
+            foreach ($keys as $key => $val) {
+                if (!isset($ptr[$val])) {
+                    break;
+                }
+                if ($end == $key) {
+                    array_splice($ptr, array_search($val, array_keys($ptr)), 1);
+                } else {
+                    $ptr = &$ptr[$val];
+                }
+            }
+        } else {
+            unset($this->_vars[$varname]);
+        }
+    }
+
+    /**
+     * TODO
+     */
+    public function merge($vars)
+    {
+        foreach ($vars as $varname => $value) {
+            $this->set($varname, $value);
+        }
+    }
+
+    /**
+     * Set $varname to $value ONLY if it's not already present.
+     */
+    public function add($varname, $value)
+    {
+        if ($this->exists($varname)) {
+            return false;
+        }
+        $this->_vars[$varname] = $value;
+    }
+
+    /**
+     * Find out whether or not $varname was set in $array.
+     *
+     * @param array $array     The array to search in (usually either
+     *                         $this->_vars or $this->_expectedVariables).
+     * @param string $varname  The name of the variable to look for.
+     * @param boolean $check   If we don't find $varname, should we check
+     *                         $this->_expectedVariables to see if should
+     *                         have existed (like a checkbox or select
+     *                         multiple).
+     *
+     * @return boolean  Whether or not the variable was set (or, if we've
+     *                  checked $this->_expectedVariables, should have been
+     *                  set).
+     */
+    protected function _exists($array, $varname, $check = true)
+    {
+        return $this->_getExists($array, $varname, $value, $check);
+    }
+
+    /**
+     * Fetch the requested variable ($varname) into $value, and return
+     * whether or not the variable was set in $array.
+     *
+     * @param array $array     The array to search in (usually either
+     *                         $this->_vars or $this->_expectedVariables).
+     * @param string $varname  The name of the variable to look for.
+     * @param mixed &$value    $varname's value gets assigned to this variable.
+     * @param boolean $check   If we don't find $varname, should we check
+     *                         $this->_expectedVariables to see if should
+     *                         have existed (like a checkbox or select
+     *                         multiple).
+     *
+     * @return boolean  Whether or not the variable was set (or, if we've
+     *                  checked $this->_expectedVariables, should have been
+     *                  set).
+     */
+    protected function _getExists($array, $varname, &$value, $check = true)
+    {
+        if (Horde_Array::getArrayParts($varname, $base, $keys)) {
+            if (!isset($array[$base])) {
+                $value = null;
+                // If we're supposed to check $this->_expectedVariables, do so,
+                // but make sure not to check it again.
+                return $check
+                    ? $this->_exists($this->_expectedVariables, $varname, false)
+                    : false;
+            } else {
+                $searchspace = &$array[$base];
+                while (count($keys)) {
+                    $key = array_shift($keys);
+                    if (!isset($searchspace[$key])) {
+                        $value = null;
+                        // If we're supposed to check
+                        // $this->_expectedVariables, do so, but make
+                        // sure not to check it again.
+                        return $check
+                            ? $this->_exists($this->_expectedVariables, $varname, false)
+                            : false;
+                    }
+                    $searchspace = &$searchspace[$key];
+                }
+                $value = $searchspace;
+                return true;
+            }
+        } else {
+            $value = isset($array[$varname]) ? $array[$varname] : null;
+            if (!is_null($value)) {
+                return true;
+            } elseif ($check) {
+                // If we're supposed to check
+                // $this->_expectedVariables, do so, but make sure not
+                // to check it again.
+                return $this->_exists($this->_expectedVariables, $varname, false);
+            } else {
+                return false;
+            }
+        }
+    }
+
+}
diff --git a/framework/Util/package.xml b/framework/Util/package.xml
new file mode 100644 (file)
index 0000000..f75353c
--- /dev/null
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
+ <name>Util</name>
+ <channel>pear.horde.org</channel>
+ <summary>Horde Utility Libraries</summary>
+ <description>These classes provide functionality useful for all kind of applications.</description>
+ <lead>
+  <name>Chuck Hagenbuch</name>
+  <user>chuck</user>
+  <email>chuck@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Jan Schneider</name>
+  <user>jan</user>
+  <email>jan@horde.org</email>
+  <active>yes</active>
+ </lead>
+ <date>2009-06-09</date>
+ <version>
+  <release>0.2.0</release>
+  <api>0.2.0</api>
+ </version>
+ <stability>
+  <release>beta</release>
+  <api>beta</api>
+ </stability>
+ <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+ <notes>* Removed Horde_Array::combine() and Horde_Util::hmac().
+ * Initial Horde 4 package.
+ </notes>
+ <contents>
+  <dir name="/">
+   <dir name="lib">
+    <dir name="Horde">
+     <dir name="Array">
+      <dir name="Sort">
+       <file name="Helper.php" role="php" />
+      </dir> <!-- /lib/Horde/Array/Sort -->
+     </dir> <!-- /lib/Horde/Array -->
+     <file name="Array.php" role="php" />
+     <file name="String.php" role="php" />
+     <file name="Util.php" role="php" />
+     <file name="Variables.php" role="php" />
+    </dir> <!-- /lib/Horde -->
+   </dir> <!-- /lib -->
+   <dir name="test">
+    <dir name="Horde">
+     <dir name="Util">
+      <file name="Array_sort.phpt" role="test" />
+      <file name="Variables_remove.phpt" role="test" />
+      <file name="addParameter.phpt" role="test" />
+      <file name="case.phpt" role="test" />
+      <file name="case_php6.phpt" role="test" />
+      <file name="length.phpt" role="test" />
+      <file name="pad.phpt" role="test" />
+      <file name="removeParameter.phpt" role="test" />
+      <file name="utf-8.phpt" role="test" />
+     </dir> <!-- /test/Horde/Util -->
+    </dir> <!-- /test/Horde -->
+   </dir> <!-- /test -->
+  </dir> <!-- / -->
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.5.4</min>
+   </pearinstaller>
+  </required>
+  <optional>
+   <package>
+    <name>PEAR</name>
+    <channel>pear.php.net</channel>
+   </package>
+   <package>
+    <name>Horde_Browser</name>
+    <channel>pear.horde.org</channel>
+   </package>
+   <extension>
+    <name>iconv</name>
+   </extension>
+   <extension>
+    <name>mbstring</name>
+   </extension>
+  </optional>
+ </dependencies>
+ <phprelease>
+  <filelist>
+   <install name="lib/Horde/Array.php" as="Horde/Array.php" />
+   <install name="lib/Horde/Array/Sort/Helper.php" as="Horde/Array/Sort/Helper.php" />
+   <install name="lib/Horde/String.php" as="Horde/String.php" />
+   <install name="lib/Horde/Util.php" as="Horde/Util.php" />
+   <install name="lib/Horde/Variables.php" as="Horde/Variables.php" />
+  </filelist>
+ </phprelease>
+ <changelog>
+  <release>
+   <version>
+    <release>0.1.0</release>
+    <api>0.1.0</api>
+   </version>
+   <date>2008-09-25</date>
+   <stability>
+    <release>beta</release>
+    <api>beta</api>
+   </stability>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>* Added magic PHP5 methods to the Variables class.
+* Added array_merge_recursive_overwrite() to Horde_Array().
+* Fixed a bug in Horde_Array::arraySort where auto-detecting the first key failed.
+* Added sorter functions for array keys.
+* Removed use of array_unique().
+* Cleaned up addParameter() in the Util class.
+* Implemented a much more efficient, yet safer file wiping algorithm.
+* Fixed Util::addParameter when it is passed a base URL that contains an urlencoded ampersand.
+* Added a parameter to Util::nocacheUrl() to not encode url.
+* Added Util::getPathInfo().
+* Signed parameters to go.php with an HMAC based on a new secret key configuration value, to prevent using go.php as an open referrer.
+* Made logout tokens only valid for a configurable length of time.
+* Made it possible to use String.php without having any other files available.
+* Use utf8_decode() in String::length() if possible.
+* Always use preg_match() in String::regexMatch().
+* Workaround for korean messages in a non-standard charset.
+* Fixed String::substr() length calculations.
+* Added multibyte-safe String::wordwrap() method.
+* Added parameter to use wordwrap() for line folding.
+* Use C as the portable locale (Bug #6194).
+* Don't use utf8_encode/decode on very large strings if other options are available. (Bug #6660)
+* Fixed order of checks in String::convertCharset (Bug #6794).
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.0.2</release>
+    <api>0.0.2</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <date>2006-05-08</date>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Converted to package.xml 2.0 for pear.horde.org
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>0.0.1</release>
+    <api>0.0.1</api>
+   </version>
+   <stability>
+    <release>alpha</release>
+    <api>alpha</api>
+   </stability>
+   <date>2003-10-28</date>
+   <license uri="http://www.gnu.org/copyleft/lesser.html">LGPL</license>
+   <notes>Initial release as a PEAR package
+   </notes>
+  </release>
+ </changelog>
+</package>
diff --git a/framework/Util/test/Horde/Util/Array_sort.phpt b/framework/Util/test/Horde/Util/Array_sort.phpt
new file mode 100644 (file)
index 0000000..5746471
--- /dev/null
@@ -0,0 +1,88 @@
+--TEST--
+Horde_Array::arraySort() tests
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../Array.php';
+$array = array(
+    array('name' => 'foo', 'desc' => 'foo long desc'),
+    array('name' => 'aaaa', 'desc' => 'aaa foo long desc'),
+    array('name' => 'baby', 'desc' => 'The test data was boring'),
+    array('name' => 'zebra', 'desc' => 'Striped armadillos'),
+    array('name' => 'umbrage', 'desc' => 'resentment'),
+);
+
+Horde_Array::arraySort($array);
+print_r($array);
+
+Horde_Array::arraySort($array, 'desc');
+print_r($array);
+
+?>
+--EXPECT--
+Array
+(
+    [1] => Array
+        (
+            [name] => aaaa
+            [desc] => aaa foo long desc
+        )
+
+    [2] => Array
+        (
+            [name] => baby
+            [desc] => The test data was boring
+        )
+
+    [0] => Array
+        (
+            [name] => foo
+            [desc] => foo long desc
+        )
+
+    [4] => Array
+        (
+            [name] => umbrage
+            [desc] => resentment
+        )
+
+    [3] => Array
+        (
+            [name] => zebra
+            [desc] => Striped armadillos
+        )
+
+)
+Array
+(
+    [1] => Array
+        (
+            [name] => aaaa
+            [desc] => aaa foo long desc
+        )
+
+    [0] => Array
+        (
+            [name] => foo
+            [desc] => foo long desc
+        )
+
+    [4] => Array
+        (
+            [name] => umbrage
+            [desc] => resentment
+        )
+
+    [3] => Array
+        (
+            [name] => zebra
+            [desc] => Striped armadillos
+        )
+
+    [2] => Array
+        (
+            [name] => baby
+            [desc] => The test data was boring
+        )
+
+)
diff --git a/framework/Util/test/Horde/Util/Variables_remove.phpt b/framework/Util/test/Horde/Util/Variables_remove.phpt
new file mode 100644 (file)
index 0000000..ff71315
--- /dev/null
@@ -0,0 +1,46 @@
+--TEST--
+Variables::remove() tests
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../Variables.php';
+$vars = new Variables(array(
+   'a' => 'a',
+   'b' => 'b',
+   'c' => array(1, 2, 3),
+   'd' => array(
+       'z' => 'z',
+       'y' => array(
+           'f' => 'f',
+           'g' => 'g'
+       )
+   )
+));
+
+$vars->remove('a');
+$vars->remove('d[y][g]');
+print_r($vars->_vars);
+
+?>
+--EXPECT--
+Array
+(
+    [b] => b
+    [c] => Array
+        (
+            [0] => 1
+            [1] => 2
+            [2] => 3
+        )
+
+    [d] => Array
+        (
+            [z] => z
+            [y] => Array
+                (
+                    [f] => f
+                )
+
+        )
+
+)
diff --git a/framework/Util/test/Horde/Util/addParameter.phpt b/framework/Util/test/Horde/Util/addParameter.phpt
new file mode 100644 (file)
index 0000000..651d72c
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+Horde_Util::addParameter() tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+
+$url = 'test';
+echo ($url = Horde_Util::addParameter($url, 'foo', 1)) . "\n";
+echo ($url = Horde_Util::addParameter($url, 'bar', 2)) . "\n";
+echo Horde_Util::addParameter($url, 'baz', 3) . "\n";
+echo Horde_Util::addParameter('test', array('foo' => 1, 'bar' => 2)) . "\n";
+echo Horde_Util::addParameter('test?foo=1', array('bar' => 2, 'baz' => 3)) . "\n";
+echo Horde_Util::addParameter('test?foo=1&bar=2', array('baz' => 3)) . "\n";
+echo Horde_Util::addParameter('test?foo=1&bar=2', array('foo' => 1, 'bar' => 3)) . "\n";
+echo Horde_Util::addParameter('test?foo=1&amp;bar=2', 'baz', 3) . "\n";
+echo ($url = Horde_Util::addParameter('test', 'foo', 'bar&baz')) . "\n";
+echo Horde_Util::addParameter($url, 'x', 'y') . "\n";
+echo Horde_Util::addParameter($url, 'x', 'y', false) . "\n";
+echo Horde_Util::addParameter(Horde_Util::addParameter('test', 'x', 'y'), 'foo', 'bar&baz') . "\n";
+
+?>
+--EXPECT--
+test?foo=1
+test?foo=1&amp;bar=2
+test?foo=1&amp;bar=2&amp;baz=3
+test?foo=1&amp;bar=2
+test?foo=1&amp;bar=2&amp;baz=3
+test?foo=1&bar=2&baz=3
+test?foo=1&bar=3
+test?foo=1&amp;bar=2&amp;baz=3
+test?foo=bar%26baz
+test?foo=bar%26baz&amp;x=y
+test?foo=bar%26baz&x=y
+test?x=y&amp;foo=bar%26baz
diff --git a/framework/Util/test/Horde/Util/case.phpt b/framework/Util/test/Horde/Util/case.phpt
new file mode 100644 (file)
index 0000000..aca8edf
--- /dev/null
@@ -0,0 +1,42 @@
+--TEST--
+Horde_String:: case tests
+--SKIPIF--
+<?php
+if (!setlocale(LC_ALL, 'tr_TR')) echo 'skip No Turkish locale installed.';
+?>
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+require_once dirname(__FILE__) . '/../../lib/Horde/String.php';
+
+echo Horde_String::upper('abCDefGHiI', true, 'us-ascii') . "\n";
+echo Horde_String::lower('abCDefGHiI', true, 'us-ascii') . "\n";
+echo "\n";
+echo Horde_String::upper('abCDefGHiI', true, 'Big5') . "\n";
+echo Horde_String::lower('abCDefGHiI', true, 'Big5') . "\n";
+echo "\n";
+setlocale(LC_ALL, 'tr_TR');
+echo strtoupper('abCDefGHiI') . "\n";
+echo strtolower('abCDefGHiI') . "\n";
+echo ucfirst('integer') . "\n";
+echo "\n";
+echo Horde_String::upper('abCDefGHiI') . "\n";
+echo Horde_String::lower('abCDefGHiI') . "\n";
+echo Horde_String::ucfirst('integer') . "\n";
+
+?>
+--EXPECT--
+ABCDEFGHII
+abcdefghii
+
+ABCDEFGHII
+abcdefghii
+
+ABCDEFGHÝI
+abcdefghiý
+Ýnteger
+
+ABCDEFGHII
+abcdefghii
+Integer
diff --git a/framework/Util/test/Horde/Util/case_php6.phpt b/framework/Util/test/Horde/Util/case_php6.phpt
new file mode 100644 (file)
index 0000000..5071236
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Horde_String:: case PHP 6 tests
+--SKIPIF--
+<?php
+if (version_compare(PHP_VERSION, '6.0', '<')) {
+   echo 'skip mbstring is broken in PHP < 6.0';
+}
+?>
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+require_once dirname(__FILE__) . '/../../lib/Horde/String.php';
+
+echo Horde_String::upper('abCDefGHiI', true, 'iso-8859-9') . "\n";
+echo Horde_String::lower('abCDefGHiI', true, 'iso-8859-9') . "\n";
+echo "\n";
+echo Horde_String::ucfirst('integer', true, 'us-ascii') . "\n";
+echo Horde_String::ucfirst('integer', true, 'iso-8859-9') . "\n";
+
+?>
+--EXPECT--
+ABCDEFGHÝI
+abcdefghiý
+
+Integer
+Ýnteger
diff --git a/framework/Util/test/Horde/Util/length.phpt b/framework/Util/test/Horde/Util/length.phpt
new file mode 100644 (file)
index 0000000..f59ba0c
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+Horde_String::length() tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+require_once dirname(__FILE__) . '/../../lib/Horde/String.php';
+
+echo Horde_String::length('Welcome', 'Big5'). "\n";
+echo Horde_String::length('Welcome', 'Big5'). "\n";
+echo Horde_String::length('Åwªï', 'Big5') . "\n";
+echo Horde_String::length('æ­¡è¿å°', 'utf-8') . "\n";
+
+?>
+--EXPECT--
+7
+7
+2
+3
diff --git a/framework/Util/test/Horde/Util/pad.phpt b/framework/Util/test/Horde/Util/pad.phpt
new file mode 100644 (file)
index 0000000..f075dd2
--- /dev/null
@@ -0,0 +1,65 @@
+--TEST--
+Horde_String::pad() tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+require_once dirname(__FILE__) . '/../../lib/Horde/String.php';
+
+/* Simple single byte tests. */
+echo Horde_String::pad('abc', 2) . "\n";
+echo Horde_String::pad('abc', 3) . "\n";
+echo Horde_String::pad('abc', 4) . "\n";
+echo Horde_String::pad('abc', 4, ' ', STR_PAD_LEFT) . "\n";
+echo Horde_String::pad('abc', 4, ' ', STR_PAD_RIGHT) . "\n";
+echo Horde_String::pad('abc', 4, ' ', STR_PAD_BOTH) . "\n";
+echo Horde_String::pad('abc', 5, ' ', STR_PAD_LEFT) . "\n";
+echo Horde_String::pad('abc', 5, ' ', STR_PAD_RIGHT) . "\n";
+echo Horde_String::pad('abc', 5, ' ', STR_PAD_BOTH) . "\n";
+
+/* Long padding tests. */
+echo "\n";
+echo Horde_String::pad('abc', 10, '=-+', STR_PAD_LEFT) . "\n";
+echo Horde_String::pad('abc', 10, '=-+', STR_PAD_RIGHT) . "\n";
+echo Horde_String::pad('abc', 10, '=-+', STR_PAD_BOTH) . "\n";
+
+/* Multibyte tests. */
+echo "\n";
+echo Horde_String::pad('äöü', 4, ' ', STR_PAD_LEFT, 'UTF-8') . "\n";
+echo Horde_String::pad('äöü', 4, ' ', STR_PAD_RIGHT, 'UTF-8') . "\n";
+echo Horde_String::pad('äöü', 4, ' ', STR_PAD_BOTH, 'UTF-8') . "\n";
+echo "\n";
+echo Horde_String::pad('abc', 10, 'äöü', STR_PAD_LEFT, 'UTF-8') . "\n";
+echo Horde_String::pad('abc', 10, 'äöü', STR_PAD_RIGHT, 'UTF-8') . "\n";
+echo Horde_String::pad('abc', 10, 'äöü', STR_PAD_BOTH, 'UTF-8') . "\n";
+
+/* Special cases. */
+echo "\n";
+echo Horde_String::pad('abc', 4, ' ', STR_PAD_RIGHT, 'UTF-8') . "\n";
+
+
+?>
+--EXPECT--
+abc
+abc
+abc 
+ abc
+abc 
+abc 
+  abc
+abc  
+ abc 
+
+=-+=-+=abc
+abc=-+=-+=
+=-+abc=-+=
+
+ äöü
+äöü 
+äöü 
+
+äöüäöüäabc
+abcäöüäöüä
+äöüabcäöüä
+
+abc 
diff --git a/framework/Util/test/Horde/Util/removeParameter.phpt b/framework/Util/test/Horde/Util/removeParameter.phpt
new file mode 100644 (file)
index 0000000..2a35b83
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+Horde_Util::removeParameter() tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+
+$url = 'test?foo=1&bar=2';
+echo Horde_Util::removeParameter($url, 'foo') . "\n";
+echo Horde_Util::removeParameter($url, 'bar') . "\n";
+echo Horde_Util::removeParameter($url, array('foo', 'bar')) . "\n";
+$url = 'test?foo=1&amp;bar=2';
+echo Horde_Util::removeParameter($url, 'foo') . "\n";
+echo Horde_Util::removeParameter($url, 'bar') . "\n";
+echo Horde_Util::removeParameter($url, array('foo', 'bar')) . "\n";
+$url = 'test?foo=1&bar=2&baz=3';
+echo Horde_Util::removeParameter($url, 'foo') . "\n";
+$url = 'test?foo=1&amp;bar=2&amp;baz=3';
+echo Horde_Util::removeParameter($url, 'foo') . "\n";
+
+?>
+--EXPECT--
+test?bar=2
+test?foo=1
+test
+test?bar=2
+test?foo=1
+test
+test?bar=2&baz=3
+test?bar=2&amp;baz=3
diff --git a/framework/Util/test/Horde/Util/substr.phpt b/framework/Util/test/Horde/Util/substr.phpt
new file mode 100644 (file)
index 0000000..733fb87
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Horde_String::substr() tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+require_once dirname(__FILE__) . '/../../lib/Horde/String.php';
+
+$string = "Lörem ipsüm dölör sit ämet";
+echo Horde_String::substr($string, 20, null, 'UTF-8') . "\n";
+echo Horde_String::substr($string, -6, null, 'utf-8') . "\n";
+echo Horde_String::substr($string, 0, 5, 'utf-8') . "\n";
+echo Horde_String::substr($string, 0, -21, 'utf-8') . "\n";
+echo Horde_String::substr($string, 6, 5, 'utf-8') . "\n";
+
+?>
+--EXPECT--
+t ämet
+t ämet
+Lörem
+Lörem
+ipsüm
diff --git a/framework/Util/test/Horde/Util/utf-8.phpt b/framework/Util/test/Horde/Util/utf-8.phpt
new file mode 100644 (file)
index 0000000..0eeb663
--- /dev/null
@@ -0,0 +1,59 @@
+--TEST--
+UTF-8 Horde_String:: tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+require_once dirname(__FILE__) . '/../../lib/Horde/String.php';
+
+/* The following strings were taken with permission from the UTF-8
+ * sampler by Frank da Cruz <fdc@columbia.edu> and the Kermit Project
+ * (http://www.columbia.edu/kermit/).  The original page is located at
+ * http://www.columbia.edu/kermit/utf8.html */
+
+// French 50
+echo Horde_String::length('Je peux manger du verre, ça ne me fait pas de mal.', 'UTF-8') . "\n";
+
+// Spanish 36
+echo Horde_String::length('Puedo comer vidrio, no me hace daño.', 'UTF-8') . "\n";
+
+// Portuguese 34
+echo Horde_String::length('Posso comer vidro, não me faz mal.', 'UTF-8') . "\n";
+
+// Brazilian Portuguese 34
+echo Horde_String::length('Posso comer vidro, não me machuca.', 'UTF-8') . "\n";
+
+// Italian 41
+echo Horde_String::length('Posso mangiare il vetro e non mi fa male.', 'UTF-8') . "\n";
+
+// English 39
+echo Horde_String::length('I can eat glass and it doesn\'t hurt me.', 'UTF-8') . "\n";
+
+// Norsk/Norwegian/Nynorsk 33 
+echo Horde_String::length('Eg kan eta glas utan å skada meg.', 'UTF-8') . "\n";
+
+// Svensk/Swedish 36
+echo Horde_String::length('Jag kan äta glas utan att skada mig.', 'UTF-8') . "\n";
+
+// Dansk/Danish 45
+echo Horde_String::length('Jeg kan spise glas, det gør ikke ondt på mig.', 'UTF-8') . "\n";
+
+// Deutsch/German 41
+echo Horde_String::length('Ich kann Glas essen, ohne mir weh zu tun.', 'UTF-8') . "\n";
+
+// Russian 38
+echo Horde_String::length('Я могу есть стекло, оно мне не вредит.', 'UTF-8') . "\n";
+
+?>
+--EXPECT--
+50
+36
+34
+34
+41
+39
+33
+36
+45
+41
+38
diff --git a/framework/Util/test/Horde/Util/wordwrap.phpt b/framework/Util/test/Horde/Util/wordwrap.phpt
new file mode 100644 (file)
index 0000000..89eb2b7
--- /dev/null
@@ -0,0 +1,111 @@
+--TEST--
+Horde_String::wordwrap() tests
+--FILE--
+<?php
+
+require_once dirname(__FILE__) . '/../../lib/Horde/Util.php';
+require_once dirname(__FILE__) . '/../../lib/Horde/String.php';
+
+// Test default parameters and break character.
+$string = "Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing elit. Aliqüäm söllicitüdin fäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 75, "\n", false, 'utf-8') . "\n\n";
+echo Horde_String::wordwrap($string, 30, "\n  ", false, 'utf-8') . "\n\n";
+
+// Test existing line breaks.
+$string = "Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing elit.\nAliqüäm söllicitüdin fäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 75, "\n", false, 'utf-8') . "\n\n";
+$string = "Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing elit. Aliqüäm\nsöllicitüdin fäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 75, "\n", false, 'utf-8') . "\n\n";
+$string = "Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing elit. Aliqüäm söllicitüdin\nfäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 75, "\n", false, 'utf-8') . "\n\n";
+
+// Test overlong words and word cut.
+$string = "Löremipsümdölörsitämet, cönsectetüerädipiscingelit.";
+echo Horde_String::wordwrap($string, 15, "\n", false, 'utf-8') . "\n\n";
+$string = "Löremipsümdölörsitämet, cönsectetüerädipiscingelit.";
+echo Horde_String::wordwrap($string, 15, "\n", true, 'utf-8') . "\n\n";
+
+// Test whitespace at wrap width.
+$string = "Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing";
+echo Horde_String::wordwrap($string, 27, "\n", false, 'utf-8') . "\n\n";
+echo Horde_String::wordwrap($string, 28, "\n", false, 'utf-8') . "\n\n";
+
+// Test line folding.
+$string = "Löremipsümdölörsitämet, cönsectetüerädipiscingelit.";
+echo Horde_String::wordwrap($string, 15, "\n", true, 'utf-8', true) . "\n\n";
+$string = "Lörem ipsüm dölör sit ämet,  cönsectetüer ädipiscing elit.  Aliqüäm söllicitüdin fäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 31, "\n", false, 'utf-8', true) . "\n\n";
+$string = "Lörem ipsüm dölör sit; ämet:  cönsectetüer ädipiscing elit.  Aliqüäm söllicitüdin fäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 31, "\n", false, 'utf-8', true) . "\n\n";
+$string = "Lörem ipsüm dölör sit; ämet:cönsectetüer ädipiscing elit.  Aliqüäm söllicitüdin fäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 31, "\n", false, 'utf-8', true) . "\n\n";
+$string = "Lörem ipsüm dölör sit; ämet;  cönsectetüer ädipiscing elit.  Aliqüäm söllicitüdin fäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 31, "\n", false, 'utf-8', true) . "\n\n";
+$string = "Lörem ipsüm dölör sit; ämet;cönsectetüer ädipiscing elit.  Aliqüäm söllicitüdin fäücibüs mäüris ämet.";
+echo Horde_String::wordwrap($string, 31, "\n", false, 'utf-8', true) . "\n\n";
+
+?>
+--EXPECT--
+Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing elit. Aliqüäm
+söllicitüdin fäücibüs mäüris ämet.
+
+Lörem ipsüm dölör sit ämet,
+  cönsectetüer ädipiscing elit.
+  Aliqüäm söllicitüdin fäücibüs
+  mäüris ämet.
+
+Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing elit.
+Aliqüäm söllicitüdin fäücibüs mäüris ämet.
+
+Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing elit. Aliqüäm
+söllicitüdin fäücibüs mäüris ämet.
+
+Lörem ipsüm dölör sit ämet, cönsectetüer ädipiscing elit. Aliqüäm
+söllicitüdin
+fäücibüs mäüris ämet.
+
+Löremipsümdölörsitämet,
+cönsectetüerädipiscingelit.
+
+Löremipsümdölör
+sitämet,
+cönsectetüerädi
+piscingelit.
+
+Lörem ipsüm dölör sit ämet,
+cönsectetüer ädipiscing
+
+Lörem ipsüm dölör sit ämet,
+cönsectetüer ädipiscing
+
+Löremipsümdölör
+sitämet,
+ cönsectetüeräd
+ipiscingelit.
+
+Lörem ipsüm dölör sit ämet,
+  cönsectetüer ädipiscing elit.
+  Aliqüäm söllicitüdin fäücibüs
+ mäüris ämet.
+
+Lörem ipsüm dölör sit;
+ ämet:
+  cönsectetüer ädipiscing elit.
+  Aliqüäm söllicitüdin fäücibüs
+ mäüris ämet.
+
+Lörem ipsüm dölör sit;
+ ämet:cönsectetüer ädipiscing
+ elit.  Aliqüäm söllicitüdin
+ fäücibüs mäüris ämet.
+
+Lörem ipsüm dölör sit;
+ ämet;
+  cönsectetüer ädipiscing elit.
+  Aliqüäm söllicitüdin fäücibüs
+ mäüris ämet.
+
+Lörem ipsüm dölör sit;
+ ämet;cönsectetüer ädipiscing
+ elit.  Aliqüäm söllicitüdin
+ fäücibüs mäüris ämet.