diff --git a/.gitignore b/.gitignore index d81178e11..49dc19fce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,23 @@ +# General +.DS_Store +._* +_* +*~ +*.sublime-project +*.sublime-workspace +.idea/ +.vscode/ +Thumbs.db +nbproject/ + +# Config config.php + +# WEB-INF +WEB-INF/cache/ WEB-INF/templates_c/*.* WEB-INF/templates_c/import_* WEB-INF/templates_c/tt* WEB-INF/lib/tcpdf/ -nbproject/ upload/ -.vscode/ -Thumbs.db -*.DS_Store -*~ -.idea/ -api/ +api/ \ No newline at end of file diff --git a/.htaccess b/.htaccess index 3b6168c75..aaca1cefd 100644 --- a/.htaccess +++ b/.htaccess @@ -1,3 +1,4 @@ +Options -Indexes AddDefaultCharset utf-8 # Restrict access to Time Tracker only from certain IPs. diff --git a/2fa.php b/2fa.php index a7e3dbb29..de38c9c90 100644 --- a/2fa.php +++ b/2fa.php @@ -18,9 +18,9 @@ $cl_auth_code = $request->getParameter('auth_code'); $form = new Form('twoFactorAuthForm'); -$form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'login','value'=>$cl_login)); +$form->addInput(array('type'=>'text','maxlength'=>'80','name'=>'login','value'=>$cl_login)); $form->getElement('login')->setEnabled(false); -$form->addInput(array('type'=>'password','maxlength'=>'50','name'=>'password','value'=>$cl_password)); +$form->addInput(array('type'=>'password','maxlength'=>'128','name'=>'password','value'=>$cl_password)); $form->addInput(array('type'=>'text','maxlength'=>'100','name'=>'auth_code','value'=>$cl_auth_code)); $form->addInput(array('type'=>'submit','name'=>'btn_login','value'=>$i18n->get('button.login'))); diff --git a/WEB-INF/.htaccess b/WEB-INF/.htaccess new file mode 100644 index 000000000..8ab380ebe --- /dev/null +++ b/WEB-INF/.htaccess @@ -0,0 +1,4 @@ + + order deny,allow + allow from all + \ No newline at end of file diff --git a/WEB-INF/cache/keepme b/WEB-INF/cache/keepme new file mode 100644 index 000000000..e69de29bb diff --git a/WEB-INF/config.php.dist b/WEB-INF/config.php.dist index 6b6a68d84..3728a830b 100644 --- a/WEB-INF/config.php.dist +++ b/WEB-INF/config.php.dist @@ -68,6 +68,13 @@ define('WEEKEND_START_DAY', 6); // define('PHP_SESSION_PATH', '/tmp/timetracker'); // Directory must exist and be writable. +// SESSION_HANDLER +// Set session storage. +// 'file' : file stroage. Default value +// 'db' : db stroage +define('SESSION_HANDLER', 'file'); + + // LOGIN_COOKIE_NAME // // Cookie name for user login to remember it between browser sessions. @@ -132,6 +139,26 @@ define('REPORT_FOOTER', true); // ldap - authentication against an LDAP directory such as OpenLDAP or Windows Active Directory. define('AUTH_MODULE', 'db'); +// Password hash algorithm +// Possible values +// - DEFAULT ; bcrypt algorithm +// - BCRYPT : crypt blowfish algorithm +// - ARGON2I : Argon2i hashing algorithm (only available if PHP has been compiled with Argon2 support) +// - ARGON2ID : Argon2id hashing algorithm (only available if PHP has been compiled with Argon2 support) +define('AUTH_DB_HASH_ALGORITHM', 'BCRYPT'); + +// Password hash options +// +define('AUTH_DB_HASH_ALGORITHM_OPTIONS', array('cost' => 10)); + +// Login minlength +// +//define('AUTH_DB_LOGIN_MINLENGTH', 5); + +// Password minlength +// +//define('AUTH_DB_PWD_MINLENGTH', 12); + // LDAP authentication examples. // Go to https://www.anuko.com/time-tracker/install-guide/ldap-auth/index.htm for detailed configuration instructions. diff --git a/WEB-INF/configs/keepme b/WEB-INF/configs/keepme new file mode 100644 index 000000000..e69de29bb diff --git a/WEB-INF/lib/Auth.class.php b/WEB-INF/lib/Auth.class.php index 783721090..1b7374956 100644 --- a/WEB-INF/lib/Auth.class.php +++ b/WEB-INF/lib/Auth.class.php @@ -31,16 +31,18 @@ class Auth { // isAuthenticated - checks authentication status for user. function isAuthenticated() { if (isset($_SESSION['authenticated'])) { -// This check does not work properly because we are not getting here. Need to improve. -// if (!isset($_COOKIE[LOGIN_COOKIE_NAME])) { -// die ("Your browser's cookie functionality is turned off. Please turn it on."); -// } + // This check does not work properly because we are not getting here. Need to improve. + // if (!isset($_COOKIE[LOGIN_COOKIE_NAME])) { + // die ("Your browser's cookie functionality is turned off. Please turn it on."); + // } global $smarty; $smarty->assign('authenticated', true); // Used in header.tpl for menu display. return true; } session_write_close(); + global $smarty; + $smarty->assign('authenticated', false); // Used in header.tpl for menu display. return false; } diff --git a/WEB-INF/lib/I18n.class.php b/WEB-INF/lib/I18n.class.php index bd4e9ffd3..03da164ed 100644 --- a/WEB-INF/lib/I18n.class.php +++ b/WEB-INF/lib/I18n.class.php @@ -46,7 +46,7 @@ function get($key) { } eval("\$value = \$this->keys".$str.";"); } else { - $value = $this->keys[$key]; + $value = isset($this->keys[$key]) ? $this->keys[$key] : ''; } return $value; } diff --git a/WEB-INF/lib/auth/Auth_db.class.php b/WEB-INF/lib/auth/Auth_db.class.php index b5fbdaef9..ed0904ad0 100644 --- a/WEB-INF/lib/auth/Auth_db.class.php +++ b/WEB-INF/lib/auth/Auth_db.class.php @@ -19,9 +19,41 @@ function authenticate($login, $password) { $mdb2 = getConnection(); + if (AUTH_DB_HASH_ALGORITHM !== '') { + $sql = "SELECT id, password as hash FROM tt_users"." WHERE login = ".$mdb2->quote($login)." AND status = 1"; + $res = $mdb2->query($sql); + if (is_a($res, 'PEAR_Error')) { + die($res->getMessage()); + } + $val = $res->fetchRow(); + if (isset($val['id']) && $val['id'] > 0) { + if (password_verify($password, $val['hash'])) { + if (password_needs_rehash($val['hash'], PASSWORD_ALGORITHM, AUTH_DB_HASH_ALGORITHM_OPTIONS)) { + $sql = "update `tt_users` set `password` = '".password_hash($password, PASSWORD_ALGORITHM, AUTH_DB_HASH_ALGORITHM_OPTIONS)."' where `id` = " . $mdb2->quote($val['id']); + $affected = $mdb2->exec($sql); + if (is_a($res, 'PEAR_Error')) die($res->getMessage()); + } + return array('login'=>$login,'id'=>$val['id']); + } + } + } + else { + // md5 hash + $sql = "SELECT id FROM tt_users"." WHERE login = ".$mdb2->quote($login)." AND password = md5(".$mdb2->quote($password).") AND status = 1"; + $res = $mdb2->query($sql); + if (is_a($res, 'PEAR_Error')) { + die($res->getMessage()); + } + $val = $res->fetchRow(); + if (isset($val['id']) && $val['id'] > 0) { + return array('login'=>$login,'id'=>$val['id']); + } + } + return false; + + /* // Try md5 password match first. - $sql = "SELECT id FROM tt_users". - " WHERE login = ".$mdb2->quote($login)." AND password = md5(".$mdb2->quote($password).") AND status = 1"; + $sql = "SELECT id FROM tt_users"." WHERE login = ".$mdb2->quote($login)." AND password = md5(".$mdb2->quote($password).") AND status = 1"; $res = $mdb2->query($sql); if (is_a($res, 'PEAR_Error')) { @@ -74,6 +106,7 @@ function authenticate($login, $password) } return false; + */ } function isPasswordExternal() { diff --git a/WEB-INF/lib/common.lib.php b/WEB-INF/lib/common.lib.php index 79aba106b..838588567 100644 --- a/WEB-INF/lib/common.lib.php +++ b/WEB-INF/lib/common.lib.php @@ -150,7 +150,7 @@ function ttValidString($val, $emptyValid = false, $maxChars = 0) // ttValidCss is used to check user input for custom css. function ttValidCss($val) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return true; @@ -169,7 +169,7 @@ function ttValidCss($val) // ttValidTranslation is used to check user input for custom translation. function ttValidTranslation($val) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return true; @@ -186,7 +186,7 @@ function ttValidTranslation($val) // ttValidTranslationLine is used to check an individual line in custom translation. function ttValidTranslationLine($val) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return false; // Empty line is not valid. @@ -211,14 +211,15 @@ function ttValidTranslationLine($val) // We identify these parts by 3 "stop sign" emojis (aka "octagonal sign" U+1F6D1). function ttValidTemplateText($val) { - $valid = strpos($val, '🛑🛑🛑') === false; // no 3 "stop sign" emojis in a row. + + $valid = (is_null($val) ? false : strpos($val, '🛑🛑🛑') === false); // no 3 "stop sign" emojis in a row. return $valid; } // ttValidEmail is used to check user input to validate an email string. function ttValidEmail($val, $emptyValid = false) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return ($emptyValid ? true : false); @@ -236,7 +237,7 @@ function ttValidEmail($val, $emptyValid = false) // ttValidEmailList is used to check user input to validate an email string. function ttValidEmailList($val, $emptyValid = false) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return ($emptyValid ? true : false); @@ -254,7 +255,7 @@ function ttValidEmailList($val, $emptyValid = false) // ttValidFloat is used to check user input to validate a float value. function ttValidFloat($val, $emptyValid = false) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return ($emptyValid ? true : false); @@ -368,7 +369,7 @@ function ttValidTime($val) // ttValidInteger is used to check user input to validate an integer. function ttValidInteger($val, $emptyValid = false) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return ($emptyValid ? true : false); @@ -424,7 +425,7 @@ function ttValidCronSpec($val) // But this works. $regexp = '/^'.$fields_re.'$/'; - + if (is_null($val)) return false; if (!preg_match($regexp, $val)) return false; @@ -434,7 +435,7 @@ function ttValidCronSpec($val) // ttValidCondition is used to check user input to validate a notification condition. function ttValidCondition($val, $emptyValid = true) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return ($emptyValid ? true : false); @@ -455,7 +456,7 @@ function ttValidCondition($val, $emptyValid = true) // For example, IPv4-mapped IPv6 addresses will fail. This may need to be fixed. function ttValidIP($val, $emptyValid = false) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0 && $emptyValid) return true; @@ -475,7 +476,7 @@ function ttValidIP($val, $emptyValid = false) // The above means Jan 1 and Dec 31 are holidays in all years, while Apr 20 is only in 2019. function ttValidHolidays($val) { - $val = trim($val); + $val = is_null($val) ? '' : trim($val); if (strlen($val) == 0) return true; $dates = explode(',', $val); @@ -660,6 +661,6 @@ function ttRandomString($length = 32) { // This mitigates a risk of CSV injection, see https://owasp.org/www-community/attacks/CSV_Injection // Additionally, it replaces each quote character with a double quote. function ttNeutralizeForCsv($val) { - $result = ltrim($val, '=+-@'); + $result = is_null($val) ? '' : ltrim($val, '=+-@'); return str_replace('"', '""', $result); } diff --git a/WEB-INF/lib/form/ActionForm.class.php b/WEB-INF/lib/form/ActionForm.class.php index 358f8af5c..10ae71e05 100644 --- a/WEB-INF/lib/form/ActionForm.class.php +++ b/WEB-INF/lib/form/ActionForm.class.php @@ -12,6 +12,7 @@ class ActionForm { var $mVariables = array(); var $mForm = null; var $mInitForm = false; + var $name = ""; function __construct($name, &$form, $request=null) { $this->setName($name); diff --git a/WEB-INF/lib/form/DateField.class.php b/WEB-INF/lib/form/DateField.class.php index d349d5687..0281c812c 100644 --- a/WEB-INF/lib/form/DateField.class.php +++ b/WEB-INF/lib/form/DateField.class.php @@ -9,6 +9,8 @@ class DateField extends TextField { var $mWeekStartDay = 0; var $mDateFormat = "d/m/Y"; var $lToday = "Today"; + var $mMonthNames; + var $mWeekDayShortNames; var $lCalendarButtons = array('today'=>'Today', 'close'=>'Close'); @@ -382,9 +384,9 @@ function adjustiFrame(pickerDiv, iFrameDiv) { if (defined('DIR_NAME')) $dir_name = trim(constant('DIR_NAME'), '/'); if (!empty($dir_name)) - $app_root = '/'.$dir_name; + $app_root = '/'.$dir_name.'/'; - $html .= " name."');\">\n"; + $html .= " name."');\">\n"; } return $html; diff --git a/WEB-INF/lib/form/Form.class.php b/WEB-INF/lib/form/Form.class.php index cee608fe5..b16998d9f 100644 --- a/WEB-INF/lib/form/Form.class.php +++ b/WEB-INF/lib/form/Form.class.php @@ -30,6 +30,7 @@ function addInput($params) { import('form.TextField'); $el = new TextField($params['name']); if (isset($params['class'])) $el->setCssClass($params['class']); + if (isset($params['minlength'])) $el->setMinLength($params['minlength']); if (isset($params['maxlength'])) $el->setMaxLength($params['maxlength']); if (isset($params['placeholder'])) $el->setPLaceholder($params['placeholder']); break; @@ -38,7 +39,8 @@ function addInput($params) { import('form.PasswordField'); $el = new PasswordField($params['name']); if (isset($params['class'])) $el->setCssClass($params['class']); - if (isset($params['maxlength'])) $el->setMaxLength($params['maxlength']); + if (isset($params['minlength'])) $el->setMinLength($params['minlength']); + if (isset($params['maxlength'])) $el->setMaxLength($params['maxlength']); break; case 'datefield': diff --git a/WEB-INF/lib/form/FormElement.class.php b/WEB-INF/lib/form/FormElement.class.php index 16b8d76d1..570702b06 100644 --- a/WEB-INF/lib/form/FormElement.class.php +++ b/WEB-INF/lib/form/FormElement.class.php @@ -11,6 +11,7 @@ class FormElement { var $placeholder = ''; // placeholder var $size = ''; // control size var $max_length = ''; // max length of text in control + var $min_length = ''; // min length of text in control var $on_change = ''; // what happens when value of control changes var $on_click = ''; // what happens when the control is clicked var $label = ''; // optional label for control @@ -52,6 +53,9 @@ function getLabel() { return $this->label; } function setMaxLength($value) { $this->max_length = $value; } function getMaxLength() { return $this->max_length; } + function setMinLength($value) { $this->min_length = $value; } + function getMinLength() { return $this->min_length; } + function setStyle($value) { $this->style = $value; } function getStyle() { return $this->style; } diff --git a/WEB-INF/lib/form/PasswordField.class.php b/WEB-INF/lib/form/PasswordField.class.php index ff6802c90..c7984b210 100644 --- a/WEB-INF/lib/form/PasswordField.class.php +++ b/WEB-INF/lib/form/PasswordField.class.php @@ -27,6 +27,9 @@ function getHtml() { if ($this->style != '') $html.= ' style="'.$this->style.'"'; + if ($this->min_length != '') + $html.= ' minlength="'.$this->min_length.'"'; + if ($this->max_length != '') $html.= ' maxlength="'.$this->max_length.'"'; diff --git a/WEB-INF/lib/form/Submit.class.php b/WEB-INF/lib/form/Submit.class.php index 151600b32..22d717706 100644 --- a/WEB-INF/lib/form/Submit.class.php +++ b/WEB-INF/lib/form/Submit.class.php @@ -39,6 +39,9 @@ function getHtml() { if (empty($this->id)) $this->id = $this->name; + if (is_array($this->value)) + return ''; + // Output HTML. $html = "\n\tname\" id=\"$this->id\""; $html .= " value=\"$this->value\""; diff --git a/WEB-INF/lib/form/Table.class.php b/WEB-INF/lib/form/Table.class.php index acdf4813a..d164efb2f 100644 --- a/WEB-INF/lib/form/Table.class.php +++ b/WEB-INF/lib/form/Table.class.php @@ -157,8 +157,9 @@ function getHtml() { // Print rows. if (is_array($this->mData)) { + $rowHoverBackgroundColor = ($this->isInteractive() ? "onmouseover=\"setRowBackground(this, '".$this->mBgColorOver."')\" onmouseout=\"setRowBackground(this, null)\"" : ""); for ($row = 0; $row < count($this->mData); $row++) { - $html .= "\nmBgColor."\" onmouseover=\"setRowBackground(this, '".$this->mBgColorOver."')\" onmouseout=\"setRowBackground(this, null)\">\n"; + $html .= "\nmBgColor."\" ".$rowHoverBackgroundColor.">\n"; for ($col = 0; $col < $this->getColumnCount(); $col++) { if (0 == $col && strtolower(get_class($this->mColumns[$col]->getRenderer())) == 'checkboxcellrenderer') { // Checkbox for the row. Determine if selected. diff --git a/WEB-INF/lib/form/TextArea.class.php b/WEB-INF/lib/form/TextArea.class.php index 4faac1447..07dfa3a10 100644 --- a/WEB-INF/lib/form/TextArea.class.php +++ b/WEB-INF/lib/form/TextArea.class.php @@ -46,7 +46,6 @@ function getHtml() { $html .= " name=\"$this->name\" id=\"$this->id\""; if ($this->max_length!="") { - if ($this->mOnKeyPress) $this->mOnKeyPress .= ";"; $html .= " maxlength=\"$this->max_length\""; } diff --git a/WEB-INF/lib/form/TextField.class.php b/WEB-INF/lib/form/TextField.class.php index bfc0e551f..dd20f0dfa 100644 --- a/WEB-INF/lib/form/TextField.class.php +++ b/WEB-INF/lib/form/TextField.class.php @@ -49,15 +49,14 @@ function getHtml() { if (!empty($this->size)) $html .= " size=\"$this->size\""; if (!empty($this->style)) $html .= " style=\"$this->style\""; if (!empty($this->title)) $html .= " title=\"$this->title\""; + if (!empty($this->min_length)) $html .= " minlength=\"$this->min_length\""; if (!empty($this->placeholder)) $html .= " placeholder=\"$this->placeholder\""; if($this->isEnabled()) { if (!empty($this->max_length)) $html .= " maxlength=\"$this->max_length\""; if (!empty($this->on_change)) $html .= " onchange=\"$this->on_change\""; } - - $html .= " value=\"".htmlspecialchars($this->getValue())."\""; - + $html .= " value=\"". (is_null($this->getValue()) ? '' : htmlspecialchars($this->getValue())) ."\""; if(!$this->isEnabled()) $html .= " readonly"; $html .= ">\n"; return $html; diff --git a/WEB-INF/lib/libchart/classes/view/chart/PieChart.php b/WEB-INF/lib/libchart/classes/view/chart/PieChart.php index 0b5c417a4..9d0350fec 100644 --- a/WEB-INF/lib/libchart/classes/view/chart/PieChart.php +++ b/WEB-INF/lib/libchart/classes/view/chart/PieChart.php @@ -26,6 +26,13 @@ class PieChart extends Chart { protected $pieCenterX; protected $pieCenterY; + protected $total; + protected $percent; + protected $pieWidth; + protected $pieHeight; + protected $pieDepth; + + /** * Constructor of a pie chart. * @@ -167,7 +174,7 @@ protected function drawDisc($cy, $colorArray, $mode) { if ($angle2 - $angle1 <= 0) $angle2 = $angle1 + 1; - imagefilledarc($img, $this->pieCenterX, $cy, $this->pieWidth, $this->pieHeight, $angle1, $angle2, $color->getColor($img), $mode); + imagefilledarc($img, intval($this->pieCenterX), intval($cy), intval($this->pieWidth), intval($this->pieHeight), intval($angle1), intval($angle2), $color->getColor($img), $mode); $angle1 = $angle2; diff --git a/WEB-INF/lib/libchart/classes/view/plot/Plot.php b/WEB-INF/lib/libchart/classes/view/plot/Plot.php index 88e42dfb3..2bdb35210 100644 --- a/WEB-INF/lib/libchart/classes/view/plot/Plot.php +++ b/WEB-INF/lib/libchart/classes/view/plot/Plot.php @@ -102,6 +102,8 @@ class Plot { * GD image */ protected $img; + protected $width; + protected $height; /** * Drawing primitives diff --git a/WEB-INF/lib/libchart/classes/view/primitive/Primitive.php b/WEB-INF/lib/libchart/classes/view/primitive/Primitive.php index f88c99e02..7db38ea87 100644 --- a/WEB-INF/lib/libchart/classes/view/primitive/Primitive.php +++ b/WEB-INF/lib/libchart/classes/view/primitive/Primitive.php @@ -44,8 +44,18 @@ public function __construct($img) { * @param Color line color */ public function line($x1, $y1, $x2, $y2, $color, $width = 1) { - imagefilledpolygon($this->img, array($x1, $y1 - $width / 2, $x1, $y1 + $width / 2, $x2, $y2 + $width / 2, $x2, $y2 - $width / 2), 4, $color->getColor($this->img)); - // imageline($this->img, $x1, $y1, $x2, $y2, $color->getColor($this->img)); + //imagefilledpolygon($this->img, array($x1, $y1 - $width / 2, $x1, $y1 + $width / 2, $x2, $y2 + $width / 2, $x2, $y2 - $width / 2), 4, $color->getColor($this->img)); + // imageline($this->img, $x1, $y1, $x2, $y2, $color->getColor($this->img)); + + if (version_compare(phpversion(), '8.0', '>=')) { + // PHP > 8.1 : Using the $num_points parameter is deprecated + // imagefilledpolygon(GdImage $image, array $points, int $color): bool + imagefilledpolygon($this->img, array($x1, $y1 - $width / 2, $x1, $y1 + $width / 2, $x2, $y2 + $width / 2, $x2, $y2 - $width / 2), $color->getColor($this->img)); + } + else { + // imagefilledpolygon(GdImage $image, array $points, int $num_points, int $color): bool + imagefilledpolygon($this->img, array($x1, $y1 - $width / 2, $x1, $y1 + $width / 2, $x2, $y2 + $width / 2, $x2, $y2 - $width / 2), 4, $color->getColor($this->img)); + } } /** diff --git a/WEB-INF/lib/libchart/classes/view/text/Text.php b/WEB-INF/lib/libchart/classes/view/text/Text.php index f66ea7d3e..088150183 100644 --- a/WEB-INF/lib/libchart/classes/view/text/Text.php +++ b/WEB-INF/lib/libchart/classes/view/text/Text.php @@ -30,6 +30,9 @@ class Text { public $VERTICAL_CENTER_ALIGN = 16; public $VERTICAL_BOTTOM_ALIGN = 32; + public $fontCondensed; + public $fontCondensedBold; + /** * Creates a new text drawing helper. */ @@ -87,7 +90,7 @@ public function printText($img, $px, $py, $color, $text, $fontFileName, $align = $py += $textHeight; } - imagettftext($img, $fontSize, $angle, $px, $py, $color->getColor($img), $fontFileName, $text); + imagettftext($img, intval($fontSize), intval($angle), intval($px), intval($py), $color->getColor($img), $fontFileName, $text); } /** diff --git a/WEB-INF/lib/pear/MDB2/Date.php b/WEB-INF/lib/pear/MDB2/Date.php index e867e48e5..c7b95ffcb 100644 --- a/WEB-INF/lib/pear/MDB2/Date.php +++ b/WEB-INF/lib/pear/MDB2/Date.php @@ -122,7 +122,7 @@ public static function mdbTime() public static function date2Mdbstamp($hour = null, $minute = null, $second = null, $month = null, $day = null, $year = null) { - return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year, -1)); + return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year)); // The "is_dst" parameter for function mktime() is deprecated since PHP 5.1 and removed since PHP 7.0 } // }}} @@ -156,7 +156,7 @@ public static function mdbstamp2Unix($mdb_timestamp) { $arr = MDB2_Date::mdbstamp2Date($mdb_timestamp); - return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year'], -1); + return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year']); // The "is_dst" parameter for function mktime() is deprecated since PHP 5.1 and removed since PHP 7.0 } // }}} diff --git a/WEB-INF/lib/pear/MDB2/Driver/mysqli.php b/WEB-INF/lib/pear/MDB2/Driver/mysqli.php index f49e8eb87..cac6784c9 100644 --- a/WEB-INF/lib/pear/MDB2/Driver/mysqli.php +++ b/WEB-INF/lib/pear/MDB2/Driver/mysqli.php @@ -94,6 +94,12 @@ class MDB2_Driver_mysqli extends MDB2_Driver_Common public $varchar_max_length = 255; + + // Added 2024-10-15 + // PHP Deprecated: Creation of dynamic property MDB2_Driver_mysqli::$loaded_version_modules is deprecated + // Ideally, this should be fixed in MDB2 package. + public $loaded_version_modules = array(); + // }}} // {{{ constructor diff --git a/WEB-INF/lib/pear/Mail.php b/WEB-INF/lib/pear/Mail.php old mode 100644 new mode 100755 index e7cff2f64..df4b28c8a --- a/WEB-INF/lib/pear/Mail.php +++ b/WEB-INF/lib/pear/Mail.php @@ -1,265 +1,267 @@ - - * @copyright 1997-2010 Chuck Hagenbuch - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id$ - * @link http://pear.php.net/package/Mail/ - */ - -require_once 'PEAR.php'; - -/** - * PEAR's Mail:: interface. Defines the interface for implementing - * mailers under the PEAR hierarchy, and provides supporting functions - * useful in multiple mailer backends. - * - * @version $Revision$ - * @package Mail - */ -class Mail -{ - /** - * Line terminator used for separating header lines. - * @var string - */ - public $sep = "\r\n"; - - /** - * Provides an interface for generating Mail:: objects of various - * types - * - * @param string $driver The kind of Mail:: object to instantiate. - * @param array $params The parameters to pass to the Mail:: object. - * - * @return object Mail a instance of the driver class or if fails a PEAR Error - */ - public static function factory($driver, $params = array()) - { - $driver = strtolower($driver); - @include_once 'Mail/' . $driver . '.php'; - $class = 'Mail_' . $driver; - if (class_exists($class)) { - $mailer = new $class($params); - return $mailer; - } else { - return PEAR::raiseError('Unable to find class for driver ' . $driver); - } - } - - /** - * Implements Mail::send() function using php's built-in mail() - * command. - * - * @param mixed $recipients Either a comma-seperated list of recipients - * (RFC822 compliant), or an array of recipients, - * each RFC822 valid. This may contain recipients not - * specified in the headers, for Bcc:, resending - * messages, etc. - * - * @param array $headers The array of headers to send with the mail, in an - * associative array, where the array key is the - * header name (ie, 'Subject'), and the array value - * is the header value (ie, 'test'). The header - * produced from those values would be 'Subject: - * test'. - * - * @param string $body The full text of the message body, including any - * Mime parts, etc. - * - * @return mixed Returns true on success, or a PEAR_Error - * containing a descriptive error message on - * failure. - * - * @deprecated use Mail_mail::send instead - */ - public function send($recipients, $headers, $body) - { - if (!is_array($headers)) { - return PEAR::raiseError('$headers must be an array'); - } - - $result = $this->_sanitizeHeaders($headers); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - // if we're passed an array of recipients, implode it. - if (is_array($recipients)) { - $recipients = implode(', ', $recipients); - } - - // get the Subject out of the headers array so that we can - // pass it as a seperate argument to mail(). - $subject = ''; - if (isset($headers['Subject'])) { - $subject = $headers['Subject']; - unset($headers['Subject']); - } - - // flatten the headers out. - list(, $text_headers) = Mail::prepareHeaders($headers); - - return mail($recipients, $subject, $body, $text_headers); - } - - /** - * Sanitize an array of mail headers by removing any additional header - * strings present in a legitimate header's value. The goal of this - * filter is to prevent mail injection attacks. - * - * @param array $headers The associative array of headers to sanitize. - */ - protected function _sanitizeHeaders(&$headers) - { - foreach ($headers as $key => $value) { - $headers[$key] = - preg_replace('=((||0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', - null, $value); - } - } - - /** - * Take an array of mail headers and return a string containing - * text usable in sending a message. - * - * @param array $headers The array of headers to prepare, in an associative - * array, where the array key is the header name (ie, - * 'Subject'), and the array value is the header - * value (ie, 'test'). The header produced from those - * values would be 'Subject: test'. - * - * @return mixed Returns false if it encounters a bad address, - * otherwise returns an array containing two - * elements: Any From: address found in the headers, - * and the plain text version of the headers. - */ - protected function prepareHeaders($headers) - { - $lines = array(); - $from = null; - - foreach ($headers as $key => $value) { - if (strcasecmp($key, 'From') === 0) { - include_once 'Mail/RFC822.php'; - $parser = new Mail_RFC822(); - $addresses = $parser->parseAddressList($value, 'localhost', false); - if (is_a($addresses, 'PEAR_Error')) { - return $addresses; - } - - $from = $addresses[0]->mailbox . '@' . $addresses[0]->host; - - // Reject envelope From: addresses with spaces. - if (strstr($from, ' ')) { - return false; - } - - $lines[] = $key . ': ' . $value; - } elseif (strcasecmp($key, 'Received') === 0) { - $received = array(); - if (is_array($value)) { - foreach ($value as $line) { - $received[] = $key . ': ' . $line; - } - } - else { - $received[] = $key . ': ' . $value; - } - // Put Received: headers at the top. Spam detectors often - // flag messages with Received: headers after the Subject: - // as spam. - $lines = array_merge($received, $lines); - } else { - // If $value is an array (i.e., a list of addresses), convert - // it to a comma-delimited string of its elements (addresses). - if (is_array($value)) { - $value = implode(', ', $value); - } - $lines[] = $key . ': ' . $value; - } - } - - return array($from, join($this->sep, $lines)); - } - - /** - * Take a set of recipients and parse them, returning an array of - * bare addresses (forward paths) that can be passed to sendmail - * or an smtp server with the rcpt to: command. - * - * @param mixed Either a comma-seperated list of recipients - * (RFC822 compliant), or an array of recipients, - * each RFC822 valid. - * - * @return mixed An array of forward paths (bare addresses) or a PEAR_Error - * object if the address list could not be parsed. - */ - protected function parseRecipients($recipients) - { - include_once 'Mail/RFC822.php'; - - // if we're passed an array, assume addresses are valid and - // implode them before parsing. - if (is_array($recipients)) { - $recipients = implode(', ', $recipients); - } - - // Parse recipients, leaving out all personal info. This is - // for smtp recipients, etc. All relevant personal information - // should already be in the headers. - $Mail_RFC822 = new Mail_RFC822(); - $addresses = $Mail_RFC822->parseAddressList($recipients, 'localhost', false); - - // If parseAddressList() returned a PEAR_Error object, just return it. - if (is_a($addresses, 'PEAR_Error')) { - return $addresses; - } - - $recipients = array(); - if (is_array($addresses)) { - foreach ($addresses as $ob) { - $recipients[] = $ob->mailbox . '@' . $ob->host; - } - } - - return $recipients; - } - -} + + * @copyright 1997-2017 Chuck Hagenbuch + * @license http://opensource.org/licenses/BSD-3-Clause New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/Mail/ + */ + +require_once 'PEAR.php'; + +/** + * PEAR's Mail:: interface. Defines the interface for implementing + * mailers under the PEAR hierarchy, and provides supporting functions + * useful in multiple mailer backends. + * + * @version $Revision$ + * @package Mail + */ +class Mail +{ + /** + * Line terminator used for separating header lines. + * @var string + */ + public $sep = "\r\n"; + + /** + * Provides an interface for generating Mail:: objects of various + * types + * + * @param string $driver The kind of Mail:: object to instantiate. + * @param array $params The parameters to pass to the Mail:: object. + * + * @return object Mail a instance of the driver class or if fails a PEAR Error + */ + public static function factory($driver, $params = array()) + { + $driver = strtolower($driver); + @include_once 'Mail/' . $driver . '.php'; + $class = 'Mail_' . $driver; + if (class_exists($class)) { + $mailer = new $class($params); + return $mailer; + } else { + return PEAR::raiseError('Unable to find class for driver ' . $driver); + } + } + + /** + * Implements Mail::send() function using php's built-in mail() + * command. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * + * @deprecated use Mail_mail::send instead + */ + public function send($recipients, $headers, $body) + { + if (!is_array($headers)) { + return PEAR::raiseError('$headers must be an array'); + } + + $result = $this->_sanitizeHeaders($headers); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + // if we're passed an array of recipients, implode it. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // get the Subject out of the headers array so that we can + // pass it as a seperate argument to mail(). + $subject = ''; + if (isset($headers['Subject'])) { + $subject = $headers['Subject']; + unset($headers['Subject']); + } + + // flatten the headers out. + list(, $text_headers) = Mail::prepareHeaders($headers); + + return mail($recipients, $subject, $body, $text_headers); + } + + /** + * Sanitize an array of mail headers by removing any additional header + * strings present in a legitimate header's value. The goal of this + * filter is to prevent mail injection attacks. + * + * @param array $headers The associative array of headers to sanitize. + */ + protected function _sanitizeHeaders(&$headers) + { + foreach ($headers as $key => $value) { + $headers[$key] = + preg_replace('=((||0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i', + '', $value); + } + } + + /** + * Take an array of mail headers and return a string containing + * text usable in sending a message. + * + * @param array $headers The array of headers to prepare, in an associative + * array, where the array key is the header name (ie, + * 'Subject'), and the array value is the header + * value (ie, 'test'). The header produced from those + * values would be 'Subject: test'. + * + * @return mixed Returns false if it encounters a bad address, + * otherwise returns an array containing two + * elements: Any From: address found in the headers, + * and the plain text version of the headers. + */ + protected function prepareHeaders($headers) + { + $lines = array(); + $from = null; + + foreach ($headers as $key => $value) { + if (strcasecmp($key, 'From') === 0) { + include_once 'Mail/RFC822.php'; + $parser = new Mail_RFC822(); + $addresses = $parser->parseAddressList($value, 'localhost', false); + if (is_a($addresses, 'PEAR_Error')) { + return $addresses; + } + + $from = $addresses[0]->mailbox . '@' . $addresses[0]->host; + + // Reject envelope From: addresses with spaces. + if (strstr($from, ' ')) { + return false; + } + + $lines[] = $key . ': ' . $value; + } elseif (strcasecmp($key, 'Received') === 0) { + $received = array(); + if (is_array($value)) { + foreach ($value as $line) { + $received[] = $key . ': ' . $line; + } + } + else { + $received[] = $key . ': ' . $value; + } + // Put Received: headers at the top. Spam detectors often + // flag messages with Received: headers after the Subject: + // as spam. + $lines = array_merge($received, $lines); + } else { + // If $value is an array (i.e., a list of addresses), convert + // it to a comma-delimited string of its elements (addresses). + if (is_array($value)) { + $value = implode(', ', $value); + } + $lines[] = $key . ': ' . $value; + } + } + + return array($from, join($this->sep, $lines)); + } + + /** + * Take a set of recipients and parse them, returning an array of + * bare addresses (forward paths) that can be passed to sendmail + * or an smtp server with the rcpt to: command. + * + * @param mixed Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. + * + * @return mixed An array of forward paths (bare addresses) or a PEAR_Error + * object if the address list could not be parsed. + */ + protected function parseRecipients($recipients) + { + include_once 'Mail/RFC822.php'; + + // if we're passed an array, assume addresses are valid and + // implode them before parsing. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // Parse recipients, leaving out all personal info. This is + // for smtp recipients, etc. All relevant personal information + // should already be in the headers. + $Mail_RFC822 = new Mail_RFC822(); + $addresses = $Mail_RFC822->parseAddressList($recipients, 'localhost', false); + + // If parseAddressList() returned a PEAR_Error object, just return it. + if (is_a($addresses, 'PEAR_Error')) { + return $addresses; + } + + $recipients = array(); + if (is_array($addresses)) { + foreach ($addresses as $ob) { + $recipients[] = $ob->mailbox . '@' . $ob->host; + } + } + + return $recipients; + } + +} diff --git a/WEB-INF/lib/pear/Mail/RFC822.php b/WEB-INF/lib/pear/Mail/RFC822.php old mode 100644 new mode 100755 index d010a20e8..0c2abd34d --- a/WEB-INF/lib/pear/Mail/RFC822.php +++ b/WEB-INF/lib/pear/Mail/RFC822.php @@ -1,927 +1,940 @@ - - * @author Chuck Hagenbuch - * @author Chuck Hagenbuch - * @version $Revision$ - * @license BSD - * @package Mail - */ -class Mail_RFC822 { - - /** - * The address being parsed by the RFC822 object. - * @var string $address - */ - var $address = ''; - - /** - * The default domain to use for unqualified addresses. - * @var string $default_domain - */ - var $default_domain = 'localhost'; - - /** - * Should we return a nested array showing groups, or flatten everything? - * @var boolean $nestGroups - */ - var $nestGroups = true; - - /** - * Whether or not to validate atoms for non-ascii characters. - * @var boolean $validate - */ - var $validate = true; - - /** - * The array of raw addresses built up as we parse. - * @var array $addresses - */ - var $addresses = array(); - - /** - * The final array of parsed address information that we build up. - * @var array $structure - */ - var $structure = array(); - - /** - * The current error message, if any. - * @var string $error - */ - var $error = null; - - /** - * An internal counter/pointer. - * @var integer $index - */ - var $index = null; - - /** - * The number of groups that have been found in the address list. - * @var integer $num_groups - * @access public - */ - var $num_groups = 0; - - /** - * A variable so that we can tell whether or not we're inside a - * Mail_RFC822 object. - * @var boolean $mailRFC822 - */ - var $mailRFC822 = true; - - /** - * A limit after which processing stops - * @var int $limit - */ - var $limit = null; - - /** - * Sets up the object. The address must either be set here or when - * calling parseAddressList(). One or the other. - * - * @param string $address The address(es) to validate. - * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost. - * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. - * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. - * - * @return object Mail_RFC822 A new Mail_RFC822 object. - */ - public function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) - { - if (isset($address)) $this->address = $address; - if (isset($default_domain)) $this->default_domain = $default_domain; - if (isset($nest_groups)) $this->nestGroups = $nest_groups; - if (isset($validate)) $this->validate = $validate; - if (isset($limit)) $this->limit = $limit; - } - - /** - * Starts the whole process. The address must either be set here - * or when creating the object. One or the other. - * - * @param string $address The address(es) to validate. - * @param string $default_domain Default domain/host etc. - * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. - * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. - * - * @return array A structured array of addresses. - */ - public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) - { - if (!isset($this) || !isset($this->mailRFC822)) { - $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); - return $obj->parseAddressList(); - } - - if (isset($address)) $this->address = $address; - if (isset($default_domain)) $this->default_domain = $default_domain; - if (isset($nest_groups)) $this->nestGroups = $nest_groups; - if (isset($validate)) $this->validate = $validate; - if (isset($limit)) $this->limit = $limit; - - $this->structure = array(); - $this->addresses = array(); - $this->error = null; - $this->index = null; - - // Unfold any long lines in $this->address. - $this->address = preg_replace('/\r?\n/', "\r\n", $this->address); - $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address); - - while ($this->address = $this->_splitAddresses($this->address)); - - if ($this->address === false || isset($this->error)) { - require_once 'PEAR.php'; - return PEAR::raiseError($this->error); - } - - // Validate each address individually. If we encounter an invalid - // address, stop iterating and return an error immediately. - foreach ($this->addresses as $address) { - $valid = $this->_validateAddress($address); - - if ($valid === false || isset($this->error)) { - require_once 'PEAR.php'; - return PEAR::raiseError($this->error); - } - - if (!$this->nestGroups) { - $this->structure = array_merge($this->structure, $valid); - } else { - $this->structure[] = $valid; - } - } - - return $this->structure; - } - - /** - * Splits an address into separate addresses. - * - * @param string $address The addresses to split. - * @return boolean Success or failure. - */ - protected function _splitAddresses($address) - { - if (!empty($this->limit) && count($this->addresses) == $this->limit) { - return ''; - } - - if ($this->_isGroup($address) && !isset($this->error)) { - $split_char = ';'; - $is_group = true; - } elseif (!isset($this->error)) { - $split_char = ','; - $is_group = false; - } elseif (isset($this->error)) { - return false; - } - - // Split the string based on the above ten or so lines. - $parts = explode($split_char, $address); - $string = $this->_splitCheck($parts, $split_char); - - // If a group... - if ($is_group) { - // If $string does not contain a colon outside of - // brackets/quotes etc then something's fubar. - - // First check there's a colon at all: - if (strpos($string, ':') === false) { - $this->error = 'Invalid address: ' . $string; - return false; - } - - // Now check it's outside of brackets/quotes: - if (!$this->_splitCheck(explode(':', $string), ':')) { - return false; - } - - // We must have a group at this point, so increase the counter: - $this->num_groups++; - } - - // $string now contains the first full address/group. - // Add to the addresses array. - $this->addresses[] = array( - 'address' => trim($string), - 'group' => $is_group - ); - - // Remove the now stored address from the initial line, the +1 - // is to account for the explode character. - $address = trim(substr($address, strlen($string) + 1)); - - // If the next char is a comma and this was a group, then - // there are more addresses, otherwise, if there are any more - // chars, then there is another address. - if ($is_group && substr($address, 0, 1) == ','){ - $address = trim(substr($address, 1)); - return $address; - - } elseif (strlen($address) > 0) { - return $address; - - } else { - return ''; - } - - // If you got here then something's off - return false; - } - - /** - * Checks for a group at the start of the string. - * - * @param string $address The address to check. - * @return boolean Whether or not there is a group at the start of the string. - */ - protected function _isGroup($address) - { - // First comma not in quotes, angles or escaped: - $parts = explode(',', $address); - $string = $this->_splitCheck($parts, ','); - - // Now we have the first address, we can reliably check for a - // group by searching for a colon that's not escaped or in - // quotes or angle brackets. - if (count($parts = explode(':', $string)) > 1) { - $string2 = $this->_splitCheck($parts, ':'); - return ($string2 !== $string); - } else { - return false; - } - } - - /** - * A common function that will check an exploded string. - * - * @param array $parts The exloded string. - * @param string $char The char that was exploded on. - * @return mixed False if the string contains unclosed quotes/brackets, or the string on success. - */ - protected function _splitCheck($parts, $char) - { - $string = $parts[0]; - - for ($i = 0; $i < count($parts); $i++) { - if ($this->_hasUnclosedQuotes($string) - || $this->_hasUnclosedBrackets($string, '<>') - || $this->_hasUnclosedBrackets($string, '[]') - || $this->_hasUnclosedBrackets($string, '()') - || substr($string, -1) == '\\') { - if (isset($parts[$i + 1])) { - $string = $string . $char . $parts[$i + 1]; - } else { - $this->error = 'Invalid address spec. Unclosed bracket or quotes'; - return false; - } - } else { - $this->index = $i; - break; - } - } - - return $string; - } - - /** - * Checks if a string has unclosed quotes or not. - * - * @param string $string The string to check. - * @return boolean True if there are unclosed quotes inside the string, - * false otherwise. - */ - protected function _hasUnclosedQuotes($string) - { - $string = trim($string); - $iMax = strlen($string); - $in_quote = false; - $i = $slashes = 0; - - for (; $i < $iMax; ++$i) { - switch ($string[$i]) { - case '\\': - ++$slashes; - break; - - case '"': - if ($slashes % 2 == 0) { - $in_quote = !$in_quote; - } - // Fall through to default action below. - - default: - $slashes = 0; - break; - } - } - - return $in_quote; - } - - /** - * Checks if a string has an unclosed brackets or not. IMPORTANT: - * This function handles both angle brackets and square brackets; - * - * @param string $string The string to check. - * @param string $chars The characters to check for. - * @return boolean True if there are unclosed brackets inside the string, false otherwise. - */ - protected function _hasUnclosedBrackets($string, $chars) - { - $num_angle_start = substr_count($string, $chars[0]); - $num_angle_end = substr_count($string, $chars[1]); - - $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]); - $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]); - - if ($num_angle_start < $num_angle_end) { - $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')'; - return false; - } else { - return ($num_angle_start > $num_angle_end); - } - } - - /** - * Sub function that is used only by hasUnclosedBrackets(). - * - * @param string $string The string to check. - * @param integer &$num The number of occurences. - * @param string $char The character to count. - * @return integer The number of occurences of $char in $string, adjusted for backslashes. - */ - protected function _hasUnclosedBracketsSub($string, &$num, $char) - { - $parts = explode($char, $string); - for ($i = 0; $i < count($parts); $i++){ - if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i])) - $num--; - if (isset($parts[$i + 1])) - $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1]; - } - - return $num; - } - - /** - * Function to begin checking the address. - * - * @param string $address The address to validate. - * @return mixed False on failure, or a structured array of address information on success. - */ - protected function _validateAddress($address) - { - $is_group = false; - $addresses = array(); - - if ($address['group']) { - $is_group = true; - - // Get the group part of the name - $parts = explode(':', $address['address']); - $groupname = $this->_splitCheck($parts, ':'); - $structure = array(); - - // And validate the group part of the name. - if (!$this->_validatePhrase($groupname)){ - $this->error = 'Group name did not validate.'; - return false; - } else { - // Don't include groups if we are not nesting - // them. This avoids returning invalid addresses. - if ($this->nestGroups) { - $structure = new stdClass; - $structure->groupname = $groupname; - } - } - - $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':'))); - } - - // If a group then split on comma and put into an array. - // Otherwise, Just put the whole address in an array. - if ($is_group) { - while (strlen($address['address']) > 0) { - $parts = explode(',', $address['address']); - $addresses[] = $this->_splitCheck($parts, ','); - $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ','))); - } - } else { - $addresses[] = $address['address']; - } - - // Trim the whitespace from all of the address strings. - array_map('trim', $addresses); - - // Validate each mailbox. - // Format could be one of: name - // geezer@domain.com - // geezer - // ... or any other format valid by RFC 822. - for ($i = 0; $i < count($addresses); $i++) { - if (!$this->validateMailbox($addresses[$i])) { - if (empty($this->error)) { - $this->error = 'Validation failed for: ' . $addresses[$i]; - } - return false; - } - } - - // Nested format - if ($this->nestGroups) { - if ($is_group) { - $structure->addresses = $addresses; - } else { - $structure = $addresses[0]; - } - - // Flat format - } else { - if ($is_group) { - $structure = array_merge($structure, $addresses); - } else { - $structure = $addresses; - } - } - - return $structure; - } - - /** - * Function to validate a phrase. - * - * @param string $phrase The phrase to check. - * @return boolean Success or failure. - */ - protected function _validatePhrase($phrase) - { - // Splits on one or more Tab or space. - $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY); - - $phrase_parts = array(); - while (count($parts) > 0){ - $phrase_parts[] = $this->_splitCheck($parts, ' '); - for ($i = 0; $i < $this->index + 1; $i++) - array_shift($parts); - } - - foreach ($phrase_parts as $part) { - // If quoted string: - if (substr($part, 0, 1) == '"') { - if (!$this->_validateQuotedString($part)) { - return false; - } - continue; - } - - // Otherwise it's an atom: - if (!$this->_validateAtom($part)) return false; - } - - return true; - } - - /** - * Function to validate an atom which from rfc822 is: - * atom = 1* - * - * If validation ($this->validate) has been turned off, then - * validateAtom() doesn't actually check anything. This is so that you - * can split a list of addresses up before encoding personal names - * (umlauts, etc.), for example. - * - * @param string $atom The string to check. - * @return boolean Success or failure. - */ - protected function _validateAtom($atom) - { - if (!$this->validate) { - // Validation has been turned off; assume the atom is okay. - return true; - } - - // Check for any char from ASCII 0 - ASCII 127 - if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) { - return false; - } - - // Check for specials: - if (preg_match('/[][()<>@,;\\:". ]/', $atom)) { - return false; - } - - // Check for control characters (ASCII 0-31): - if (preg_match('/[\\x00-\\x1F]+/', $atom)) { - return false; - } - - return true; - } - - /** - * Function to validate quoted string, which is: - * quoted-string = <"> *(qtext/quoted-pair) <"> - * - * @param string $qstring The string to check - * @return boolean Success or failure. - */ - protected function _validateQuotedString($qstring) - { - // Leading and trailing " - $qstring = substr($qstring, 1, -1); - - // Perform check, removing quoted characters first. - return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring)); - } - - /** - * Function to validate a mailbox, which is: - * mailbox = addr-spec ; simple address - * / phrase route-addr ; name and route-addr - * - * @param string &$mailbox The string to check. - * @return boolean Success or failure. - */ - public function validateMailbox(&$mailbox) - { - // A couple of defaults. - $phrase = ''; - $comment = ''; - $comments = array(); - - // Catch any RFC822 comments and store them separately. - $_mailbox = $mailbox; - while (strlen(trim($_mailbox)) > 0) { - $parts = explode('(', $_mailbox); - $before_comment = $this->_splitCheck($parts, '('); - if ($before_comment != $_mailbox) { - // First char should be a (. - $comment = substr(str_replace($before_comment, '', $_mailbox), 1); - $parts = explode(')', $comment); - $comment = $this->_splitCheck($parts, ')'); - $comments[] = $comment; - - // +2 is for the brackets - $_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment)+strlen($comment)+2); - } else { - break; - } - } - - foreach ($comments as $comment) { - $mailbox = str_replace("($comment)", '', $mailbox); - } - - $mailbox = trim($mailbox); - - // Check for name + route-addr - if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') { - $parts = explode('<', $mailbox); - $name = $this->_splitCheck($parts, '<'); - - $phrase = trim($name); - $route_addr = trim(substr($mailbox, strlen($name.'<'), -1)); - - if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) { - return false; - } - - // Only got addr-spec - } else { - // First snip angle brackets if present. - if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') { - $addr_spec = substr($mailbox, 1, -1); - } else { - $addr_spec = $mailbox; - } - - if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { - return false; - } - } - - // Construct the object that will be returned. - $mbox = new stdClass(); - - // Add the phrase (even if empty) and comments - $mbox->personal = $phrase; - $mbox->comment = isset($comments) ? $comments : array(); - - if (isset($route_addr)) { - $mbox->mailbox = $route_addr['local_part']; - $mbox->host = $route_addr['domain']; - $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : ''; - } else { - $mbox->mailbox = $addr_spec['local_part']; - $mbox->host = $addr_spec['domain']; - } - - $mailbox = $mbox; - return true; - } - - /** - * This function validates a route-addr which is: - * route-addr = "<" [route] addr-spec ">" - * - * Angle brackets have already been removed at the point of - * getting to this function. - * - * @param string $route_addr The string to check. - * @return mixed False on failure, or an array containing validated address/route information on success. - */ - protected function _validateRouteAddr($route_addr) - { - // Check for colon. - if (strpos($route_addr, ':') !== false) { - $parts = explode(':', $route_addr); - $route = $this->_splitCheck($parts, ':'); - } else { - $route = $route_addr; - } - - // If $route is same as $route_addr then the colon was in - // quotes or brackets or, of course, non existent. - if ($route === $route_addr){ - unset($route); - $addr_spec = $route_addr; - if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { - return false; - } - } else { - // Validate route part. - if (($route = $this->_validateRoute($route)) === false) { - return false; - } - - $addr_spec = substr($route_addr, strlen($route . ':')); - - // Validate addr-spec part. - if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { - return false; - } - } - - if (isset($route)) { - $return['adl'] = $route; - } else { - $return['adl'] = ''; - } - - $return = array_merge($return, $addr_spec); - return $return; - } - - /** - * Function to validate a route, which is: - * route = 1#("@" domain) ":" - * - * @param string $route The string to check. - * @return mixed False on failure, or the validated $route on success. - */ - protected function _validateRoute($route) - { - // Split on comma. - $domains = explode(',', trim($route)); - - foreach ($domains as $domain) { - $domain = str_replace('@', '', trim($domain)); - if (!$this->_validateDomain($domain)) return false; - } - - return $route; - } - - /** - * Function to validate a domain, though this is not quite what - * you expect of a strict internet domain. - * - * domain = sub-domain *("." sub-domain) - * - * @param string $domain The string to check. - * @return mixed False on failure, or the validated domain on success. - */ - protected function _validateDomain($domain) - { - // Note the different use of $subdomains and $sub_domains - $subdomains = explode('.', $domain); - - while (count($subdomains) > 0) { - $sub_domains[] = $this->_splitCheck($subdomains, '.'); - for ($i = 0; $i < $this->index + 1; $i++) - array_shift($subdomains); - } - - foreach ($sub_domains as $sub_domain) { - if (!$this->_validateSubdomain(trim($sub_domain))) - return false; - } - - // Managed to get here, so return input. - return $domain; - } - - /** - * Function to validate a subdomain: - * subdomain = domain-ref / domain-literal - * - * @param string $subdomain The string to check. - * @return boolean Success or failure. - */ - protected function _validateSubdomain($subdomain) - { - if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){ - if (!$this->_validateDliteral($arr[1])) return false; - } else { - if (!$this->_validateAtom($subdomain)) return false; - } - - // Got here, so return successful. - return true; - } - - /** - * Function to validate a domain literal: - * domain-literal = "[" *(dtext / quoted-pair) "]" - * - * @param string $dliteral The string to check. - * @return boolean Success or failure. - */ - protected function _validateDliteral($dliteral) - { - return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\'; - } - - /** - * Function to validate an addr-spec. - * - * addr-spec = local-part "@" domain - * - * @param string $addr_spec The string to check. - * @return mixed False on failure, or the validated addr-spec on success. - */ - protected function _validateAddrSpec($addr_spec) - { - $addr_spec = trim($addr_spec); - - // Split on @ sign if there is one. - if (strpos($addr_spec, '@') !== false) { - $parts = explode('@', $addr_spec); - $local_part = $this->_splitCheck($parts, '@'); - $domain = substr($addr_spec, strlen($local_part . '@')); - - // No @ sign so assume the default domain. - } else { - $local_part = $addr_spec; - $domain = $this->default_domain; - } - - if (($local_part = $this->_validateLocalPart($local_part)) === false) return false; - if (($domain = $this->_validateDomain($domain)) === false) return false; - - // Got here so return successful. - return array('local_part' => $local_part, 'domain' => $domain); - } - - /** - * Function to validate the local part of an address: - * local-part = word *("." word) - * - * @param string $local_part - * @return mixed False on failure, or the validated local part on success. - */ - protected function _validateLocalPart($local_part) - { - $parts = explode('.', $local_part); - $words = array(); - - // Split the local_part into words. - while (count($parts) > 0) { - $words[] = $this->_splitCheck($parts, '.'); - for ($i = 0; $i < $this->index + 1; $i++) { - array_shift($parts); - } - } - - // Validate each word. - foreach ($words as $word) { - // word cannot be empty (#17317) - if ($word === '') { - return false; - } - // If this word contains an unquoted space, it is invalid. (6.2.4) - if (strpos($word, ' ') && $word[0] !== '"') - { - return false; - } - - if ($this->_validatePhrase(trim($word)) === false) return false; - } - - // Managed to get here, so return the input. - return $local_part; - } - - /** - * Returns an approximate count of how many addresses are in the - * given string. This is APPROXIMATE as it only splits based on a - * comma which has no preceding backslash. Could be useful as - * large amounts of addresses will end up producing *large* - * structures when used with parseAddressList(). - * - * @param string $data Addresses to count - * @return int Approximate count - */ - public function approximateCount($data) - { - return count(preg_split('/(?@. This can be sufficient for most - * people. Optional stricter mode can be utilised which restricts - * mailbox characters allowed to alphanumeric, full stop, hyphen - * and underscore. - * - * @param string $data Address to check - * @param boolean $strict Optional stricter mode - * @return mixed False if it fails, an indexed array - * username/domain if it matches - */ - public function isValidInetAddress($data, $strict = false) - { - $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i'; - if (preg_match($regex, trim($data), $matches)) { - return array($matches[1], $matches[2]); - } else { - return false; - } - } - -} + + * @author Chuck Hagenbuch parseAddressList($address_string, 'example.com', true); + * print_r($structure); + * + * @author Richard Heyes + * @author Chuck Hagenbuch + * @version $Revision$ + * @license BSD + * @package Mail + */ +class Mail_RFC822 { + + /** + * The address being parsed by the RFC822 object. + * @var string $address + */ + var $address = ''; + + /** + * The default domain to use for unqualified addresses. + * @var string $default_domain + */ + var $default_domain = 'localhost'; + + /** + * Should we return a nested array showing groups, or flatten everything? + * @var boolean $nestGroups + */ + var $nestGroups = true; + + /** + * Whether or not to validate atoms for non-ascii characters. + * @var boolean $validate + */ + var $validate = true; + + /** + * The array of raw addresses built up as we parse. + * @var array $addresses + */ + var $addresses = array(); + + /** + * The final array of parsed address information that we build up. + * @var array $structure + */ + var $structure = array(); + + /** + * The current error message, if any. + * @var string $error + */ + var $error = null; + + /** + * An internal counter/pointer. + * @var integer $index + */ + var $index = null; + + /** + * The number of groups that have been found in the address list. + * @var integer $num_groups + * @access public + */ + var $num_groups = 0; + + /** + * A variable so that we can tell whether or not we're inside a + * Mail_RFC822 object. + * @var boolean $mailRFC822 + */ + var $mailRFC822 = true; + + /** + * A limit after which processing stops + * @var int $limit + */ + var $limit = null; + + /** + * Sets up the object. The address must either be set here or when + * calling parseAddressList(). One or the other. + * + * @param string $address The address(es) to validate. + * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost. + * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. + * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. + * + * @return object Mail_RFC822 A new Mail_RFC822 object. + */ + public function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) + { + if (isset($address)) $this->address = $address; + if (isset($default_domain)) $this->default_domain = $default_domain; + if (isset($nest_groups)) $this->nestGroups = $nest_groups; + if (isset($validate)) $this->validate = $validate; + if (isset($limit)) $this->limit = $limit; + } + + /** + * Starts the whole process. The address must either be set here + * or when creating the object. One or the other. + * + * @param string $address The address(es) to validate. + * @param string $default_domain Default domain/host etc. + * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. + * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. + * + * @return array A structured array of addresses. + */ + public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) + { + if (version_compare(PHP_VERSION, '8.0.0', '<')) { + if (!isset($this) || !isset($this->mailRFC822)) { + $warn = "Calling non-static methods statically is no longer supported since PHP 8"; + trigger_error($warn, E_USER_NOTICE); + $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); + return $obj->parseAddressList(); + } + } + + if (isset($address)) $this->address = $address; + if (isset($default_domain)) $this->default_domain = $default_domain; + if (isset($nest_groups)) $this->nestGroups = $nest_groups; + if (isset($validate)) $this->validate = $validate; + if (isset($limit)) $this->limit = $limit; + + $this->structure = array(); + $this->addresses = array(); + $this->error = null; + $this->index = null; + + // Unfold any long lines in $this->address. + $this->address = preg_replace('/\r?\n/', "\r\n", $this->address); + $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address); + + while ($this->address = $this->_splitAddresses($this->address)); + + if ($this->address === false || isset($this->error)) { + require_once 'PEAR.php'; + return PEAR::raiseError($this->error); + } + + // Validate each address individually. If we encounter an invalid + // address, stop iterating and return an error immediately. + foreach ($this->addresses as $address) { + $valid = $this->_validateAddress($address); + + if ($valid === false || isset($this->error)) { + require_once 'PEAR.php'; + return PEAR::raiseError($this->error); + } + + if (!$this->nestGroups) { + $this->structure = array_merge($this->structure, $valid); + } else { + $this->structure[] = $valid; + } + } + + return $this->structure; + } + + /** + * Splits an address into separate addresses. + * + * @param string $address The addresses to split. + * @return boolean Success or failure. + */ + protected function _splitAddresses($address) + { + $is_group = false; + $split_char = ','; + + if (!empty($this->limit) && count($this->addresses) == $this->limit) { + return ''; + } + + if ($this->_isGroup($address) && !isset($this->error)) { + $split_char = ';'; + $is_group = true; + } elseif (!isset($this->error)) { + $split_char = ','; + $is_group = false; + } elseif (isset($this->error)) { + return false; + } + + // Split the string based on the above ten or so lines. + $parts = explode($split_char, $address); + $string = $this->_splitCheck($parts, $split_char); + + // If a group... + if ($is_group) { + // If $string does not contain a colon outside of + // brackets/quotes etc then something's fubar. + + // First check there's a colon at all: + if (strpos($string, ':') === false) { + $this->error = 'Invalid address: ' . $string; + return false; + } + + // Now check it's outside of brackets/quotes: + if (!$this->_splitCheck(explode(':', $string), ':')) { + return false; + } + + // We must have a group at this point, so increase the counter: + $this->num_groups++; + } + + // $string now contains the first full address/group. + // Add to the addresses array. + $this->addresses[] = array( + 'address' => trim($string), + 'group' => $is_group + ); + + // Remove the now stored address from the initial line, the +1 + // is to account for the explode character. + $address = trim(substr($address, strlen($string) + 1)); + + // If the next char is a comma and this was a group, then + // there are more addresses, otherwise, if there are any more + // chars, then there is another address. + if ($is_group && substr($address, 0, 1) == ','){ + $address = trim(substr($address, 1)); + return $address; + + } elseif (strlen($address) > 0) { + return $address; + + } else { + return ''; + } + + // If you got here then something's off + return false; + } + + /** + * Checks for a group at the start of the string. + * + * @param string $address The address to check. + * @return boolean Whether or not there is a group at the start of the string. + */ + protected function _isGroup($address) + { + // First comma not in quotes, angles or escaped: + $parts = explode(',', $address); + $string = $this->_splitCheck($parts, ','); + + // Now we have the first address, we can reliably check for a + // group by searching for a colon that's not escaped or in + // quotes or angle brackets. + if (count($parts = explode(':', $string)) > 1) { + $string2 = $this->_splitCheck($parts, ':'); + return ($string2 !== $string); + } else { + return false; + } + } + + /** + * A common function that will check an exploded string. + * + * @param array $parts The exloded string. + * @param string $char The char that was exploded on. + * @return mixed False if the string contains unclosed quotes/brackets, or the string on success. + */ + protected function _splitCheck($parts, $char) + { + $string = $parts[0]; + + for ($i = 0; $i < count($parts); $i++) { + if ($this->_hasUnclosedQuotes($string) + || $this->_hasUnclosedBrackets($string, '<>') + || $this->_hasUnclosedBrackets($string, '[]') + || $this->_hasUnclosedBrackets($string, '()') + || substr($string, -1) == '\\') { + if (isset($parts[$i + 1])) { + $string = $string . $char . $parts[$i + 1]; + } else { + $this->error = 'Invalid address spec. Unclosed bracket or quotes'; + return false; + } + } else { + $this->index = $i; + break; + } + } + + return $string; + } + + /** + * Checks if a string has unclosed quotes or not. + * + * @param string $string The string to check. + * @return boolean True if there are unclosed quotes inside the string, + * false otherwise. + */ + protected function _hasUnclosedQuotes($string) + { + $string = trim($string); + $iMax = strlen($string); + $in_quote = false; + $i = $slashes = 0; + + for (; $i < $iMax; ++$i) { + switch ($string[$i]) { + case '\\': + ++$slashes; + break; + + case '"': + if ($slashes % 2 == 0) { + $in_quote = !$in_quote; + } + // Fall through to default action below. + + default: + $slashes = 0; + break; + } + } + + return $in_quote; + } + + /** + * Checks if a string has an unclosed brackets or not. IMPORTANT: + * This function handles both angle brackets and square brackets; + * + * @param string $string The string to check. + * @param string $chars The characters to check for. + * @return boolean True if there are unclosed brackets inside the string, false otherwise. + */ + protected function _hasUnclosedBrackets($string, $chars) + { + $num_angle_start = substr_count($string, $chars[0]); + $num_angle_end = substr_count($string, $chars[1]); + + $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]); + $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]); + + if ($num_angle_start < $num_angle_end) { + $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')'; + return false; + } else { + return ($num_angle_start > $num_angle_end); + } + } + + /** + * Sub function that is used only by hasUnclosedBrackets(). + * + * @param string $string The string to check. + * @param integer &$num The number of occurences. + * @param string $char The character to count. + * @return integer The number of occurences of $char in $string, adjusted for backslashes. + */ + protected function _hasUnclosedBracketsSub($string, &$num, $char) + { + $parts = explode($char, $string); + for ($i = 0; $i < count($parts); $i++){ + if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i])) + $num--; + if (isset($parts[$i + 1])) + $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1]; + } + + return $num; + } + + /** + * Function to begin checking the address. + * + * @param string $address The address to validate. + * @return mixed False on failure, or a structured array of address information on success. + */ + protected function _validateAddress($address) + { + $structure = null; + $is_group = false; + $addresses = array(); + + if ($address['group']) { + $is_group = true; + + // Get the group part of the name + $parts = explode(':', $address['address']); + $groupname = $this->_splitCheck($parts, ':'); + $structure = array(); + + // And validate the group part of the name. + if (!$this->_validatePhrase($groupname)){ + $this->error = 'Group name did not validate.'; + return false; + } else { + // Don't include groups if we are not nesting + // them. This avoids returning invalid addresses. + if ($this->nestGroups) { + $structure = new stdClass; + $structure->groupname = $groupname; + } + } + + $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':'))); + } + + // If a group then split on comma and put into an array. + // Otherwise, Just put the whole address in an array. + if ($is_group) { + while (strlen($address['address']) > 0) { + $parts = explode(',', $address['address']); + $addresses[] = $this->_splitCheck($parts, ','); + $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ','))); + } + } else { + $addresses[] = $address['address']; + } + + // Trim the whitespace from all of the address strings. + $addresses = array_map('trim', $addresses); + + // Validate each mailbox. + // Format could be one of: name + // geezer@domain.com + // geezer + // ... or any other format valid by RFC 822. + for ($i = 0; $i < count($addresses); $i++) { + if (!$this->validateMailbox($addresses[$i])) { + if (empty($this->error)) { + $this->error = 'Validation failed for: ' . $addresses[$i]; + } + return false; + } + } + + // Nested format + if ($this->nestGroups) { + if ($is_group) { + $structure->addresses = $addresses; + } else { + $structure = $addresses[0]; + } + + // Flat format + } else { + if ($is_group) { + $structure = array_merge($structure, $addresses); + } else { + $structure = $addresses; + } + } + + return $structure; + } + + /** + * Function to validate a phrase. + * + * @param string $phrase The phrase to check. + * @return boolean Success or failure. + */ + protected function _validatePhrase($phrase) + { + // Splits on one or more Tab or space. + $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY); + + $phrase_parts = array(); + while (count($parts) > 0){ + $phrase_parts[] = $this->_splitCheck($parts, ' '); + for ($i = 0; $i < $this->index + 1; $i++) + array_shift($parts); + } + + foreach ($phrase_parts as $part) { + // If quoted string: + if (substr($part, 0, 1) == '"') { + if (!$this->_validateQuotedString($part)) { + return false; + } + continue; + } + + // Otherwise it's an atom: + if (!$this->_validateAtom($part)) return false; + } + + return true; + } + + /** + * Function to validate an atom which from rfc822 is: + * atom = 1* + * + * If validation ($this->validate) has been turned off, then + * validateAtom() doesn't actually check anything. This is so that you + * can split a list of addresses up before encoding personal names + * (umlauts, etc.), for example. + * + * @param string $atom The string to check. + * @return boolean Success or failure. + */ + protected function _validateAtom($atom) + { + if (!$this->validate) { + // Validation has been turned off; assume the atom is okay. + return true; + } + + // Check for any char from ASCII 0 - ASCII 127 + if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) { + return false; + } + + // Check for specials: + if (preg_match('/[][()<>@,;\\:". ]/', $atom)) { + return false; + } + + // Check for control characters (ASCII 0-31): + if (preg_match('/[\\x00-\\x1F]+/', $atom)) { + return false; + } + + return true; + } + + /** + * Function to validate quoted string, which is: + * quoted-string = <"> *(qtext/quoted-pair) <"> + * + * @param string $qstring The string to check + * @return boolean Success or failure. + */ + protected function _validateQuotedString($qstring) + { + // Leading and trailing " + $qstring = substr($qstring, 1, -1); + + // Perform check, removing quoted characters first. + return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring)); + } + + /** + * Function to validate a mailbox, which is: + * mailbox = addr-spec ; simple address + * / phrase route-addr ; name and route-addr + * + * @param string &$mailbox The string to check. + * @return boolean Success or failure. + */ + public function validateMailbox(&$mailbox) + { + // A couple of defaults. + $phrase = ''; + $comment = ''; + $comments = array(); + $addr_spec = null; + + // Catch any RFC822 comments and store them separately. + $_mailbox = $mailbox; + while (strlen(trim($_mailbox)) > 0) { + $parts = explode('(', $_mailbox); + $before_comment = $this->_splitCheck($parts, '('); + if ($before_comment != $_mailbox) { + // First char should be a (. + $comment = substr(str_replace($before_comment, '', $_mailbox), 1); + $parts = explode(')', $comment); + $comment = $this->_splitCheck($parts, ')'); + $comments[] = $comment; + + // +2 is for the brackets + $_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment)+strlen($comment)+2); + } else { + break; + } + } + + foreach ($comments as $comment) { + $mailbox = str_replace("($comment)", '', $mailbox); + } + + $mailbox = trim($mailbox); + + // Check for name + route-addr + if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') { + $parts = explode('<', $mailbox); + $name = $this->_splitCheck($parts, '<'); + + $phrase = trim($name); + $route_addr = trim(substr($mailbox, strlen($name.'<'), -1)); + + if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) { + return false; + } + + // Only got addr-spec + } else { + // First snip angle brackets if present. + if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') { + $addr_spec = substr($mailbox, 1, -1); + } else { + $addr_spec = $mailbox; + } + + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } + + // Construct the object that will be returned. + $mbox = new stdClass(); + + // Add the phrase (even if empty) and comments + $mbox->personal = $phrase; + $mbox->comment = isset($comments) ? $comments : array(); + + if (isset($route_addr)) { + $mbox->mailbox = $route_addr['local_part']; + $mbox->host = $route_addr['domain']; + $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : ''; + } else { + $mbox->mailbox = $addr_spec['local_part']; + $mbox->host = $addr_spec['domain']; + } + + $mailbox = $mbox; + return true; + } + + /** + * This function validates a route-addr which is: + * route-addr = "<" [route] addr-spec ">" + * + * Angle brackets have already been removed at the point of + * getting to this function. + * + * @param string $route_addr The string to check. + * @return mixed False on failure, or an array containing validated address/route information on success. + */ + protected function _validateRouteAddr($route_addr) + { + // Check for colon. + if (strpos($route_addr, ':') !== false) { + $parts = explode(':', $route_addr); + $route = $this->_splitCheck($parts, ':'); + } else { + $route = $route_addr; + } + + // If $route is same as $route_addr then the colon was in + // quotes or brackets or, of course, non existent. + if ($route === $route_addr){ + unset($route); + $addr_spec = $route_addr; + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } else { + // Validate route part. + if (($route = $this->_validateRoute($route)) === false) { + return false; + } + + $addr_spec = substr($route_addr, strlen($route . ':')); + + // Validate addr-spec part. + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } + + if (isset($route)) { + $return['adl'] = $route; + } else { + $return['adl'] = ''; + } + + $return = array_merge($return, $addr_spec); + return $return; + } + + /** + * Function to validate a route, which is: + * route = 1#("@" domain) ":" + * + * @param string $route The string to check. + * @return mixed False on failure, or the validated $route on success. + */ + protected function _validateRoute($route) + { + // Split on comma. + $domains = explode(',', trim($route)); + + foreach ($domains as $domain) { + $domain = str_replace('@', '', trim($domain)); + if (!$this->_validateDomain($domain)) return false; + } + + return $route; + } + + /** + * Function to validate a domain, though this is not quite what + * you expect of a strict internet domain. + * + * domain = sub-domain *("." sub-domain) + * + * @param string $domain The string to check. + * @return mixed False on failure, or the validated domain on success. + */ + protected function _validateDomain($domain) + { + // Note the different use of $subdomains and $sub_domains + $subdomains = explode('.', $domain); + $sub_domains = array(); + + while (count($subdomains) > 0) { + $sub_domains[] = $this->_splitCheck($subdomains, '.'); + for ($i = 0; $i < $this->index + 1; $i++) + array_shift($subdomains); + } + + foreach ($sub_domains as $sub_domain) { + if (!$this->_validateSubdomain(trim($sub_domain))) + return false; + } + + // Managed to get here, so return input. + return $domain; + } + + /** + * Function to validate a subdomain: + * subdomain = domain-ref / domain-literal + * + * @param string $subdomain The string to check. + * @return boolean Success or failure. + */ + protected function _validateSubdomain($subdomain) + { + if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){ + if (!$this->_validateDliteral($arr[1])) return false; + } else { + if (!$this->_validateAtom($subdomain)) return false; + } + + // Got here, so return successful. + return true; + } + + /** + * Function to validate a domain literal: + * domain-literal = "[" *(dtext / quoted-pair) "]" + * + * @param string $dliteral The string to check. + * @return boolean Success or failure. + */ + protected function _validateDliteral($dliteral) + { + return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && ((! isset($matches[1])) || $matches[1] != '\\'); + } + + /** + * Function to validate an addr-spec. + * + * addr-spec = local-part "@" domain + * + * @param string $addr_spec The string to check. + * @return mixed False on failure, or the validated addr-spec on success. + */ + protected function _validateAddrSpec($addr_spec) + { + $addr_spec = trim($addr_spec); + + // Split on @ sign if there is one. + if (strpos($addr_spec, '@') !== false) { + $parts = explode('@', $addr_spec); + $local_part = $this->_splitCheck($parts, '@'); + $domain = substr($addr_spec, strlen($local_part . '@')); + + // No @ sign so assume the default domain. + } else { + $local_part = $addr_spec; + $domain = $this->default_domain; + } + + if (($local_part = $this->_validateLocalPart($local_part)) === false) return false; + if (($domain = $this->_validateDomain($domain)) === false) return false; + + // Got here so return successful. + return array('local_part' => $local_part, 'domain' => $domain); + } + + /** + * Function to validate the local part of an address: + * local-part = word *("." word) + * + * @param string $local_part + * @return mixed False on failure, or the validated local part on success. + */ + protected function _validateLocalPart($local_part) + { + $parts = explode('.', $local_part); + $words = array(); + + // Split the local_part into words. + while (count($parts) > 0) { + $words[] = $this->_splitCheck($parts, '.'); + for ($i = 0; $i < $this->index + 1; $i++) { + array_shift($parts); + } + } + + // Validate each word. + foreach ($words as $word) { + // word cannot be empty (#17317) + if ($word === '') { + return false; + } + // If this word contains an unquoted space, it is invalid. (6.2.4) + if (strpos($word, ' ') && $word[0] !== '"') + { + return false; + } + + if ($this->_validatePhrase(trim($word)) === false) return false; + } + + // Managed to get here, so return the input. + return $local_part; + } + + /** + * Returns an approximate count of how many addresses are in the + * given string. This is APPROXIMATE as it only splits based on a + * comma which has no preceding backslash. Could be useful as + * large amounts of addresses will end up producing *large* + * structures when used with parseAddressList(). + * + * @param string $data Addresses to count + * @return int Approximate count + */ + public function approximateCount($data) + { + return count(preg_split('/(?@. This can be sufficient for most + * people. Optional stricter mode can be utilised which restricts + * mailbox characters allowed to alphanumeric, full stop, hyphen + * and underscore. + * + * @param string $data Address to check + * @param boolean $strict Optional stricter mode + * @return mixed False if it fails, an indexed array + * username/domain if it matches + */ + public function isValidInetAddress($data, $strict = false) + { + $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i'; + if (preg_match($regex, trim($data), $matches)) { + return array($matches[1], $matches[2]); + } else { + return false; + } + } + +} diff --git a/WEB-INF/lib/pear/Mail/mail.php b/WEB-INF/lib/pear/Mail/mail.php old mode 100644 new mode 100755 index 4d21dc29a..d5160c0cf --- a/WEB-INF/lib/pear/Mail/mail.php +++ b/WEB-INF/lib/pear/Mail/mail.php @@ -1,166 +1,158 @@ - - * @copyright 2010 Chuck Hagenbuch - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id$ - * @link http://pear.php.net/package/Mail/ - */ - -/** - * internal PHP-mail() implementation of the PEAR Mail:: interface. - * @package Mail - * @version $Revision$ - */ -class Mail_mail extends Mail { - - /** - * Any arguments to pass to the mail() function. - * @var string - */ - var $_params = ''; - - /** - * Constructor. - * - * Instantiates a new Mail_mail:: object based on the parameters - * passed in. - * - * @param array $params Extra arguments for the mail() function. - */ - public function __construct($params = null) - { - // The other mail implementations accept parameters as arrays. - // In the interest of being consistent, explode an array into - // a string of parameter arguments. - if (is_array($params)) { - $this->_params = join(' ', $params); - } else { - $this->_params = $params; - } - - /* Because the mail() function may pass headers as command - * line arguments, we can't guarantee the use of the standard - * "\r\n" separator. Instead, we use the system's native line - * separator. */ - if (defined('PHP_EOL')) { - $this->sep = PHP_EOL; - } else { - $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n"; - } - } - - /** - * Implements Mail_mail::send() function using php's built-in mail() - * command. - * - * @param mixed $recipients Either a comma-seperated list of recipients - * (RFC822 compliant), or an array of recipients, - * each RFC822 valid. This may contain recipients not - * specified in the headers, for Bcc:, resending - * messages, etc. - * - * @param array $headers The array of headers to send with the mail, in an - * associative array, where the array key is the - * header name (ie, 'Subject'), and the array value - * is the header value (ie, 'test'). The header - * produced from those values would be 'Subject: - * test'. - * - * @param string $body The full text of the message body, including any - * Mime parts, etc. - * - * @return mixed Returns true on success, or a PEAR_Error - * containing a descriptive error message on - * failure. - */ - public function send($recipients, $headers, $body) - { - if (!is_array($headers)) { - return PEAR::raiseError('$headers must be an array'); - } - - $result = $this->_sanitizeHeaders($headers); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - // If we're passed an array of recipients, implode it. - if (is_array($recipients)) { - $recipients = implode(', ', $recipients); - } - - // Get the Subject out of the headers array so that we can - // pass it as a seperate argument to mail(). - $subject = ''; - if (isset($headers['Subject'])) { - $subject = $headers['Subject']; - unset($headers['Subject']); - } - - // Also remove the To: header. The mail() function will add its own - // To: header based on the contents of $recipients. - unset($headers['To']); - - // Flatten the headers out. - $headerElements = $this->prepareHeaders($headers); - if (is_a($headerElements, 'PEAR_Error')) { - return $headerElements; - } - list(, $text_headers) = $headerElements; - - // We only use mail()'s optional fifth parameter if the additional - // parameters have been provided and we're not running in safe mode. - if (empty($this->_params) || ini_get('safe_mode')) { - $result = mail($recipients, $subject, $body, $text_headers); - } else { - $result = mail($recipients, $subject, $body, $text_headers, - $this->_params); - } - - // If the mail() function returned failure, we need to create a - // PEAR_Error object and return it instead of the boolean result. - if ($result === false) { - $result = PEAR::raiseError('mail() returned failure'); - } - - return $result; - } - -} + + * @copyright 2010-2017 Chuck Hagenbuch + * @license http://opensource.org/licenses/BSD-3-Clause New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/Mail/ + */ + +/** + * internal PHP-mail() implementation of the PEAR Mail:: interface. + * @package Mail + * @version $Revision$ + */ +class Mail_mail extends Mail { + + /** + * Any arguments to pass to the mail() function. + * @var string + */ + var $_params = ''; + + /** + * Constructor. + * + * Instantiates a new Mail_mail:: object based on the parameters + * passed in. + * + * @param array $params Extra arguments for the mail() function. + */ + public function __construct($params = null) + { + // The other mail implementations accept parameters as arrays. + // In the interest of being consistent, explode an array into + // a string of parameter arguments. + if (is_array($params)) { + $this->_params = join(' ', $params); + } else { + $this->_params = $params; + } + } + + /** + * Implements Mail_mail::send() function using php's built-in mail() + * command. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + */ + public function send($recipients, $headers, $body) + { + if (!is_array($headers)) { + return PEAR::raiseError('$headers must be an array'); + } + + $result = $this->_sanitizeHeaders($headers); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + // If we're passed an array of recipients, implode it. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // Get the Subject out of the headers array so that we can + // pass it as a seperate argument to mail(). + $subject = ''; + if (isset($headers['Subject'])) { + $subject = $headers['Subject']; + unset($headers['Subject']); + } + + // Also remove the To: header. The mail() function will add its own + // To: header based on the contents of $recipients. + unset($headers['To']); + + // Flatten the headers out. + $headerElements = $this->prepareHeaders($headers); + if (is_a($headerElements, 'PEAR_Error')) { + return $headerElements; + } + list(, $text_headers) = $headerElements; + + // We only use mail()'s optional fifth parameter if the additional + // parameters have been provided and we're not running in safe mode. + if (empty($this->_params) || ini_get('safe_mode')) { + $result = mail($recipients, $subject, $body, $text_headers); + } else { + $result = mail($recipients, $subject, $body, $text_headers, + $this->_params); + } + + // If the mail() function returned failure, we need to create a + // PEAR_Error object and return it instead of the boolean result. + if ($result === false) { + $result = PEAR::raiseError('mail() returned failure'); + } + + return $result; + } + +} diff --git a/WEB-INF/lib/pear/Mail/mock.php b/WEB-INF/lib/pear/Mail/mock.php old mode 100644 new mode 100755 index e3e290bdc..dd84792ef --- a/WEB-INF/lib/pear/Mail/mock.php +++ b/WEB-INF/lib/pear/Mail/mock.php @@ -1,140 +1,142 @@ - - * @copyright 2010 Chuck Hagenbuch - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id$ - * @link http://pear.php.net/package/Mail/ - */ - -/** - * Mock implementation of the PEAR Mail:: interface for testing. - * @access public - * @package Mail - * @version $Revision$ - */ -class Mail_mock extends Mail { - - /** - * Array of messages that have been sent with the mock. - * - * @var array - */ - public $sentMessages = array(); - - /** - * Callback before sending mail. - * - * @var callback - */ - protected $_preSendCallback; - - /** - * Callback after sending mai. - * - * @var callback - */ - protected $_postSendCallback; - - /** - * Constructor. - * - * Instantiates a new Mail_mock:: object based on the parameters - * passed in. It looks for the following parameters, both optional: - * preSendCallback Called before an email would be sent. - * postSendCallback Called after an email would have been sent. - * - * @param array Hash containing any parameters. - */ - public function __construct($params) - { - if (isset($params['preSendCallback']) && - is_callable($params['preSendCallback'])) { - $this->_preSendCallback = $params['preSendCallback']; - } - - if (isset($params['postSendCallback']) && - is_callable($params['postSendCallback'])) { - $this->_postSendCallback = $params['postSendCallback']; - } - } - - /** - * Implements Mail_mock::send() function. Silently discards all - * mail. - * - * @param mixed $recipients Either a comma-seperated list of recipients - * (RFC822 compliant), or an array of recipients, - * each RFC822 valid. This may contain recipients not - * specified in the headers, for Bcc:, resending - * messages, etc. - * - * @param array $headers The array of headers to send with the mail, in an - * associative array, where the array key is the - * header name (ie, 'Subject'), and the array value - * is the header value (ie, 'test'). The header - * produced from those values would be 'Subject: - * test'. - * - * @param string $body The full text of the message body, including any - * Mime parts, etc. - * - * @return mixed Returns true on success, or a PEAR_Error - * containing a descriptive error message on - * failure. - */ - public function send($recipients, $headers, $body) - { - if ($this->_preSendCallback) { - call_user_func_array($this->_preSendCallback, - array(&$this, $recipients, $headers, $body)); - } - - $entry = array('recipients' => $recipients, 'headers' => $headers, 'body' => $body); - $this->sentMessages[] = $entry; - - if ($this->_postSendCallback) { - call_user_func_array($this->_postSendCallback, - array(&$this, $recipients, $headers, $body)); - } - - return true; - } - -} + + * @copyright 2010-2017 Chuck Hagenbuch + * @license http://opensource.org/licenses/BSD-3-Clause New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/Mail/ + */ + +/** + * Mock implementation of the PEAR Mail:: interface for testing. + * @access public + * @package Mail + * @version $Revision$ + */ +class Mail_mock extends Mail { + + /** + * Array of messages that have been sent with the mock. + * + * @var array + */ + public $sentMessages = array(); + + /** + * Callback before sending mail. + * + * @var callback + */ + protected $_preSendCallback; + + /** + * Callback after sending mai. + * + * @var callback + */ + protected $_postSendCallback; + + /** + * Constructor. + * + * Instantiates a new Mail_mock:: object based on the parameters + * passed in. It looks for the following parameters, both optional: + * preSendCallback Called before an email would be sent. + * postSendCallback Called after an email would have been sent. + * + * @param array Hash containing any parameters. + */ + public function __construct($params) + { + if (isset($params['preSendCallback']) && + is_callable($params['preSendCallback'])) { + $this->_preSendCallback = $params['preSendCallback']; + } + + if (isset($params['postSendCallback']) && + is_callable($params['postSendCallback'])) { + $this->_postSendCallback = $params['postSendCallback']; + } + } + + /** + * Implements Mail_mock::send() function. Silently discards all + * mail. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + */ + public function send($recipients, $headers, $body) + { + if ($this->_preSendCallback) { + call_user_func_array($this->_preSendCallback, + array(&$this, $recipients, $headers, $body)); + } + + $entry = array('recipients' => $recipients, 'headers' => $headers, 'body' => $body); + $this->sentMessages[] = $entry; + + if ($this->_postSendCallback) { + call_user_func_array($this->_postSendCallback, + array(&$this, $recipients, $headers, $body)); + } + + return true; + } + +} diff --git a/WEB-INF/lib/pear/Mail/null.php b/WEB-INF/lib/pear/Mail/null.php old mode 100644 new mode 100755 index 7896a4299..36d8e8464 --- a/WEB-INF/lib/pear/Mail/null.php +++ b/WEB-INF/lib/pear/Mail/null.php @@ -1,83 +1,85 @@ - - * @copyright 2010 Phil Kernick - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id$ - * @link http://pear.php.net/package/Mail/ - */ - -/** - * Null implementation of the PEAR Mail:: interface. - * @access public - * @package Mail - * @version $Revision$ - */ -class Mail_null extends Mail { - - /** - * Implements Mail_null::send() function. Silently discards all - * mail. - * - * @param mixed $recipients Either a comma-seperated list of recipients - * (RFC822 compliant), or an array of recipients, - * each RFC822 valid. This may contain recipients not - * specified in the headers, for Bcc:, resending - * messages, etc. - * - * @param array $headers The array of headers to send with the mail, in an - * associative array, where the array key is the - * header name (ie, 'Subject'), and the array value - * is the header value (ie, 'test'). The header - * produced from those values would be 'Subject: - * test'. - * - * @param string $body The full text of the message body, including any - * Mime parts, etc. - * - * @return mixed Returns true on success, or a PEAR_Error - * containing a descriptive error message on - * failure. - */ - public function send($recipients, $headers, $body) - { - return true; - } - -} + + * @copyright 2010-2017 Phil Kernick + * @license http://opensource.org/licenses/BSD-3-Clause New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/Mail/ + */ + +/** + * Null implementation of the PEAR Mail:: interface. + * @access public + * @package Mail + * @version $Revision$ + */ +class Mail_null extends Mail { + + /** + * Implements Mail_null::send() function. Silently discards all + * mail. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + */ + public function send($recipients, $headers, $body) + { + return true; + } + +} diff --git a/WEB-INF/lib/pear/Mail/sendmail.php b/WEB-INF/lib/pear/Mail/sendmail.php old mode 100644 new mode 100755 index f8866bdf3..0c3f9801d --- a/WEB-INF/lib/pear/Mail/sendmail.php +++ b/WEB-INF/lib/pear/Mail/sendmail.php @@ -1,169 +1,199 @@ - | -// +----------------------------------------------------------------------+ - -/** - * Sendmail implementation of the PEAR Mail:: interface. - * @access public - * @package Mail - * @version $Revision$ - */ -class Mail_sendmail extends Mail { - - /** - * The location of the sendmail or sendmail wrapper binary on the - * filesystem. - * @var string - */ - var $sendmail_path = '/usr/sbin/sendmail'; - - /** - * Any extra command-line parameters to pass to the sendmail or - * sendmail wrapper binary. - * @var string - */ - var $sendmail_args = '-i'; - - /** - * Constructor. - * - * Instantiates a new Mail_sendmail:: object based on the parameters - * passed in. It looks for the following parameters: - * sendmail_path The location of the sendmail binary on the - * filesystem. Defaults to '/usr/sbin/sendmail'. - * - * sendmail_args Any extra parameters to pass to the sendmail - * or sendmail wrapper binary. - * - * If a parameter is present in the $params array, it replaces the - * default. - * - * @param array $params Hash containing any parameters different from the - * defaults. - */ - public function __construct($params) - { - if (isset($params['sendmail_path'])) { - $this->sendmail_path = $params['sendmail_path']; - } - if (isset($params['sendmail_args'])) { - $this->sendmail_args = $params['sendmail_args']; - } - - /* - * Because we need to pass message headers to the sendmail program on - * the commandline, we can't guarantee the use of the standard "\r\n" - * separator. Instead, we use the system's native line separator. - */ - if (defined('PHP_EOL')) { - $this->sep = PHP_EOL; - } else { - $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n"; - } - } - - /** - * Implements Mail::send() function using the sendmail - * command-line binary. - * - * @param mixed $recipients Either a comma-seperated list of recipients - * (RFC822 compliant), or an array of recipients, - * each RFC822 valid. This may contain recipients not - * specified in the headers, for Bcc:, resending - * messages, etc. - * - * @param array $headers The array of headers to send with the mail, in an - * associative array, where the array key is the - * header name (ie, 'Subject'), and the array value - * is the header value (ie, 'test'). The header - * produced from those values would be 'Subject: - * test'. - * - * @param string $body The full text of the message body, including any - * Mime parts, etc. - * - * @return mixed Returns true on success, or a PEAR_Error - * containing a descriptive error message on - * failure. - */ - public function send($recipients, $headers, $body) - { - if (!is_array($headers)) { - return PEAR::raiseError('$headers must be an array'); - } - - $result = $this->_sanitizeHeaders($headers); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - $recipients = $this->parseRecipients($recipients); - if (is_a($recipients, 'PEAR_Error')) { - return $recipients; - } - $recipients = implode(' ', array_map('escapeshellarg', $recipients)); - - $headerElements = $this->prepareHeaders($headers); - if (is_a($headerElements, 'PEAR_Error')) { - return $headerElements; - } - list($from, $text_headers) = $headerElements; - - /* Since few MTAs are going to allow this header to be forged - * unless it's in the MAIL FROM: exchange, we'll use - * Return-Path instead of From: if it's set. */ - if (!empty($headers['Return-Path'])) { - $from = $headers['Return-Path']; - } - - if (!isset($from)) { - return PEAR::raiseError('No from address given.'); - } elseif (strpos($from, ' ') !== false || - strpos($from, ';') !== false || - strpos($from, '&') !== false || - strpos($from, '`') !== false) { - return PEAR::raiseError('From address specified with dangerous characters.'); - } - - $from = escapeshellarg($from); // Security bug #16200 - - $mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w'); - if (!$mail) { - return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.'); - } - - // Write the headers following by two newlines: one to end the headers - // section and a second to separate the headers block from the body. - fputs($mail, $text_headers . $this->sep . $this->sep); - - fputs($mail, $body); - $result = pclose($mail); - if (version_compare(phpversion(), '4.2.3') == -1) { - // With older php versions, we need to shift the pclose - // result to get the exit code. - $result = $result >> 8 & 0xFF; - } - - if ($result != 0) { - return PEAR::raiseError('sendmail returned error code ' . $result, - $result); - } - - return true; - } - -} + + * @author Chuck Hagenbuch + * @copyright 2010-2017 Chuck Hagenbuch + * @license http://opensource.org/licenses/BSD-3-Clause New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/Mail/ + */ + +/** + * Sendmail implementation of the PEAR Mail:: interface. + * @access public + * @package Mail + * @version $Revision$ + */ +class Mail_sendmail extends Mail { + + /** + * The location of the sendmail or sendmail wrapper binary on the + * filesystem. + * @var string + */ + var $sendmail_path = '/usr/sbin/sendmail'; + + /** + * Any extra command-line parameters to pass to the sendmail or + * sendmail wrapper binary. + * @var string + */ + var $sendmail_args = '-i'; + + /** + * Constructor. + * + * Instantiates a new Mail_sendmail:: object based on the parameters + * passed in. It looks for the following parameters: + * sendmail_path The location of the sendmail binary on the + * filesystem. Defaults to '/usr/sbin/sendmail'. + * + * sendmail_args Any extra parameters to pass to the sendmail + * or sendmail wrapper binary. + * + * If a parameter is present in the $params array, it replaces the + * default. + * + * @param array $params Hash containing any parameters different from the + * defaults. + */ + public function __construct($params) + { + if (isset($params['sendmail_path'])) { + $this->sendmail_path = $params['sendmail_path']; + } + if (isset($params['sendmail_args'])) { + $this->sendmail_args = $params['sendmail_args']; + } + + /* + * Because we need to pass message headers to the sendmail program on + * the commandline, we can't guarantee the use of the standard "\r\n" + * separator. Instead, we use the system's native line separator. + */ + if (defined('PHP_EOL')) { + $this->sep = PHP_EOL; + } else { + $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n"; + } + } + + /** + * Implements Mail::send() function using the sendmail + * command-line binary. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + */ + public function send($recipients, $headers, $body) + { + if (!is_array($headers)) { + return PEAR::raiseError('$headers must be an array'); + } + + $result = $this->_sanitizeHeaders($headers); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + $recipients = $this->parseRecipients($recipients); + if (is_a($recipients, 'PEAR_Error')) { + return $recipients; + } + $recipients = implode(' ', array_map('escapeshellarg', $recipients)); + + $headerElements = $this->prepareHeaders($headers); + if (is_a($headerElements, 'PEAR_Error')) { + return $headerElements; + } + list($from, $text_headers) = $headerElements; + + /* Since few MTAs are going to allow this header to be forged + * unless it's in the MAIL FROM: exchange, we'll use + * Return-Path instead of From: if it's set. */ + if (!empty($headers['Return-Path'])) { + $from = $headers['Return-Path']; + } + + if (!isset($from)) { + return PEAR::raiseError('No from address given.'); + } elseif (strpos($from, ' ') !== false || + strpos($from, ';') !== false || + strpos($from, '&') !== false || + strpos($from, '`') !== false) { + return PEAR::raiseError('From address specified with dangerous characters.'); + } + + $from = escapeshellarg($from); // Security bug #16200 + + $mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w'); + if (!$mail) { + return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.'); + } + + // Write the headers following by two newlines: one to end the headers + // section and a second to separate the headers block from the body. + fputs($mail, $text_headers . $this->sep . $this->sep); + + fputs($mail, $body); + $result = pclose($mail); + if (version_compare(phpversion(), '4.2.3') == -1) { + // With older php versions, we need to shift the pclose + // result to get the exit code. + $result = $result >> 8 & 0xFF; + } + + if ($result != 0) { + return PEAR::raiseError('sendmail returned error code ' . $result, + $result); + } + + return true; + } + +} diff --git a/WEB-INF/lib/pear/Mail/smtp.php b/WEB-INF/lib/pear/Mail/smtp.php old mode 100644 new mode 100755 index d446b1bcd..8d3181891 --- a/WEB-INF/lib/pear/Mail/smtp.php +++ b/WEB-INF/lib/pear/Mail/smtp.php @@ -1,441 +1,562 @@ - - * @author Chuck Hagenbuch - * @copyright 2010 Chuck Hagenbuch - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id$ - * @link http://pear.php.net/package/Mail/ - */ - -/** Error: Failed to create a Net_SMTP object */ -define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000); - -/** Error: Failed to connect to SMTP server */ -define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001); - -/** Error: SMTP authentication failure */ -define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002); - -/** Error: No From: address has been provided */ -define('PEAR_MAIL_SMTP_ERROR_FROM', 10003); - -/** Error: Failed to set sender */ -define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004); - -/** Error: Failed to add recipient */ -define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005); - -/** Error: Failed to send data */ -define('PEAR_MAIL_SMTP_ERROR_DATA', 10006); - -/** - * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class. - * @access public - * @package Mail - * @version $Revision$ - */ -class Mail_smtp extends Mail { - - /** - * SMTP connection object. - * - * @var object - * @access private - */ - var $_smtp = null; - - /** - * The list of service extension parameters to pass to the Net_SMTP - * mailFrom() command. - * @var array - */ - var $_extparams = array(); - - /** - * The SMTP host to connect to. - * @var string - */ - var $host = 'localhost'; - - /** - * The port the SMTP server is on. - * @var integer - */ - var $port = 25; - - /** - * Should SMTP authentication be used? - * - * This value may be set to true, false or the name of a specific - * authentication method. - * - * If the value is set to true, the Net_SMTP package will attempt to use - * the best authentication method advertised by the remote SMTP server. - * - * @var mixed - */ - var $auth = false; - - /** - * The username to use if the SMTP server requires authentication. - * @var string - */ - var $username = ''; - - /** - * The password to use if the SMTP server requires authentication. - * @var string - */ - var $password = ''; - - /** - * Hostname or domain that will be sent to the remote SMTP server in the - * HELO / EHLO message. - * - * @var string - */ - var $localhost = 'localhost'; - - /** - * SMTP connection timeout value. NULL indicates no timeout. - * - * @var integer - */ - var $timeout = null; - - /** - * Turn on Net_SMTP debugging? - * - * @var boolean $debug - */ - var $debug = false; - - /** - * Indicates whether or not the SMTP connection should persist over - * multiple calls to the send() method. - * - * @var boolean - */ - var $persist = false; - - /** - * Use SMTP command pipelining (specified in RFC 2920) if the SMTP server - * supports it. This speeds up delivery over high-latency connections. By - * default, use the default value supplied by Net_SMTP. - * @var bool - */ - var $pipelining; - - var $socket_options = array(); - - /** - * Constructor. - * - * Instantiates a new Mail_smtp:: object based on the parameters - * passed in. It looks for the following parameters: - * host The server to connect to. Defaults to localhost. - * port The port to connect to. Defaults to 25. - * auth SMTP authentication. Defaults to none. - * username The username to use for SMTP auth. No default. - * password The password to use for SMTP auth. No default. - * localhost The local hostname / domain. Defaults to localhost. - * timeout The SMTP connection timeout. Defaults to none. - * verp Whether to use VERP or not. Defaults to false. - * DEPRECATED as of 1.2.0 (use setMailParams()). - * debug Activate SMTP debug mode? Defaults to false. - * persist Should the SMTP connection persist? - * pipelining Use SMTP command pipelining - * - * If a parameter is present in the $params array, it replaces the - * default. - * - * @param array Hash containing any parameters different from the - * defaults. - */ - public function __construct($params) - { - if (isset($params['host'])) $this->host = $params['host']; - if (isset($params['port'])) $this->port = $params['port']; - if (isset($params['auth'])) $this->auth = $params['auth']; - if (isset($params['username'])) $this->username = $params['username']; - if (isset($params['password'])) $this->password = $params['password']; - if (isset($params['localhost'])) $this->localhost = $params['localhost']; - if (isset($params['timeout'])) $this->timeout = $params['timeout']; - if (isset($params['debug'])) $this->debug = (bool)$params['debug']; - if (isset($params['persist'])) $this->persist = (bool)$params['persist']; - if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining']; - if (isset($params['socket_options'])) $this->socket_options = $params['socket_options']; - // Deprecated options - if (isset($params['verp'])) { - $this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']); - } - } - - /** - * Destructor implementation to ensure that we disconnect from any - * potentially-alive persistent SMTP connections. - */ - public function __destruct() - { - $this->disconnect(); - } - - /** - * Implements Mail::send() function using SMTP. - * - * @param mixed $recipients Either a comma-seperated list of recipients - * (RFC822 compliant), or an array of recipients, - * each RFC822 valid. This may contain recipients not - * specified in the headers, for Bcc:, resending - * messages, etc. - * - * @param array $headers The array of headers to send with the mail, in an - * associative array, where the array key is the - * header name (e.g., 'Subject'), and the array value - * is the header value (e.g., 'test'). The header - * produced from those values would be 'Subject: - * test'. - * - * @param string $body The full text of the message body, including any - * MIME parts, etc. - * - * @return mixed Returns true on success, or a PEAR_Error - * containing a descriptive error message on - * failure. - */ - public function send($recipients, $headers, $body) - { - /* If we don't already have an SMTP object, create one. */ - $result = $this->getSMTPObject(); - if (PEAR::isError($result)) { - return $result; - } - - if (!is_array($headers)) { - return PEAR::raiseError('$headers must be an array'); - } - - $this->_sanitizeHeaders($headers); - - $headerElements = $this->prepareHeaders($headers); - if (is_a($headerElements, 'PEAR_Error')) { - $this->_smtp->rset(); - return $headerElements; - } - list($from, $textHeaders) = $headerElements; - - /* Since few MTAs are going to allow this header to be forged - * unless it's in the MAIL FROM: exchange, we'll use - * Return-Path instead of From: if it's set. */ - if (!empty($headers['Return-Path'])) { - $from = $headers['Return-Path']; - } - - if (!isset($from)) { - $this->_smtp->rset(); - return PEAR::raiseError('No From: address has been provided', - PEAR_MAIL_SMTP_ERROR_FROM); - } - - $params = null; - if (!empty($this->_extparams)) { - foreach ($this->_extparams as $key => $val) { - $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val); - } - } - if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) { - $error = $this->_error("Failed to set sender: $from", $res); - $this->_smtp->rset(); - return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER); - } - - $recipients = $this->parseRecipients($recipients); - if (is_a($recipients, 'PEAR_Error')) { - $this->_smtp->rset(); - return $recipients; - } - - foreach ($recipients as $recipient) { - $res = $this->_smtp->rcptTo($recipient); - if (is_a($res, 'PEAR_Error')) { - $error = $this->_error("Failed to add recipient: $recipient", $res); - $this->_smtp->rset(); - return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT); - } - } - - /* Send the message's headers and the body as SMTP data. */ - $res = $this->_smtp->data($body, $textHeaders); - list(,$args) = $this->_smtp->getResponse(); - - if (preg_match("/Ok: queued as (.*)/", $args, $queued)) { - $this->queued_as = $queued[1]; - } - - /* we need the greeting; from it we can extract the authorative name of the mail server we've really connected to. - * ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */ - $this->greeting = $this->_smtp->getGreeting(); - - if (is_a($res, 'PEAR_Error')) { - $error = $this->_error('Failed to send data', $res); - $this->_smtp->rset(); - return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA); - } - - /* If persistent connections are disabled, destroy our SMTP object. */ - if ($this->persist === false) { - $this->disconnect(); - } - - return true; - } - - /** - * Connect to the SMTP server by instantiating a Net_SMTP object. - * - * @return mixed Returns a reference to the Net_SMTP object on success, or - * a PEAR_Error containing a descriptive error message on - * failure. - * - * @since 1.2.0 - */ - public function getSMTPObject() - { - if (is_object($this->_smtp) !== false) { - return $this->_smtp; - } - - include_once 'Net/SMTP.php'; - $this->_smtp = new Net_SMTP($this->host, - $this->port, - $this->localhost, - $this->pipelining, - 0, - $this->socket_options); - - /* If we still don't have an SMTP object at this point, fail. */ - if (is_object($this->_smtp) === false) { - return PEAR::raiseError('Failed to create a Net_SMTP object', - PEAR_MAIL_SMTP_ERROR_CREATE); - } - - /* Configure the SMTP connection. */ - if ($this->debug) { - $this->_smtp->setDebug(true); - } - - /* Attempt to connect to the configured SMTP server. */ - if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) { - $error = $this->_error('Failed to connect to ' . - $this->host . ':' . $this->port, - $res); - return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT); - } - - /* Attempt to authenticate if authentication has been enabled. */ - if ($this->auth) { - $method = is_string($this->auth) ? $this->auth : ''; - - if (PEAR::isError($res = $this->_smtp->auth($this->username, - $this->password, - $method))) { - $error = $this->_error("$method authentication failure", - $res); - $this->_smtp->rset(); - return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH); - } - } - - return $this->_smtp; - } - - /** - * Add parameter associated with a SMTP service extension. - * - * @param string Extension keyword. - * @param string Any value the keyword needs. - * - * @since 1.2.0 - */ - public function addServiceExtensionParameter($keyword, $value = null) - { - $this->_extparams[$keyword] = $value; - } - - /** - * Disconnect and destroy the current SMTP connection. - * - * @return boolean True if the SMTP connection no longer exists. - * - * @since 1.1.9 - */ - public function disconnect() - { - /* If we have an SMTP object, disconnect and destroy it. */ - if (is_object($this->_smtp) && $this->_smtp->disconnect()) { - $this->_smtp = null; - } - - /* We are disconnected if we no longer have an SMTP object. */ - return ($this->_smtp === null); - } - - /** - * Build a standardized string describing the current SMTP error. - * - * @param string $text Custom string describing the error context. - * @param object $error Reference to the current PEAR_Error object. - * - * @return string A string describing the current SMTP error. - * - * @since 1.1.7 - */ - protected function _error($text, $error) - { - /* Split the SMTP response into a code and a response string. */ - list($code, $response) = $this->_smtp->getResponse(); - - /* Build our standardized error string. */ - return $text - . ' [SMTP: ' . $error->getMessage() - . " (code: $code, response: $response)]"; - } - -} + + * @author Chuck Hagenbuch + * @copyright 2010-2021 Chuck Hagenbuch + * @license http://opensource.org/licenses/BSD-3-Clause New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/Mail/ + */ + +/** Error: Failed to create a Net_SMTP object */ +define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000); + +/** Error: Failed to connect to SMTP server */ +define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001); + +/** Error: SMTP authentication failure */ +define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002); + +/** Error: No From: address has been provided */ +define('PEAR_MAIL_SMTP_ERROR_FROM', 10003); + +/** Error: Failed to set sender */ +define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004); + +/** Error: Failed to add recipient */ +define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005); + +/** Error: Failed to send data */ +define('PEAR_MAIL_SMTP_ERROR_DATA', 10006); + +/** + * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class. + * @access public + * @package Mail + * @version $Revision$ + */ +class Mail_smtp extends Mail { + + /** + * SMTP connection object. + * + * @var object + * @access private + */ + var $_smtp = null; + + /** + * The list of service extension parameters to pass to the Net_SMTP + * mailFrom() command. + * + * @var array + */ + var $_extparams = array(); + + /** + * The SMTP host to connect to. + * + * @var string + */ + var $host = 'localhost'; + + /** + * The port the SMTP server is on. + * + * @var integer + */ + var $port = 25; + + /** + * Should STARTTLS connection be used? + * + * This value may be set to true or false. + * + * If the value is set to true, the Net_SMTP package will attempt to use + * a STARTTLS encrypted connection. + * + * If the value is set to false, the Net_SMTP package will avoid + * a STARTTLS encrypted connection. + * + * NULL indicates only STARTTLS if $auth is set. + * + * PEAR/Net_SMTP >= 1.10.0 required. + * + * @var boolean + */ + var $starttls = null; + + /** + * Should SMTP authentication be used? + * + * This value may be set to true, false or the name of a specific + * authentication method. + * + * If the value is set to true, the Net_SMTP package will attempt to use + * the best authentication method advertised by the remote SMTP server. + * + * @var mixed + */ + var $auth = false; + + /** + * The username to use if the SMTP server requires authentication. + * + * @var string + */ + var $username = ''; + + /** + * The password to use if the SMTP server requires authentication. + * + * @var string + */ + var $password = ''; + + /** + * Hostname or domain that will be sent to the remote SMTP server in the + * HELO / EHLO message. + * + * @var string + */ + var $localhost = 'localhost'; + + /** + * SMTP connection timeout value. NULL indicates no timeout. + * + * @var integer + */ + var $timeout = null; + + /** + * Turn on Net_SMTP debugging? + * + * @var boolean $debug + */ + var $debug = false; + + /** + * Set debug_handler on Net_SMTP + * + * @var callable $debug_handler + */ + var $debug_handler = null; + + /** + * we need the greeting; from it we can extract the authorative name of the mail + * server we've really connected to. ideal if we're connecting to a round-robin + * of relay servers and need to track which exact one took the email + * + * @var string + */ + var $greeting = null; + + /** + * Indicates whether or not the SMTP connection should persist over + * multiple calls to the send() method. + * + * @var boolean + */ + var $persist = false; + + /** + * Use SMTP command pipelining (specified in RFC 2920) if the SMTP server + * supports it. This speeds up delivery over high-latency connections. By + * default, use the default value supplied by Net_SMTP. + * + * @var boolean + */ + var $pipelining; + + /** + * The list of socket options + * + * @var array + */ + var $socket_options = array(); + + /** + * SMTP response message + * + * @var string + * @since 1.6.0 + */ + var $response = null; + + /** + * If the message ends up in the queue, on the recipient server, + * the response will be saved here. + * Some successfully delivered emails will include a “queued” + * notation in the SMTP response, such as "250 OK; queued as 12345". + * This indicates that the email was delivered to the recipient + * as expected, but may require additional processing before it + * lands in the recipient’s inbox. + * + * @var string + */ + var $queued_as = null; + + /** + * Constructor. + * + * Instantiates a new Mail_smtp:: object based on the parameters + * passed in. It looks for the following parameters: + * host The server to connect to. Defaults to localhost. + * port The port to connect to. Defaults to 25. + * auth SMTP authentication. Defaults to none. + * starttls Should STARTTLS connection be used? No default. PEAR/Net_SMTP >= 1.10.0 required. + * username The username to use for SMTP auth. No default. + * password The password to use for SMTP auth. No default. + * localhost The local hostname / domain. Defaults to localhost. + * timeout The SMTP connection timeout. Defaults to none. + * verp Whether to use VERP or not. Defaults to false. + * DEPRECATED as of 1.2.0 (use setMailParams()). + * debug Activate SMTP debug mode? Defaults to false. + * debug_handler Set SMTP debug handler function. Defaults to null. + * persist Should the SMTP connection persist? + * pipelining Use SMTP command pipelining + * socket_options Socket stream_context_create() options. + * + * If a parameter is present in the $params array, it replaces the + * default. + * + * @param array Hash containing any parameters different from the + * defaults. + */ + public function __construct($params) + { + if (isset($params['host'])) $this->host = $params['host']; + if (isset($params['port'])) $this->port = $params['port']; + if (isset($params['auth'])) $this->auth = $params['auth']; + if (isset($params['starttls'])) $this->starttls = $params['starttls']; + if (isset($params['username'])) $this->username = $params['username']; + if (isset($params['password'])) $this->password = $params['password']; + if (isset($params['localhost'])) $this->localhost = $params['localhost']; + if (isset($params['timeout'])) $this->timeout = $params['timeout']; + if (isset($params['debug'])) $this->debug = (bool)$params['debug']; + if (isset($params['debug_handler'])) $this->debug_handler = $params['debug_handler']; + if (isset($params['persist'])) $this->persist = (bool)$params['persist']; + if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining']; + if (isset($params['socket_options'])) $this->socket_options = $params['socket_options']; + // Deprecated options + if (isset($params['verp'])) { + $this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']); + } + } + + /** + * Destructor implementation to ensure that we disconnect from any + * potentially-alive persistent SMTP connections. + */ + public function __destruct() + { + $this->disconnect(); + } + + /** + * Implements Mail::send() function using SMTP. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (e.g., 'Subject'), and the array value + * is the header value (e.g., 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * MIME parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + */ + public function send($recipients, $headers, $body) + { + $result = $this->send_or_fail($recipients, $headers, $body); + + /* If persistent connections are disabled, destroy our SMTP object. */ + if ($this->persist === false) { + $this->disconnect(); + } + + return $result; + } + + protected function send_or_fail($recipients, $headers, $body) + { + /* If we don't already have an SMTP object, create one. */ + $result = $this->getSMTPObject(); + if (PEAR::isError($result)) { + return $result; + } + + if (!is_array($headers)) { + return PEAR::raiseError('$headers must be an array'); + } + + $this->_sanitizeHeaders($headers); + + $headerElements = $this->prepareHeaders($headers); + if (is_a($headerElements, 'PEAR_Error')) { + $this->_smtp->rset(); + return $headerElements; + } + list($from, $textHeaders) = $headerElements; + + /* Since few MTAs are going to allow this header to be forged + * unless it's in the MAIL FROM: exchange, we'll use + * Return-Path instead of From: if it's set. */ + if (!empty($headers['Return-Path'])) { + $from = $headers['Return-Path']; + } + + if (!isset($from)) { + $this->_smtp->rset(); + return PEAR::raiseError('No From: address has been provided', + PEAR_MAIL_SMTP_ERROR_FROM); + } + + $params = ''; + if (!empty($this->_extparams)) { + foreach ($this->_extparams as $key => $val) { + $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val); + } + } + if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) { + $error = $this->_error("Failed to set sender: $from", $res); + $this->_smtp->rset(); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER); + } + + $recipients = $this->parseRecipients($recipients); + if (is_a($recipients, 'PEAR_Error')) { + $this->_smtp->rset(); + return $recipients; + } + + foreach ($recipients as $recipient) { + $res = $this->_smtp->rcptTo($recipient); + if (is_a($res, 'PEAR_Error')) { + $error = $this->_error("Failed to add recipient: $recipient", $res); + $this->_smtp->rset(); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT); + } + } + + /* Send the message's headers and the body as SMTP data. */ + $res = $this->_smtp->data($body, $textHeaders); + + list($code, $args) = $this->_smtp->getResponse(); + + $this->response = $code . ' ' . $args; + + if (preg_match("/ queued as (.*)/", $args, $queued)) { + $this->queued_as = $queued[1]; + } + + /* we need the greeting; from it we can extract the authorative name of the mail server we've really connected to. + * ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */ + $this->greeting = $this->_smtp->getGreeting(); + + if (is_a($res, 'PEAR_Error')) { + $error = $this->_error('Failed to send data', $res); + $this->_smtp->rset(); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA); + } + + return true; + } + + /** + * Connect to the SMTP server by instantiating a Net_SMTP object. + * + * @return mixed Returns a reference to the Net_SMTP object on success, or + * a PEAR_Error containing a descriptive error message on + * failure. + * + * @since 1.2.0 + */ + public function getSMTPObject() + { + if (is_object($this->_smtp) !== false) { + return $this->_smtp; + } + + include_once 'Net/SMTP.php'; + $this->_smtp = new Net_SMTP($this->host, + $this->port, + $this->localhost, + $this->pipelining, + 0, + $this->socket_options); + + /* If we still don't have an SMTP object at this point, fail. */ + if (is_object($this->_smtp) === false) { + return PEAR::raiseError('Failed to create a Net_SMTP object', + PEAR_MAIL_SMTP_ERROR_CREATE); + } + + /* Configure the SMTP connection. */ + if ($this->debug) { + $this->_smtp->setDebug(true, $this->debug_handler); + } + + /* Attempt to connect to the configured SMTP server. */ + if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) { + $error = $this->_error('Failed to connect to ' . + $this->host . ':' . $this->port, + $res); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT); + } + + /* Attempt to authenticate if authentication has been enabled. */ + if ($this->auth) { + $method = is_string($this->auth) ? $this->auth : ''; + + $tls = $this->starttls === false ? false : true; + + if (PEAR::isError($res = $this->_smtp->auth($this->username, + $this->password, + $method, + $tls))) { + $error = $this->_error("$method authentication failure", + $res); + $this->_smtp->rset(); + return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH); + } + } + + /* Attempt to establish a TLS encrypted connection. PEAR/Net_SMTP >= 1.10.0 required. */ + if ($this->starttls && !$this->auth) { + $starttls = $this->_smtp->starttls(); + if (PEAR::isError($starttls)) { + return PEAR::raiseError($starttls); + } elseif ($starttls === false) { + return PEAR::raiseError('STARTTLS failed'); + } + } + + return $this->_smtp; + } + + /** + * Add parameter associated with a SMTP service extension. + * + * @param string Extension keyword. + * @param string Any value the keyword needs. + * + * @since 1.2.0 + */ + public function addServiceExtensionParameter($keyword, $value = null) + { + $this->_extparams[$keyword] = $value; + } + + /** + * Disconnect and destroy the current SMTP connection. + * + * @return boolean True if the SMTP connection no longer exists. + * + * @since 1.1.9 + */ + public function disconnect() + { + /* If we have an SMTP object, disconnect and destroy it. */ + if (is_object($this->_smtp) && $this->_smtp->disconnect()) { + $this->_smtp = null; + } + + /* We are disconnected if we no longer have an SMTP object. */ + return ($this->_smtp === null); + } + + /** + * Returns the SMTP response message after sending. + * + * @return string SMTP response message or NULL. + * + * @since 1.6.0 + */ + public function getResponse() + { + return $this->response; + } + + /** + * Returns the SMTP response message if includes "queue" after sending. + * + * @return string SMTP queue message or NULL. + * + * @since 1.6.0 + */ + public function getQueuedAs() + { + return $this->queued_as; + } + + /** + * Build a standardized string describing the current SMTP error. + * + * @param string $text Custom string describing the error context. + * @param object $error Reference to the current PEAR_Error object. + * + * @return string A string describing the current SMTP error. + * + * @since 1.1.7 + */ + protected function _error($text, $error) + { + /* Split the SMTP response into a code and a response string. */ + list($code, $response) = $this->_smtp->getResponse(); + + /* Build our standardized error string. */ + return $text + . ' [SMTP: ' . $error->getMessage() + . " (code: $code, response: $response)]"; + } + +} diff --git a/WEB-INF/lib/pear/Mail/smtpmx.php b/WEB-INF/lib/pear/Mail/smtpmx.php old mode 100644 new mode 100755 index 6eb8bec2e..5c63b5240 --- a/WEB-INF/lib/pear/Mail/smtpmx.php +++ b/WEB-INF/lib/pear/Mail/smtpmx.php @@ -1,502 +1,515 @@ - - * @copyright 2010 gERD Schaufelberger - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version CVS: $Id$ - * @link http://pear.php.net/package/Mail/ - */ - -require_once 'Net/SMTP.php'; - -/** - * SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class. - * - * - * @access public - * @author gERD Schaufelberger - * @package Mail - * @version $Revision$ - */ -class Mail_smtpmx extends Mail { - - /** - * SMTP connection object. - * - * @var object - * @access private - */ - var $_smtp = null; - - /** - * The port the SMTP server is on. - * @var integer - * @see getservicebyname() - */ - var $port = 25; - - /** - * Hostname or domain that will be sent to the remote SMTP server in the - * HELO / EHLO message. - * - * @var string - * @see posix_uname() - */ - var $mailname = 'localhost'; - - /** - * SMTP connection timeout value. NULL indicates no timeout. - * - * @var integer - */ - var $timeout = 10; - - /** - * use either PEAR:Net_DNS or getmxrr - * - * @var boolean - */ - var $withNetDns = true; - - /** - * PEAR:Net_DNS_Resolver - * - * @var object - */ - var $resolver; - - /** - * Whether to use VERP or not. If not a boolean, the string value - * will be used as the VERP separators. - * - * @var mixed boolean or string - */ - var $verp = false; - - /** - * Whether to use VRFY or not. - * - * @var boolean $vrfy - */ - var $vrfy = false; - - /** - * Switch to test mode - don't send emails for real - * - * @var boolean $debug - */ - var $test = false; - - /** - * Turn on Net_SMTP debugging? - * - * @var boolean $peardebug - */ - var $debug = false; - - /** - * internal error codes - * - * translate internal error identifier to PEAR-Error codes and human - * readable messages. - * - * @var boolean $debug - * @todo as I need unique error-codes to identify what exactly went wrond - * I did not use intergers as it should be. Instead I added a "namespace" - * for each code. This avoids conflicts with error codes from different - * classes. How can I use unique error codes and stay conform with PEAR? - */ - var $errorCode = array( - 'not_connected' => array( - 'code' => 1, - 'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.' - ), - 'failed_vrfy_rcpt' => array( - 'code' => 2, - 'msg' => 'Recipient "{RCPT}" could not be veryfied.' - ), - 'failed_set_from' => array( - 'code' => 3, - 'msg' => 'Failed to set sender: {FROM}.' - ), - 'failed_set_rcpt' => array( - 'code' => 4, - 'msg' => 'Failed to set recipient: {RCPT}.' - ), - 'failed_send_data' => array( - 'code' => 5, - 'msg' => 'Failed to send mail to: {RCPT}.' - ), - 'no_from' => array( - 'code' => 5, - 'msg' => 'No from address has be provided.' - ), - 'send_data' => array( - 'code' => 7, - 'msg' => 'Failed to create Net_SMTP object.' - ), - 'no_mx' => array( - 'code' => 8, - 'msg' => 'No MX-record for {RCPT} found.' - ), - 'no_resolver' => array( - 'code' => 9, - 'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"' - ), - 'failed_rset' => array( - 'code' => 10, - 'msg' => 'RSET command failed, SMTP-connection corrupt.' - ), - ); - - /** - * Constructor. - * - * Instantiates a new Mail_smtp:: object based on the parameters - * passed in. It looks for the following parameters: - * mailname The name of the local mail system (a valid hostname which matches the reverse lookup) - * port smtp-port - the default comes from getservicebyname() and should work fine - * timeout The SMTP connection timeout. Defaults to 30 seconds. - * vrfy Whether to use VRFY or not. Defaults to false. - * verp Whether to use VERP or not. Defaults to false. - * test Activate test mode? Defaults to false. - * debug Activate SMTP and Net_DNS debug mode? Defaults to false. - * netdns whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true - * - * If a parameter is present in the $params array, it replaces the - * default. - * - * @access public - * @param array Hash containing any parameters different from the - * defaults. - * @see _Mail_smtpmx() - */ - function __construct($params) - { - if (isset($params['mailname'])) { - $this->mailname = $params['mailname']; - } else { - // try to find a valid mailname - if (function_exists('posix_uname')) { - $uname = posix_uname(); - $this->mailname = $uname['nodename']; - } - } - - // port number - if (isset($params['port'])) { - $this->_port = $params['port']; - } else { - $this->_port = getservbyname('smtp', 'tcp'); - } - - if (isset($params['timeout'])) $this->timeout = $params['timeout']; - if (isset($params['verp'])) $this->verp = $params['verp']; - if (isset($params['test'])) $this->test = $params['test']; - if (isset($params['peardebug'])) $this->test = $params['peardebug']; - if (isset($params['netdns'])) $this->withNetDns = $params['netdns']; - } - - /** - * Constructor wrapper for PHP4 - * - * @access public - * @param array Hash containing any parameters different from the defaults - * @see __construct() - */ - function Mail_smtpmx($params) - { - $this->__construct($params); - register_shutdown_function(array(&$this, '__destruct')); - } - - /** - * Destructor implementation to ensure that we disconnect from any - * potentially-alive persistent SMTP connections. - */ - function __destruct() - { - if (is_object($this->_smtp)) { - $this->_smtp->disconnect(); - $this->_smtp = null; - } - } - - /** - * Implements Mail::send() function using SMTP direct delivery - * - * @access public - * @param mixed $recipients in RFC822 style or array - * @param array $headers The array of headers to send with the mail. - * @param string $body The full text of the message body, - * @return mixed Returns true on success, or a PEAR_Error - */ - function send($recipients, $headers, $body) - { - if (!is_array($headers)) { - return PEAR::raiseError('$headers must be an array'); - } - - $result = $this->_sanitizeHeaders($headers); - if (is_a($result, 'PEAR_Error')) { - return $result; - } - - // Prepare headers - $headerElements = $this->prepareHeaders($headers); - if (is_a($headerElements, 'PEAR_Error')) { - return $headerElements; - } - list($from, $textHeaders) = $headerElements; - - // use 'Return-Path' if possible - if (!empty($headers['Return-Path'])) { - $from = $headers['Return-Path']; - } - if (!isset($from)) { - return $this->_raiseError('no_from'); - } - - // Prepare recipients - $recipients = $this->parseRecipients($recipients); - if (is_a($recipients, 'PEAR_Error')) { - return $recipients; - } - - foreach ($recipients as $rcpt) { - list($user, $host) = explode('@', $rcpt); - - $mx = $this->_getMx($host); - if (is_a($mx, 'PEAR_Error')) { - return $mx; - } - - if (empty($mx)) { - $info = array('rcpt' => $rcpt); - return $this->_raiseError('no_mx', $info); - } - - $connected = false; - foreach ($mx as $mserver => $mpriority) { - $this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname); - - // configure the SMTP connection. - if ($this->debug) { - $this->_smtp->setDebug(true); - } - - // attempt to connect to the configured SMTP server. - $res = $this->_smtp->connect($this->timeout); - if (is_a($res, 'PEAR_Error')) { - $this->_smtp = null; - continue; - } - - // connection established - if ($res) { - $connected = true; - break; - } - } - - if (!$connected) { - $info = array( - 'host' => implode(', ', array_keys($mx)), - 'port' => $this->port, - 'rcpt' => $rcpt, - ); - return $this->_raiseError('not_connected', $info); - } - - // Verify recipient - if ($this->vrfy) { - $res = $this->_smtp->vrfy($rcpt); - if (is_a($res, 'PEAR_Error')) { - $info = array('rcpt' => $rcpt); - return $this->_raiseError('failed_vrfy_rcpt', $info); - } - } - - // mail from: - $args['verp'] = $this->verp; - $res = $this->_smtp->mailFrom($from, $args); - if (is_a($res, 'PEAR_Error')) { - $info = array('from' => $from); - return $this->_raiseError('failed_set_from', $info); - } - - // rcpt to: - $res = $this->_smtp->rcptTo($rcpt); - if (is_a($res, 'PEAR_Error')) { - $info = array('rcpt' => $rcpt); - return $this->_raiseError('failed_set_rcpt', $info); - } - - // Don't send anything in test mode - if ($this->test) { - $result = $this->_smtp->rset(); - $res = $this->_smtp->rset(); - if (is_a($res, 'PEAR_Error')) { - return $this->_raiseError('failed_rset'); - } - - $this->_smtp->disconnect(); - $this->_smtp = null; - return true; - } - - // Send data - $res = $this->_smtp->data($body, $textHeaders); - if (is_a($res, 'PEAR_Error')) { - $info = array('rcpt' => $rcpt); - return $this->_raiseError('failed_send_data', $info); - } - - $this->_smtp->disconnect(); - $this->_smtp = null; - } - - return true; - } - - /** - * Recieve mx rexords for a spciefied host - * - * The MX records - * - * @access private - * @param string $host mail host - * @return mixed sorted - */ - function _getMx($host) - { - $mx = array(); - - if ($this->withNetDns) { - $res = $this->_loadNetDns(); - if (is_a($res, 'PEAR_Error')) { - return $res; - } - - $response = $this->resolver->query($host, 'MX'); - if (!$response) { - return false; - } - - foreach ($response->answer as $rr) { - if ($rr->type == 'MX') { - $mx[$rr->exchange] = $rr->preference; - } - } - } else { - $mxHost = array(); - $mxWeight = array(); - - if (!getmxrr($host, $mxHost, $mxWeight)) { - return false; - } - for ($i = 0; $i < count($mxHost); ++$i) { - $mx[$mxHost[$i]] = $mxWeight[$i]; - } - } - - asort($mx); - return $mx; - } - - /** - * initialize PEAR:Net_DNS_Resolver - * - * @access private - * @return boolean true on success - */ - function _loadNetDns() - { - if (is_object($this->resolver)) { - return true; - } - - if (!include_once 'Net/DNS.php') { - return $this->_raiseError('no_resolver'); - } - - $this->resolver = new Net_DNS_Resolver(); - if ($this->debug) { - $this->resolver->test = 1; - } - - return true; - } - - /** - * raise standardized error - * - * include additional information in error message - * - * @access private - * @param string $id maps error ids to codes and message - * @param array $info optional information in associative array - * @see _errorCode - */ - function _raiseError($id, $info = array()) - { - $code = $this->errorCode[$id]['code']; - $msg = $this->errorCode[$id]['msg']; - - // include info to messages - if (!empty($info)) { - $search = array(); - $replace = array(); - - foreach ($info as $key => $value) { - array_push($search, '{' . strtoupper($key) . '}'); - array_push($replace, $value); - } - - $msg = str_replace($search, $replace, $msg); - } - - return PEAR::raiseError($msg, $code); - } - -} + + * @copyright 2010-2017 gERD Schaufelberger + * @license http://opensource.org/licenses/BSD-3-Clause New BSD License + * @version CVS: $Id$ + * @link http://pear.php.net/package/Mail/ + */ + +require_once 'Net/SMTP.php'; + +/** + * SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class. + * + * + * @access public + * @author gERD Schaufelberger + * @package Mail + * @version $Revision$ + */ +class Mail_smtpmx extends Mail { + + /** + * SMTP connection object. + * + * @var object + * @access private + */ + var $_smtp = null; + + /** + * The port the SMTP server is on. + * @var integer + * @see getservicebyname() + */ + var $port = 25; + + /** + * Hostname or domain that will be sent to the remote SMTP server in the + * HELO / EHLO message. + * + * @var string + * @see posix_uname() + */ + var $mailname = 'localhost'; + + /** + * SMTP connection timeout value. NULL indicates no timeout. + * + * @var integer + */ + var $timeout = 10; + + /** + * use either PEAR:Net_DNS or getmxrr + * + * @var boolean + */ + var $withNetDns = true; + + /** + * PEAR:Net_DNS_Resolver + * + * @var object + */ + var $resolver; + + /** + * Whether to use VERP or not. If not a boolean, the string value + * will be used as the VERP separators. + * + * @var mixed boolean or string + */ + var $verp = false; + + /** + * Whether to use VRFY or not. + * + * @var boolean $vrfy + */ + var $vrfy = false; + + /** + * Switch to test mode - don't send emails for real + * + * @var boolean $test + */ + var $test = false; + + /** + * Turn on Net_SMTP debugging? + * + * @var boolean $debug + */ + var $debug = false; + + /** + * Set debug_handler on Net_SMTP + * + * @var string $debug_handler + */ + var $debug_handler = null; + + /** + * internal error codes + * + * translate internal error identifier to PEAR-Error codes and human + * readable messages. + * + * @var array $errorCode + * @todo as I need unique error-codes to identify what exactly went wrond + * I did not use intergers as it should be. Instead I added a "namespace" + * for each code. This avoids conflicts with error codes from different + * classes. How can I use unique error codes and stay conform with PEAR? + */ + var $errorCode = array( + 'not_connected' => array( + 'code' => 1, + 'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.' + ), + 'failed_vrfy_rcpt' => array( + 'code' => 2, + 'msg' => 'Recipient "{RCPT}" could not be veryfied.' + ), + 'failed_set_from' => array( + 'code' => 3, + 'msg' => 'Failed to set sender: {FROM}.' + ), + 'failed_set_rcpt' => array( + 'code' => 4, + 'msg' => 'Failed to set recipient: {RCPT}.' + ), + 'failed_send_data' => array( + 'code' => 5, + 'msg' => 'Failed to send mail to: {RCPT}.' + ), + 'no_from' => array( + 'code' => 5, + 'msg' => 'No from address has be provided.' + ), + 'send_data' => array( + 'code' => 7, + 'msg' => 'Failed to create Net_SMTP object.' + ), + 'no_mx' => array( + 'code' => 8, + 'msg' => 'No MX-record for {RCPT} found.' + ), + 'no_resolver' => array( + 'code' => 9, + 'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"' + ), + 'failed_rset' => array( + 'code' => 10, + 'msg' => 'RSET command failed, SMTP-connection corrupt.' + ), + ); + + /** + * Constructor. + * + * Instantiates a new Mail_smtp:: object based on the parameters + * passed in. It looks for the following parameters: + * mailname The name of the local mail system (a valid hostname which matches the reverse lookup) + * port smtp-port - the default comes from getservicebyname() and should work fine + * timeout The SMTP connection timeout. Defaults to 30 seconds. + * vrfy Whether to use VRFY or not. Defaults to false. + * verp Whether to use VERP or not. Defaults to false. + * test Activate test mode? Defaults to false. + * debug Activate SMTP and Net_DNS debug mode? Defaults to false. + * debug_handler Set SMTP debug handler function. Defaults to null. + * netdns whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true + * + * If a parameter is present in the $params array, it replaces the + * default. + * + * @access public + * @param array Hash containing any parameters different from the + * defaults. + * @see _Mail_smtpmx() + */ + function __construct($params) + { + if (isset($params['mailname'])) { + $this->mailname = $params['mailname']; + } else { + // try to find a valid mailname + if (function_exists('posix_uname')) { + $uname = posix_uname(); + $this->mailname = $uname['nodename']; + } + } + + // port number + if (isset($params['port'])) { + $this->port = $params['port']; + } else { + $this->port = getservbyname('smtp', 'tcp'); + } + + if (isset($params['timeout'])) $this->timeout = $params['timeout']; + if (isset($params['vrfy'])) $this->vrfy = (bool)$params['vrfy']; + if (isset($params['verp'])) $this->verp = $params['verp']; + if (isset($params['test'])) $this->test = (bool)$params['test']; + if (isset($params['peardebug'])) $this->debug = (bool)$params['peardebug']; + if (isset($params['debug'])) $this->debug = (bool)$params['debug']; + if (isset($params['debug_handler'])) $this->debug_handler = $params['debug_handler']; + if (isset($params['netdns'])) $this->withNetDns = $params['netdns']; + } + + /** + * Constructor wrapper for PHP4 + * + * @access public + * @param array Hash containing any parameters different from the defaults + * @see __construct() + */ + function Mail_smtpmx($params) + { + $this->__construct($params); + register_shutdown_function(array(&$this, '__destruct')); + } + + /** + * Destructor implementation to ensure that we disconnect from any + * potentially-alive persistent SMTP connections. + */ + function __destruct() + { + if (is_object($this->_smtp)) { + $this->_smtp->disconnect(); + $this->_smtp = null; + } + } + + /** + * Implements Mail::send() function using SMTP direct delivery + * + * @access public + * @param mixed $recipients in RFC822 style or array + * @param array $headers The array of headers to send with the mail. + * @param string $body The full text of the message body, + * @return mixed Returns true on success, or a PEAR_Error + */ + function send($recipients, $headers, $body) + { + if (!is_array($headers)) { + return PEAR::raiseError('$headers must be an array'); + } + + $result = $this->_sanitizeHeaders($headers); + if (is_a($result, 'PEAR_Error')) { + return $result; + } + + // Prepare headers + $headerElements = $this->prepareHeaders($headers); + if (is_a($headerElements, 'PEAR_Error')) { + return $headerElements; + } + list($from, $textHeaders) = $headerElements; + + // use 'Return-Path' if possible + if (!empty($headers['Return-Path'])) { + $from = $headers['Return-Path']; + } + if (!isset($from)) { + return $this->_raiseError('no_from'); + } + + // Prepare recipients + $recipients = $this->parseRecipients($recipients); + if (is_a($recipients, 'PEAR_Error')) { + return $recipients; + } + + foreach ($recipients as $rcpt) { + list($user, $host) = explode('@', $rcpt); + + $mx = $this->_getMx($host); + if (is_a($mx, 'PEAR_Error')) { + return $mx; + } + + if (empty($mx)) { + $info = array('rcpt' => $rcpt); + return $this->_raiseError('no_mx', $info); + } + + $connected = false; + foreach ($mx as $mserver => $mpriority) { + $this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname); + + // configure the SMTP connection. + if ($this->debug) { + $this->_smtp->setDebug(true, $this->debug_handler); + } + + // attempt to connect to the configured SMTP server. + $res = $this->_smtp->connect($this->timeout); + if (is_a($res, 'PEAR_Error')) { + $this->_smtp = null; + continue; + } + + // connection established + if ($res) { + $connected = true; + break; + } + } + + if (!$connected) { + $info = array( + 'host' => implode(', ', array_keys($mx)), + 'port' => $this->port, + 'rcpt' => $rcpt, + ); + return $this->_raiseError('not_connected', $info); + } + + // Verify recipient + if ($this->vrfy) { + $res = $this->_smtp->vrfy($rcpt); + if (is_a($res, 'PEAR_Error')) { + $info = array('rcpt' => $rcpt); + return $this->_raiseError('failed_vrfy_rcpt', $info); + } + } + + // mail from: + $args['verp'] = $this->verp; + $res = $this->_smtp->mailFrom($from, $args); + if (is_a($res, 'PEAR_Error')) { + $info = array('from' => $from); + return $this->_raiseError('failed_set_from', $info); + } + + // rcpt to: + $res = $this->_smtp->rcptTo($rcpt); + if (is_a($res, 'PEAR_Error')) { + $info = array('rcpt' => $rcpt); + return $this->_raiseError('failed_set_rcpt', $info); + } + + // Don't send anything in test mode + if ($this->test) { + $result = $this->_smtp->rset(); + $res = $this->_smtp->rset(); + if (is_a($res, 'PEAR_Error')) { + return $this->_raiseError('failed_rset'); + } + + $this->_smtp->disconnect(); + $this->_smtp = null; + return true; + } + + // Send data + $res = $this->_smtp->data($body, $textHeaders); + if (is_a($res, 'PEAR_Error')) { + $info = array('rcpt' => $rcpt); + return $this->_raiseError('failed_send_data', $info); + } + + $this->_smtp->disconnect(); + $this->_smtp = null; + } + + return true; + } + + /** + * Recieve mx rexords for a spciefied host + * + * The MX records + * + * @access private + * @param string $host mail host + * @return mixed sorted + */ + function _getMx($host) + { + $mx = array(); + + if ($this->withNetDns) { + $res = $this->_loadNetDns(); + if (is_a($res, 'PEAR_Error')) { + return $res; + } + + $response = $this->resolver->query($host, 'MX'); + if (!$response) { + return false; + } + + foreach ($response->answer as $rr) { + if ($rr->type == 'MX') { + $mx[$rr->exchange] = $rr->preference; + } + } + } else { + $mxHost = array(); + $mxWeight = array(); + + if (!getmxrr($host, $mxHost, $mxWeight)) { + return false; + } + for ($i = 0; $i < count($mxHost); ++$i) { + $mx[$mxHost[$i]] = $mxWeight[$i]; + } + } + + asort($mx); + return $mx; + } + + /** + * initialize PEAR:Net_DNS_Resolver + * + * @access private + * @return boolean true on success + */ + function _loadNetDns() + { + if (is_object($this->resolver)) { + return true; + } + + if (!include_once 'Net/DNS.php') { + return $this->_raiseError('no_resolver'); + } + + $this->resolver = new Net_DNS_Resolver(); + if ($this->debug) { + $this->resolver->debug = 1; + } + + return true; + } + + /** + * raise standardized error + * + * include additional information in error message + * + * @access private + * @param string $id maps error ids to codes and message + * @param array $info optional information in associative array + * @see _errorCode + */ + function _raiseError($id, $info = array()) + { + $code = $this->errorCode[$id]['code']; + $msg = $this->errorCode[$id]['msg']; + + // include info to messages + if (!empty($info)) { + $search = array(); + $replace = array(); + + foreach ($info as $key => $value) { + array_push($search, '{' . strtoupper($key) . '}'); + array_push($replace, $value); + } + + $msg = str_replace($search, $replace, $msg); + } + + return PEAR::raiseError($msg, $code); + } + +} diff --git a/WEB-INF/lib/pear/Net/SMTP.php b/WEB-INF/lib/pear/Net/SMTP.php old mode 100644 new mode 100755 index dd822a565..a2ccaeb9f --- a/WEB-INF/lib/pear/Net/SMTP.php +++ b/WEB-INF/lib/pear/Net/SMTP.php @@ -3,15 +3,33 @@ // +----------------------------------------------------------------------+ // | PHP Version 5 and 7 | // +----------------------------------------------------------------------+ -// | Copyright (c) 1997-2015 Jon Parise and Chuck Hagenbuch | -// +----------------------------------------------------------------------+ -// | This source file is subject to version 3.01 of the PHP license, | -// | that is bundled with this package in the file LICENSE, and is | -// | available at through the world-wide-web at | -// | http://www.php.net/license/3_01.txt. | -// | If you did not receive a copy of the PHP license and are unable to | -// | obtain it through the world-wide-web, please send a note to | -// | license@php.net so we can mail you a copy immediately. | +// | Copyright (c) 1997-2021 Jon Parise and Chuck Hagenbuch | +// | All rights reserved. | +// | | +// | Redistribution and use in source and binary forms, with or without | +// | modification, are permitted provided that the following conditions | +// | are met: | +// | | +// | 1. Redistributions of source code must retain the above copyright | +// | notice, this list of conditions and the following disclaimer. | +// | | +// | 2. Redistributions in binary form must reproduce the above copyright | +// | notice, this list of conditions and the following disclaimer in | +// | the documentation and/or other materials provided with the | +// | distribution. | +// | | +// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | +// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | +// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | +// | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | +// | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | +// | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | +// | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | +// | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | +// | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | +// | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | +// | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | +// | POSSIBILITY OF SUCH DAMAGE. | // +----------------------------------------------------------------------+ // | Authors: Chuck Hagenbuch | // | Jon Parise | @@ -29,6 +47,7 @@ * @author Chuck Hagenbuch * @author Jon Parise * @author Damian Alejandro Fernandez Sosa + * @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause * * @example basic.php A basic implementation of the Net_SMTP package. */ @@ -131,6 +150,25 @@ class Net_SMTP */ protected $esmtp = array(); + /** + * GSSAPI principal. + * @var string + */ + protected $gssapi_principal = null; + + /** + * GSSAPI principal. + * @var string + */ + protected $gssapi_cname = null; + + /** + * SCRAM SHA-Hash algorithm. + * + * @var string + */ + protected $scram_sha_hash_algorithm = null; + /** * Instantiates a new Net_SMTP object, overriding any defaults * with parameters that are passed in. @@ -142,17 +180,20 @@ class Net_SMTP * $smtp = new Net_SMTP('ssl://mail.host.com', 465); * $smtp->connect(); * - * @param string $host The server to connect to. - * @param integer $port The port to connect to. - * @param string $localhost The value to give when sending EHLO or HELO. - * @param boolean $pipelining Use SMTP command pipelining - * @param integer $timeout Socket I/O timeout in seconds. - * @param array $socket_options Socket stream_context_create() options. + * @param string $host The server to connect to. + * @param integer $port The port to connect to. + * @param string $localhost The value to give when sending EHLO or HELO. + * @param boolean $pipelining Use SMTP command pipelining + * @param integer $timeout Socket I/O timeout in seconds. + * @param array $socket_options Socket stream_context_create() options. + * @param string $gssapi_principal GSSAPI service principal name + * @param string $gssapi_cname GSSAPI credentials cache * * @since 1.0 */ public function __construct($host = null, $port = null, $localhost = null, - $pipelining = false, $timeout = 0, $socket_options = null + $pipelining = false, $timeout = 0, $socket_options = null, + $gssapi_principal = null, $gssapi_cname = null ) { if (isset($host)) { $this->host = $host; @@ -164,21 +205,35 @@ public function __construct($host = null, $port = null, $localhost = null, $this->localhost = $localhost; } - $this->pipelining = $pipelining; - $this->socket = new Net_Socket(); - $this->socket_options = $socket_options; - $this->timeout = $timeout; + $this->pipelining = $pipelining; + $this->socket = new Net_Socket(); + $this->socket_options = $socket_options; + $this->timeout = $timeout; + $this->gssapi_principal = $gssapi_principal; + $this->gssapi_cname = $gssapi_cname; + + /* If PHP krb5 extension is loaded, we enable GSSAPI method. */ + if (isset($gssapi_principal) && extension_loaded('krb5')) { + $this->setAuthMethod('GSSAPI', array($this, 'authGSSAPI')); + } /* Include the Auth_SASL package. If the package is available, we * enable the authentication methods that depend upon it. */ if (@include_once 'Auth/SASL.php') { $this->setAuthMethod('CRAM-MD5', array($this, 'authCramMD5')); $this->setAuthMethod('DIGEST-MD5', array($this, 'authDigestMD5')); + $this->setAuthMethod('SCRAM-SHA-1', array($this, 'authScramSHA1')); + $this->setAuthMethod('SCRAM-SHA-224', array($this, 'authScramSHA224')); + $this->setAuthMethod('SCRAM-SHA-256', array($this, 'authScramSHA256')); + $this->setAuthMethod('SCRAM-SHA-384', array($this, 'authScramSHA384')); + $this->setAuthMethod('SCRAM-SHA-512', array($this, 'authScramSHA512')); } /* These standard authentication methods are always available. */ $this->setAuthMethod('LOGIN', array($this, 'authLogin'), false); $this->setAuthMethod('PLAIN', array($this, 'authPlain'), false); + $this->setAuthMethod('XOAUTH2', array($this, 'authXOAuth2'), false); + $this->setAuthMethod('OAUTHBEARER', array($this, 'authOAuthBearer'), false); } /** @@ -384,7 +439,7 @@ public function command($command, $valid) */ public function getResponse() { - return array($this->code, join("\n", $this->arguments)); + return array($this->code, implode("\n", $this->arguments)); } /** @@ -455,22 +510,32 @@ public function connect($timeout = null, $persistent = false) /** * Attempt to disconnect from the SMTP server. * + * @param bool $force Forces a disconnection of the socket even if + * the QUIT command fails + * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @since 1.0 */ - public function disconnect() + public function disconnect($force = false) { - if (PEAR::isError($error = $this->put('QUIT'))) { - return $error; + /* parseResponse is only needed if put QUIT is successful */ + if (!PEAR::isError($error = $this->put('QUIT'))) { + $error = $this->parseResponse(221); } - if (PEAR::isError($error = $this->parseResponse(221))) { - return $error; + + /* disconnecting socket if there is no error on the QUIT + * command or force disconnecting is requested */ + if (!PEAR::isError($error) || $force) { + if (PEAR::isError($error_socket = $this->socket->disconnect())) { + return PEAR::raiseError( + 'Failed to disconnect socket: ' . $error_socket->getMessage() + ); + } } - if (PEAR::isError($error = $this->socket->disconnect())) { - return PEAR::raiseError( - 'Failed to disconnect socket: ' . $error->getMessage() - ); + + if (PEAR::isError($error)) { + return $error; } return true; @@ -538,14 +603,123 @@ protected function getBestAuthMethod() return PEAR::raiseError('No supported authentication methods'); } + + /** + * Establish STARTTLS Connection. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, true on success, or false if SSL/TLS + * isn't available. + * @since 1.10.0 + */ + public function starttls() + { + /* We can only attempt a TLS connection if one has been requested, + * we're running PHP 5.1.0 or later, have access to the OpenSSL + * extension, are connected to an SMTP server which supports the + * STARTTLS extension, and aren't already connected over a secure + * (SSL) socket connection. */ + if (version_compare(PHP_VERSION, '5.1.0', '>=') + && extension_loaded('openssl') && isset($this->esmtp['STARTTLS']) + && strncasecmp($this->host, 'ssl://', 6) !== 0 + ) { + /* Start the TLS connection attempt. */ + if (PEAR::isError($result = $this->put('STARTTLS'))) { + return $result; + } + if (PEAR::isError($result = $this->parseResponse(220))) { + return $result; + } + if (isset($this->socket_options['ssl']['crypto_method'])) { + $crypto_method = $this->socket_options['ssl']['crypto_method']; + } else { + /* STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT constant does not exist + * and STREAM_CRYPTO_METHOD_SSLv23_CLIENT constant is + * inconsistent across PHP versions. */ + $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT; + + if (defined('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT')) { + $crypto_method |= @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; + } + + if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { + $crypto_method |= @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + } + + if (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT')) { + $crypto_method |= @STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT; + } + } + + for ($attempts = 1; $attempts < 15; $attempts++) { + if(PEAR::isError( + $result = $this->socket->enableCrypto( + true, $crypto_method) + ) + ) { + return $result; + } + if ($this->socket->isBlocking() !== true) { + usleep($attempts); + } + if ($result !== 0) { + break; + } + } + + if ($result !== true) { + $last_error = error_get_last(); + $crypto_types_arr = $this->getDefinedConstantsKeyFilter( + 'STREAM_CRYPTO_METHOD_' + ); + $error_types_arr = $this->getDefinedConstantsKeyFilter( + 'E_' + ); + + $resultErrorString = "STARTTLS failed "; + //{enableCrypto: false; + $resultErrorString .= "{enableCrypto: %s; "; + //crypto_method: STREAM_CRYPTO_METHOD_TLS_CLIENT (3); + $resultErrorString .= "crypto_method: %s (%s); "; + //attempts: 1; + $resultErrorString .= "attempts: %d; "; + //E_ERROR (1): ErrorMessage} + $resultErrorString .= "%s (%s): %s}"; + + return PEAR::raiseError( + sprintf( + $resultErrorString, + var_export($result, true), + array_search($crypto_method, $crypto_types_arr), + var_export($crypto_method, true), + $attempts, + array_search($last_error['type'], $error_types_arr), + $last_error['type'], + $last_error['message'] + ) + ); + } + + /* Send EHLO again to recieve the AUTH string from the + * SMTP server. */ + $this->negotiate(); + } else { + return false; + } + + return true; + } /** * Attempt to do SMTP authentication. * * @param string $uid The userid to authenticate as. * @param string $pwd The password to authenticate with. - * @param string $method The requested authentication method. If none is + * @param string $method The requested authentication method. If none is * specified, the best supported method will be used. + * If you use the special method `OAUTH`, library + * will choose between OAUTHBEARER or XOAUTH2 + * according the server's capabilities. * @param bool $tls Flag indicating whether or not TLS should be attempted. * @param string $authz An optional authorization identifier. If specified, this * identifier will be used as the authorization proxy. @@ -561,36 +735,11 @@ public function auth($uid, $pwd , $method = '', $tls = true, $authz = '') * extension, are connected to an SMTP server which supports the * STARTTLS extension, and aren't already connected over a secure * (SSL) socket connection. */ - if ($tls && version_compare(PHP_VERSION, '5.1.0', '>=') - && extension_loaded('openssl') && isset($this->esmtp['STARTTLS']) - && strncasecmp($this->host, 'ssl://', 6) !== 0 - ) { + if ($tls) { /* Start the TLS connection attempt. */ - if (PEAR::isError($result = $this->put('STARTTLS'))) { - return $result; - } - if (PEAR::isError($result = $this->parseResponse(220))) { - return $result; + if (PEAR::isError($starttls = $this->starttls())) { + return $starttls; } - if (isset($this->socket_options['ssl']['crypto_method'])) { - $crypto_method = $this->socket_options['ssl']['crypto_method']; - } else { - /* STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT constant does not exist - * and STREAM_CRYPTO_METHOD_SSLv23_CLIENT constant is - * inconsistent across PHP versions. */ - $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT - | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT - | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; - } - if (PEAR::isError($result = $this->socket->enableCrypto(true, $crypto_method))) { - return $result; - } elseif ($result !== true) { - return PEAR::raiseError('STARTTLS failed'); - } - - /* Send EHLO again to recieve the AUTH string from the - * SMTP server. */ - $this->negotiate(); } if (empty($this->esmtp['AUTH'])) { @@ -604,6 +753,19 @@ public function auth($uid, $pwd , $method = '', $tls = true, $authz = '') /* Return the PEAR_Error object from _getBestAuthMethod(). */ return $method; } + } elseif ($method === 'OAUTH') { + // special case of OAUTH, use the supported method + $found = false; + $available_methods = explode(' ', $this->esmtp['AUTH']); + foreach (['OAUTHBEARER', 'XOAUTH2'] as $method) { + if (in_array($method, $available_methods)) { + $found = true; + break; + } + } + if (!$found) { + return PEAR::raiseError("neither OAUTHBEARER nor XOAUTH2 is a supported authentication method"); + } } else { $method = strtoupper($method); if (!array_key_exists($method, $this->auth_methods)) { @@ -686,9 +848,15 @@ public function setAuthMethod($name, $callback, $prepend = true) * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @since 1.1.0 + * @deprecated 1.11.0 */ protected function authDigestMD5($uid, $pwd, $authz = '') { + /* TODO trigger deprecation error in 2.0.0 and remove authDigestMD5() in 3.0.0 + trigger_error(__CLASS__ . ' (' . $this->host . '): Authentication method DIGEST-MD5' . + ' is no longer secure and should be avoided.', E_USER_DEPRECATED); + */ + if (PEAR::isError($error = $this->put('AUTH', 'DIGEST-MD5'))) { return $error; } @@ -737,9 +905,15 @@ protected function authDigestMD5($uid, $pwd, $authz = '') * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @since 1.1.0 + * @deprecated 1.11.0 */ protected function authCRAMMD5($uid, $pwd, $authz = '') { + /* TODO trigger deprecation error in 2.0.0 and remove authCRAMMD5() in 3.0.0 + trigger_error(__CLASS__ . ' (' . $this->host . '): Authentication method CRAM-MD5' . + ' is no longer secure and should be avoided.', E_USER_DEPRECATED); + */ + if (PEAR::isError($error = $this->put('AUTH', 'CRAM-MD5'))) { return $error; } @@ -776,9 +950,15 @@ protected function authCRAMMD5($uid, $pwd, $authz = '') * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * @since 1.1.0 + * @deprecated 1.11.0 */ protected function authLogin($uid, $pwd, $authz = '') { + /* TODO trigger deprecation error in 2.0.0 and remove authLogin() in 3.0.0 + trigger_error(__CLASS__ . ' (' . $this->host . '): Authentication method LOGIN' . + ' is no longer secure and should be avoided.', E_USER_DEPRECATED); + */ + if (PEAR::isError($error = $this->put('AUTH', 'LOGIN'))) { return $error; } @@ -850,6 +1030,341 @@ protected function authPlain($uid, $pwd, $authz = '') return true; } + /** + * Authenticates the user using the GSSAPI method. + * + * PHP krb5 extension is required, + * service principal and credentials cache must be set. + * + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + */ + protected function authGSSAPI($uid, $pwd, $authz = '') + { + if (PEAR::isError($error = $this->put('AUTH', 'GSSAPI'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->code === 503) { + return true; + } + return $error; + } + + if (!$this->gssapi_principal) { + return PEAR::raiseError('No Kerberos service principal set', 2); + } + + if (!empty($this->gssapi_cname)) { + putenv('KRB5CCNAME=' . $this->gssapi_cname); + } + + try { + $ccache = new KRB5CCache(); + if (!empty($this->gssapi_cname)) { + $ccache->open($this->gssapi_cname); + } + + $gssapicontext = new GSSAPIContext(); + $gssapicontext->acquireCredentials($ccache); + + $token = ''; + $success = $gssapicontext->initSecContext($this->gssapi_principal, null, null, null, $token); + $token = base64_encode($token); + } + catch (Exception $e) { + return PEAR::raiseError('GSSAPI authentication failed: ' . $e->getMessage()); + } + + if (PEAR::isError($error = $this->put($token))) { + return $error; + } + + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->parseResponse(334))) { + return $error; + } + + $response = $this->arguments[0]; + + try { + $challenge = base64_decode($response); + $gssapicontext->unwrap($challenge, $challenge); + $gssapicontext->wrap($challenge, $challenge, true); + } + catch (Exception $e) { + return PEAR::raiseError('GSSAPI authentication failed: ' . $e->getMessage()); + } + + if (PEAR::isError($error = $this->put(base64_encode($challenge)))) { + return $error; + } + + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->parseResponse(235))) { + return $error; + } + + return true; + } + + /** + * Authenticates the user using the XOAUTH2 method. + * + * @param string $uid The userid to authenticate as. + * @param string $token The access token prefixed by it's type + * example: "Bearer $access_token". + * @param string $authz The optional authorization proxy identifier. + * @param object $conn The current object + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @since 1.9.0 + */ + //FIXME: to switch into protected method on next major release + public function authXOAuth2($uid, $token, $authz, $conn) + { + $auth = base64_encode("user=$uid\1auth=$token\1\1"); + return $this->authenticateOAuth('XOAUTH2', $auth, $authz, $conn); + } + + /** + * Authenticates the user using the OAUTHBEARER method. + * + * @param string $uid The userid to authenticate as. + * @param string $token The access token prefixed by it's type + * example: "Bearer $access_token". + * @param string $authz The optional authorization proxy identifier. + * @param object $conn The current object + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @since 1.9.3 + * @see https://www.rfc-editor.org/rfc/rfc7628.html + */ + protected function authOAuthBearer($uid, $token, $authz, $conn) + { + $auth = base64_encode("n,a=$uid\1auth=$token\1\1"); + return $this->authenticateOAuth('OAUTHBEARER', $auth, $authz, $conn); + } + + /** + * Authenticates the user using the OAUTHBEARER or XOAUTH2 method. + * + * @param string $method The method (OAUTHBEARER or XOAUTH2) + * @param string $auth The authentication string (base64 coded) + * @param string $authz The optional authorization proxy identifier. + * @param object $conn The current object + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + */ + protected function authenticateOAuth( $method, $auth, $authz, $conn) + { + // Maximum length of the base64-encoded token to be sent in the initial response is 504 - strlen($method) bytes, + // according to RFC 4954 (https://datatracker.ietf.org/doc/html/rfc4954); for longer tokens an empty initial + // response MUST be sent and the token must be sent separately + // (504 bytes = /SMTP command length limit/ - 6 bytes /"AUTH "/ -strlen($method) - 1 byte /" "/ - 2 bytes /CRLF/) + if (strlen($auth) <= (504-strlen($method))) { + if (PEAR::isError($error = $this->put('AUTH', $method . ' ' . $auth))) { + return $error; + } + } else { + if (PEAR::isError($error = $this->put('AUTH', $method))) { + return $error; + } + + // server is expected to respond with 334 + if (PEAR::isError($error = $this->parseResponse(334))) { + return $error; + } + + // then follows the token + if (PEAR::isError($error = $this->put($auth))) { + return $error; + } + } + + /* 235: Authentication successful or 334: Continue authentication */ + if (PEAR::isError($error = $this->parseResponse([235, 334]))) { + return $error; + } + + /* 334: Continue authentication request */ + if ($this->code === 334) { + /* Send an empty line as response to 334 */ + if (PEAR::isError($error = $this->put(''))) { + return $error; + } + + /* Expect 235: Authentication successful */ + if (PEAR::isError($error = $this->parseResponse(235))) { + return $error; + } + } + + return true; + } + + /** + * Authenticates the user using the SCRAM-SHA-1 method. + * + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @since 1.11.0 + */ + protected function authScramSHA1($uid, $pwd, $authz = '') + { + $this->scram_sha_hash_algorithm = 'SCRAM-SHA-1'; + return $this->authScramSHA($uid, $pwd, $authz); + } + + /** + * Authenticates the user using the SCRAM-SHA-224 method. + * + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @since 1.11.0 + */ + protected function authScramSHA224($uid, $pwd, $authz = '') + { + $this->scram_sha_hash_algorithm = 'SCRAM-SHA-224'; + return $this->authScramSHA($uid, $pwd, $authz); + } + + /** + * Authenticates the user using the SCRAM-SHA-256 method. + * + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @since 1.11.0 + */ + protected function authScramSHA256($uid, $pwd, $authz = '') + { + $this->scram_sha_hash_algorithm = 'SCRAM-SHA-256'; + return $this->authScramSHA($uid, $pwd, $authz); + } + + /** + * Authenticates the user using the SCRAM-SHA-384 method. + * + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @since 1.11.0 + */ + protected function authScramSHA384($uid, $pwd, $authz = '') + { + $this->scram_sha_hash_algorithm = 'SCRAM-SHA-384'; + return $this->authScramSHA($uid, $pwd, $authz); + } + + /** + * Authenticates the user using the SCRAM-SHA-512 method. + * + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @since 1.11.0 + */ + protected function authScramSHA512($uid, $pwd, $authz = '') + { + $this->scram_sha_hash_algorithm = 'SCRAM-SHA-512'; + return $this->authScramSHA($uid, $pwd, $authz); + } + + /** + * Authenticates the user using the SCRAM-SHA method. + * + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @since 1.11.0 + */ + protected function authScramSHA($uid, $pwd, $authz = '') + { + if (PEAR::isError($error = $this->put('AUTH', $this->scram_sha_hash_algorithm))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->code === 503) { + return true; + } + return $error; + } + + $cram = Auth_SASL::factory($this->scram_sha_hash_algorithm); + $auth_str = base64_encode($cram->getResponse($uid, $pwd)); + + /* Step 1: Send first authentication request */ + if (PEAR::isError($error = $this->put($auth_str))) { + return $error; + } + + /* 334: Continue authentication request with password salt */ + if (PEAR::isError($error = $this->parseResponse(334))) { + return $error; + } + + $challenge = base64_decode($this->arguments[0]); + $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); + + /* Step 2: Send salted authentication request */ + if (PEAR::isError($error = $this->put($auth_str))) { + return $error; + } + + /* 334: Continue authentication request with password salt */ + if (PEAR::isError($error = $this->parseResponse(334))) { + return $error; + } + + /* Verify server signature */ + $verification = $cram->processOutcome(base64_decode($this->arguments[0])); + if ($verification == false) { + return PEAR::raiseError("SCRAM Server verification on step 3 not successful"); + } + + /* Step 3: Send a request to acknowledge verification */ + if (PEAR::isError($error = $this->put("NOOP"))) { + return $error; + } + + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->parseResponse(235))) { + return $error; + } + } + /** * Send the HELO command. * @@ -998,7 +1513,7 @@ public function data($data, $headers = null) /* Start by considering the size of the optional headers string. We * also account for the addition 4 character "\r\n\r\n" separator * sequence. */ - $size = (is_null($headers)) ? 0 : strlen($headers) + 4; + $size = $headers_size = (is_null($headers)) ? 0 : strlen($headers) + 4; if (is_resource($data)) { $stat = fstat($data); @@ -1016,7 +1531,6 @@ public function data($data, $headers = null) * about the server's fixed maximum message size". */ $limit = (isset($this->esmtp['SIZE'])) ? $this->esmtp['SIZE'] : 0; if ($limit > 0 && $size >= $limit) { - $this->disconnect(); return PEAR::raiseError('Message size exceeds server limit'); } @@ -1036,7 +1550,7 @@ public function data($data, $headers = null) } /* Subtract the headers size now that they've been sent. */ - $size -= strlen($headers) + 4; + $size -= $headers_size; } /* Now we can send the message body data. */ @@ -1251,4 +1765,25 @@ public function identifySender() { return true; } + + /** + * Backwards-compatibility method. + * array_filter alternative in PHP5.4 for using + * key filter because array_filter mode parameter + * is only available since PHP5.6. + * + * @param string $filter The string to filter + * @return array Filtered constants array. + */ + private function getDefinedConstantsKeyFilter($filter) { + $constants_filtered = array(); + $filter_length = strlen($filter); + $constants = get_defined_constants(); + foreach ($constants as $key=>$value){ + if (substr($key, 0, $filter_length) == $filter) { + $constants_filtered[$key] = $value; + } + } + return $constants_filtered; + } } diff --git a/WEB-INF/lib/pear/Net/Socket.php b/WEB-INF/lib/pear/Net/Socket.php index bf1d1bbcd..5a057cf78 100644 --- a/WEB-INF/lib/pear/Net/Socket.php +++ b/WEB-INF/lib/pear/Net/Socket.php @@ -2,27 +2,41 @@ /** * Net_Socket * - * PHP Version 4 + * PHP Version 5 * - * Copyright (c) 1997-2013 The PHP Group + * LICENSE: * - * This source file is subject to version 2.0 of the PHP license, - * that is bundled with this package in the file LICENSE, and is - * available at through the world-wide-web at - * http://www.php.net/license/2_02.txt. - * If you did not receive a copy of the PHP license and are unable to - * obtain it through the world-wide-web, please send a note to - * license@php.net so we can mail you a copy immediately. + * Copyright (c) 1997-2017 The PHP Group + * All rights reserved. * - * Authors: Stig Bakken - * Chuck Hagenbuch + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * o Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * o Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @category Net * @package Net_Socket * @author Stig Bakken * @author Chuck Hagenbuch - * @copyright 1997-2003 The PHP Group - * @license http://www.php.net/license/2_02.txt PHP 2.02 + * @copyright 1997-2017 The PHP Group + * @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause * @link http://pear.php.net/packages/Net_Socket */ @@ -39,8 +53,8 @@ * @package Net_Socket * @author Stig Bakken * @author Chuck Hagenbuch - * @copyright 1997-2003 The PHP Group - * @license http://www.php.net/license/2_02.txt PHP 2.02 + * @copyright 1997-2017 The PHP Group + * @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause * @link http://pear.php.net/packages/Net_Socket */ class Net_Socket extends PEAR @@ -49,71 +63,75 @@ class Net_Socket extends PEAR * Socket file pointer. * @var resource $fp */ - var $fp = null; + public $fp = null; /** * Whether the socket is blocking. Defaults to true. * @var boolean $blocking */ - var $blocking = true; + public $blocking = true; /** * Whether the socket is persistent. Defaults to false. * @var boolean $persistent */ - var $persistent = false; + public $persistent = false; /** * The IP address to connect to. * @var string $addr */ - var $addr = ''; + public $addr = ''; /** * The port number to connect to. * @var integer $port */ - var $port = 0; + public $port = 0; /** * Number of seconds to wait on socket operations before assuming * there's no more data. Defaults to no timeout. * @var integer|float $timeout */ - var $timeout = null; + public $timeout = null; /** * Number of bytes to read at a time in readLine() and * readAll(). Defaults to 2048. * @var integer $lineLength */ - var $lineLength = 2048; + public $lineLength = 2048; /** * The string to use as a newline terminator. Usually "\r\n" or "\n". * @var string $newline */ - var $newline = "\r\n"; + public $newline = "\r\n"; /** * Connect to the specified port. If called when the socket is * already connected, it disconnects and connects again. * - * @param string $addr IP address or host name (may be with protocol prefix). - * @param integer $port TCP port number. + * @param string $addr IP address or host name (may be with protocol prefix). + * @param integer $port TCP port number. * @param boolean $persistent (optional) Whether the connection is * persistent (kept open between requests * by the web server). - * @param integer $timeout (optional) Connection socket timeout. - * @param array $options See options for stream_context_create. + * @param integer $timeout (optional) Connection socket timeout. + * @param array $options See options for stream_context_create. * * @access public * * @return boolean|PEAR_Error True on success or a PEAR_Error on failure. */ - function connect($addr, $port = 0, $persistent = null, - $timeout = null, $options = null) - { + public function connect( + $addr, + $port = 0, + $persistent = null, + $timeout = null, + $options = null + ) { if (is_resource($this->fp)) { @fclose($this->fp); $this->fp = null; @@ -121,10 +139,12 @@ function connect($addr, $port = 0, $persistent = null, if (!$addr) { return $this->raiseError('$addr cannot be empty'); - } else if (strspn($addr, ':.0123456789') == strlen($addr)) { - $this->addr = strpos($addr, ':') !== false ? '['.$addr.']' : $addr; } else { - $this->addr = $addr; + if (strspn($addr, ':.0123456789') === strlen($addr)) { + $this->addr = strpos($addr, ':') !== false ? '[' . $addr . ']' : $addr; + } else { + $this->addr = $addr; + } } $this->port = $port % 65536; @@ -134,10 +154,14 @@ function connect($addr, $port = 0, $persistent = null, } $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; - $errno = 0; - $errstr = ''; + $errno = 0; + $errstr = ''; - $old_track_errors = @ini_set('track_errors', 1); + if (function_exists('error_clear_last')) { + error_clear_last(); + } else { + $old_track_errors = @ini_set('track_errors', 1); + } if ($timeout <= 0) { $timeout = @ini_get('default_socket_timeout'); @@ -155,27 +179,40 @@ function connect($addr, $port = 0, $persistent = null, } $addr = $this->addr . ':' . $this->port; - $fp = stream_socket_client($addr, $errno, $errstr, - $timeout, $flags, $context); + $fp = @stream_socket_client($addr, $errno, $errstr, + $timeout, $flags, $context); } else { $fp = @$openfunc($this->addr, $this->port, $errno, - $errstr, $timeout, $context); + $errstr, $timeout, $context); } } else { $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout); } if (!$fp) { - if ($errno == 0 && !strlen($errstr) && isset($php_errormsg)) { - $errstr = $php_errormsg; + if ($errno === 0 && !strlen($errstr)) { + $errstr = ''; + if (isset($old_track_errors)) { + $errstr = $php_errormsg ?: ''; + @ini_set('track_errors', $old_track_errors); + } else { + $lastError = error_get_last(); + if (isset($lastError['message'])) { + $errstr = $lastError['message']; + } + } } - @ini_set('track_errors', $old_track_errors); + return $this->raiseError($errstr, $errno); } - @ini_set('track_errors', $old_track_errors); + if (isset($old_track_errors)) { + @ini_set('track_errors', $old_track_errors); + } + $this->fp = $fp; $this->setTimeout(); + return $this->setBlocking($this->blocking); } @@ -185,7 +222,7 @@ function connect($addr, $port = 0, $persistent = null, * @access public * @return mixed true on success or a PEAR_Error instance otherwise */ - function disconnect() + public function disconnect() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); @@ -193,18 +230,20 @@ function disconnect() @fclose($this->fp); $this->fp = null; + return true; } /** * Set the newline character/sequence to use. * - * @param string $newline Newline character(s) + * @param string $newline Newline character(s) * @return boolean True */ - function setNewline($newline) + public function setNewline($newline) { $this->newline = $newline; + return true; } @@ -214,7 +253,7 @@ function setNewline($newline) * @access public * @return boolean The current blocking mode. */ - function isBlocking() + public function isBlocking() { return $this->blocking; } @@ -230,7 +269,7 @@ function isBlocking() * @access public * @return mixed true on success or a PEAR_Error instance otherwise */ - function setBlocking($mode) + public function setBlocking($mode) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); @@ -238,6 +277,7 @@ function setBlocking($mode) $this->blocking = $mode; stream_set_blocking($this->fp, (int)$this->blocking); + return true; } @@ -245,30 +285,29 @@ function setBlocking($mode) * Sets the timeout value on socket descriptor, * expressed in the sum of seconds and microseconds * - * @param integer $seconds Seconds. + * @param integer $seconds Seconds. * @param integer $microseconds Microseconds, optional. * * @access public * @return mixed True on success or false on failure or * a PEAR_Error instance when not connected */ - function setTimeout($seconds = null, $microseconds = null) + public function setTimeout($seconds = null, $microseconds = null) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } if ($seconds === null && $microseconds === null) { - $seconds = (int) $this->timeout; - $microseconds = (int) (($this->timeout - $seconds) * 1000000); + $seconds = (int)$this->timeout; + $microseconds = (int)(($this->timeout - $seconds) * 1000000); } else { - $this->timeout = $seconds + $microseconds/1000000; + $this->timeout = $seconds + $microseconds / 1000000; } if ($this->timeout > 0) { - return stream_set_timeout($this->fp, (int) $seconds, (int) $microseconds); - } - else { + return stream_set_timeout($this->fp, (int)$seconds, (int)$microseconds); + } else { return false; } } @@ -282,16 +321,17 @@ function setTimeout($seconds = null, $microseconds = null) * @access public * @return mixed on success or an PEAR_Error object otherwise */ - function setWriteBuffer($size) + public function setWriteBuffer($size) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $returned = stream_set_write_buffer($this->fp, $size); - if ($returned == 0) { + if ($returned === 0) { return true; } + return $this->raiseError('Cannot set write buffer.'); } @@ -310,7 +350,7 @@ function setWriteBuffer($size) * @return mixed Array containing information about existing socket * resource or a PEAR_Error instance otherwise */ - function getStatus() + public function getStatus() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); @@ -331,13 +371,13 @@ function getStatus() * @return mixed $size bytes of data from the socket, or a PEAR_Error if * not connected. If an error occurs, FALSE is returned. */ - function gets($size = null) + public function gets($size = null) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } - if (is_null($size)) { + if (null === $size) { return @fgets($this->fp); } else { return @fgets($this->fp, $size); @@ -353,10 +393,10 @@ function gets($size = null) * @param integer $size The number of bytes to read from the socket. * * @access public - * @return $size bytes of data from the socket, or a PEAR_Error if + * @return string $size bytes of data from the socket, or a PEAR_Error if * not connected. */ - function read($size) + public function read($size) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); @@ -368,7 +408,7 @@ function read($size) /** * Write a specified amount of data. * - * @param string $data Data to write. + * @param string $data Data to write. * @param integer $blocksize Amount of data to write at once. * NULL means all at once. * @@ -379,17 +419,17 @@ function read($size) * If the write fails, returns false. * If the socket times out, returns an instance of PEAR_Error. */ - function write($data, $blocksize = null) + public function write($data, $blocksize = null) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } - if (is_null($blocksize) && !OS_WINDOWS) { + if (null === $blocksize && !OS_WINDOWS) { $written = @fwrite($this->fp, $data); // Check for timeout or lost connection - if (!$written) { + if ($written === false) { $meta_data = $this->getStatus(); if (!is_array($meta_data)) { @@ -403,17 +443,17 @@ function write($data, $blocksize = null) return $written; } else { - if (is_null($blocksize)) { + if (null === $blocksize) { $blocksize = 1024; } - $pos = 0; + $pos = 0; $size = strlen($data); while ($pos < $size) { $written = @fwrite($this->fp, substr($data, $pos, $blocksize)); // Check for timeout or lost connection - if (!$written) { + if ($written === false) { $meta_data = $this->getStatus(); if (!is_array($meta_data)) { @@ -442,7 +482,7 @@ function write($data, $blocksize = null) * @access public * @return mixed fwrite() result, or PEAR_Error when not connected */ - function writeLine($data) + public function writeLine($data) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); @@ -459,7 +499,7 @@ function writeLine($data) * @access public * @return bool */ - function eof() + public function eof() { return (!is_resource($this->fp) || feof($this->fp)); } @@ -468,10 +508,10 @@ function eof() * Reads a byte of data * * @access public - * @return 1 byte of data from the socket, or a PEAR_Error if + * @return integer 1 byte of data from the socket, or a PEAR_Error if * not connected. */ - function readByte() + public function readByte() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); @@ -484,16 +524,17 @@ function readByte() * Reads a word of data * * @access public - * @return 1 word of data from the socket, or a PEAR_Error if + * @return integer 1 word of data from the socket, or a PEAR_Error if * not connected. */ - function readWord() + public function readWord() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $buf = @fread($this->fp, 2); + return (ord($buf[0]) + (ord($buf[1]) << 8)); } @@ -504,15 +545,16 @@ function readWord() * @return integer 1 int of data from the socket, or a PEAR_Error if * not connected. */ - function readInt() + public function readInt() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $buf = @fread($this->fp, 4); + return (ord($buf[0]) + (ord($buf[1]) << 8) + - (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); + (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); } /** @@ -522,16 +564,17 @@ function readInt() * @return string, or a PEAR_Error if * not connected. */ - function readString() + public function readString() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $string = ''; - while (($char = @fread($this->fp, 1)) != "\x00") { + while (($char = @fread($this->fp, 1)) !== "\x00") { $string .= $char; } + return $string; } @@ -539,18 +582,19 @@ function readString() * Reads an IP Address and returns it in a dot formatted string * * @access public - * @return Dot formatted string, or a PEAR_Error if + * @return string Dot formatted string, or a PEAR_Error if * not connected. */ - function readIPAddress() + public function readIPAddress() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $buf = @fread($this->fp, 4); + return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]), - ord($buf[2]), ord($buf[3])); + ord($buf[2]), ord($buf[3])); } /** @@ -558,11 +602,11 @@ function readIPAddress() * comes first. Strips the trailing newline from the returned data. * * @access public - * @return All available data up to a newline, without that + * @return string All available data up to a newline, without that * newline, or until the end of the socket, or a PEAR_Error if * not connected. */ - function readLine() + public function readLine() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); @@ -578,6 +622,7 @@ function readLine() return rtrim($line, $this->newline); } } + return $line; } @@ -594,16 +639,19 @@ function readLine() * @return string All data until the socket closes, or a PEAR_Error if * not connected. */ - function readAll() + public function readAll() { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } $data = ''; - while (!feof($this->fp)) { + $timeout = time() + $this->timeout; + + while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) { $data .= @fread($this->fp, $this->lineLength); } + return $data; } @@ -611,22 +659,22 @@ function readAll() * Runs the equivalent of the select() system call on the socket * with a timeout specified by tv_sec and tv_usec. * - * @param integer $state Which of read/write/error to check for. - * @param integer $tv_sec Number of seconds for timeout. + * @param integer $state Which of read/write/error to check for. + * @param integer $tv_sec Number of seconds for timeout. * @param integer $tv_usec Number of microseconds for timeout. * * @access public * @return False if select fails, integer describing which of read/write/error * are ready, or PEAR_Error if not connected. */ - function select($state, $tv_sec, $tv_usec = 0) + public function select($state, $tv_sec, $tv_usec = 0) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } - $read = null; - $write = null; + $read = null; + $write = null; $except = null; if ($state & NET_SOCKET_READ) { $read[] = $this->fp; @@ -638,7 +686,8 @@ function select($state, $tv_sec, $tv_usec = 0) $except[] = $this->fp; } if (false === ($sr = stream_select($read, $write, $except, - $tv_sec, $tv_usec))) { + $tv_sec, $tv_usec)) + ) { return false; } @@ -652,15 +701,16 @@ function select($state, $tv_sec, $tv_usec = 0) if (count($except)) { $result |= NET_SOCKET_ERROR; } + return $result; } /** * Turns encryption on/off on a connected socket. * - * @param bool $enabled Set this parameter to true to enable encryption + * @param bool $enabled Set this parameter to true to enable encryption * and false to disable encryption. - * @param integer $type Type of encryption. See stream_socket_enable_crypto() + * @param integer $type Type of encryption. See stream_socket_enable_crypto() * for values. * * @see http://se.php.net/manual/en/function.stream-socket-enable-crypto.php @@ -670,15 +720,17 @@ function select($state, $tv_sec, $tv_usec = 0) * A PEAR_Error object is returned if the socket is not * connected */ - function enableCrypto($enabled, $type) + public function enableCrypto($enabled, $type) { - if (version_compare(phpversion(), "5.1.0", ">=")) { + if (version_compare(phpversion(), '5.1.0', '>=')) { if (!is_resource($this->fp)) { return $this->raiseError('not connected'); } + return @stream_socket_enable_crypto($this->fp, $enabled, $type); } else { $msg = 'Net_Socket::enableCrypto() requires php version >= 5.1.0'; + return $this->raiseError($msg); } } diff --git a/WEB-INF/lib/pear/OS/Guess.php b/WEB-INF/lib/pear/OS/Guess.php index 4c9254a26..f240bb499 100644 --- a/WEB-INF/lib/pear/OS/Guess.php +++ b/WEB-INF/lib/pear/OS/Guess.php @@ -4,14 +4,14 @@ * * PHP versions 4 and 5 * - * @category pear - * @package PEAR - * @author Stig Bakken - * @author Gregory Beaver - * @copyright 1997-2009 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/package/PEAR - * @since File available since PEAR 0.1 + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Gregory Beaver + * @copyright 1997-2009 The Authors + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @link http://pear.php.net/package/PEAR + * @since File available since PEAR 0.1 */ // {{{ uname examples @@ -80,15 +80,15 @@ * * This class uses php_uname() to grok information about the current OS * - * @category pear - * @package PEAR - * @author Stig Bakken - * @author Gregory Beaver - * @copyright 1997-2009 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 - * @link http://pear.php.net/package/PEAR - * @since Class available since Release 0.1 + * @category pear + * @package PEAR + * @author Stig Bakken + * @author Gregory Beaver + * @copyright 1997-2020 The Authors + * @license http://opensource.org/licenses/bsd-license.php New BSD License + * @version Release: 1.10.15 + * @link http://pear.php.net/package/PEAR + * @since Class available since Release 0.1 */ class OS_Guess { @@ -138,13 +138,9 @@ function parseSignature($uname = null) $release = "$parts[3].$parts[2]"; break; case 'Windows' : - switch ($parts[1]) { - case '95/98': - $release = '9x'; - break; - default: - $release = $parts[1]; - break; + $release = $parts[1]; + if ($release == '95/98') { + $release = '9x'; } $cpu = 'i386'; break; @@ -157,18 +153,10 @@ function parseSignature($uname = null) $sysname = 'darwin'; $nodename = $parts[2]; $release = $parts[3]; - if ($cpu == 'Macintosh') { - if ($parts[$n - 2] == 'Power') { - $cpu = 'powerpc'; - } - } + $cpu = $this->_determineIfPowerpc($cpu, $parts); break; case 'Darwin' : - if ($cpu == 'Macintosh') { - if ($parts[$n - 2] == 'Power') { - $cpu = 'powerpc'; - } - } + $cpu = $this->_determineIfPowerpc($cpu, $parts); $release = preg_replace('/^([0-9]+\.[0-9]+).*/', '\1', $parts[2]); break; default: @@ -187,6 +175,15 @@ function parseSignature($uname = null) return array($sysname, $release, $cpu, $extra, $nodename); } + function _determineIfPowerpc($cpu, $parts) + { + $n = count($parts); + if ($cpu == 'Macintosh' && $parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + return $cpu; + } + function _detectGlibcVersion() { static $glibc = false; @@ -195,75 +192,132 @@ function _detectGlibcVersion() } $major = $minor = 0; include_once "System.php"; + + // Let's try reading possible libc.so.6 symlinks + $libcs = array( + '/lib64/libc.so.6', + '/lib/libc.so.6', + '/lib/i386-linux-gnu/libc.so.6' + ); + $versions = array(); + foreach ($libcs as $file) { + $versions = $this->_readGlibCVersionFromSymlink($file); + if ($versions != []) { + list($major, $minor) = $versions; + break; + } + } + // Use glibc's header file to // get major and minor version number: - if (@file_exists('/usr/include/features.h') && - @is_readable('/usr/include/features.h')) { - if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) { - $features_file = fopen('/usr/include/features.h', 'rb'); - while (!feof($features_file)) { - $line = fgets($features_file, 8192); - if (!$line || (strpos($line, '#define') === false)) { - continue; - } - if (strpos($line, '__GLIBC__')) { - // major version number #define __GLIBC__ version - $line = preg_split('/\s+/', $line); - $glibc_major = trim($line[2]); - if (isset($glibc_minor)) { - break; - } - continue; - } - - if (strpos($line, '__GLIBC_MINOR__')) { - // got the minor version number - // #define __GLIBC_MINOR__ version - $line = preg_split('/\s+/', $line); - $glibc_minor = trim($line[2]); - if (isset($glibc_major)) { - break; - } - continue; - } - } - fclose($features_file); - if (!isset($glibc_major) || !isset($glibc_minor)) { - return $glibc = ''; - } - return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ; - } // no cpp - - $tmpfile = System::mktemp("glibctest"); - $fp = fopen($tmpfile, "w"); - fwrite($fp, "#include \n__GLIBC__ __GLIBC_MINOR__\n"); - fclose($fp); - $cpp = popen("/usr/bin/cpp $tmpfile", "r"); - while ($line = fgets($cpp, 1024)) { - if ($line{0} == '#' || trim($line) == '') { - continue; - } + if (!($major && $minor)) { + $versions = $this->_readGlibCVersionFromFeaturesHeaderFile(); + } + if (is_array($versions) && $versions != []) { + list($major, $minor) = $versions; + } + + if (!($major && $minor)) { + return $glibc = ''; + } + + return $glibc = "glibc{$major}.{$minor}"; + } - if (list($major, $minor) = explode(' ', trim($line))) { + function _readGlibCVersionFromSymlink($file) + { + $versions = array(); + if (@is_link($file) + && (preg_match('/^libc-(.*)\.so$/', basename(readlink($file)), $matches)) + ) { + $versions = explode('.', $matches[1]); + } + return $versions; + } + + + function _readGlibCVersionFromFeaturesHeaderFile() + { + $features_header_file = '/usr/include/features.h'; + if (!(@file_exists($features_header_file) + && @is_readable($features_header_file)) + ) { + return array(); + } + if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) { + return $this->_parseFeaturesHeaderFile($features_header_file); + } // no cpp + + return $this->_fromGlibCTest(); + } + + function _parseFeaturesHeaderFile($features_header_file) + { + $features_file = fopen($features_header_file, 'rb'); + while (!feof($features_file)) { + $line = fgets($features_file, 8192); + if (!$this->_IsADefinition($line)) { + continue; + } + if (strpos($line, '__GLIBC__')) { + // major version number #define __GLIBC__ version + $line = preg_split('/\s+/', $line); + $glibc_major = trim($line[2]); + if (isset($glibc_minor)) { break; } + continue; } - pclose($cpp); - unlink($tmpfile); - } // features.h - - if (!($major && $minor) && @is_link('/lib/libc.so.6')) { - // Let's try reading the libc.so.6 symlink - if (preg_match('/^libc-(.*)\.so$/', basename(readlink('/lib/libc.so.6')), $matches)) { - list($major, $minor) = explode('.', $matches[1]); + + if (strpos($line, '__GLIBC_MINOR__')) { + // got the minor version number + // #define __GLIBC_MINOR__ version + $line = preg_split('/\s+/', $line); + $glibc_minor = trim($line[2]); + if (isset($glibc_major)) { + break; + } } } + fclose($features_file); + if (!isset($glibc_major) || !isset($glibc_minor)) { + return array(); + } + return array(trim($glibc_major), trim($glibc_minor)); + } - if (!($major && $minor)) { - return $glibc = ''; + function _IsADefinition($line) + { + if ($line === false) { + return false; } + return strpos(trim($line), '#define') !== false; + } - return $glibc = "glibc{$major}.{$minor}"; + function _fromGlibCTest() + { + $major = null; + $minor = null; + + $tmpfile = System::mktemp("glibctest"); + $fp = fopen($tmpfile, "w"); + fwrite($fp, "#include \n__GLIBC__ __GLIBC_MINOR__\n"); + fclose($fp); + $cpp = popen("/usr/bin/cpp $tmpfile", "r"); + while ($line = fgets($cpp, 1024)) { + if ($line[0] == '#' || trim($line) == '') { + continue; + } + + if (list($major, $minor) = explode(' ', trim($line))) { + break; + } + } + pclose($cpp); + unlink($tmpfile); + if ($major !== null && $minor !== null) { + return [$major, $minor]; + } } function getSignature() @@ -322,12 +376,16 @@ function matchSignature($match) function _matchFragment($fragment, $value) { if (strcspn($fragment, '*?') < strlen($fragment)) { - $reg = '/^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '\\z/'; + $expression = str_replace( + array('*', '?', '/'), + array('.*', '.', '\\/'), + $fragment + ); + $reg = '/^' . $expression . '\\z/'; return preg_match($reg, $value); } return ($fragment == '*' || !strcasecmp($fragment, $value)); } - } /* * Local Variables: diff --git a/WEB-INF/lib/pear/PEAR.php b/WEB-INF/lib/pear/PEAR.php index d661cc212..38ffedf29 100644 --- a/WEB-INF/lib/pear/PEAR.php +++ b/WEB-INF/lib/pear/PEAR.php @@ -75,7 +75,7 @@ * @author Greg Beaver * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @see PEAR_Error * @since Class available since PHP 4.0.2 @@ -170,7 +170,7 @@ function __construct($error_class = null) $destructor = "_$classname"; if (method_exists($this, $destructor)) { global $_PEAR_destructor_object_list; - $_PEAR_destructor_object_list[] = &$this; + $_PEAR_destructor_object_list[] = $this; if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) { register_shutdown_function("_PEAR_call_destructors"); $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true; @@ -219,7 +219,7 @@ public function __call($method, $arguments) ); } return call_user_func_array( - array(get_class(), '_' . $method), + array(__CLASS__, '_' . $method), array_merge(array($this), $arguments) ); } @@ -232,7 +232,7 @@ public static function __callStatic($method, $arguments) ); } return call_user_func_array( - array(get_class(), '_' . $method), + array(__CLASS__, '_' . $method), array_merge(array(null), $arguments) ); } @@ -450,7 +450,7 @@ function _checkDelExpect($error_code) } /** - * This method deletes all occurences of the specified element from + * This method deletes all occurrences of the specified element from * the expected error codes stack. * * @param mixed $error_code error code that should be deleted @@ -542,7 +542,7 @@ protected static function _raiseError($object, count($object->_expected_errors) > 0 && count($exp = end($object->_expected_errors)) ) { - if ($exp[0] == "*" || + if ($exp[0] === "*" || (is_int(reset($exp)) && in_array($code, $exp)) || (is_string(reset($exp)) && in_array($message, $exp)) ) { @@ -598,11 +598,11 @@ protected static function _raiseError($object, protected static function _throwError($object, $message = null, $code = null, $userinfo = null) { if ($object !== null) { - $a = &$object->raiseError($message, $code, null, null, $userinfo); + $a = $object->raiseError($message, $code, null, null, $userinfo); return $a; } - $a = &PEAR::raiseError($message, $code, null, null, $userinfo); + $a = PEAR::raiseError($message, $code, null, null, $userinfo); return $a; } @@ -766,6 +766,28 @@ function_exists('dl') === false || return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); } + + /** + * Get SOURCE_DATE_EPOCH environment variable + * See https://reproducible-builds.org/specs/source-date-epoch/ + * + * @return int + * @access public + */ + static function getSourceDateEpoch() + { + if ($source_date_epoch = getenv('SOURCE_DATE_EPOCH')) { + if (preg_match('/^\d+$/', $source_date_epoch)) { + return (int) $source_date_epoch; + } else { + // "If the value is malformed, the build process SHOULD exit with a non-zero error code." + self::raiseError("Invalid SOURCE_DATE_EPOCH: $source_date_epoch"); + exit(1); + } + } else { + return time(); + } + } } function _PEAR_call_destructors() @@ -782,7 +804,7 @@ function _PEAR_call_destructors() $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list); } - while (list($k, $objref) = each($_PEAR_destructor_object_list)) { + foreach ($_PEAR_destructor_object_list as $k => $objref) { $classname = get_class($objref); while ($classname) { $destructor = "_$classname"; @@ -823,7 +845,7 @@ function _PEAR_call_destructors() * @author Gregory Beaver * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/manual/en/core.pear.pear-error.php * @see PEAR::raiseError(), PEAR::throwError() * @since Class available since PHP 4.0.2 @@ -837,6 +859,7 @@ class PEAR_Error var $message = ''; var $userinfo = ''; var $backtrace = null; + var $callback = null; /** * PEAR_Error constructor @@ -914,7 +937,8 @@ function __construct($message = 'unknown error', $code = null, } else { $format = $options; } - die(sprintf($format, $msg)); + printf($format, $msg); + exit($code); } if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) { diff --git a/WEB-INF/lib/pear/PEAR/Autoloader.php b/WEB-INF/lib/pear/PEAR/Autoloader.php deleted file mode 100644 index bcb57f65b..000000000 --- a/WEB-INF/lib/pear/PEAR/Autoloader.php +++ /dev/null @@ -1,217 +0,0 @@ - - * @copyright 1997-2009 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader - * @since File available since Release 0.1 - * @deprecated File deprecated in Release 1.4.0a1 - */ - -// /* vim: set expandtab tabstop=4 shiftwidth=4: */ - -if (!extension_loaded("overload")) { - // die hard without ext/overload - die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader"); -} - -/** - * Include for PEAR_Error and PEAR classes - */ -require_once "PEAR.php"; - -/** - * This class is for objects where you want to separate the code for - * some methods into separate classes. This is useful if you have a - * class with not-frequently-used methods that contain lots of code - * that you would like to avoid always parsing. - * - * The PEAR_Autoloader class provides autoloading and aggregation. - * The autoloading lets you set up in which classes the separated - * methods are found. Aggregation is the technique used to import new - * methods, an instance of each class providing separated methods is - * stored and called every time the aggregated method is called. - * - * @category pear - * @package PEAR - * @author Stig Bakken - * @copyright 1997-2009 The Authors - * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 - * @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader - * @since File available since Release 0.1 - * @deprecated File deprecated in Release 1.4.0a1 - */ -class PEAR_Autoloader extends PEAR -{ - // {{{ properties - - /** - * Map of methods and classes where they are defined - * - * @var array - * - * @access private - */ - var $_autoload_map = array(); - - /** - * Map of methods and aggregate objects - * - * @var array - * - * @access private - */ - var $_method_map = array(); - - // }}} - // {{{ addAutoload() - - /** - * Add one or more autoload entries. - * - * @param string $method which method to autoload - * - * @param string $classname (optional) which class to find the method in. - * If the $method parameter is an array, this - * parameter may be omitted (and will be ignored - * if not), and the $method parameter will be - * treated as an associative array with method - * names as keys and class names as values. - * - * @return void - * - * @access public - */ - function addAutoload($method, $classname = null) - { - if (is_array($method)) { - array_walk($method, create_function('$a,&$b', '$b = strtolower($b);')); - $this->_autoload_map = array_merge($this->_autoload_map, $method); - } else { - $this->_autoload_map[strtolower($method)] = $classname; - } - } - - // }}} - // {{{ removeAutoload() - - /** - * Remove an autoload entry. - * - * @param string $method which method to remove the autoload entry for - * - * @return bool TRUE if an entry was removed, FALSE if not - * - * @access public - */ - function removeAutoload($method) - { - $method = strtolower($method); - $ok = isset($this->_autoload_map[$method]); - unset($this->_autoload_map[$method]); - return $ok; - } - - // }}} - // {{{ addAggregateObject() - - /** - * Add an aggregate object to this object. If the specified class - * is not defined, loading it will be attempted following PEAR's - * file naming scheme. All the methods in the class will be - * aggregated, except private ones (name starting with an - * underscore) and constructors. - * - * @param string $classname what class to instantiate for the object. - * - * @return void - * - * @access public - */ - function addAggregateObject($classname) - { - $classname = strtolower($classname); - if (!class_exists($classname)) { - $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname); - include_once $include_file; - } - $obj = new $classname; - $methods = get_class_methods($classname); - foreach ($methods as $method) { - // don't import priviate methods and constructors - if ($method{0} != '_' && $method != $classname) { - $this->_method_map[$method] = $obj; - } - } - } - - // }}} - // {{{ removeAggregateObject() - - /** - * Remove an aggregate object. - * - * @param string $classname the class of the object to remove - * - * @return bool TRUE if an object was removed, FALSE if not - * - * @access public - */ - function removeAggregateObject($classname) - { - $ok = false; - $classname = strtolower($classname); - reset($this->_method_map); - while (list($method, $obj) = each($this->_method_map)) { - if (is_a($obj, $classname)) { - unset($this->_method_map[$method]); - $ok = true; - } - } - return $ok; - } - - // }}} - // {{{ __call() - - /** - * Overloaded object call handler, called each time an - * undefined/aggregated method is invoked. This method repeats - * the call in the right aggregate object and passes on the return - * value. - * - * @param string $method which method that was called - * - * @param string $args An array of the parameters passed in the - * original call - * - * @return mixed The return value from the aggregated method, or a PEAR - * error if the called method was unknown. - */ - function __call($method, $args, &$retval) - { - $method = strtolower($method); - if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) { - $this->addAggregateObject($this->_autoload_map[$method]); - } - if (isset($this->_method_map[$method])) { - $retval = call_user_func_array(array($this->_method_map[$method], $method), $args); - return true; - } - return false; - } - - // }}} -} - -overload("PEAR_Autoloader"); - -?> diff --git a/WEB-INF/lib/pear/PEAR/Builder.php b/WEB-INF/lib/pear/PEAR/Builder.php index 94b09f08d..de44a2df0 100644 --- a/WEB-INF/lib/pear/PEAR/Builder.php +++ b/WEB-INF/lib/pear/PEAR/Builder.php @@ -33,7 +33,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since PHP 4.0.2 * @see http://pear.php.net/manual/en/core.ppm.pear-builder.php @@ -56,17 +56,72 @@ class PEAR_Builder extends PEAR_Common var $_lastline = null; var $_firstline = null; + /** + * Parsed --configureoptions. + * + * @var mixed[] + */ + var $_parsed_configure_options; + /** * PEAR_Builder constructor. * + * @param mixed[] $configureoptions * @param object $ui user interface object (instance of PEAR_Frontend_*) * * @access public */ - function __construct(&$ui) + function __construct($configureoptions, &$ui) { parent::__construct(); $this->setFrontendObject($ui); + $this->_parseConfigureOptions($configureoptions); + } + + /** + * Parse --configureoptions string. + * + * @param string Options, in the form "X=1 Y=2 Z='there\'s always one'" + */ + function _parseConfigureOptions($options) + { + $data = ''; + $parser = xml_parser_create('ISO-8859-1'); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_set_element_handler( + $parser, array($this, '_parseConfigureOptionsStartElement'), + array($this, '_parseConfigureOptionsEndElement')); + xml_parse($parser, $data, true); + xml_parser_free($parser); + } + + /** + * Handle element start. + * + * @see PEAR_Builder::_parseConfigureOptions() + * + * @param resource $parser + * @param string $tagName + * @param mixed[] $attribs + */ + function _parseConfigureOptionsStartElement($parser, $tagName, $attribs) + { + if ($tagName !== 'PROPERTIES') { + return; + } + $this->_parsed_configure_options = $attribs; + } + + /** + * Handle element end. + * + * @see PEAR_Builder::_parseConfigureOptions() + * + * @param resource + * @param string $element + */ + function _parseConfigureOptionsEndElement($parser, $element) + { } /** @@ -136,7 +191,7 @@ function _build_win32($descfile, $callback = null) // msdev doesn't tell us the output directory :/ // open the dsp, find /out and use that directory - $dsptext = join(file($dsp),''); + $dsptext = join('', file($dsp)); // this regex depends on the build platform and type having been // correctly identified above. @@ -191,7 +246,7 @@ function _harvestInstDir($dest_prefix, $dirname, &$built_files) $ret = true; while (($ent = readdir($d)) !== false) { - if ($ent{0} == '.') + if ($ent[0] == '.') continue; $full = $dirname . DIRECTORY_SEPARATOR . $ent; @@ -276,7 +331,7 @@ function build($descfile, $callback = null) } else { $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName(); // automatically delete at session end - $this->addTempFile($dir); + self::addTempFile($dir); } } else { $pf = new PEAR_PackageFile($this->config); @@ -307,7 +362,10 @@ function build($descfile, $callback = null) $dir = getcwd(); $this->log(2, "building in $dir"); - putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); + $binDir = $this->config->get('bin_dir'); + if (!preg_match('@(^|:)' . preg_quote($binDir, '@') . '(:|$)@', getenv('PATH'))) { + putenv('PATH=' . $binDir . ':' . getenv('PATH')); + } $err = $this->_runCommand($this->config->get('php_prefix') . "phpize" . $this->config->get('php_suffix'), @@ -334,17 +392,19 @@ function build($descfile, $callback = null) $configure_options = $pkg->getConfigureOptions(); if ($configure_options) { - foreach ($configure_options as $o) { - $default = array_key_exists('default', $o) ? $o['default'] : null; - list($r) = $this->ui->userDialog('build', - array($o['prompt']), - array('text'), - array($default)); - if (substr($o['name'], 0, 5) == 'with-' && - ($r == 'yes' || $r == 'autodetect')) { - $configure_command .= " --$o[name]"; + foreach ($configure_options as $option) { + $default = array_key_exists('default', $option) ? $option['default'] : null; + if (array_key_exists($option['name'], $this->_parsed_configure_options)) { + $response = $this->_parsed_configure_options[$option['name']]; + } else { + list($response) = $this->ui->userDialog( + 'build', [$option['prompt']], ['text'], [$default]); + } + if (substr($option['name'], 0, 5) === 'with-' && + ($response === 'yes' || $response === 'autodetect')) { + $configure_command .= " --{$option['name']}"; } else { - $configure_command .= " --$o[name]=".trim($r); + $configure_command .= " --{$option['name']}=".trim($response); } } } @@ -368,11 +428,11 @@ function build($descfile, $callback = null) return $this->raiseError("could not create build dir: $build_dir"); } - $this->addTempFile($build_dir); + self::addTempFile($build_dir); if (!System::mkDir(array('-p', $inst_dir))) { return $this->raiseError("could not create temporary install dir: $inst_dir"); } - $this->addTempFile($inst_dir); + self::addTempFile($inst_dir); $make_command = getenv('MAKE') ? getenv('MAKE') : 'make'; @@ -385,7 +445,7 @@ function build($descfile, $callback = null) if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) { return $this->raiseError("could not chdir to $build_dir"); } - putenv('PHP_PEAR_VERSION=1.10.1'); + putenv('PHP_PEAR_VERSION=1.10.15'); foreach ($to_run as $cmd) { $err = $this->_runCommand($cmd, $callback); if (PEAR::isError($err)) { diff --git a/WEB-INF/lib/pear/PEAR/ChannelFile.php b/WEB-INF/lib/pear/PEAR/ChannelFile.php index f993764c8..1a36045c9 100644 --- a/WEB-INF/lib/pear/PEAR/ChannelFile.php +++ b/WEB-INF/lib/pear/PEAR/ChannelFile.php @@ -145,7 +145,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/ChannelFile/Parser.php b/WEB-INF/lib/pear/PEAR/ChannelFile/Parser.php index a27e8fd06..1903b9752 100644 --- a/WEB-INF/lib/pear/PEAR/ChannelFile/Parser.php +++ b/WEB-INF/lib/pear/PEAR/ChannelFile/Parser.php @@ -25,7 +25,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Command.php b/WEB-INF/lib/pear/PEAR/Command.php index 9ec55507d..246cedc6b 100644 --- a/WEB-INF/lib/pear/PEAR/Command.php +++ b/WEB-INF/lib/pear/PEAR/Command.php @@ -93,7 +93,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -233,7 +233,7 @@ public static function registerCommands($merge = false, $dir = null) } while ($file = readdir($dp)) { - if ($file{0} == '.' || substr($file, -4) != '.xml') { + if ($file[0] == '.' || substr($file, -4) != '.xml') { continue; } diff --git a/WEB-INF/lib/pear/PEAR/Command/Auth.php b/WEB-INF/lib/pear/PEAR/Command/Auth.php index aa021ec26..1f6b0dcf3 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Auth.php +++ b/WEB-INF/lib/pear/PEAR/Command/Auth.php @@ -29,7 +29,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 * @deprecated since 1.8.0alpha1 diff --git a/WEB-INF/lib/pear/PEAR/Command/Build.php b/WEB-INF/lib/pear/PEAR/Command/Build.php index 7f851932d..bb6f0b6c5 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Build.php +++ b/WEB-INF/lib/pear/PEAR/Command/Build.php @@ -30,7 +30,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -41,7 +41,13 @@ class PEAR_Command_Build extends PEAR_Command_Common 'summary' => 'Build an Extension From C Source', 'function' => 'doBuild', 'shortcut' => 'b', - 'options' => array(), + 'options' => array( + 'configureoptions' => array( + 'shortopt' => 'D', + 'arg' => 'OPTION1=VALUE[ OPTION2=VALUE]', + 'doc' => 'space-delimited list of configure options', + ), + ), 'doc' => '[package.xml] Builds one or more extensions contained in a package.' ), @@ -64,7 +70,8 @@ function doBuild($command, $options, $params) $params[0] = 'package.xml'; } - $builder = new PEAR_Builder($this->ui); + $configureoptions = empty($options['configureoptions']) ? '' : $options['configureoptions']; + $builder = new PEAR_Builder($configureoptions, $this->ui); $this->debug = $this->config->get('verbose'); $err = $builder->build($params[0], array(&$this, 'buildCallback')); if (PEAR::isError($err)) { diff --git a/WEB-INF/lib/pear/PEAR/Command/Build.xml b/WEB-INF/lib/pear/PEAR/Command/Build.xml index ec4e6f554..507f17926 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Build.xml +++ b/WEB-INF/lib/pear/PEAR/Command/Build.xml @@ -3,7 +3,12 @@ Build an Extension From C Source doBuild b - + + + D + OPTION1=VALUE[ OPTION2=VALUE] + + [package.xml] Builds one or more extensions contained in a package. diff --git a/WEB-INF/lib/pear/PEAR/Command/Channels.php b/WEB-INF/lib/pear/PEAR/Command/Channels.php index 690483d1d..4ccd83155 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Channels.php +++ b/WEB-INF/lib/pear/PEAR/Command/Channels.php @@ -31,7 +31,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -673,7 +673,7 @@ function doAlias($command, $options, $params) return $this->raiseError('No channel alias specified'); } - if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) { + if (count($params) !== 2 || (!empty($params[1]) && $params[1][0] == '-')) { return $this->raiseError( 'Invalid format, correct is: channel-alias channel alias'); } diff --git a/WEB-INF/lib/pear/PEAR/Command/Common.php b/WEB-INF/lib/pear/PEAR/Command/Common.php index 4be537629..3356bbcd4 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Common.php +++ b/WEB-INF/lib/pear/PEAR/Command/Common.php @@ -28,7 +28,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -143,10 +143,10 @@ function getGetoptArgs($command, &$short_args, &$long_args) } reset($this->commands[$command]['options']); - while (list($option, $info) = each($this->commands[$command]['options'])) { + foreach ($this->commands[$command]['options'] as $option => $info) { $larg = $sarg = ''; if (isset($info['arg'])) { - if ($info['arg']{0} == '(') { + if ($info['arg'][0] == '(') { $larg = '=='; $sarg = '::'; $arg = substr($info['arg'], 1, -1); @@ -193,7 +193,7 @@ function getHelp($command) $help = $this->commands[$command]['summary']; } - if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) { + if (preg_match_all('/{config\s+([^\}]+)}/', $help, $matches)) { foreach($matches[0] as $k => $v) { $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help); } diff --git a/WEB-INF/lib/pear/PEAR/Command/Config.php b/WEB-INF/lib/pear/PEAR/Command/Config.php index 705a7cbb8..122a48e5e 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Config.php +++ b/WEB-INF/lib/pear/PEAR/Command/Config.php @@ -28,7 +28,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -315,7 +315,7 @@ function doConfigCreate($command, $options, $params) $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"), array('/', '/', '/'), $root); - if ($root{0} != '/') { + if ($root[0] != '/') { if (!isset($options['windows'])) { return PEAR::raiseError('Root directory must be an absolute path beginning ' . 'with "/", was: "' . $root . '"'); @@ -338,7 +338,7 @@ function doConfigCreate($command, $options, $params) $params[1] = realpath($params[1]); $config = new PEAR_Config($params[1], '#no#system#config#', false, false); - if ($root{strlen($root) - 1} == '/') { + if ($root[strlen($root) - 1] == '/') { $root = substr($root, 0, strlen($root) - 1); } diff --git a/WEB-INF/lib/pear/PEAR/Command/Install.php b/WEB-INF/lib/pear/PEAR/Command/Install.php index 9d572eda8..8146060d6 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Install.php +++ b/WEB-INF/lib/pear/PEAR/Command/Install.php @@ -29,7 +29,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -67,6 +67,11 @@ class PEAR_Command_Install extends PEAR_Command_Common 'shortopt' => 'B', 'doc' => 'don\'t build C extensions', ), + 'configureoptions' => array( + 'shortopt' => 'D', + 'arg' => 'OPTION1=VALUE[ OPTION2=VALUE]', + 'doc' => 'space-delimited list of configure options', + ), 'nocompress' => array( 'shortopt' => 'Z', 'doc' => 'request uncompressed files when downloading', @@ -717,8 +722,7 @@ function doInstall($command, $options, $params) $pkg = &$param->getPackageFile(); if ($info->getCode() != PEAR_INSTALLER_NOBINARY) { if (!($info = $pkg->installBinary($this->installer))) { - $this->ui->outputData('ERROR: ' .$oldinfo->getMessage()); - continue; + return $this->raiseError('ERROR: ' .$oldinfo->getMessage()); } // we just installed a different package than requested, diff --git a/WEB-INF/lib/pear/PEAR/Command/Install.xml b/WEB-INF/lib/pear/PEAR/Command/Install.xml index 1b1e933c2..d163bd581 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Install.xml +++ b/WEB-INF/lib/pear/PEAR/Command/Install.xml @@ -28,6 +28,10 @@ B don't build C extensions + + D + OPTION1=VALUE[ OPTION2=VALUE] + Z request uncompressed files when downloading diff --git a/WEB-INF/lib/pear/PEAR/Command/Mirror.php b/WEB-INF/lib/pear/PEAR/Command/Mirror.php index bae7ad13e..52eace535 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Mirror.php +++ b/WEB-INF/lib/pear/PEAR/Command/Mirror.php @@ -26,7 +26,7 @@ * @author Alexander Merz * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.2.0 */ diff --git a/WEB-INF/lib/pear/PEAR/Command/Package.php b/WEB-INF/lib/pear/PEAR/Command/Package.php index c62948f1e..fa51f004d 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Package.php +++ b/WEB-INF/lib/pear/PEAR/Command/Package.php @@ -872,7 +872,6 @@ function doPackageDependencies($command, $options, $params) $deps = $info->getDependencies(); $reg = &$this->config->getRegistry(); if (is_array($deps)) { - $d = new PEAR_Dependency2($this->config, array(), ''); $data = array( 'caption' => 'Dependencies for ' . $info->getPackage(), 'border' => true, @@ -929,7 +928,7 @@ function doPackageDependencies($command, $options, $params) if (isset($inf['conflicts'])) { $ver = 'conflicts'; } else { - $ver = $d->_getExtraString($inf); + $ver = PEAR_Dependency2::_getExtraString($inf); } $data['data'][] = array($req, ucfirst($deptype), $name, diff --git a/WEB-INF/lib/pear/PEAR/Command/Pickle.php b/WEB-INF/lib/pear/PEAR/Command/Pickle.php index af6079b69..fe84137cd 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Pickle.php +++ b/WEB-INF/lib/pear/PEAR/Command/Pickle.php @@ -26,7 +26,7 @@ * @author Greg Beaver * @copyright 2005-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.1 */ diff --git a/WEB-INF/lib/pear/PEAR/Command/Registry.php b/WEB-INF/lib/pear/PEAR/Command/Registry.php index 37ee48bea..cb39f551d 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Registry.php +++ b/WEB-INF/lib/pear/PEAR/Command/Registry.php @@ -28,7 +28,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -585,8 +585,9 @@ function doInfo($command, $options, $params) case 'configure_options' : { foreach ($info[$key] as $i => $p) { $info[$key][$i] = array_map(null, array_keys($p), array_values($p)); - $info[$key][$i] = array_map(create_function('$a', - 'return join(" = ",$a);'), $info[$key][$i]); + $info[$key][$i] = array_map( + function($a) { return join(" = ", $a); }, + $info[$key][$i]); $info[$key][$i] = implode(', ', $info[$key][$i]); } $info[$key] = implode("\n", $info[$key]); diff --git a/WEB-INF/lib/pear/PEAR/Command/Remote.php b/WEB-INF/lib/pear/PEAR/Command/Remote.php index f73db24f8..da47b8e73 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Remote.php +++ b/WEB-INF/lib/pear/PEAR/Command/Remote.php @@ -30,7 +30,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -222,7 +222,7 @@ function doRemoteInfo($command, $options, $params) } $installed = $reg->packageInfo($info['name'], null, $channel); - $info['installed'] = $installed['version'] ? $installed['version'] : '- no -'; + $info['installed'] = $installed ? $installed['version'] : '- no -'; if (is_array($info['installed'])) { $info['installed'] = $info['installed']['release']; } @@ -351,7 +351,7 @@ function doListAll($command, $options, $params) foreach ($available as $name => $info) { $installed = $reg->packageInfo($name, null, $channel); - if (is_array($installed['version'])) { + if ($installed && is_array($installed['version'])) { $installed['version'] = $installed['version']['release']; } $desc = $info['summary']; @@ -589,7 +589,7 @@ function doDownload($command, $options, $params) // eliminate error messages for preferred_state-related errors /* TODO: Should be an option, but until now download does respect - prefered state */ + preferred state */ /* $options['ignorepreferred_state'] = 1; */ // eliminate error messages for preferred_state-related errors diff --git a/WEB-INF/lib/pear/PEAR/Command/Test.php b/WEB-INF/lib/pear/PEAR/Command/Test.php index a59b1cf81..18f533cde 100644 --- a/WEB-INF/lib/pear/PEAR/Command/Test.php +++ b/WEB-INF/lib/pear/PEAR/Command/Test.php @@ -30,7 +30,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ diff --git a/WEB-INF/lib/pear/PEAR/Common.php b/WEB-INF/lib/pear/PEAR/Common.php index 5fe76ad18..5a05e261b 100644 --- a/WEB-INF/lib/pear/PEAR/Common.php +++ b/WEB-INF/lib/pear/PEAR/Common.php @@ -117,7 +117,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 * @deprecated This class will disappear, and its components will be spread @@ -205,7 +205,7 @@ function _PEAR_Common() * * @access public */ - function addTempFile($file) + static function addTempFile($file) { if (!class_exists('PEAR_Frontend')) { require_once 'PEAR/Frontend.php'; @@ -280,7 +280,7 @@ function mkTempDir($tmpdir = '') return false; } - $this->addTempFile($tmpdir); + self::addTempFile($tmpdir); return $tmpdir; } @@ -304,7 +304,7 @@ function setFrontendObject(&$ui) * @param boolean Determines whether to include $state in the list * @return false|array False if $state is not a valid release state */ - function betterStates($state, $include = false) + static function betterStates($state, $include = false) { static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); $i = array_search($state, $states); @@ -686,7 +686,7 @@ function buildProvidesArray($srcinfo) foreach ($methods as $method) { $function = "$class::$method"; $key = "function;$function"; - if ($method{0} == '_' || !strcasecmp($method, $class) || + if ($method[0] == '_' || !strcasecmp($method, $class) || isset($this->pkginfo['provides'][$key])) { continue; } @@ -698,7 +698,7 @@ function buildProvidesArray($srcinfo) foreach ($srcinfo['declared_functions'] as $function) { $key = "function;$function"; - if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) { + if ($function[0] == '_' || isset($this->pkginfo['provides'][$key])) { continue; } @@ -718,7 +718,7 @@ function buildProvidesArray($srcinfo) * @return mixed * @access public */ - function analyzeSourceCode($file) + static function analyzeSourceCode($file) { if (!class_exists('PEAR_PackageFile_v2_Validator')) { require_once 'PEAR/PackageFile/v2/Validator.php'; diff --git a/WEB-INF/lib/pear/PEAR/Config.php b/WEB-INF/lib/pear/PEAR/Config.php index 3856acb10..1e83cb2c8 100644 --- a/WEB-INF/lib/pear/PEAR/Config.php +++ b/WEB-INF/lib/pear/PEAR/Config.php @@ -79,11 +79,7 @@ if (getenv('PHP_PEAR_INSTALL_DIR')) { define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR')); } else { - if (@file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) { - define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); - } else { - define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); - } + define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); } // Default for metadata_dir @@ -264,7 +260,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -727,7 +723,7 @@ public static function &singleton($user_file = '', $system_file = '', $strict = $t_conf = new PEAR_Config($user_file, $system_file, false, $strict); if ($t_conf->_errorsFound > 0) { - return $t_conf->lastError; + return $t_conf->_lastError; } $GLOBALS['_PEAR_Config_instance'] = &$t_conf; @@ -775,7 +771,7 @@ function readConfigFile($file = null, $layer = 'user', $strict = true) } $this->_errorsFound++; - $this->lastError = $data; + $this->_lastError = $data; return $data; } @@ -928,7 +924,7 @@ function mergeConfigFile($file, $override = true, $layer = 'user', $strict = tru } $this->_errorsFound++; - $this->lastError = $data; + $this->_lastError = $data; return $data; } @@ -2086,13 +2082,13 @@ function &getFTP() return $a; } - function _prependPath($path, $prepend) + static function _prependPath($path, $prepend) { if (strlen($prepend) > 0) { if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { if (preg_match('/^[a-z]:/i', $prepend)) { $prepend = substr($prepend, 2); - } elseif ($prepend{0} != '\\') { + } elseif ($prepend[0] != '\\') { $prepend = "\\$prepend"; } $path = substr($path, 0, 2) . $prepend . substr($path, 2); diff --git a/WEB-INF/lib/pear/PEAR/Dependency2.php b/WEB-INF/lib/pear/PEAR/Dependency2.php index 635c551ec..cb0a8178f 100644 --- a/WEB-INF/lib/pear/PEAR/Dependency2.php +++ b/WEB-INF/lib/pear/PEAR/Dependency2.php @@ -30,7 +30,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -110,7 +110,7 @@ function __construct(&$config, $installoptions, $package, $this->_currentPackage = $package; } - function _getExtraString($dep) + static function _getExtraString($dep) { $extra = ' ('; if (isset($dep['uri'])) { @@ -337,7 +337,7 @@ function validateExtensionDependency($dep, $required = true) } $loaded = $this->extension_loaded($dep['name']); - $extra = $this->_getExtraString($dep); + $extra = self::_getExtraString($dep); if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); @@ -486,7 +486,7 @@ function validatePhpDependency($dep) } $version = $this->phpversion(); - $extra = $this->_getExtraString($dep); + $extra = self::_getExtraString($dep); if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); @@ -540,13 +540,13 @@ function validatePhpDependency($dep) */ function getPEARVersion() { - return '1.10.1'; + return '1.10.15'; } function validatePearinstallerDependency($dep) { $pearversion = $this->getPEARVersion(); - $extra = $this->_getExtraString($dep); + $extra = self::_getExtraString($dep); if (isset($dep['exclude'])) { if (!is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); @@ -700,7 +700,7 @@ function _validatePackageDownload($dep, $required, $params, $depv1 = false) } } - $extra = $this->_getExtraString($dep); + $extra = self::_getExtraString($dep); if (isset($dep['exclude']) && !is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } @@ -1098,7 +1098,7 @@ function _validatePackageUninstall($dep, $required, $dl) return true; } - $extra = $this->_getExtraString($dep); + $extra = self::_getExtraString($dep); if (isset($dep['exclude']) && !is_array($dep['exclude'])) { $dep['exclude'] = array($dep['exclude']); } @@ -1232,7 +1232,7 @@ function validateDependency1($dep, $params = array()) $dep['optional'] = 'no'; } - list($newdep, $type) = $this->normalizeDep($dep); + list($newdep, $type) = self::normalizeDep($dep); if (!$newdep) { return $this->raiseError("Invalid Dependency"); } @@ -1246,7 +1246,7 @@ function validateDependency1($dep, $params = array()) /** * Convert a 1.0 dep into a 2.0 dep */ - function normalizeDep($dep) + static function normalizeDep($dep) { $types = array( 'pkg' => 'Package', @@ -1325,7 +1325,7 @@ function normalizeDep($dep) * @param string Operator * @return string Sign equivalent */ - function signOperator($operator) + static function signOperator($operator) { switch($operator) { case 'lt': return '<'; diff --git a/WEB-INF/lib/pear/PEAR/DependencyDB.php b/WEB-INF/lib/pear/PEAR/DependencyDB.php index 1ee604343..ede1fe0ef 100644 --- a/WEB-INF/lib/pear/PEAR/DependencyDB.php +++ b/WEB-INF/lib/pear/PEAR/DependencyDB.php @@ -29,7 +29,7 @@ * @author Tomas V.V.Cox * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -174,7 +174,7 @@ function assertDepsDB() $this->rebuildDB(); } - if ($depdb['_version']{0} > $this->_version{0}) { + if ($depdb['_version'][0] > $this->_version[0]) { return PEAR::raiseError('Dependency database is version ' . $depdb['_version'] . ', and we are version ' . $this->_version . ', cannot continue'); @@ -216,9 +216,11 @@ function getDependentPackageDependencies(&$pkg) if (is_object($pkg)) { $channel = strtolower($pkg->getChannel()); $package = strtolower($pkg->getPackage()); - } else { + } else if (is_array($pkg)) { $channel = strtolower($pkg['channel']); $package = strtolower($pkg['package']); + } else { + return false; } $depend = $this->getDependentPackages($pkg); @@ -499,8 +501,9 @@ function _lock($mode = LOCK_EX) } if (!is_resource($this->_lockFp)) { + $last_errormsg = error_get_last(); return PEAR::raiseError("could not create Dependency lock file" . - (isset($php_errormsg) ? ": " . $php_errormsg : "")); + (isset($last_errormsg) ? ": " . $last_errormsg : "")); } if (!(int)flock($this->_lockFp, $mode)) { diff --git a/WEB-INF/lib/pear/PEAR/Downloader.php b/WEB-INF/lib/pear/PEAR/Downloader.php index 6d6cdd7a2..9d4f98243 100644 --- a/WEB-INF/lib/pear/PEAR/Downloader.php +++ b/WEB-INF/lib/pear/PEAR/Downloader.php @@ -20,6 +20,7 @@ * Needed for constants, extending */ require_once 'PEAR/Common.php'; +require_once 'PEAR/Proxy.php'; define('PEAR_INSTALLER_OK', 1); define('PEAR_INSTALLER_FAILED', 0); @@ -38,7 +39,7 @@ * @author Martin Jansen * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.0 */ @@ -61,11 +62,12 @@ class PEAR_Downloader extends PEAR_Common * Options from command-line passed to Install. * * Recognized options:
- * - onlyreqdeps : install all required dependencies as well - * - alldeps : install all dependencies, including optional - * - installroot : base relative path to install files in - * - force : force a download even if warnings would prevent it - * - nocompress : download uncompressed tarballs + * - onlyreqdeps : install all required dependencies as well + * - alldeps : install all dependencies, including optional + * - installroot : base relative path to install files in + * - force : force a download even if warnings would prevent it + * - nocompress : download uncompressed tarballs + * - configureoptions : additional configure options * @see PEAR_Command_Install * @access private * @var array @@ -167,7 +169,7 @@ function __construct($ui = null, $options = array(), $config = null) } $this->ui = &$ui; if (!$this->_preferredState) { - // don't inadvertantly use a non-set preferred_state + // don't inadvertently use a non-set preferred_state $this->_preferredState = null; } @@ -184,7 +186,7 @@ function __construct($ui = null, $options = array(), $config = null) if (!count($unused)) { continue; } - $strtolower = create_function('$a','return strtolower($a);'); + $strtolower = function($a) { return strtolower($a); }; array_walk($this->_installed[$key], $strtolower); } } @@ -786,7 +788,7 @@ function configSet($key, $value, $layer = 'user', $channel = false) $this->config->set($key, $value, $layer, $channel); $this->_preferredState = $this->config->get('preferred_state', null, $channel); if (!$this->_preferredState) { - // don't inadvertantly use a non-set preferred_state + // don't inadvertently use a non-set preferred_state $this->_preferredState = null; } } @@ -848,7 +850,7 @@ function _getPackageDownloadUrl($parr) !($base = $chan->getBaseURL('REST1.0', $preferred_mirror)) ) ) { - return $this->raiseError($parr['channel'] . ' is using a unsupported protocol - This should never happen.'); + return $this->raiseError($parr['channel'] . ' is using an unsupported protocol - This should never happen. Use --force to continue'); } if ($base2) { @@ -1155,7 +1157,7 @@ function _prependPath($path, $prepend) if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { if (preg_match('/^[a-z]:/i', $prepend)) { $prepend = substr($prepend, 2); - } elseif ($prepend{0} != '\\') { + } elseif ($prepend[0] != '\\') { $prepend = "\\$prepend"; } $path = substr($path, 0, 2) . $prepend . substr($path, 2); @@ -1584,20 +1586,10 @@ public static function _downloadHttp( $config = &PEAR_Config::singleton(); } - $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; - if ($config->get('http_proxy') && - $proxy = parse_url($config->get('http_proxy'))) { - $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; - if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { - $proxy_host = 'ssl://' . $proxy_host; - } - $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; - $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; - $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; + $proxy = new PEAR_Proxy($config); - if ($callback) { - call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); - } + if ($proxy->isProxyConfigured() && $callback) { + call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); } if (empty($port)) { @@ -1605,47 +1597,30 @@ public static function _downloadHttp( } $scheme = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http'; + $secure = ($scheme == 'https'); - if ($proxy_host != '') { - $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr); - if (!$fp) { - if ($callback) { - call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port, - $errno, $errstr)); - } - return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno); - } - - if ($lastmodified === false || $lastmodified) { - $request = "GET $url HTTP/1.1\r\n"; - $request .= "Host: $host\r\n"; - } else { - $request = "GET $url HTTP/1.0\r\n"; - $request .= "Host: $host\r\n"; - } - } else { - $network_host = $host; - if (isset($info['scheme']) && $info['scheme'] == 'https') { - $network_host = 'ssl://' . $host; + $fp = $proxy->openSocket($host, $port, $secure); + if (PEAR::isError($fp)) { + if ($callback) { + $errno = $fp->getCode(); + $errstr = $fp->getMessage(); + call_user_func($callback, 'connfailed', array($host, $port, + $errno, $errstr)); } + return $fp; + } - $fp = @fsockopen($network_host, $port, $errno, $errstr); - if (!$fp) { - if ($callback) { - call_user_func($callback, 'connfailed', array($host, $port, - $errno, $errstr)); - } - return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); - } + $requestPath = $path; + if ($proxy->isProxyConfigured()) { + $requestPath = $url; + } - if ($lastmodified === false || $lastmodified) { - $request = "GET $path HTTP/1.1\r\n"; - $request .= "Host: $host\r\n"; - } else { - $request = "GET $path HTTP/1.0\r\n"; - $request .= "Host: $host\r\n"; - } + if ($lastmodified === false || $lastmodified) { + $request = "GET $requestPath HTTP/1.1\r\n"; + } else { + $request = "GET $requestPath HTTP/1.0\r\n"; } + $request .= "Host: $host\r\n"; $ifmodifiedsince = ''; if (is_array($lastmodified)) { @@ -1661,7 +1636,7 @@ public static function _downloadHttp( } $request .= $ifmodifiedsince . - "User-Agent: PEAR/1.10.1/PHP/" . PHP_VERSION . "\r\n"; + "User-Agent: PEAR/1.10.15/PHP/" . PHP_VERSION . "\r\n"; if ($object !== null) { // only pass in authentication for non-static calls $username = $config->get('username', null, $channel); @@ -1672,9 +1647,10 @@ public static function _downloadHttp( } } - if ($proxy_host != '' && $proxy_user != '') { + $proxyAuth = $proxy->getProxyAuth(); + if ($proxyAuth) { $request .= 'Proxy-Authorization: Basic ' . - base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n"; + $proxyAuth . "\r\n"; } if ($accept) { @@ -1737,7 +1713,8 @@ public static function _downloadHttp( if (!$wp = @fopen($dest_file, 'wb')) { fclose($fp); if ($callback) { - call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + call_user_func($callback, 'writefailed', + array($dest_file, error_get_last()["message"])); } return PEAR::raiseError("could not open $dest_file for writing"); } @@ -1757,9 +1734,11 @@ public static function _downloadHttp( if (!@fwrite($wp, $data)) { fclose($fp); if ($callback) { - call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + call_user_func($callback, 'writefailed', + array($dest_file, error_get_last()["message"])); } - return PEAR::raiseError("$dest_file: write failed ($php_errormsg)"); + return PEAR::raiseError( + "$dest_file: write failed (" . error_get_last()["message"] . ")"); } } diff --git a/WEB-INF/lib/pear/PEAR/Downloader/Package.php b/WEB-INF/lib/pear/PEAR/Downloader/Package.php index fe979eb67..b47f4935e 100644 --- a/WEB-INF/lib/pear/PEAR/Downloader/Package.php +++ b/WEB-INF/lib/pear/PEAR/Downloader/Package.php @@ -49,7 +49,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -1507,7 +1507,7 @@ function &getPackagefileObject(&$c, $d) function _fromFile(&$param) { $saveparam = $param; - if (is_string($param)) { + if (is_string($param) && substr($param, 0, 10) !== 'channel://') { if (!@file_exists($param)) { $test = explode('#', $param); $group = array_pop($test); diff --git a/WEB-INF/lib/pear/PEAR/ErrorStack.php b/WEB-INF/lib/pear/PEAR/ErrorStack.php index 7b705bdbb..1085e4421 100644 --- a/WEB-INF/lib/pear/PEAR/ErrorStack.php +++ b/WEB-INF/lib/pear/PEAR/ErrorStack.php @@ -131,7 +131,7 @@ * $local_stack = new PEAR_ErrorStack('MyPackage'); * * @author Greg Beaver - * @version 1.10.1 + * @version 1.10.15 * @package PEAR_ErrorStack * @category Debugging * @copyright 2004-2008 Greg Beaver @@ -676,7 +676,7 @@ function pop() * @return boolean * @since PEAR1.5.0a1 */ - function staticPop($package) + static function staticPop($package) { if ($package) { if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { diff --git a/WEB-INF/lib/pear/PEAR/Exception.php b/WEB-INF/lib/pear/PEAR/Exception.php index 0aba17104..8ea888106 100644 --- a/WEB-INF/lib/pear/PEAR/Exception.php +++ b/WEB-INF/lib/pear/PEAR/Exception.php @@ -88,7 +88,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.3 * diff --git a/WEB-INF/lib/pear/PEAR/Frontend.php b/WEB-INF/lib/pear/PEAR/Frontend.php index 8c8c8c6b4..43c618e04 100644 --- a/WEB-INF/lib/pear/PEAR/Frontend.php +++ b/WEB-INF/lib/pear/PEAR/Frontend.php @@ -38,7 +38,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -160,7 +160,7 @@ function setConfig(&$config) * needs to be able to sustain a list over many sessions in order to support * user interaction with install scripts */ - function addTempFile($file) + static function addTempFile($file) { $GLOBALS['_PEAR_Common_tempfiles'][] = $file; } @@ -220,4 +220,4 @@ function outputData($data, $command = '_default') function userDialog($command, $prompts, $types = array(), $defaults = array()) { } -} \ No newline at end of file +} diff --git a/WEB-INF/lib/pear/PEAR/Frontend/CLI.php b/WEB-INF/lib/pear/PEAR/Frontend/CLI.php index f0723d039..3bae041b2 100644 --- a/WEB-INF/lib/pear/PEAR/Frontend/CLI.php +++ b/WEB-INF/lib/pear/PEAR/Frontend/CLI.php @@ -26,7 +26,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer.php b/WEB-INF/lib/pear/PEAR/Installer.php index d5cc7df69..35649e933 100644 --- a/WEB-INF/lib/pear/PEAR/Installer.php +++ b/WEB-INF/lib/pear/PEAR/Installer.php @@ -35,7 +35,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ @@ -225,7 +225,7 @@ function _installFile($file, $atts, $tmp_path, $options) $os = new OS_Guess(); } - if (strlen($atts['platform']) && $atts['platform']{0} == '!') { + if (strlen($atts['platform']) && $atts['platform'][0] == '!') { $negate = true; $platform = substr($atts['platform'], 1); } else { @@ -323,8 +323,9 @@ function _installFile($file, $atts, $tmp_path, $options) } if (!@copy($orig_file, $dest_file)) { - return $this->raiseError("failed to write $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); + return $this->raiseError( + "failed to write $dest_file: " . error_get_last()["message"], + PEAR_INSTALLER_FAILED); } $this->log(3, "+ cp $orig_file $dest_file"); @@ -399,13 +400,15 @@ function _installFile($file, $atts, $tmp_path, $options) $wp = @fopen($dest_file, "wb"); if (!is_resource($wp)) { - return $this->raiseError("failed to create $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); + return $this->raiseError( + "failed to create $dest_file: " . error_get_last()["message"], + PEAR_INSTALLER_FAILED); } if (@fwrite($wp, $contents) === false) { - return $this->raiseError("failed writing to $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); + return $this->raiseError( + "failed writing to $dest_file: " . error_get_last()["message"], + PEAR_INSTALLER_FAILED); } fclose($wp); @@ -452,7 +455,8 @@ function _installFile($file, $atts, $tmp_path, $options) $this->addFileOperation("chmod", array($mode, $dest_file)); if (!@chmod($dest_file, $mode)) { if (!isset($options['soft'])) { - $this->log(0, "failed to change mode of $dest_file: $php_errormsg"); + $this->log(0, "failed to change mode of $dest_file: " . + error_get_last()["message"]); } } } @@ -562,8 +566,9 @@ function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options) } if (!@copy($orig_file, $dest_file)) { - return $this->raiseError("failed to write $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); + return $this->raiseError( + "failed to write $dest_file: " . error_get_last()["message"], + PEAR_INSTALLER_FAILED); } $this->log(3, "+ cp $orig_file $dest_file"); @@ -605,13 +610,15 @@ function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options) $wp = @fopen($dest_file, "wb"); if (!is_resource($wp)) { - return $this->raiseError("failed to create $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); + return $this->raiseError( + "failed to create $dest_file: " . error_get_last()["message"], + PEAR_INSTALLER_FAILED); } if (fwrite($wp, $contents) === false) { - return $this->raiseError("failed writing to $dest_file: $php_errormsg", - PEAR_INSTALLER_FAILED); + return $this->raiseError( + "failed writing to $dest_file: " . error_get_last()["message"], + PEAR_INSTALLER_FAILED); } fclose($wp); @@ -667,7 +674,8 @@ function _installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options) $this->addFileOperation("chmod", array($mode, $dest_file)); if (!@chmod($dest_file, $mode)) { if (!isset($options['soft'])) { - $this->log(0, "failed to change mode of $dest_file: $php_errormsg"); + $this->log(0, "failed to change mode of $dest_file: " . + error_get_last()["message"]); } } } @@ -854,7 +862,7 @@ function commitFileTransaction() if (!@copy($data[0], $data[0] . '.bak')) { $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] . - '.bak ' . $php_errormsg); + '.bak ' . error_get_last()["message"]); return false; } $this->log(3, "+ backup $data[0] to $data[0].bak"); @@ -889,7 +897,7 @@ function commitFileTransaction() $perms = @fileperms($data[0]); if (!@copy($data[0], $data[1])) { $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] . - ' ' . $php_errormsg); + ' ' . error_get_last()["message"]); return false; } @@ -901,7 +909,7 @@ function commitFileTransaction() case 'chmod': if (!@chmod($data[1], $data[0])) { $this->log(1, 'Could not chmod ' . $data[1] . ' to ' . - decoct($data[0]) . ' ' . $php_errormsg); + decoct($data[0]) . ' ' . error_get_last()["message"]); return false; } @@ -912,7 +920,7 @@ function commitFileTransaction() if (file_exists($data[0])) { if (!@unlink($data[0])) { $this->log(1, 'Could not delete ' . $data[0] . ' ' . - $php_errormsg); + error_get_last()["message"]); return false; } $this->log(3, "+ rm $data[0]"); @@ -934,7 +942,7 @@ function commitFileTransaction() closedir($testme); if (!@rmdir($data[0])) { $this->log(1, 'Could not rmdir ' . $data[0] . ' ' . - $php_errormsg); + error_get_last()["message"]); return false; } $this->log(3, "+ rmdir $data[0]"); @@ -1263,7 +1271,7 @@ function install($pkgfile, $options = array()) if (count($test)) { $msg = "$channel/$pkgname: conflicting files found:\n"; $longest = max(array_map("strlen", array_keys($test))); - $fmt = "%${longest}s (%s)\n"; + $fmt = "%{$longest}s (%s)\n"; foreach ($test as $file => $info) { if (!is_array($info)) { $info = array('pear.php.net', $info); @@ -1403,8 +1411,9 @@ function install($pkgfile, $options = array()) // {{{ compile and install source files if ($this->source_files > 0 && empty($options['nobuild'])) { + $configureoptions = empty($options['configureoptions']) ? '' : $options['configureoptions']; if (PEAR::isError($err = - $this->_compileSourceFiles($savechannel, $pkg))) { + $this->_compileSourceFiles($savechannel, $pkg, $configureoptions))) { return $err; } } @@ -1501,12 +1510,13 @@ function install($pkgfile, $options = array()) /** * @param string * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 + * @param mixed[] $configureoptions */ - function _compileSourceFiles($savechannel, &$filelist) + function _compileSourceFiles($savechannel, &$filelist, $configureoptions) { require_once 'PEAR/Builder.php'; $this->log(1, "$this->source_files source files, building"); - $bob = new PEAR_Builder($this->ui); + $bob = new PEAR_Builder($configureoptions, $this->ui); $bob->debug = $this->debug; $built = $bob->build($filelist, array(&$this, '_buildCallback')); if (PEAR::isError($built)) { @@ -1519,11 +1529,11 @@ function _compileSourceFiles($savechannel, &$filelist) foreach ($built as $ext) { $bn = basename($ext['file']); list($_ext_name, $_ext_suff) = explode('.', $bn); - if ($_ext_suff == '.so' || $_ext_suff == '.dll') { + if ($_ext_suff == 'so' || $_ext_suff == 'dll') { if (extension_loaded($_ext_name)) { - $this->raiseError("Extension '$_ext_name' already loaded. " . - 'Please unload it in your php.ini file ' . - 'prior to install or upgrade'); + return $this->raiseError("Extension '$_ext_name' already loaded. " . + 'Please unload it in your php.ini file ' . + 'prior to install or upgrade'); } $role = 'ext'; } else { @@ -1553,7 +1563,9 @@ function _compileSourceFiles($savechannel, &$filelist) } if (!@copy($ext['file'], $copyto)) { - return $this->raiseError("failed to write $copyto ($php_errormsg)", PEAR_INSTALLER_FAILED); + return $this->raiseError( + "failed to write $copyto (" . error_get_last()["message"] . ")", + PEAR_INSTALLER_FAILED); } $this->log(3, "+ cp $ext[file] $copyto"); @@ -1562,7 +1574,8 @@ function _compileSourceFiles($savechannel, &$filelist) $mode = 0666 & ~(int)octdec($this->config->get('umask')); $this->addFileOperation('chmod', array($mode, $copyto)); if (!@chmod($copyto, $mode)) { - $this->log(0, "failed to change mode of $copyto ($php_errormsg)"); + $this->log(0, "failed to change mode of $copyto (" . + error_get_last()["message"] . ")"); } } } diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role.php b/WEB-INF/lib/pear/PEAR/Installer/Role.php index 0623424a2..e03ba96f7 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role.php @@ -24,7 +24,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -237,7 +237,7 @@ public static function registerRoles($dir = null) } while ($entry = readdir($dp)) { - if ($entry{0} == '.' || substr($entry, -4) != '.xml') { + if ($entry[0] == '.' || substr($entry, -4) != '.xml') { continue; } diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Cfg.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Cfg.php index 903b1d641..f6c4c3783 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Cfg.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Cfg.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 2007-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.7.0 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Common.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Common.php index df0b3c66c..8d6be6a8e 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Common.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Common.php @@ -23,7 +23,7 @@ * @author Greg Beaver * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Data.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Data.php index 1a2c9c30c..b87c08fb3 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Data.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Data.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Doc.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Doc.php index 675cc8777..989e58549 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Doc.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Doc.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Ext.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Ext.php index 6224e2b89..5c1f225ee 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Ext.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Ext.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Man.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Man.php index 5c3a842b8..e478e45c2 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Man.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Man.php @@ -20,7 +20,7 @@ * @author Hannes Magnusson * @copyright 2011 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.10.0 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Php.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Php.php index d1b97a863..ff2df61eb 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Php.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Php.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Script.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Script.php index f1eeda0b6..fbf0a2675 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Script.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Script.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Src.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Src.php index 2c7ae2142..6b20e4182 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Src.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Src.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Test.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Test.php index c19c5dc06..43f352687 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Test.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Test.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Installer/Role/Www.php b/WEB-INF/lib/pear/PEAR/Installer/Role/Www.php index 42b197a90..2799f7bd0 100644 --- a/WEB-INF/lib/pear/PEAR/Installer/Role/Www.php +++ b/WEB-INF/lib/pear/PEAR/Installer/Role/Www.php @@ -19,7 +19,7 @@ * @author Greg Beaver * @copyright 2007-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.7.0 */ diff --git a/WEB-INF/lib/pear/PEAR/PackageFile.php b/WEB-INF/lib/pear/PEAR/PackageFile.php index 8fb6e41fa..cd279c338 100644 --- a/WEB-INF/lib/pear/PEAR/PackageFile.php +++ b/WEB-INF/lib/pear/PEAR/PackageFile.php @@ -34,7 +34,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -94,13 +94,13 @@ function setLogger(&$l) */ function &parserFactory($version) { - if (!in_array($version{0}, array('1', '2'))) { + if (!in_array($version[0], array('1', '2'))) { $a = false; return $a; } - include_once 'PEAR/PackageFile/Parser/v' . $version{0} . '.php'; - $version = $version{0}; + include_once 'PEAR/PackageFile/Parser/v' . $version[0] . '.php'; + $version = $version[0]; $class = "PEAR_PackageFile_Parser_v$version"; $a = new $class; return $a; @@ -122,13 +122,13 @@ function getClassPrefix() */ function &factory($version) { - if (!in_array($version{0}, array('1', '2'))) { + if (!in_array($version[0], array('1', '2'))) { $a = false; return $a; } - include_once 'PEAR/PackageFile/v' . $version{0} . '.php'; - $version = $version{0}; + include_once 'PEAR/PackageFile/v' . $version[0] . '.php'; + $version = $version[0]; $class = $this->getClassPrefix() . $version; $a = new $class; return $a; @@ -283,13 +283,13 @@ function &fromXmlString($data, $state, $file, $archive = false) * @param string $file name of file or directory * @return void */ - function addTempFile($file) + static function addTempFile($file) { $GLOBALS['_PEAR_Common_tempfiles'][] = $file; } /** - * Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file. + * Create a PEAR_PackageFile_v* from a compressed Tar or Tgz file. * @access public * @param string contents of package.xml file * @param int package state (one of PEAR_VALIDATE_* constants) @@ -315,7 +315,7 @@ function &fromTgzFile($file, $state) } if (!is_array($content)) { - if (is_string($file) && strlen($file < 255) && + if (is_string($file) && strlen($file) < 255 && (!file_exists($file) || !@is_file($file))) { $ret = PEAR::raiseError("could not open file \"$file\""); return $ret; diff --git a/WEB-INF/lib/pear/PEAR/PackageFile/Generator/v1.php b/WEB-INF/lib/pear/PEAR/PackageFile/Generator/v1.php index 5a963787c..4b92695e2 100644 --- a/WEB-INF/lib/pear/PEAR/PackageFile/Generator/v1.php +++ b/WEB-INF/lib/pear/PEAR/PackageFile/Generator/v1.php @@ -28,7 +28,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -45,7 +45,7 @@ function __construct(&$packagefile) function getPackagerVersion() { - return '1.10.1'; + return '1.10.15'; } /** @@ -196,7 +196,7 @@ function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false) ); $ret = "\n"; $ret .= "\n"; - $ret .= "\n" . + $ret .= "\n" . " $pkginfo[package]"; if (isset($pkginfo['extends'])) { $ret .= "\n$pkginfo[extends]"; @@ -738,8 +738,10 @@ function _convertDependencies2_0(&$release, $internal = false) $php = $this->_processPhpDeps($deps['php']); } else { if (!isset($deps['php'][0])) { - list($key, $blah) = each ($deps['php']); // stupid buggy versions - $deps['php'] = array($blah[0]); + // Buggy versions + $key = key($deps['php']); + $info = current($deps['php']); + $deps['php'] = array($info[0]); } $php = $this->_processDep($deps['php'][0]); if (!$php) { @@ -887,13 +889,13 @@ function _convertRelease2_0(&$release, $package) } //o tags for if (isset($package['platform'][$file]) && - $package['platform'][$file]{0} == '!') { + $package['platform'][$file][0] == '!') { $generic[] = $file; continue; } //o tags for if (isset($package['platform'][$file]) && - $package['platform'][$file]{0} != '!') { + $package['platform'][$file][0] != '!') { $genericIgnore[] = $file; continue; } @@ -902,7 +904,7 @@ function _convertRelease2_0(&$release, $package) if (isset($package['install-as'][$file])) { continue; } - if ($platform{0} != '!') { + if ($platform[0] != '!') { //o tags for $genericIgnore[] = $file; } @@ -911,7 +913,7 @@ function _convertRelease2_0(&$release, $package) $oses = $notplatform = $platform = array(); foreach ($package['platform'] as $file => $os) { // get a list of oses - if ($os{0} == '!') { + if ($os[0] == '!') { if (isset($oses[substr($os, 1)])) { continue; } @@ -957,7 +959,7 @@ function _convertRelease2_0(&$release, $package) // if (isset($package['platform'][$file]) && $package['platform'][$file] != "!$os" && - $package['platform'][$file]{0} == '!') { + $package['platform'][$file][0] == '!') { $release[$releaseNum]['filelist']['install'][] = array( 'attribs' => array( @@ -982,7 +984,7 @@ function _convertRelease2_0(&$release, $package) //o tags for // if (isset($package['platform'][$file]) && - $package['platform'][$file]{0} != '!' && + $package['platform'][$file][0] != '!' && $package['platform'][$file] != $os) { $release[$releaseNum]['filelist']['ignore'][] = array( @@ -1008,7 +1010,7 @@ function _convertRelease2_0(&$release, $package) continue; } //o tags for - if ($platform{0} != '!' && $platform != $os) { + if ($platform[0] != '!' && $platform != $os) { $release[$releaseNum]['filelist']['ignore'][] = array( 'attribs' => array( diff --git a/WEB-INF/lib/pear/PEAR/PackageFile/Generator/v2.php b/WEB-INF/lib/pear/PEAR/PackageFile/Generator/v2.php index 24e89f3aa..3866bd509 100644 --- a/WEB-INF/lib/pear/PEAR/PackageFile/Generator/v2.php +++ b/WEB-INF/lib/pear/PEAR/PackageFile/Generator/v2.php @@ -30,7 +30,7 @@ * @author Stephan Schmidt (original XML_Serializer code) * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -112,7 +112,7 @@ function __construct(&$packagefile) */ function getPackagerVersion() { - return '1.10.1'; + return '1.10.15'; } /** @@ -397,7 +397,7 @@ function toXml($state = PEAR_VALIDATE_NORMAL, $options = array()) $this->options['beautifyFilelist'] = true; } - $arr['attribs']['packagerversion'] = '1.10.1'; + $arr['attribs']['packagerversion'] = '1.10.15'; if ($this->serialize($arr, $options)) { return $this->_serializedData . "\n"; } @@ -781,7 +781,7 @@ function _serializeArray(&$array, $tagName = null, $attributes = array()) } } - if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) { + if (is_string($value) && $value && ($value[strlen($value) - 1] == "\n")) { $value .= str_repeat($this->options['indent'], $this->_tagDepth); } $tmp .= $this->_createXMLTag(array( diff --git a/WEB-INF/lib/pear/PEAR/PackageFile/v1.php b/WEB-INF/lib/pear/PEAR/PackageFile/v1.php index 413db67d1..69cdedad7 100644 --- a/WEB-INF/lib/pear/PEAR/PackageFile/v1.php +++ b/WEB-INF/lib/pear/PEAR/PackageFile/v1.php @@ -274,7 +274,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -1420,8 +1420,8 @@ function _analyzeSourceCode($file) } } switch ($token) { - case T_WHITESPACE : - continue; + case T_WHITESPACE: + break; case ';': if ($interface) { $current_function = ''; @@ -1575,7 +1575,7 @@ function _buildProvidesArray($srcinfo) foreach ($methods as $method) { $function = "$class::$method"; $key = "function;$function"; - if ($method{0} == '_' || !strcasecmp($method, $class) || + if ($method[0] == '_' || !strcasecmp($method, $class) || isset($this->_packageInfo['provides'][$key])) { continue; } @@ -1586,7 +1586,7 @@ function _buildProvidesArray($srcinfo) foreach ($srcinfo['declared_functions'] as $function) { $key = "function;$function"; - if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) { + if ($function[0] == '_' || isset($this->_packageInfo['provides'][$key])) { continue; } if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { diff --git a/WEB-INF/lib/pear/PEAR/PackageFile/v2.php b/WEB-INF/lib/pear/PEAR/PackageFile/v2.php index ae0a1fa89..b7cac639c 100644 --- a/WEB-INF/lib/pear/PEAR/PackageFile/v2.php +++ b/WEB-INF/lib/pear/PEAR/PackageFile/v2.php @@ -22,7 +22,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -423,12 +423,12 @@ function _differentName($handle, $name, $selfname) function _unmatchedMaintainers($my, $yours) { if ($my) { - array_walk($my, create_function('&$i, $k', '$i = $i["handle"];')); + array_walk($my, function(&$i, $k) { $i = $i["handle"]; }); $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my), 'package.xml 2.0 has unmatched extra maintainers "%handles%"'); } if ($yours) { - array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];')); + array_walk($yours, function(&$i, $k) { $i = $i["handle"]; }); $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours), 'package.xml 1.0 has unmatched extra maintainers "%handles%"'); } @@ -625,15 +625,14 @@ function initPostinstallScripts() $lastversion = isset($this->_packageInfo['_lastversion']) ? $this->_packageInfo['_lastversion'] : null; $task->init($raw, $atts, $lastversion); - $res = $task->startSession($this, $atts['installed_as']); + $res = $task->startSession($this, $atts['installed_as'], null); if (!$res) { continue; // skip this file } if (PEAR::isError($res)) { return $res; } - $assign = &$task; - $this->_scripts[] = &$assign; + $this->_scripts[] = $task; } } if (count($this->_scripts)) { @@ -1669,7 +1668,7 @@ function getDeps($raw = false, $nopearinstaller = false) if ($dtype == 'pearinstaller' && $nopearinstaller) { continue; } - if (!isset($deps[0])) { + if ((is_array($deps) && !isset($deps[0])) || !is_array($deps)) { $deps = array($deps); } foreach ($deps as $dep) { @@ -2047,7 +2046,7 @@ function _mergeTag($manip, $contents, $order) if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) { $manip[$tag][] = $contents; } else { - if (!count($manip[$tag])) { + if (is_array($manip[$tag]) && !count($manip[$tag])) { $manip[$tag] = $contents; } else { $manip[$tag] = array($manip[$tag]); diff --git a/WEB-INF/lib/pear/PEAR/PackageFile/v2/Validator.php b/WEB-INF/lib/pear/PEAR/PackageFile/v2/Validator.php index eff9d03ca..bbf3e523d 100644 --- a/WEB-INF/lib/pear/PEAR/PackageFile/v2/Validator.php +++ b/WEB-INF/lib/pear/PEAR/PackageFile/v2/Validator.php @@ -20,7 +20,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a8 * @access private @@ -111,8 +111,8 @@ function validate(&$pf, $state = PEAR_VALIDATE_NORMAL) isset($test['dependencies']['required']) && isset($test['dependencies']['required']['pearinstaller']) && isset($test['dependencies']['required']['pearinstaller']['min']) && - '1.10.1' != '@package' . '_version@' && - version_compare('1.10.1', + '1.10.15' != '@package' . '_version@' && + version_compare('1.10.15', $test['dependencies']['required']['pearinstaller']['min'], '<') ) { $this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']); @@ -419,7 +419,7 @@ function _processAttribs($choice, $tag, $context) foreach ($tags as $i => $tag) { if (!is_array($tag) || !isset($tag['attribs'])) { foreach ($choice['attribs'] as $attrib) { - if ($attrib{0} != '?') { + if ($attrib[0] != '?') { $ret &= $this->_tagHasNoAttribs($choice['tag'], $context); continue 2; @@ -427,7 +427,7 @@ function _processAttribs($choice, $tag, $context) } } foreach ($choice['attribs'] as $attrib) { - if ($attrib{0} != '?') { + if ($attrib[0] != '?') { if (!isset($tag['attribs'][$attrib])) { $ret &= $this->_tagMissingAttribute($choice['tag'], $attrib, $context); @@ -450,9 +450,9 @@ function _processStructure($key) } return $ret; } - $multi = $key{0}; + $multi = $key[0]; if ($multi == '+' || $multi == '*') { - $ret['multiple'] = $key{0}; + $ret['multiple'] = $key[0]; $key = substr($key, 1); } if (count($attrs = explode('->', $key)) > 1) { @@ -1080,8 +1080,8 @@ function _validateFilelist($list = false, $allowignore = false, $dirs = '') foreach ($list['file'] as $i => $file) { if (isset($file['attribs']) && isset($file['attribs']['name'])) { - if ($file['attribs']['name']{0} == '.' && - $file['attribs']['name']{1} == '/') { + if ($file['attribs']['name'][0] == '.' && + $file['attribs']['name'][1] == '/') { // name is something like "./doc/whatever.txt" $this->_invalidFileName($file['attribs']['name'], $dirname); } @@ -1350,7 +1350,7 @@ function _pearVersionTooLow($version) $this->_stack->push(__FUNCTION__, 'error', array('version' => $version), 'This package.xml requires PEAR version %version% to parse properly, we are ' . - 'version 1.10.1'); + 'version 1.10.15'); } function _invalidTagOrder($oktags, $actual, $root) @@ -1930,7 +1930,7 @@ function analyzeSourceCode($file, $string = false) switch ($token) { case T_WHITESPACE : - continue; + continue 2; case ';': if ($interface) { $current_function = ''; @@ -2106,7 +2106,7 @@ function _buildProvidesArray($srcinfo) foreach ($methods as $method) { $function = "$class::$method"; $key = "function;$function"; - if ($method{0} == '_' || !strcasecmp($method, $class) || + if ($method[0] == '_' || !strcasecmp($method, $class) || isset($providesret[$key])) { continue; } @@ -2118,7 +2118,7 @@ function _buildProvidesArray($srcinfo) foreach ($srcinfo['declared_functions'] as $function) { $key = "function;$function"; - if ($function{0} == '_' || isset($providesret[$key])) { + if ($function[0] == '_' || isset($providesret[$key])) { continue; } diff --git a/WEB-INF/lib/pear/PEAR/PackageFile/v2/rw.php b/WEB-INF/lib/pear/PEAR/PackageFile/v2/rw.php index f2b58e396..0e007ef17 100644 --- a/WEB-INF/lib/pear/PEAR/PackageFile/v2/rw.php +++ b/WEB-INF/lib/pear/PEAR/PackageFile/v2/rw.php @@ -22,7 +22,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a8 */ diff --git a/WEB-INF/lib/pear/PEAR/Packager.php b/WEB-INF/lib/pear/PEAR/Packager.php index 3303f4c10..eb52f4a4f 100644 --- a/WEB-INF/lib/pear/PEAR/Packager.php +++ b/WEB-INF/lib/pear/PEAR/Packager.php @@ -30,7 +30,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 */ diff --git a/WEB-INF/lib/pear/PEAR/Proxy.php b/WEB-INF/lib/pear/PEAR/Proxy.php new file mode 100644 index 000000000..2f74631ff --- /dev/null +++ b/WEB-INF/lib/pear/PEAR/Proxy.php @@ -0,0 +1,191 @@ +config = $config; + $this->_parseProxyInfo(); + } + + /** + * @access private + */ + function _parseProxyInfo() + { + $this->proxy_host = $this->proxy_port = $this->proxy_user = $this->proxy_pass = ''; + if ($this->config->get('http_proxy')&& + $proxy = parse_url($this->config->get('http_proxy')) + ) { + $this->proxy_host = isset($proxy['host']) ? $proxy['host'] : null; + + $this->proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; + $this->proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; + $this->proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; + $this->proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http'; + } + } + + /** + * @access private + */ + function _httpConnect($fp, $host, $port) + { + fwrite($fp, "CONNECT $host:$port HTTP/1.1\r\n"); + fwrite($fp, "Host: $host:$port\r\n"); + if ($this->getProxyAuth()) { + fwrite($fp, 'Proxy-Authorization: Basic ' . $this->getProxyAuth() . "\r\n"); + } + fwrite($fp, "\r\n"); + + while ($line = trim(fgets($fp, 1024))) { + if (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { + $code = (int)$matches[1]; + + /* as per RFC 2817 */ + if ($code < 200 || $code >= 300) { + return PEAR::raiseError("Establishing a CONNECT tunnel through proxy failed with response code $code"); + } + } + } + + // connection was successful -- establish SSL through + // the tunnel + $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT; + + if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) { + $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + $crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; + } + + // set the correct hostname for working hostname + // verification + stream_context_set_option($fp, 'ssl', 'peer_name', $host); + + // blocking socket needed for + // stream_socket_enable_crypto() + // see + // + stream_set_blocking ($fp, true); + $crypto_res = stream_socket_enable_crypto($fp, true, $crypto_method); + if (!$crypto_res) { + return PEAR::raiseError("Could not establish SSL connection through proxy: $crypto_res"); + } + + return true; + } + + /** + * get the authorization information for the proxy, encoded to be + * passed in the Proxy-Authentication HTTP header. + * @return null|string the encoded authentication information if a + * proxy and authentication is configured, null + * otherwise. + */ + function getProxyAuth() + { + if ($this->isProxyConfigured() && $this->proxy_user != '') { + return base64_encode($this->proxy_user . ':' . $this->proxy_pass); + } + return null; + } + + function getProxyUser() + { + return $this->proxy_user; + } + + /** + * Check if we are configured to use a proxy. + * + * @return boolean true if we are configured to use a proxy, false + * otherwise. + * @access public + */ + function isProxyConfigured() + { + return $this->proxy_host != ''; + } + + /** + * Open a socket to a remote server, possibly involving a HTTP + * proxy. + * + * If an HTTP proxy has been configured (http_proxy PEAR_Config + * setting), the proxy will be used. + * + * @param string $host the host to connect to + * @param string $port the port to connect to + * @param boolean $secure if true, establish a secure connection + * using TLS. + * @access public + */ + function openSocket($host, $port, $secure = false) + { + if ($this->isProxyConfigured()) { + $fp = @fsockopen( + $this->proxy_host, $this->proxy_port, + $errno, $errstr, 15 + ); + + if (!$fp) { + return PEAR::raiseError("Connection to the proxy failed: $errstr", -9276); + } + + /* HTTPS is to be used and we have a proxy, use CONNECT verb */ + if ($secure) { + $res = $this->_httpConnect($fp, $host, $port); + + if (PEAR::isError($res)) { + return $res; + } + } + } else { + if ($secure) { + $host = 'ssl://' . $host; + } + + $fp = @fsockopen($host, $port, $errno, $errstr); + if (!$fp) { + return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); + } + } + + return $fp; + } +} diff --git a/WEB-INF/lib/pear/PEAR/REST.php b/WEB-INF/lib/pear/PEAR/REST.php index c0dfeaa69..1c0b0a828 100644 --- a/WEB-INF/lib/pear/PEAR/REST.php +++ b/WEB-INF/lib/pear/PEAR/REST.php @@ -18,6 +18,7 @@ */ require_once 'PEAR.php'; require_once 'PEAR/XMLParser.php'; +require_once 'PEAR/Proxy.php'; /** * Intelligently retrieve data, following hyperlinks if necessary, and re-directing @@ -27,7 +28,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -171,25 +172,24 @@ function retrieveData($url, $accept = false, $forcestring = false, $channel = fa function useLocalCache($url, $cacheid = null) { - if ($cacheid === null) { - $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . - md5($url) . 'rest.cacheid'; - if (!file_exists($cacheidfile)) { - return false; - } - - $cacheid = unserialize(implode('', file($cacheidfile))); + if (!is_array($cacheid)) { + $cacheid = $this->getCacheId($url); } $cachettl = $this->config->get('cache_ttl'); // If cache is newer than $cachettl seconds, we use the cache! - if (time() - $cacheid['age'] < $cachettl) { + if (is_array($cacheid) && time() - $cacheid['age'] < $cachettl) { return $this->getCache($url); } return false; } + /** + * @param string $url + * + * @return bool|mixed + */ function getCacheId($url) { $cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR . @@ -356,26 +356,13 @@ function downloadHttp($url, $lastmodified = null, $accept = false, $channel = fa $path = isset($info['path']) ? $info['path'] : null; $schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http'; - $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; - if ($this->config->get('http_proxy')&& - $proxy = parse_url($this->config->get('http_proxy')) - ) { - $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; - if ($schema === 'https') { - $proxy_host = 'ssl://' . $proxy_host; - } - - $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; - $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; - $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; - $proxy_schema = (isset($proxy['scheme']) && $proxy['scheme'] == 'https') ? 'https' : 'http'; - } + $proxy = new PEAR_Proxy($this->config); if (empty($port)) { $port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80; } - if (isset($proxy['host'])) { + if ($proxy->isProxyConfigured() && $schema === 'http') { $request = "GET $url HTTP/1.1\r\n"; } else { $request = "GET $path HTTP/1.1\r\n"; @@ -396,7 +383,7 @@ function downloadHttp($url, $lastmodified = null, $accept = false, $channel = fa } $request .= $ifmodifiedsince . - "User-Agent: PEAR/1.10.1/PHP/" . PHP_VERSION . "\r\n"; + "User-Agent: PEAR/1.10.15/PHP/" . PHP_VERSION . "\r\n"; $username = $this->config->get('username', null, $channel); $password = $this->config->get('password', null, $channel); @@ -406,9 +393,10 @@ function downloadHttp($url, $lastmodified = null, $accept = false, $channel = fa $request .= "Authorization: Basic $tmp\r\n"; } - if ($proxy_host != '' && $proxy_user != '') { + $proxyAuth = $proxy->getProxyAuth(); + if ($proxyAuth) { $request .= 'Proxy-Authorization: Basic ' . - base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n"; + $proxyAuth . "\r\n"; } if ($accept) { @@ -419,20 +407,10 @@ function downloadHttp($url, $lastmodified = null, $accept = false, $channel = fa $request .= "Connection: close\r\n"; $request .= "\r\n"; - if ($proxy_host != '') { - $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr, 15); - if (!$fp) { - return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", -9276); - } - } else { - if ($schema === 'https') { - $host = 'ssl://' . $host; - } - - $fp = @fsockopen($host, $port, $errno, $errstr); - if (!$fp) { - return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); - } + $secure = ($schema == 'https'); + $fp = $proxy->openSocket($host, $port, $secure); + if (PEAR::isError($fp)) { + return $fp; } fwrite($fp, $request); diff --git a/WEB-INF/lib/pear/PEAR/REST/10.php b/WEB-INF/lib/pear/PEAR/REST/10.php index affcc18ee..79932ae72 100644 --- a/WEB-INF/lib/pear/PEAR/REST/10.php +++ b/WEB-INF/lib/pear/PEAR/REST/10.php @@ -26,7 +26,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a12 */ diff --git a/WEB-INF/lib/pear/PEAR/REST/11.php b/WEB-INF/lib/pear/PEAR/REST/11.php index 9bd51ba6f..7b5cbcffb 100644 --- a/WEB-INF/lib/pear/PEAR/REST/11.php +++ b/WEB-INF/lib/pear/PEAR/REST/11.php @@ -26,7 +26,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.3 */ diff --git a/WEB-INF/lib/pear/PEAR/REST/13.php b/WEB-INF/lib/pear/PEAR/REST/13.php index 3855c6e05..312ebe80d 100644 --- a/WEB-INF/lib/pear/PEAR/REST/13.php +++ b/WEB-INF/lib/pear/PEAR/REST/13.php @@ -27,7 +27,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a12 */ diff --git a/WEB-INF/lib/pear/PEAR/Registry.php b/WEB-INF/lib/pear/PEAR/Registry.php index c22d82f4a..b615b55f6 100644 --- a/WEB-INF/lib/pear/PEAR/Registry.php +++ b/WEB-INF/lib/pear/PEAR/Registry.php @@ -36,7 +36,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -780,7 +780,8 @@ function _readFileMap() $fp = @fopen($this->filemap, 'r'); if (!$fp) { - return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); + $last_errormsg = error_get_last(); + return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $last_errormsg); } clearstatcache(); @@ -906,7 +907,7 @@ function _channelExists($channel, $noaliases = false) } /** - * Determine whether a mirror exists within the deafult channel in the registry + * Determine whether a mirror exists within the default channel in the registry * * @param string Channel name * @param string Mirror name @@ -1008,7 +1009,7 @@ function _addChannel($channel, $update = false, $lastmodified = false) if ($lastmodified) { $info['_lastmodified'] = $lastmodified; } else { - $info['_lastmodified'] = date('r'); + $info['_lastmodified'] = self::getSourceDateEpoch(); } fwrite($fp, serialize($info)); @@ -1187,7 +1188,7 @@ function _listChannels() $dp = opendir($this->channelsdir); while ($ent = readdir($dp)) { - if ($ent{0} == '.' || substr($ent, -4) != '.reg') { + if ($ent[0] == '.' || substr($ent, -4) != '.reg') { continue; } @@ -1238,13 +1239,14 @@ function _listPackages($channel = false) } while ($ent = readdir($dp)) { - if ($ent{0} == '.' || substr($ent, -4) != '.reg') { + if ($ent[0] == '.' || substr($ent, -4) != '.reg') { continue; } $pkglist[] = substr($ent, 0, -4); } closedir($dp); + sort($pkglist); return $pkglist; } @@ -1262,7 +1264,7 @@ function _listChannelPackages($channel) } while ($ent = readdir($dp)) { - if ($ent{0} == '.' || substr($ent, -4) != '.reg') { + if ($ent[0] == '.' || substr($ent, -4) != '.reg') { continue; } $pkglist[] = substr($ent, 0, -4); @@ -1300,7 +1302,7 @@ function _addPackage($package, $info) return false; } - $info['_lastmodified'] = time(); + $info['_lastmodified'] = self::getSourceDateEpoch(); fwrite($fp, serialize($info)); $this->_closePackageFile($fp); if (isset($info['filelist'])) { @@ -1354,7 +1356,7 @@ function _addPackage2($info) return false; } - $info['_lastmodified'] = time(); + $info['_lastmodified'] = self::getSourceDateEpoch(); fwrite($fp, serialize($info)); $this->_closePackageFile($fp); $this->_rebuildFileMap(); @@ -1382,7 +1384,7 @@ function _updatePackage($package, $info, $merge = true) if (is_object($info)) { $info = $info->toArray(); } - $info['_lastmodified'] = time(); + $info['_lastmodified'] = self::getSourceDateEpoch(); $newinfo = $info; if ($merge) { @@ -1418,7 +1420,7 @@ function _updatePackage2($info) $save = $info; $info = $save->getArray(true); - $info['_lastmodified'] = time(); + $info['_lastmodified'] = self::getSourceDateEpoch(); fwrite($fp, serialize($info)); $this->_closePackageFile($fp); $this->_rebuildFileMap(); @@ -2064,7 +2066,7 @@ function checkFileMap($path, $package = false, $api = '1.0', $attrs = false) if (!class_exists('PEAR_Installer_Role')) { require_once 'PEAR/Installer/Role.php'; } - $notempty = create_function('$a','return !empty($a);'); + $notempty = function($a) { return !empty($a); }; } $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1])) : strtolower($package); @@ -2204,7 +2206,7 @@ function parsePackageName($param, $defaultchannel = 'pear.php.net') } if (!isset($components['scheme'])) { if (strpos($components['path'], '/') !== false) { - if ($components['path']{0} == '/') { + if ($components['path'][0] == '/') { return PEAR::raiseError('parsePackageName(): this is not ' . 'a package name, it begins with "/" in "' . $param . '"', 'invalid', null, null, $param); diff --git a/WEB-INF/lib/pear/PEAR/RunTest.php b/WEB-INF/lib/pear/PEAR/RunTest.php index 59dedbf9b..ee3629f64 100644 --- a/WEB-INF/lib/pear/PEAR/RunTest.php +++ b/WEB-INF/lib/pear/PEAR/RunTest.php @@ -37,7 +37,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.3.3 */ @@ -64,7 +64,6 @@ class PEAR_RunTest 'display_errors=1', 'log_errors=0', 'html_errors=0', - 'track_errors=1', 'report_memleaks=0', 'report_zend_debug=0', 'docref_root=', @@ -130,7 +129,8 @@ function system_with_timeout($commandline, $env = null, $stdin = null) while (true) { /* hide errors from interrupted syscalls */ $r = $pipes; - $e = $w = null; + unset($r[0]); + $e = $w = []; $n = @stream_select($r, $w, $e, 60); if ($n === 0) { @@ -343,7 +343,7 @@ function run($file, $ini_settings = array(), $test_number = 1) // Check if test should be skipped. $res = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings); - if (count($res) != 2) { + if ($res == 'SKIPPED' || count($res) != 2) { return $res; } $info = $res['info']; @@ -512,6 +512,7 @@ function run($file, $ini_settings = array(), $test_number = 1) $wanted_re = preg_quote($wanted_re, '/'); // Stick to basics $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy + $wanted_re = str_replace("%S", ".*?", $wanted_re); //not greedy $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re); $wanted_re = str_replace("%d", "[0-9]+", $wanted_re); $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re); diff --git a/WEB-INF/lib/pear/PEAR/Task/Common.php b/WEB-INF/lib/pear/PEAR/Task/Common.php index ebb71dc8a..e8b2adfdd 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Common.php +++ b/WEB-INF/lib/pear/PEAR/Task/Common.php @@ -47,7 +47,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 * @abstract diff --git a/WEB-INF/lib/pear/PEAR/Task/Postinstallscript.php b/WEB-INF/lib/pear/PEAR/Task/Postinstallscript.php index 950deb5ce..3ba3ed7d6 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Postinstallscript.php +++ b/WEB-INF/lib/pear/PEAR/Task/Postinstallscript.php @@ -27,7 +27,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -292,11 +292,12 @@ public function _stripNamespace($params = null) * * @param mixed $pkg PEAR_PackageFile_v1|PEAR_PackageFile_v2 * @param string $contents file name + * @param string $dest the eventual final file location (informational only) * * @return bool|PEAR_Error false to skip this file, PEAR_Error to fail * (use $this->throwError) */ - public function startSession($pkg, $contents) + public function startSession($pkg, $contents, $dest) { if ($this->installphase != PEAR_TASK_INSTALL) { return false; @@ -343,7 +344,7 @@ public function startSession($pkg, $contents) * @param string install or upgrade * @access protected */ - public static function run() + public static function run($tasks) { } } diff --git a/WEB-INF/lib/pear/PEAR/Task/Postinstallscript/rw.php b/WEB-INF/lib/pear/PEAR/Task/Postinstallscript/rw.php index 662960062..7f89ef9bc 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Postinstallscript/rw.php +++ b/WEB-INF/lib/pear/PEAR/Task/Postinstallscript/rw.php @@ -23,7 +23,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ @@ -159,7 +159,7 @@ public function getXml() * * @return array */ - public static function getParam( + public function getParam( $name, $prompt, $type = 'string', $default = null ) { if ($default !== null) { diff --git a/WEB-INF/lib/pear/PEAR/Task/Replace.php b/WEB-INF/lib/pear/PEAR/Task/Replace.php index 7483282bb..7b69fa198 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Replace.php +++ b/WEB-INF/lib/pear/PEAR/Task/Replace.php @@ -23,7 +23,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Task/Replace/rw.php b/WEB-INF/lib/pear/PEAR/Task/Replace/rw.php index ace1e9ea2..5f426dbcf 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Replace/rw.php +++ b/WEB-INF/lib/pear/PEAR/Task/Replace/rw.php @@ -23,7 +23,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ diff --git a/WEB-INF/lib/pear/PEAR/Task/Unixeol.php b/WEB-INF/lib/pear/PEAR/Task/Unixeol.php index 6ef7174bb..093cf557a 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Unixeol.php +++ b/WEB-INF/lib/pear/PEAR/Task/Unixeol.php @@ -23,7 +23,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Task/Unixeol/rw.php b/WEB-INF/lib/pear/PEAR/Task/Unixeol/rw.php index 9134e2c93..621385473 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Unixeol/rw.php +++ b/WEB-INF/lib/pear/PEAR/Task/Unixeol/rw.php @@ -23,7 +23,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ diff --git a/WEB-INF/lib/pear/PEAR/Task/Windowseol.php b/WEB-INF/lib/pear/PEAR/Task/Windowseol.php index 620c940fe..100637865 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Windowseol.php +++ b/WEB-INF/lib/pear/PEAR/Task/Windowseol.php @@ -24,7 +24,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/PEAR/Task/Windowseol/rw.php b/WEB-INF/lib/pear/PEAR/Task/Windowseol/rw.php index e3cf0052b..5c60fbe87 100644 --- a/WEB-INF/lib/pear/PEAR/Task/Windowseol/rw.php +++ b/WEB-INF/lib/pear/PEAR/Task/Windowseol/rw.php @@ -24,7 +24,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a10 */ diff --git a/WEB-INF/lib/pear/PEAR/Validate.php b/WEB-INF/lib/pear/PEAR/Validate.php index 8e29b7cd2..9326e521a 100644 --- a/WEB-INF/lib/pear/PEAR/Validate.php +++ b/WEB-INF/lib/pear/PEAR/Validate.php @@ -31,7 +31,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ @@ -209,7 +209,7 @@ function validatePackageName() } $vlen = strlen($test); $majver = substr($name, strlen($name) - $vlen); - while ($majver && !is_numeric($majver{0})) { + while ($majver && !is_numeric($majver[0])) { $majver = substr($majver, 1); } if ($majver != $test) { @@ -287,7 +287,7 @@ function validateVersion() } if (!$this->_packagexml->getExtends()) { if ($versioncomponents[0] == '1') { - if ($versioncomponents[2]{0} == '0') { + if ($versioncomponents[2][0] == '0') { if ($versioncomponents[2] == '0') { // version 1.*.0000 $this->_addWarning('version', @@ -328,7 +328,7 @@ function validateVersion() } else { $vlen = strlen($versioncomponents[0] . ''); $majver = substr($name, strlen($name) - $vlen); - while ($majver && !is_numeric($majver{0})) { + while ($majver && !is_numeric($majver[0])) { $majver = substr($majver, 1); } if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) { @@ -339,7 +339,7 @@ function validateVersion() return true; } if ($versioncomponents[0] == $majver) { - if ($versioncomponents[2]{0} == '0') { + if ($versioncomponents[2][0] == '0') { if ($versioncomponents[2] == '0') { // version 2.*.0000 $this->_addWarning('version', @@ -398,7 +398,7 @@ function validateVersion() if ($this->_packagexml->getExtends()) { $vlen = strlen($versioncomponents[0] . ''); $majver = substr($name, strlen($name) - $vlen); - while ($majver && !is_numeric($majver{0})) { + while ($majver && !is_numeric($majver[0])) { $majver = substr($majver, 1); } if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) { diff --git a/WEB-INF/lib/pear/PEAR/Validator/PECL.php b/WEB-INF/lib/pear/PEAR/Validator/PECL.php index 830c8e9b2..a9d16934e 100644 --- a/WEB-INF/lib/pear/PEAR/Validator/PECL.php +++ b/WEB-INF/lib/pear/PEAR/Validator/PECL.php @@ -23,7 +23,7 @@ * @author Greg Beaver * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license.php New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a5 */ diff --git a/WEB-INF/lib/pear/PEAR/XMLParser.php b/WEB-INF/lib/pear/PEAR/XMLParser.php index 619743bcd..d16c9535c 100644 --- a/WEB-INF/lib/pear/PEAR/XMLParser.php +++ b/WEB-INF/lib/pear/PEAR/XMLParser.php @@ -22,7 +22,7 @@ * @author Stephan Schmidt (original XML_Unserializer code) * @copyright 1997-2009 The Authors * @license http://opensource.org/licenses/bsd-license New BSD License - * @version Release: 1.10.1 + * @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 1.4.0a1 */ diff --git a/WEB-INF/lib/pear/README.rst b/WEB-INF/lib/pear/README.rst index ac8e6fd1a..9f5f7940c 100644 --- a/WEB-INF/lib/pear/README.rst +++ b/WEB-INF/lib/pear/README.rst @@ -61,28 +61,11 @@ Test dependencies ========= Releasing ========= -Create a PEAR package as well as phars for pear-less installation:: - - $ rm -f PEAR-*.tgz - $ pear package package2.xml - $ cd go-pear-tarballs - $ rm -f PEAR-* - $ cp ../PEAR-*.tgz . - $ gunzip PEAR-*.tgz - $ pear download -Z Archive_Tar Console_Getopt Structures_Graph XML_Util - $ mkdir src && cd src - $ for i in ../*.tar; do tar xvf $i; done - $ mv *\/* . - $ cd ../../ - $ php make-gopear-phar.php - $ php make-installpear-nozlib-phar.php - -(Or simply run ``build-release.sh``). - -``go-pear.phar`` is contains the PEAR installer installer that asks questions -where to install it. +Create a PEAR package, as well as phars for pear-less installation, +simply run ``build-release.sh``). + +``go-pear.phar`` contains the PEAR installer installer that asks where to install it. It is available from http://pear.php.net/go-pear.phar. -``install-pear-nozlib.phar`` installs PEAR automatically without asking -anything. +``install-pear-nozlib.phar`` installs PEAR automatically without asking anything. It is shipped with PHP itself. diff --git a/WEB-INF/lib/pear/System.php b/WEB-INF/lib/pear/System.php index 9ff3fedb9..77944233e 100644 --- a/WEB-INF/lib/pear/System.php +++ b/WEB-INF/lib/pear/System.php @@ -22,7 +22,7 @@ $GLOBALS['_System_temp_files'] = array(); /** -* System offers cross plattform compatible system functions +* System offers cross platform compatible system functions * * Static functions for different operations. Should work under * Unix and Windows. The names and usage has been taken from its respectively @@ -50,7 +50,7 @@ * @author Tomas V.V. Cox * @copyright 1997-2006 The PHP Group * @license http://opensource.org/licenses/bsd-license.php New BSD License -* @version Release: 1.10.1 +* @version Release: 1.10.15 * @link http://pear.php.net/package/PEAR * @since Class available since Release 0.1 * @static @@ -74,7 +74,7 @@ public static function _parseArgs($argv, $short_options, $long_options = null) $offset = 0; foreach ($av as $a) { $b = trim($a[0]); - if ($b{0} == '"' || $b{0} == "'") { + if ($b[0] == '"' || $b[0] == "'") { continue; } @@ -265,7 +265,7 @@ public static function mkDir($args) } elseif ($opt[0] == 'm') { // if the mode is clearly an octal number (starts with 0) // convert it to decimal - if (strlen($opt[1]) && $opt[1]{0} == '0') { + if (strlen($opt[1]) && $opt[1][0] == '0') { $opt[1] = octdec($opt[1]); } else { // convert to int @@ -315,7 +315,7 @@ public static function mkDir($args) * 2) System::cat('sample.txt test.txt > final.txt'); * 3) System::cat('sample.txt test.txt >> final.txt'); * - * Note: as the class use fopen, urls should work also (test that) + * Note: as the class use fopen, urls should work also * * @param string $args the arguments * @return boolean true on success @@ -480,7 +480,7 @@ public static function tmpdir() if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { return $var; } - return realpath('/tmp'); + return realpath(function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '/tmp'); } /** @@ -527,8 +527,16 @@ public static function which($program, $fallback = false) foreach ($exe_suffixes as $suff) { foreach ($path_elements as $dir) { $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; - if (is_executable($file)) { - return $file; + // It's possible to run a .bat on Windows that is_executable + // would return false for. The is_executable check is meaningless... + if (OS_WINDOWS) { + if (file_exists($file)) { + return $file; + } + } else { + if (is_executable($file)) { + return $file; + } } } } @@ -547,7 +555,7 @@ public static function which($program, $fallback = false) * System::find("$dir -name *.php -name *.htm*"); * System::find("$dir -maxdepth 1"); * - * Params implmented: + * Params implemented: * $dir -> Start the search at this directory * -type d -> return only directories * -type f -> return only files @@ -619,4 +627,4 @@ public static function find($args) } return $files; } -} \ No newline at end of file +} diff --git a/WEB-INF/lib/pear/package.dtd b/WEB-INF/lib/pear/package.dtd index 5b471b7fe..1550ca94c 100644 --- a/WEB-INF/lib/pear/package.dtd +++ b/WEB-INF/lib/pear/package.dtd @@ -1,6 +1,4 @@