diff options
author | Meik Sievertsen <acydburn@phpbb.com> | 2009-10-04 18:13:59 +0000 |
---|---|---|
committer | Meik Sievertsen <acydburn@phpbb.com> | 2009-10-04 18:13:59 +0000 |
commit | bf8ac19eaa8d74f9dfd6d597190f5664e7339382 (patch) | |
tree | c3ad876736748e36cb9176a0248cc43badfc1d9a /phpBB/includes/libraries | |
parent | 3215bbf88864139dc8c7e9ac5773b1ea8a7e96c1 (diff) | |
download | forums-bf8ac19eaa8d74f9dfd6d597190f5664e7339382.tar forums-bf8ac19eaa8d74f9dfd6d597190f5664e7339382.tar.gz forums-bf8ac19eaa8d74f9dfd6d597190f5664e7339382.tar.bz2 forums-bf8ac19eaa8d74f9dfd6d597190f5664e7339382.tar.xz forums-bf8ac19eaa8d74f9dfd6d597190f5664e7339382.zip |
Move trunk/phpBB to old_trunk/phpBB
git-svn-id: file:///svn/phpbb/trunk@10210 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB/includes/libraries')
-rw-r--r-- | phpBB/includes/libraries/diff/diff.php | 823 | ||||
-rw-r--r-- | phpBB/includes/libraries/diff/engine.php | 536 | ||||
-rw-r--r-- | phpBB/includes/libraries/diff/renderer.php | 858 | ||||
-rw-r--r-- | phpBB/includes/libraries/ezcomponents/loader.php | 73 | ||||
-rw-r--r-- | phpBB/includes/libraries/sftp/aes.php | 1526 | ||||
-rw-r--r-- | phpBB/includes/libraries/sftp/biginteger.php | 2162 | ||||
-rw-r--r-- | phpBB/includes/libraries/sftp/des.php | 1428 | ||||
-rw-r--r-- | phpBB/includes/libraries/sftp/hash.php | 278 | ||||
-rw-r--r-- | phpBB/includes/libraries/sftp/random.php | 64 | ||||
-rw-r--r-- | phpBB/includes/libraries/sftp/rc4.php | 490 | ||||
-rw-r--r-- | phpBB/includes/libraries/sftp/sftp.php | 3247 | ||||
-rw-r--r-- | phpBB/includes/libraries/zend/Exception.php | 30 | ||||
-rw-r--r-- | phpBB/includes/libraries/zend/loader.php | 58 |
13 files changed, 0 insertions, 11573 deletions
diff --git a/phpBB/includes/libraries/diff/diff.php b/phpBB/includes/libraries/diff/diff.php deleted file mode 100644 index c5249ee3c1..0000000000 --- a/phpBB/includes/libraries/diff/diff.php +++ /dev/null @@ -1,823 +0,0 @@ -<?php -/** -* -* @package diff -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Code from pear.php.net, Text_Diff-1.1.0 package -* http://pear.php.net/package/Text_Diff/ -* -* Modified by phpBB Group to meet our coding standards -* and being able to integrate into phpBB -* -* General API for generating and formatting diffs - the differences between -* two sequences of strings. -* -* Copyright 2004 Geoffrey T. Dairiki <dairiki@dairiki.org> -* Copyright 2004-2008 The Horde Project (http://www.horde.org/) -* -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -*/ -class diff -{ - /** - * Array of changes. - * @var array - */ - var $_edits; - - /** - * Computes diffs between sequences of strings. - * - * @param array $from_lines An array of strings. Typically these are lines from a file. - * @param array $to_lines An array of strings. - */ - function __construct(&$from_content, &$to_content, $preserve_cr = true) - { - $diff_engine = new diff_engine(); - $this->_edits = $diff_engine->diff($from_content, $to_content, $preserve_cr); - } - - /** - * Returns the array of differences. - */ - function get_diff() - { - return $this->_edits; - } - - /** - * returns the number of new (added) lines in a given diff. - * - * @since Text_Diff 1.1.0 - * - * @return integer The number of new lines - */ - function count_added_lines() - { - $count = 0; - - foreach ($this->_edits as $edit) - { - if (is_a($edit, 'diff_op_add') || is_a($edit, 'diff_op_change')) - { - $count += $edit->nfinal(); - } - } - return $count; - } - - /** - * Returns the number of deleted (removed) lines in a given diff. - * - * @since Text_Diff 1.1.0 - * - * @return integer The number of deleted lines - */ - function count_deleted_lines() - { - $count = 0; - - foreach ($this->_edits as $edit) - { - if (is_a($edit, 'diff_op_delete') || is_a($edit, 'diff_op_change')) - { - $count += $edit->norig(); - } - } - return $count; - } - - /** - * Computes a reversed diff. - * - * Example: - * <code> - * $diff = new diff($lines1, $lines2); - * $rev = $diff->reverse(); - * </code> - * - * @return diff A Diff object representing the inverse of the original diff. - * Note that we purposely don't return a reference here, since - * this essentially is a clone() method. - */ - function reverse() - { - if (version_compare(zend_version(), '2', '>')) - { - $rev = clone($this); - } - else - { - $rev = $this; - } - - $rev->_edits = array(); - - foreach ($this->_edits as $edit) - { - $rev->_edits[] = $edit->reverse(); - } - - return $rev; - } - - /** - * Checks for an empty diff. - * - * @return boolean True if two sequences were identical. - */ - function is_empty() - { - foreach ($this->_edits as $edit) - { - if (!is_a($edit, 'diff_op_copy')) - { - return false; - } - } - return true; - } - - /** - * Computes the length of the Longest Common Subsequence (LCS). - * - * This is mostly for diagnostic purposes. - * - * @return integer The length of the LCS. - */ - function lcs() - { - $lcs = 0; - - foreach ($this->_edits as $edit) - { - if (is_a($edit, 'diff_op_copy')) - { - $lcs += sizeof($edit->orig); - } - } - return $lcs; - } - - /** - * Gets the original set of lines. - * - * This reconstructs the $from_lines parameter passed to the constructor. - * - * @return array The original sequence of strings. - */ - function get_original() - { - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->orig) - { - array_splice($lines, sizeof($lines), 0, $edit->orig); - } - } - return $lines; - } - - /** - * Gets the final set of lines. - * - * This reconstructs the $to_lines parameter passed to the constructor. - * - * @return array The sequence of strings. - */ - function get_final() - { - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->final) - { - array_splice($lines, sizeof($lines), 0, $edit->final); - } - } - return $lines; - } - - /** - * Removes trailing newlines from a line of text. This is meant to be used with array_walk(). - * - * @param string &$line The line to trim. - * @param integer $key The index of the line in the array. Not used. - */ - function trim_newlines(&$line, $key) - { - $line = str_replace(array("\n", "\r"), '', $line); - } - - /** - * Checks a diff for validity. - * - * This is here only for debugging purposes. - */ - function _check($from_lines, $to_lines) - { - if (serialize($from_lines) != serialize($this->get_original())) - { - trigger_error("[diff] Reconstructed original doesn't match", E_USER_ERROR); - } - - if (serialize($to_lines) != serialize($this->get_final())) - { - trigger_error("[diff] Reconstructed final doesn't match", E_USER_ERROR); - } - - $rev = $this->reverse(); - - if (serialize($to_lines) != serialize($rev->get_original())) - { - trigger_error("[diff] Reversed original doesn't match", E_USER_ERROR); - } - - if (serialize($from_lines) != serialize($rev->get_final())) - { - trigger_error("[diff] Reversed final doesn't match", E_USER_ERROR); - } - - $prevtype = null; - - foreach ($this->_edits as $edit) - { - if ($prevtype == get_class($edit)) - { - trigger_error("[diff] Edit sequence is non-optimal", E_USER_ERROR); - } - $prevtype = get_class($edit); - } - - return true; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -*/ -class mapped_diff extends diff -{ - /** - * Computes a diff between sequences of strings. - * - * This can be used to compute things like case-insensitve diffs, or diffs - * which ignore changes in white-space. - * - * @param array $from_lines An array of strings. - * @param array $to_lines An array of strings. - * @param array $mapped_from_lines This array should have the same size number of elements as $from_lines. - * The elements in $mapped_from_lines and $mapped_to_lines are what is actually - * compared when computing the diff. - * @param array $mapped_to_lines This array should have the same number of elements as $to_lines. - */ - function mapped_diff(&$from_lines, &$to_lines, &$mapped_from_lines, &$mapped_to_lines) - { - if (sizeof($from_lines) != sizeof($mapped_from_lines) || sizeof($to_lines) != sizeof($mapped_to_lines)) - { - return false; - } - - parent::diff($mapped_from_lines, $mapped_to_lines); - - $xi = $yi = 0; - for ($i = 0; $i < sizeof($this->_edits); $i++) - { - $orig = &$this->_edits[$i]->orig; - if (is_array($orig)) - { - $orig = array_slice($from_lines, $xi, sizeof($orig)); - $xi += sizeof($orig); - } - - $final = &$this->_edits[$i]->final; - if (is_array($final)) - { - $final = array_slice($to_lines, $yi, sizeof($final)); - $yi += sizeof($final); - } - } - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op -{ - var $orig; - var $final; - - function &reverse() - { - trigger_error('[diff] Abstract method', E_USER_ERROR); - } - - function norig() - { - return ($this->orig) ? sizeof($this->orig) : 0; - } - - function nfinal() - { - return ($this->final) ? sizeof($this->final) : 0; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op_copy extends diff_op -{ - function diff_op_copy($orig, $final = false) - { - if (!is_array($final)) - { - $final = $orig; - } - $this->orig = $orig; - $this->final = $final; - } - - function &reverse() - { - $reverse = new diff_op_copy($this->final, $this->orig); - return $reverse; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op_delete extends diff_op -{ - function diff_op_delete($lines) - { - $this->orig = $lines; - $this->final = false; - } - - function &reverse() - { - $reverse = new diff_op_add($this->orig); - return $reverse; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op_add extends diff_op -{ - function diff_op_add($lines) - { - $this->final = $lines; - $this->orig = false; - } - - function &reverse() - { - $reverse = new diff_op_delete($this->final); - return $reverse; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op_change extends diff_op -{ - function diff_op_change($orig, $final) - { - $this->orig = $orig; - $this->final = $final; - } - - function &reverse() - { - $reverse = new diff_op_change($this->final, $this->orig); - return $reverse; - } -} - - -/** -* A class for computing three way diffs. -* -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -*/ -class diff3 extends diff -{ - /** - * Conflict counter. - * @var integer - */ - var $_conflicting_blocks = 0; - - /** - * Computes diff between 3 sequences of strings. - * - * @param array $orig The original lines to use. - * @param array $final1 The first version to compare to. - * @param array $final2 The second version to compare to. - */ - function diff3(&$orig, &$final1, &$final2) - { - $diff_engine = new diff_engine(); - - $diff_1 = $diff_engine->diff($orig, $final1); - $diff_2 = $diff_engine->diff($orig, $final2); - - unset($engine); - - $this->_edits = $this->_diff3($diff_1, $diff_2); - } - - /** - * Return number of conflicts - */ - function get_num_conflicts() - { - $conflicts = 0; - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $conflicts++; - } - } - - return $conflicts; - } - - /** - * Get conflicts content for download. This is generally a merged file, but preserving conflicts and adding explanations to it. - * A user could then go through this file, search for the conflicts and changes the code accordingly. - * - * @param string $label1 the cvs file version/label from the original set of lines - * @param string $label2 the cvs file version/label from the new set of lines - * @param string $label_sep the explanation between label1 and label2 - more of a helper for the user - * - * @return mixed the merged output - */ - function get_conflicts_content($label1 = 'CURRENT_FILE', $label2 = 'NEW_FILE', $label_sep = 'DIFF_SEP_EXPLAIN') - { - $label1 = (!empty(phpbb::$user->lang[$label1])) ? phpbb::$user->lang[$label1] : $label1; - $label2 = (!empty(phpbb::$user->lang[$label2])) ? phpbb::$user->lang[$label2] : $label2; - $label_sep = (!empty(phpbb::$user->lang[$label_sep])) ? phpbb::$user->lang[$label_sep] : $label_sep; - - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - // Start conflict label - $label_start = array('<<<<<<< ' . $label1); - $label_mid = array('======= ' . $label_sep); - $label_end = array('>>>>>>> ' . $label2); - - $lines = array_merge($lines, $label_start, $edit->final1, $label_mid, $edit->final2, $label_end); - } - else - { - $lines = array_merge($lines, $edit->merged()); - } - } - - return $lines; - } - - /** - * Merge the output and use the new file code for conflicts - */ - function merged_new_output() - { - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $lines = array_merge($lines, $edit->final2); - } - else - { - $lines = array_merge($lines, $edit->merged()); - } - } - - return $lines; - } - - /** - * Merge the output and use the original file code for conflicts - */ - function merged_orig_output() - { - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $lines = array_merge($lines, $edit->final1); - } - else - { - $lines = array_merge($lines, $edit->merged()); - } - } - - return $lines; - } - - /** - * Get conflicting block(s) - */ - function get_conflicts() - { - $conflicts = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $conflicts[] = array($edit->final1, $edit->final2); - } - } - - return $conflicts; - } - - /** - * @access private - */ - function _diff3(&$edits1, &$edits2) - { - $edits = array(); - $bb = new diff3_block_builder(); - - $e1 = current($edits1); - $e2 = current($edits2); - - while ($e1 || $e2) - { - if ($e1 && $e2 && is_a($e1, 'diff_op_copy') && is_a($e2, 'diff_op_copy')) - { - // We have copy blocks from both diffs. This is the (only) time we want to emit a diff3 copy block. - // Flush current diff3 diff block, if any. - if ($edit = $bb->finish()) - { - $edits[] = $edit; - } - - $ncopy = min($e1->norig(), $e2->norig()); - $edits[] = new diff3_op_copy(array_slice($e1->orig, 0, $ncopy)); - - if ($e1->norig() > $ncopy) - { - array_splice($e1->orig, 0, $ncopy); - array_splice($e1->final, 0, $ncopy); - } - else - { - $e1 = next($edits1); - } - - if ($e2->norig() > $ncopy) - { - array_splice($e2->orig, 0, $ncopy); - array_splice($e2->final, 0, $ncopy); - } - else - { - $e2 = next($edits2); - } - } - else - { - if ($e1 && $e2) - { - if ($e1->orig && $e2->orig) - { - $norig = min($e1->norig(), $e2->norig()); - $orig = array_splice($e1->orig, 0, $norig); - array_splice($e2->orig, 0, $norig); - $bb->input($orig); - } - else - { - $norig = 0; - } - - if (is_a($e1, 'diff_op_copy')) - { - $bb->out1(array_splice($e1->final, 0, $norig)); - } - - if (is_a($e2, 'diff_op_copy')) - { - $bb->out2(array_splice($e2->final, 0, $norig)); - } - } - - if ($e1 && ! $e1->orig) - { - $bb->out1($e1->final); - $e1 = next($edits1); - } - - if ($e2 && ! $e2->orig) - { - $bb->out2($e2->final); - $e2 = next($edits2); - } - } - } - - if ($edit = $bb->finish()) - { - $edits[] = $edit; - } - - return $edits; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff3_op -{ - function __construct($orig = false, $final1 = false, $final2 = false) - { - $this->orig = $orig ? $orig : array(); - $this->final1 = $final1 ? $final1 : array(); - $this->final2 = $final2 ? $final2 : array(); - } - - function merged() - { - if (!isset($this->_merged)) - { - if ($this->final1 === $this->final2) - { - $this->_merged = &$this->final1; - } - else if ($this->final1 === $this->orig) - { - $this->_merged = &$this->final2; - } - else if ($this->final2 === $this->orig) - { - $this->_merged = &$this->final1; - } - else - { - $this->_merged = false; - } - } - - return $this->_merged; - } - - function is_conflict() - { - return ($this->merged() === false) ? true : false; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff3_op_copy extends diff3_op -{ - function diff3_op_copy($lines = false) - { - $this->orig = $lines ? $lines : array(); - $this->final1 = &$this->orig; - $this->final2 = &$this->orig; - } - - function merged() - { - return $this->orig; - } - - function is_conflict() - { - return false; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff3_block_builder -{ - function __construct() - { - $this->_init(); - } - - function input($lines) - { - if ($lines) - { - $this->_append($this->orig, $lines); - } - } - - function out1($lines) - { - if ($lines) - { - $this->_append($this->final1, $lines); - } - } - - function out2($lines) - { - if ($lines) - { - $this->_append($this->final2, $lines); - } - } - - function is_empty() - { - return !$this->orig && !$this->final1 && !$this->final2; - } - - function finish() - { - if ($this->is_empty()) - { - return false; - } - else - { - $edit = new diff3_op($this->orig, $this->final1, $this->final2); - $this->_init(); - return $edit; - } - } - - function _init() - { - $this->orig = $this->final1 = $this->final2 = array(); - } - - function _append(&$array, $lines) - { - array_splice($array, sizeof($array), 0, $lines); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/diff/engine.php b/phpBB/includes/libraries/diff/engine.php deleted file mode 100644 index eb0dcce395..0000000000 --- a/phpBB/includes/libraries/diff/engine.php +++ /dev/null @@ -1,536 +0,0 @@ -<?php -/** -* -* @package diff -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Code from pear.php.net, Text_Diff-1.1.0 package -* http://pear.php.net/package/Text_Diff/ (native engine) -* -* Modified by phpBB Group to meet our coding standards -* and being able to integrate into phpBB -* -* Class used internally by Text_Diff to actually compute the diffs. This -* class is implemented using native PHP code. -* -* The algorithm used here is mostly lifted from the perl module -* Algorithm::Diff (version 1.06) by Ned Konz, which is available at: -* http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip -* -* More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html -* -* Some ideas (and a bit of code) are taken from analyze.c, of GNU -* diffutils-2.7, which can be found at: -* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz -* -* Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from -* Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this -* code was written by him, and is used/adapted with his permission. -* -* Copyright 2004-2008 The Horde Project (http://www.horde.org/) -* -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* @package diff -* -* @access private -*/ -class diff_engine -{ - function diff(&$from_lines, &$to_lines, $preserve_cr = true) - { - // Remove empty lines... - // If preserve_cr is true, we basically only change \r\n and bare \r to \n to get the same carriage returns for both files - // If it is false, we try to only use \n once per line and ommit all empty lines to be able to get a proper data diff - - if (is_array($from_lines)) - { - $from_lines = implode("\n", $from_lines); - } - - if (is_array($to_lines)) - { - $to_lines = implode("\n", $to_lines); - } - - if ($preserve_cr) - { - $from_lines = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $from_lines))); - $to_lines = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $to_lines))); - } - else - { - $from_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $from_lines)); - $to_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $to_lines)); - } - - $n_from = sizeof($from_lines); - $n_to = sizeof($to_lines); - - $this->xchanged = $this->ychanged = $this->xv = $this->yv = $this->xind = $this->yind = array(); - unset($this->seq, $this->in_seq, $this->lcs); - - // Skip leading common lines. - for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) - { - if ($from_lines[$skip] !== $to_lines[$skip]) - { - break; - } - $this->xchanged[$skip] = $this->ychanged[$skip] = false; - } - - // Skip trailing common lines. - $xi = $n_from; - $yi = $n_to; - - for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) - { - if ($from_lines[$xi] !== $to_lines[$yi]) - { - break; - } - $this->xchanged[$xi] = $this->ychanged[$yi] = false; - } - - // Ignore lines which do not exist in both files. - for ($xi = $skip; $xi < $n_from - $endskip; $xi++) - { - $xhash[$from_lines[$xi]] = 1; - } - - for ($yi = $skip; $yi < $n_to - $endskip; $yi++) - { - $line = $to_lines[$yi]; - - if (($this->ychanged[$yi] = empty($xhash[$line]))) - { - continue; - } - $yhash[$line] = 1; - $this->yv[] = $line; - $this->yind[] = $yi; - } - - for ($xi = $skip; $xi < $n_from - $endskip; $xi++) - { - $line = $from_lines[$xi]; - - if (($this->xchanged[$xi] = empty($yhash[$line]))) - { - continue; - } - $this->xv[] = $line; - $this->xind[] = $xi; - } - - // Find the LCS. - $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv)); - - // Merge edits when possible. - $this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged); - $this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged); - - // Compute the edit operations. - $edits = array(); - $xi = $yi = 0; - - while ($xi < $n_from || $yi < $n_to) - { - // Skip matching "snake". - $copy = array(); - - while ($xi < $n_from && $yi < $n_to && !$this->xchanged[$xi] && !$this->ychanged[$yi]) - { - $copy[] = $from_lines[$xi++]; - $yi++; - } - - if ($copy) - { - $edits[] = new diff_op_copy($copy); - } - - // Find deletes & adds. - $delete = array(); - while ($xi < $n_from && $this->xchanged[$xi]) - { - $delete[] = $from_lines[$xi++]; - } - - $add = array(); - while ($yi < $n_to && $this->ychanged[$yi]) - { - $add[] = $to_lines[$yi++]; - } - - if ($delete && $add) - { - $edits[] = new diff_op_change($delete, $add); - } - else if ($delete) - { - $edits[] = new diff_op_delete($delete); - } - else if ($add) - { - $edits[] = new diff_op_add($add); - } - } - - return $edits; - } - - /** - * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, - * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized segments. - * - * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of - * NCHUNKS+1 (X, Y) indexes giving the diving points between sub - * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1), - * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) == - * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). - * - * This function assumes that the first lines of the specified portions of - * the two files do not match, and likewise that the last lines do not - * match. The caller must trim matching lines from the beginning and end - * of the portions it is going to specify. - */ - function _diag($xoff, $xlim, $yoff, $ylim, $nchunks) - { - $flip = false; - - if ($xlim - $xoff > $ylim - $yoff) - { - // Things seems faster (I'm not sure I understand why) when the shortest sequence is in X. - $flip = true; - list($xoff, $xlim, $yoff, $ylim) = array($yoff, $ylim, $xoff, $xlim); - } - - if ($flip) - { - for ($i = $ylim - 1; $i >= $yoff; $i--) - { - $ymatches[$this->xv[$i]][] = $i; - } - } - else - { - for ($i = $ylim - 1; $i >= $yoff; $i--) - { - $ymatches[$this->yv[$i]][] = $i; - } - } - - $this->lcs = 0; - $this->seq[0]= $yoff - 1; - $this->in_seq = array(); - $ymids[0] = array(); - - $numer = $xlim - $xoff + $nchunks - 1; - $x = $xoff; - - for ($chunk = 0; $chunk < $nchunks; $chunk++) - { - if ($chunk > 0) - { - for ($i = 0; $i <= $this->lcs; $i++) - { - $ymids[$i][$chunk - 1] = $this->seq[$i]; - } - } - - $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks); - - for (; $x < $x1; $x++) - { - $line = $flip ? $this->yv[$x] : $this->xv[$x]; - if (empty($ymatches[$line])) - { - continue; - } - $matches = $ymatches[$line]; - - reset($matches); - while (list(, $y) = each($matches)) - { - if (empty($this->in_seq[$y])) - { - $k = $this->_lcs_pos($y); - $ymids[$k] = $ymids[$k - 1]; - break; - } - } - - // no reset() here - while (list(, $y) = each($matches)) - { - if ($y > $this->seq[$k - 1]) - { - // Optimization: this is a common case: next match is just replacing previous match. - $this->in_seq[$this->seq[$k]] = false; - $this->seq[$k] = $y; - $this->in_seq[$y] = 1; - } - else if (empty($this->in_seq[$y])) - { - $k = $this->_lcs_pos($y); - $ymids[$k] = $ymids[$k - 1]; - } - } - } - } - - $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); - $ymid = $ymids[$this->lcs]; - - for ($n = 0; $n < $nchunks - 1; $n++) - { - $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); - $y1 = $ymid[$n] + 1; - $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); - } - $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); - - return array($this->lcs, $seps); - } - - function _lcs_pos($ypos) - { - $end = $this->lcs; - - if ($end == 0 || $ypos > $this->seq[$end]) - { - $this->seq[++$this->lcs] = $ypos; - $this->in_seq[$ypos] = 1; - return $this->lcs; - } - - $beg = 1; - while ($beg < $end) - { - $mid = (int)(($beg + $end) / 2); - if ($ypos > $this->seq[$mid]) - { - $beg = $mid + 1; - } - else - { - $end = $mid; - } - } - - $this->in_seq[$this->seq[$end]] = false; - $this->seq[$end] = $ypos; - $this->in_seq[$ypos] = 1; - - return $end; - } - - /** - * Finds LCS of two sequences. - * - * The results are recorded in the vectors $this->{x,y}changed[], by - * storing a 1 in the element for each line that is an insertion or - * deletion (ie. is not in the LCS). - * - * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1. - * - * Note that XLIM, YLIM are exclusive bounds. All line numbers are - * origin-0 and discarded lines are not counted. - */ - function _compareseq($xoff, $xlim, $yoff, $ylim) - { - // Slide down the bottom initial diagonal. - while ($xoff < $xlim && $yoff < $ylim && $this->xv[$xoff] == $this->yv[$yoff]) - { - ++$xoff; - ++$yoff; - } - - // Slide up the top initial diagonal. - while ($xlim > $xoff && $ylim > $yoff && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) - { - --$xlim; - --$ylim; - } - - if ($xoff == $xlim || $yoff == $ylim) - { - $lcs = 0; - } - else - { - // This is ad hoc but seems to work well. - // $nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); - // $nchunks = max(2,min(8,(int)$nchunks)); - $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; - list($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); - } - - if ($lcs == 0) - { - // X and Y sequences have no common subsequence: mark all changed. - while ($yoff < $ylim) - { - $this->ychanged[$this->yind[$yoff++]] = 1; - } - - while ($xoff < $xlim) - { - $this->xchanged[$this->xind[$xoff++]] = 1; - } - } - else - { - // Use the partitions to split this problem into subproblems. - reset($seps); - $pt1 = $seps[0]; - - while ($pt2 = next($seps)) - { - $this->_compareseq($pt1[0], $pt2[0], $pt1[1], $pt2[1]); - $pt1 = $pt2; - } - } - } - - /** - * Adjusts inserts/deletes of identical lines to join changes as much as possible. - * - * We do something when a run of changed lines include a line at one end - * and has an excluded, identical line at the other. We are free to - * choose which identical line is included. 'compareseq' usually chooses - * the one at the beginning, but usually it is cleaner to consider the - * following identical line to be the "change". - * - * This is extracted verbatim from analyze.c (GNU diffutils-2.7). - */ - function _shift_boundaries($lines, &$changed, $other_changed) - { - $i = 0; - $j = 0; - - $len = sizeof($lines); - $other_len = sizeof($other_changed); - - while (1) - { - // Scan forward to find the beginning of another run of - // changes. Also keep track of the corresponding point in the other file. - // - // Throughout this code, $i and $j are adjusted together so that - // the first $i elements of $changed and the first $j elements of - // $other_changed both contain the same number of zeros (unchanged lines). - // - // Furthermore, $j is always kept so that $j == $other_len or $other_changed[$j] == false. - while ($j < $other_len && $other_changed[$j]) - { - $j++; - } - - while ($i < $len && ! $changed[$i]) - { - $i++; - $j++; - - while ($j < $other_len && $other_changed[$j]) - { - $j++; - } - } - - if ($i == $len) - { - break; - } - - $start = $i; - - // Find the end of this run of changes. - while (++$i < $len && $changed[$i]) - { - continue; - } - - do - { - // Record the length of this run of changes, so that we can later determine whether the run has grown. - $runlength = $i - $start; - - // Move the changed region back, so long as the previous unchanged line matches the last changed one. - // This merges with previous changed regions. - while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) - { - $changed[--$start] = 1; - $changed[--$i] = false; - - while ($start > 0 && $changed[$start - 1]) - { - $start--; - } - - while ($other_changed[--$j]) - { - continue; - } - } - - // Set CORRESPONDING to the end of the changed run, at the last point where it corresponds to a changed run in the - // other file. CORRESPONDING == LEN means no such point has been found. - $corresponding = $j < $other_len ? $i : $len; - - // Move the changed region forward, so long as the first changed line matches the following unchanged one. - // This merges with following changed regions. - // Do this second, so that if there are no merges, the changed region is moved forward as far as possible. - while ($i < $len && $lines[$start] == $lines[$i]) - { - $changed[$start++] = false; - $changed[$i++] = 1; - - while ($i < $len && $changed[$i]) - { - $i++; - } - - $j++; - if ($j < $other_len && $other_changed[$j]) - { - $corresponding = $i; - while ($j < $other_len && $other_changed[$j]) - { - $j++; - } - } - } - } - while ($runlength != $i - $start); - - // If possible, move the fully-merged run of changes back to a corresponding run in the other file. - while ($corresponding < $i) - { - $changed[--$start] = 1; - $changed[--$i] = 0; - - while ($other_changed[--$j]) - { - continue; - } - } - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/diff/renderer.php b/phpBB/includes/libraries/diff/renderer.php deleted file mode 100644 index 2d3ab88a26..0000000000 --- a/phpBB/includes/libraries/diff/renderer.php +++ /dev/null @@ -1,858 +0,0 @@ -<?php -/** -* -* @package diff -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Code from pear.php.net, Text_Diff-1.1.0 package -* http://pear.php.net/package/Text_Diff/ -* -* Modified by phpBB Group to meet our coding standards -* and being able to integrate into phpBB -* -* A class to render Diffs in different formats. -* -* This class renders the diff in classic diff format. It is intended that -* this class be customized via inheritance, to obtain fancier outputs. -* -* Copyright 2004-2008 The Horde Project (http://www.horde.org/) -* -* @package diff -*/ -class diff_renderer -{ - /** - * Number of leading context "lines" to preserve. - * - * This should be left at zero for this class, but subclasses may want to - * set this to other values. - */ - var $_leading_context_lines = 0; - - /** - * Number of trailing context "lines" to preserve. - * - * This should be left at zero for this class, but subclasses may want to - * set this to other values. - */ - var $_trailing_context_lines = 0; - - /** - * Constructor. - */ - function __construct($params = array()) - { - foreach ($params as $param => $value) - { - $v = '_' . $param; - if (isset($this->$v)) - { - $this->$v = $value; - } - } - } - - /** - * Get any renderer parameters. - * - * @return array All parameters of this renderer object. - */ - function get_params() - { - $params = array(); - foreach (get_object_vars($this) as $k => $v) - { - if ($k[0] == '_') - { - $params[substr($k, 1)] = $v; - } - } - - return $params; - } - - /** - * Renders a diff. - * - * @param diff &$diff A diff object. - * - * @return string The formatted output. - */ - function render(&$diff) - { - $xi = $yi = 1; - $block = false; - $context = array(); - - // Create a new diff object if it is a 3-way diff - if (is_a($diff, 'diff3')) - { - $diff3 = &$diff; - - $diff_1 = $diff3->get_original(); - $diff_2 = $diff3->merged_output(); - - unset($diff3); - - $diff = new diff($diff_1, $diff_2); - } - - $nlead = $this->_leading_context_lines; - $ntrail = $this->_trailing_context_lines; - - $output = $this->_start_diff(); - $diffs = $diff->get_diff(); - - foreach ($diffs as $i => $edit) - { - // If these are unchanged (copied) lines, and we want to keep leading or trailing context lines, extract them from the copy block. - if (is_a($edit, 'diff_op_copy')) - { - // Do we have any diff blocks yet? - if (is_array($block)) - { - // How many lines to keep as context from the copy block. - $keep = ($i == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail; - if (sizeof($edit->orig) <= $keep) - { - // We have less lines in the block than we want for context => keep the whole block. - $block[] = $edit; - } - else - { - if ($ntrail) - { - // Create a new block with as many lines as we need for the trailing context. - $context = array_slice($edit->orig, 0, $ntrail); - $block[] = new diff_op_copy($context); - } - - $output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block); - $block = false; - } - } - // Keep the copy block as the context for the next block. - $context = $edit->orig; - } - else - { - // Don't we have any diff blocks yet? - if (!is_array($block)) - { - // Extract context lines from the preceding copy block. - $context = array_slice($context, sizeof($context) - $nlead); - $x0 = $xi - sizeof($context); - $y0 = $yi - sizeof($context); - $block = array(); - - if ($context) - { - $block[] = new diff_op_copy($context); - } - } - $block[] = $edit; - } - - $xi += ($edit->orig) ? sizeof($edit->orig) : 0; - $yi += ($edit->final) ? sizeof($edit->final) : 0; - } - - if (is_array($block)) - { - $output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block); - } - - return $output . $this->_end_diff(); - } - - function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) - { - $output = $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen)); - - foreach ($edits as $edit) - { - switch (get_class($edit)) - { - case 'diff_op_copy': - $output .= $this->_context($edit->orig); - break; - - case 'diff_op_add': - $output .= $this->_added($edit->final); - break; - - case 'diff_op_delete': - $output .= $this->_deleted($edit->orig); - break; - - case 'diff_op_change': - $output .= $this->_changed($edit->orig, $edit->final); - break; - } - } - - return $output . $this->_end_block(); - } - - function _start_diff() - { - return ''; - } - - function _end_diff() - { - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen > 1) - { - $xbeg .= ',' . ($xbeg + $xlen - 1); - } - - if ($ylen > 1) - { - $ybeg .= ',' . ($ybeg + $ylen - 1); - } - - // this matches the GNU Diff behaviour - if ($xlen && !$ylen) - { - $ybeg--; - } - else if (!$xlen) - { - $xbeg--; - } - - return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; - } - - function _start_block($header) - { - return $header . "\n"; - } - - function _end_block() - { - return ''; - } - - function _lines($lines, $prefix = ' ') - { - return $prefix . implode("\n$prefix", $lines) . "\n"; - } - - function _context($lines) - { - return $this->_lines($lines, ' '); - } - - function _added($lines) - { - return $this->_lines($lines, '> '); - } - - function _deleted($lines) - { - return $this->_lines($lines, '< '); - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . "---\n" . $this->_added($final); - } - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return $this->render($diff); - } -} - -/** -* Renders a unified diff -* @package diff -*/ -class diff_renderer_unified extends diff_renderer -{ - var $_leading_context_lines = 4; - var $_trailing_context_lines = 4; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return nl2br($this->render($diff)); - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen != 1) - { - $xbeg .= ',' . $xlen; - } - - if ($ylen != 1) - { - $ybeg .= ',' . $ylen; - } - return '<div class="diff"><big class="info">@@ -' . $xbeg . ' +' . $ybeg . ' @@</big></div>'; - } - - function _context($lines) - { - return '<pre class="diff context">' . htmlspecialchars($this->_lines($lines, ' ')) . '<br /></pre>'; - } - - function _added($lines) - { - return '<pre class="diff added">' . htmlspecialchars($this->_lines($lines, '+')) . '<br /></pre>'; - } - - function _deleted($lines) - { - return '<pre class="diff removed">' . htmlspecialchars($this->_lines($lines, '-')) . '<br /></pre>'; - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } - - function _start_diff() - { - $start = '<div class="file">'; - - return $start; - } - - function _end_diff() - { - return '</div>'; - } - - function _end_block() - { - return ''; - } -} - -/** -* "Inline" diff renderer. -* -* This class renders diffs in the Wiki-style "inline" format. -* -* @author Ciprian Popovici -* @package diff -*/ -class diff_renderer_inline extends diff_renderer -{ - var $_leading_context_lines = 10000; - var $_trailing_context_lines = 10000; - - // Prefix and suffix for inserted text - var $_ins_prefix = '<span class="ins">'; - var $_ins_suffix = '</span>'; - - // Prefix and suffix for deleted text - var $_del_prefix = '<span class="del">'; - var $_del_suffix = '</span>'; - - var $_block_head = ''; - - // What are we currently splitting on? Used to recurse to show word-level - var $_split_level = 'lines'; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return '<pre>' . nl2br($this->render($diff)) . '<br /></pre>'; - } - - function _start_diff() - { - return ''; - } - - function _end_diff() - { - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - return $this->_block_head; - } - - function _start_block($header) - { - return $header; - } - - function _lines($lines, $prefix = ' ', $encode = true) - { - if ($encode) - { - array_walk($lines, array(&$this, '_encode')); - } - - if ($this->_split_level == 'words') - { - return implode('', $lines); - } - else - { - return implode("\n", $lines) . "\n"; - } - } - - function _added($lines) - { - array_walk($lines, array(&$this, '_encode')); - $lines[0] = $this->_ins_prefix . $lines[0]; - $lines[sizeof($lines) - 1] .= $this->_ins_suffix; - return $this->_lines($lines, ' ', false); - } - - function _deleted($lines, $words = false) - { - array_walk($lines, array(&$this, '_encode')); - $lines[0] = $this->_del_prefix . $lines[0]; - $lines[sizeof($lines) - 1] .= $this->_del_suffix; - return $this->_lines($lines, ' ', false); - } - - function _changed($orig, $final) - { - // If we've already split on words, don't try to do so again - just display. - if ($this->_split_level == 'words') - { - $prefix = ''; - while ($orig[0] !== false && $final[0] !== false && substr($orig[0], 0, 1) == ' ' && substr($final[0], 0, 1) == ' ') - { - $prefix .= substr($orig[0], 0, 1); - $orig[0] = substr($orig[0], 1); - $final[0] = substr($final[0], 1); - } - - return $prefix . $this->_deleted($orig) . $this->_added($final); - } - - $text1 = implode("\n", $orig); - $text2 = implode("\n", $final); - - // Non-printing newline marker. - $nl = "\0"; - - // We want to split on word boundaries, but we need to preserve whitespace as well. - // Therefore we split on words, but include all blocks of whitespace in the wordlist. - $splitted_text_1 = $this->_split_on_words($text1, $nl); - $splitted_text_2 = $this->_split_on_words($text2, $nl); - - $diff = new diff($splitted_text_1, $splitted_text_2); - unset($splitted_text_1, $splitted_text_2); - - // Get the diff in inline format. - $renderer = new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words'))); - - // Run the diff and get the output. - return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; - } - - function _split_on_words($string, $newline_escape = "\n") - { - // Ignore \0; otherwise the while loop will never finish. - $string = str_replace("\0", '', $string); - - $words = array(); - $length = strlen($string); - $pos = 0; - - $tab_there = true; - while ($pos < $length) - { - // Check for tabs... do not include them - if ($tab_there && substr($string, $pos, 1) === "\t") - { - $words[] = "\t"; - $pos++; - - continue; - } - else - { - $tab_there = false; - } - - // Eat a word with any preceding whitespace. - $spaces = strspn(substr($string, $pos), " \n"); - $nextpos = strcspn(substr($string, $pos + $spaces), " \n"); - $words[] = str_replace("\n", $newline_escape, substr($string, $pos, $spaces + $nextpos)); - $pos += $spaces + $nextpos; - } - - return $words; - } - - function _encode(&$string) - { - $string = htmlspecialchars($string); - } -} - -/** -* "raw" diff renderer. -* This class could be used to output a raw unified patch file -* -* @package diff -*/ -class diff_renderer_raw extends diff_renderer -{ - var $_leading_context_lines = 4; - var $_trailing_context_lines = 4; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return '<textarea style="height: 290px;" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>'; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen != 1) - { - $xbeg .= ',' . $xlen; - } - - if ($ylen != 1) - { - $ybeg .= ',' . $ylen; - } - return '@@ -' . $xbeg . ' +' . $ybeg . ' @@'; - } - - function _context($lines) - { - return $this->_lines($lines, ' '); - } - - function _added($lines) - { - return $this->_lines($lines, '+'); - } - - function _deleted($lines) - { - return $this->_lines($lines, '-'); - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } -} - -/** -* "chora (Horde)" diff renderer - similar style. -* This renderer class is a modified human_readable function from the Horde Framework. -* -* @package diff -*/ -class diff_renderer_side_by_side extends diff_renderer -{ - var $_leading_context_lines = 3; - var $_trailing_context_lines = 3; - - var $lines = array(); - - // Hold the left and right columns of lines for change blocks. - var $cols; - var $state; - - var $data = false; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - $output = ''; - $output .= '<table cellspacing="0" class="hrdiff"> -<caption> - <span class="unmodified"> </span> ' . phpbb::$user->lang['LINE_UNMODIFIED'] . ' - <span class="added"> </span> ' . phpbb::$user->lang['LINE_ADDED'] . ' - <span class="modified"> </span> ' . phpbb::$user->lang['LINE_MODIFIED'] . ' - <span class="removed"> </span> ' . phpbb::$user->lang['LINE_REMOVED'] . ' -</caption> -<tbody> -'; - - $this->render($diff); - - // Is the diff empty? - if (!sizeof($this->lines)) - { - $output .= '<tr><th colspan="2">' . phpbb::$user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>'; - } - else - { - // Iterate through every header block of changes - foreach ($this->lines as $header) - { - $output .= '<tr><th>' . phpbb::$user->lang['LINE'] . ' ' . $header['oldline'] . '</th><th>' . phpbb::$user->lang['LINE'] . ' ' . $header['newline'] . '</th></tr>'; - - // Each header block consists of a number of changes (add, remove, change). - $current_context = ''; - - foreach ($header['contents'] as $change) - { - if (!empty($current_context) && $change['type'] != 'empty') - { - $line = $current_context; - $current_context = ''; - - $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td> - <td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>'; - } - - switch ($change['type']) - { - case 'add': - $line = ''; - - foreach ($change['lines'] as $_line) - { - $line .= htmlspecialchars($_line) . '<br />'; - } - - $output .= '<tr><td class="added_empty"> </td><td class="added"><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>'; - break; - - case 'remove': - $line = ''; - - foreach ($change['lines'] as $_line) - { - $line .= htmlspecialchars($_line) . '<br />'; - } - - $output .= '<tr><td class="removed"><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td><td class="removed_empty"> </td></tr>'; - break; - - case 'empty': - $current_context .= htmlspecialchars($change['line']) . '<br />'; - break; - - case 'change': - // Pop the old/new stacks one by one, until both are empty. - $oldsize = sizeof($change['old']); - $newsize = sizeof($change['new']); - $left = $right = ''; - - for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row) - { - $left .= isset($change['old'][$row]) ? htmlspecialchars($change['old'][$row]) : ''; - $left .= '<br />'; - $right .= isset($change['new'][$row]) ? htmlspecialchars($change['new'][$row]) : ''; - $right .= '<br />'; - } - - $output .= '<tr>'; - - if (!empty($left)) - { - $output .= '<td class="modified"><pre>' . $left . '<br /></pre></td>'; - } - else if ($row < $oldsize) - { - $output .= '<td class="modified"> </td>'; - } - else - { - $output .= '<td class="unmodified"> </td>'; - } - - if (!empty($right)) - { - $output .= '<td class="modified"><pre>' . $right . '<br /></pre></td>'; - } - else if ($row < $newsize) - { - $output .= '<td class="modified"> </td>'; - } - else - { - $output .= '<td class="unmodified"> </td>'; - } - - $output .= '</tr>'; - break; - } - } - - if (!empty($current_context)) - { - $line = $current_context; - $current_context = ''; - - $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td>'; - $output .= '<td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>'; - } - } - } - - $output .= '</tbody></table>'; - - return $output; - } - - function _start_diff() - { - $this->lines = array(); - - $this->data = false; - $this->cols = array(array(), array()); - $this->state = 'empty'; - - return ''; - } - - function _end_diff() - { - // Just flush any remaining entries in the columns stack. - switch ($this->state) - { - case 'add': - $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]); - break; - - case 'remove': - // We have some removal lines pending in our stack, so flush them. - $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]); - break; - - case 'change': - // We have both remove and addition lines, so this is a change block. - $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]); - break; - } - - if ($this->data !== false) - { - $this->lines[] = $this->data; - } - - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - // Push any previous header information to the return stack. - if ($this->data !== false) - { - $this->lines[] = $this->data; - } - - $this->data = array('type' => 'header', 'oldline' => $xbeg, 'newline' => $ybeg, 'contents' => array()); - $this->state = 'dump'; - } - - function _added($lines) - { - array_walk($lines, array(&$this, '_perform_add')); - } - - function _perform_add($line) - { - if ($this->state == 'empty') - { - return ''; - } - - // This is just an addition line. - if ($this->state == 'dump' || $this->state == 'add') - { - // Start adding to the addition stack. - $this->cols[0][] = $line; - $this->state = 'add'; - } - else - { - // This is inside a change block, so start accumulating lines. - $this->state = 'change'; - $this->cols[1][] = $line; - } - } - - function _deleted($lines) - { - array_walk($lines, array(&$this, '_perform_delete')); - } - - function _perform_delete($line) - { - // This is a removal line. - $this->state = 'remove'; - $this->cols[0][] = $line; - } - - function _context($lines) - { - array_walk($lines, array(&$this, '_perform_context')); - } - - function _perform_context($line) - { - // An empty block with no action. - switch ($this->state) - { - case 'add': - $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]); - break; - - case 'remove': - // We have some removal lines pending in our stack, so flush them. - $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]); - break; - - case 'change': - // We have both remove and addition lines, so this is a change block. - $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]); - break; - } - - $this->cols = array(array(), array()); - $this->data['contents'][] = array('type' => 'empty', 'line' => $line); - $this->state = 'dump'; - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } - -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/ezcomponents/loader.php b/phpBB/includes/libraries/ezcomponents/loader.php deleted file mode 100644 index 62aaa7667d..0000000000 --- a/phpBB/includes/libraries/ezcomponents/loader.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php -/** -* -* @package ezcomponents -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* eZ components class loader -* Replaces the autoload mechanism eZ Components normally use -* @package ezcomponents -*/ -class phpbb_ezcomponents_loader -{ - var $loaded; - - /** - * Constructor which makes sure the PHP version requirement is met. - */ - function phpbb_ezcomponents_loader() - { - $this->loaded = array(); - if (version_compare(PHP_VERSION, '5.2.1', '<')) - { - trigger_error('PHP >= 5.2.1 required', E_USER_ERROR); - } - } - - /** - * Loads all classes of a particular component. - * The base component is always loaded first. - * - * @param $component string Lower case component name - */ - function load_component($component) - { - global $phpbb_root_path; - - // don't allow loading the same component twice - if (isset($this->loaded[$component]) && $this->loaded[$component]) - { - return; - } - - // make sure base is always loaded first - if ($component != 'base' && !isset($this->loaded['base'])) - { - $this->load_component('base'); - } - - $ezc_path = $phpbb_root_path . 'includes/ezcomponents/'; - - // retrieve the autoload list - $classes = include($ezc_path . ucfirst($component) . '/' . $component . '_autoload.php'); - - // include all files related to this component - foreach ($classes as $class => $path) - { - include($ezc_path . $path); - } - } -}
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/aes.php b/phpBB/includes/libraries/sftp/aes.php deleted file mode 100644 index 612e20830b..0000000000 --- a/phpBB/includes/libraries/sftp/aes.php +++ /dev/null @@ -1,1526 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementation of AES
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access public
- * @see rijndael::encrypt()
- * @see rijndael::decrypt()
- */
-/**
- * Encrypt / decrypt using the Electronic Code Book mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
- */
-define('CRYPT_RIJNDAEL_MODE_ECB', 1);
-/**
- * Encrypt / decrypt using the Code Book Chaining mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
- */
-define('CRYPT_RIJNDAEL_MODE_CBC', 2);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see rijndael::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_RIJNDAEL_MODE_INTERNAL', 1);
-/**
- * Toggles the mcrypt implementation
- */
-define('CRYPT_RIJNDAEL_MODE_MCRYPT', 2);
-/**#@-*/
-
-/**#@+
- * @access public
- * @see aes::encrypt()
- * @see aes::decrypt()
- */
-/**
- * Encrypt / decrypt using the Electronic Code Book mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
- */
-define('CRYPT_AES_MODE_ECB', 1);
-/**
- * Encrypt / decrypt using the Code Book Chaining mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
- */
-define('CRYPT_AES_MODE_CBC', 2);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see aes::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_AES_MODE_INTERNAL', 1);
-/**
- * Toggles the mcrypt implementation
- */
-define('CRYPT_AES_MODE_MCRYPT', 2);
-/**#@-*/
-
-/**
- * Pure-PHP implementation of Rijndael.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package rijndael
- */
-class rijndael
-{
- /**
- * The Encryption Mode
- *
- * @see rijndael::__construct()
- * @var Integer
- * @access private
- */
- var $mode;
-
- /**
- * The Key
- *
- * @see rijndael::set_key()
- * @var String
- * @access private
- */
- var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-
- /**
- * The Initialization Vector
- *
- * @see rijndael::set_iv()
- * @var String
- * @access private
- */
- var $iv = '';
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see rijndael::enable_continuous_buffer()
- * @var String
- * @access private
- */
- var $encryptIV = '';
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see rijndael::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $decryptIV = '';
-
- /**
- * Continuous Buffer status
- *
- * @see rijndael::enable_continuous_buffer()
- * @var Boolean
- * @access private
- */
- var $continuousBuffer = false;
-
- /**
- * Padding status
- *
- * @see rijndael::enable_padding()
- * @var Boolean
- * @access private
- */
- var $padding = true;
-
- /**
- * Does the key schedule need to be (re)calculated?
- *
- * @see setKey()
- * @see setBlockLength()
- * @see setKeyLength()
- * @var Boolean
- * @access private
- */
- var $changed = true;
-
- /**
- * Has the key length explicitly been set or should it be derived from the key, itself?
- *
- * @see setKeyLength()
- * @var Boolean
- * @access private
- */
- var $explicit_key_length = false;
-
- /**
- * The Key Schedule
- *
- * @see _setup()
- * @var Array
- * @access private
- */
- var $w;
-
- /**
- * The Inverse Key Schedule
- *
- * @see _setup()
- * @var Array
- * @access private
- */
- var $dw;
-
- /**
- * The Block Length
- *
- * @see setBlockLength()
- * @var Integer
- * @access private
- * @internal The max value is 32, the min value is 16. All valid values are multiples of 4. Exists in conjunction with
- * $Nb because we need this value and not $Nb to pad strings appropriately.
- */
- var $block_size = 16;
-
- /**
- * The Block Length divided by 32
- *
- * @see setBlockLength()
- * @var Integer
- * @access private
- * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
- * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
- * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
- * of that, we'll just precompute it once.
- *
- */
- var $Nb = 4;
-
- /**
- * The Key Length
- *
- * @see setKeyLength()
- * @var Integer
- * @access private
- * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $key_size
- * because the encryption / decryption / key schedule creation requires this number and not $key_size. We could
- * derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
- * of that, we'll just precompute it once.
- */
- var $key_size = 16;
-
- /**
- * The Key Length divided by 32
- *
- * @see setKeyLength()
- * @var Integer
- * @access private
- * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
- */
- var $Nk = 4;
-
- /**
- * The Number of Rounds
- *
- * @var Integer
- * @access private
- * @internal The max value is 14, the min value is 10.
- */
- var $Nr;
-
- /**
- * Shift offsets
- *
- * @var Array
- * @access private
- */
- var $c;
-
- /**
- * Precomputed mixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $t0;
-
- /**
- * Precomputed mixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $t1;
-
- /**
- * Precomputed mixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $t2;
-
- /**
- * Precomputed mixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $t3;
-
- /**
- * Precomputed invMixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $dt0;
-
- /**
- * Precomputed invMixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $dt1;
-
- /**
- * Precomputed invMixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $dt2;
-
- /**
- * Precomputed invMixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $dt3;
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
- * CRYPT_RIJNDAEL_MODE_ECB or CRYPT_RIJNDAEL_MODE_CBC. If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
- *
- * @param optional Integer $mode
- * @return rijndael
- * @access public
- */
- function __construct($mode = CRYPT_MODE_CRYPT_RIJNDAEL_CBC)
- {
- switch ($mode)
- {
- case CRYPT_RIJNDAEL_MODE_ECB:
- case CRYPT_RIJNDAEL_MODE_CBC:
- $this->mode = $mode;
- break;
- default:
- $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
- }
-
- // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
- // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
- // those are the names we'll use.
- $this->t3 = array(
- 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
- 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
- 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
- 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
- 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
- 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
- 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
- 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
- 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
- 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
- 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
- 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
- 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
- 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
- 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
- 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
- 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
- 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
- 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
- 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
- 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
- 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
- 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
- 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
- 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
- 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
- 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
- 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
- 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
- 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
- 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
- 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
- );
-
- $this->dt3 = array(
- 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
- 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
- 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
- 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
- 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
- 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
- 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
- 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
- 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
- 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
- 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
- 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
- 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
- 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
- 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
- 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
- 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
- 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
- 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
- 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
- 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
- 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
- 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
- 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
- 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
- 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
- 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
- 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
- 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
- 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
- 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
- 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
- );
-
- for ($i = 0; $i < 256; $i++)
- {
- $this->t2[$i << 8] = (($this->t3[$i] << 8) & 0xFFFFFF00) | (($this->t3[$i] >> 24) & 0x000000FF);
- $this->t1[$i << 16] = (($this->t3[$i] << 16) & 0xFFFF0000) | (($this->t3[$i] >> 16) & 0x0000FFFF);
- $this->t0[$i << 24] = (($this->t3[$i] << 24) & 0xFF000000) | (($this->t3[$i] >> 8) & 0x00FFFFFF);
-
- $this->dt2[$i << 8] = (($this->dt3[$i] << 8) & 0xFFFFFF00) | (($this->dt3[$i] >> 24) & 0x000000FF);
- $this->dt1[$i << 16] = (($this->dt3[$i] << 16) & 0xFFFF0000) | (($this->dt3[$i] >> 16) & 0x0000FFFF);
- $this->dt0[$i << 24] = (($this->dt3[$i] << 24) & 0xFF000000) | (($this->dt3[$i] >> 8) & 0x00FFFFFF);
- }
- }
-
- /**
- * Sets the key.
- *
- * Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
- * whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
- * up to the closest valid key length, padding $key with null bytes. If the key is more tan 256-bits, we trim the
- * excess bits.
- *
- * If the key is not explicitly set, it'll be assumed to be all null bytes.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $this->key = $key;
- $this->changed = true;
- }
-
- /**
- * Sets the initialization vector. (optional)
- *
- * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed
- * to be all zero's.
- *
- * @access public
- * @param String $iv
- */
- function set_iv($iv)
- {
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, $this->block_size), $this->block_size, chr(0));;
- }
-
- /**
- * Sets the key length
- *
- * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
- * 128. If the length is greater then 128 and invalid, it will be rounded down to the closest valid amount.
- *
- * @access public
- * @param Integer $length
- */
- function set_key_length($length)
- {
- $length >>= 5;
- if ($length > 8)
- {
- $length = 8;
- }
- else if ($length < 4)
- {
- $length = 4;
- }
- $this->Nk = $length;
- $this->key_size = $length << 2;
-
- $this->explicit_key_length = true;
- $this->changed = true;
- }
-
- /**
- * Sets the block length
- *
- * Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
- * 128. If the length is greater then 128 and invalid, it will be rounded down to the closest valid amount.
- *
- * @access public
- * @param Integer $length
- */
- function set_block_length($length)
- {
- $length >>= 5;
- if ($length > 8)
- {
- $length = 8;
- }
- else if ($length < 4)
- {
- $length = 4;
- }
- $this->Nb = $length;
- $this->block_size = $length << 2;
- $this->changed = true;
- }
-
- /**
- * Encrypts a message.
- *
- * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other Rjindael
- * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
- * necessary are discussed in the following
- * URL:
- *
- * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
- *
- * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
- * strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
- * length.
- *
- * @see rijndael::decrypt()
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- $this->_setup();
- $plaintext = $this->_pad($plaintext);
-
- $ciphertext = '';
- switch ($this->mode)
- {
- case CRYPT_RIJNDAEL_MODE_ECB:
- for ($i = 0; $i < strlen($plaintext); $i+=$this->block_size)
- {
- $ciphertext.= $this->_encrypt_block(substr($plaintext, $i, $this->block_size));
- }
- break;
- case CRYPT_RIJNDAEL_MODE_CBC:
- $xor = $this->encryptIV;
- for ($i = 0; $i < strlen($plaintext); $i+=$this->block_size)
- {
- $block = substr($plaintext, $i, $this->block_size);
- $block = $this->_encrypt_block($block ^ $xor);
- $xor = $block;
- $ciphertext.= $block;
- }
- if ($this->continuousBuffer)
- {
- $this->encryptIV = $xor;
- }
- }
-
- return $ciphertext;
- }
-
- /**
- * Decrypts a message.
- *
- * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
- * it is.
- *
- * @see rijndael::encrypt()
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- $this->_setup();
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + $this->block_size - 1) % $this->block_size, chr(0));
-
- $plaintext = '';
- switch ($this->mode)
- {
- case CRYPT_RIJNDAEL_MODE_ECB:
- for ($i = 0; $i < strlen($ciphertext); $i+=$this->block_size)
- {
- $plaintext.= $this->_decrypt_block(substr($ciphertext, $i, $this->block_size));
- }
- break;
- case CRYPT_RIJNDAEL_MODE_CBC:
- $xor = $this->decryptIV;
- for ($i = 0; $i < strlen($ciphertext); $i+=$this->block_size)
- {
- $block = substr($ciphertext, $i, $this->block_size);
- $plaintext.= $this->_decrypt_block($block) ^ $xor;
- $xor = $block;
- }
- if ($this->continuousBuffer)
- {
- $this->decryptIV = $xor;
- }
- }
-
- return $this->_unpad($plaintext);
- }
-
- /**
- * Encrypts a block
- *
- * @access private
- * @param String $in
- * @return String
- */
- function _encrypt_block($in)
- {
- // unpack starts it's indices at 1 - not 0.
- $state = unpack('N*', $in);
-
- // addRoundKey and reindex $state
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $state[$i + 1] ^ $this->w[0][$i];
- }
- unset($state[$i]);
-
- // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
- // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
- // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
- // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
- // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
- // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
-
- // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
- $temp = array();
- for ($round = 1; $round < $this->Nr; $round++)
- {
- $i = 0; // $this->c[0] == 0
- $j = $this->c[1];
- $k = $this->c[2];
- $l = $this->c[3];
-
- while ($i < $this->Nb)
- {
- $temp[$i] = $this->t0[$state[$i] & 0xFF000000] ^
- $this->t1[$state[$j] & 0x00FF0000] ^
- $this->t2[$state[$k] & 0x0000FF00] ^
- $this->t3[$state[$l] & 0x000000FF] ^
- $this->w[$round][$i];
- $i++;
- $j = ($j + 1) % $this->Nb;
- $k = ($k + 1) % $this->Nb;
- $l = ($l + 1) % $this->Nb;
- }
-
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $temp[$i];
- }
- }
-
- // subWord
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $this->_sub_word($state[$i]);
- }
-
- // shiftRows + addRoundKey
- $i = 0; // $this->c[0] == 0
- $j = $this->c[1];
- $k = $this->c[2];
- $l = $this->c[3];
- while ($i < $this->Nb)
- {
- $temp[$i] = ($state[$i] & 0xFF000000) ^
- ($state[$j] & 0x00FF0000) ^
- ($state[$k] & 0x0000FF00) ^
- ($state[$l] & 0x000000FF) ^
- $this->w[$this->Nr][$i];
- $i++;
- $j = ($j + 1) % $this->Nb;
- $k = ($k + 1) % $this->Nb;
- $l = ($l + 1) % $this->Nb;
- }
- $state = $temp;
-
- array_unshift($state, 'N*');
-
- return call_user_func_array('pack', $state);
- }
-
- /**
- * Decrypts a block
- *
- * @access private
- * @param String $in
- * @return String
- */
- function _decrypt_block($in)
- {
- // unpack starts it's indices at 1 - not 0.
- $state = unpack('N*', $in);
-
- // addRoundKey and reindex $state
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $state[$i + 1] ^ $this->dw[$this->Nr][$i];
- }
- unset($state[$i]);
-
- $temp = array();
- for ($round = $this->Nr - 1; $round > 0; $round--)
- {
- $i = 0; // $this->c[0] == 0
- $j = $this->Nb - $this->c[1];
- $k = $this->Nb - $this->c[2];
- $l = $this->Nb - $this->c[3];
-
- while ($i < $this->Nb)
- {
- $temp[$i] = $this->dt0[$state[$i] & 0xFF000000] ^
- $this->dt1[$state[$j] & 0x00FF0000] ^
- $this->dt2[$state[$k] & 0x0000FF00] ^
- $this->dt3[$state[$l] & 0x000000FF] ^
- $this->dw[$round][$i];
- $i++;
- $j = ($j + 1) % $this->Nb;
- $k = ($k + 1) % $this->Nb;
- $l = ($l + 1) % $this->Nb;
- }
-
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $temp[$i];
- }
- }
-
- // invShiftRows + invSubWord + addRoundKey
- $i = 0; // $this->c[0] == 0
- $j = $this->Nb - $this->c[1];
- $k = $this->Nb - $this->c[2];
- $l = $this->Nb - $this->c[3];
-
- while ($i < $this->Nb)
- {
- $temp[$i] = $this->dw[0][$i] ^
- $this->_inv_sub_word(($state[$i] & 0xFF000000) |
- ($state[$j] & 0x00FF0000) |
- ($state[$k] & 0x0000FF00) |
- ($state[$l] & 0x000000FF));
- $i++;
- $j = ($j + 1) % $this->Nb;
- $k = ($k + 1) % $this->Nb;
- $l = ($l + 1) % $this->Nb;
- }
-
- $state = $temp;
-
- array_unshift($state, 'N*');
-
- return call_user_func_array('pack', $state);
- }
-
- /**
- * Setup Rijndael
- *
- * Validates all the variables and calculates $Nr - the number of rounds that need to be performed - and $w - the key
- * key schedule.
- *
- * @access private
- */
- function _setup()
- {
- // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
- // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
- static $rcon = array(0,
- 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
- 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
- 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
- 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
- 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
- 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
- );
-
- if (!$this->changed)
- {
- return;
- }
-
- if (!$this->explicit_key_length)
- {
- // we do >> 2, here, and not >> 5, as we do above, since strlen($this->key) tells us the number of bytes - not bits
- $length = strlen($this->key) >> 2;
- if ($length > 8)
- {
- $length = 8;
- }
- else if ($length < 4)
- {
- $length = 4;
- }
- $this->Nk = $length;
- $this->key_size = $length << 2;
- }
-
- $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, chr(0));
-
- // see Rijndael-ammended.pdf#page=44
- $this->Nr = max($this->Nk, $this->Nb) + 6;
-
- // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
- // "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
- // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
- // "Table 2: Shift offsets for different block lengths"
- switch ($this->Nb)
- {
- case 4:
- case 5:
- case 6:
- $this->c = array(0, 1, 2, 3);
- break;
- case 7:
- $this->c = array(0, 1, 2, 4);
- break;
- case 8:
- $this->c = array(0, 1, 3, 4);
- }
-
- $key = $this->key;
-
- $w = array();
- for ($i = 0; $i < $this->Nk; $i++)
- {
- list(, $w[$i]) = unpack('N', $this->_string_shift($key, 4));
- }
-
- $length = $this->Nb * ($this->Nr + 1);
- for (; $i < $length; $i++)
- {
- $temp = $w[$i - 1];
- if ($i % $this->Nk == 0)
- {
- // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
- // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
- // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
- // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
- $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
- $temp = $this->_sub_word($temp) ^ $rcon[$i / $this->Nk];
- }
- else if ($this->Nk > 6 && $i % $this->Nk == 4)
- {
- $temp = $this->_sub_word($temp);
- }
- $w[$i] = $w[$i - $this->Nk] ^ $temp;
- }
-
- // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
- // and generate the inverse key schedule. more specifically,
- // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
- // "The key expansion for the Inverse Cipher is defined as follows:
- // 1. Apply the Key Expansion.
- // 2. Apply InvMixColumn to all Round Keys except the first and the last one."
- // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
- $temp = array();
- for ($i = $row = $col = 0; $i < $length; $i++, $col++)
- {
- if ($col == $this->Nb)
- {
- if ($row == 0)
- {
- $this->dw[0] = $this->w[0];
- }
- else
- {
- // subWord + invMixColumn + invSubWord = invMixColumn
- $j = 0;
- while ($j < $this->Nb)
- {
- $dw = $this->_sub_word($this->w[$row][$j]);
- $temp[$j] = $this->dt0[$dw & 0xFF000000] ^
- $this->dt1[$dw & 0x00FF0000] ^
- $this->dt2[$dw & 0x0000FF00] ^
- $this->dt3[$dw & 0x000000FF];
- $j++;
- }
- $this->dw[$row] = $temp;
- }
-
- $col = 0;
- $row++;
- }
- $this->w[$row][$col] = $w[$i];
- }
-
- $this->dw[$row] = $this->w[$row];
-
- $this->changed = false;
- }
-
- /**
- * Performs S-Box substitutions
- *
- * @access private
- */
- function _sub_word($word)
- {
- static $sbox0, $sbox1, $sbox2, $sbox3;
-
- if (empty($sbox0))
- {
- $sbox0 = array(
- 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
- 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
- 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
- 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
- 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
- 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
- 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
- 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
- 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
- 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
- 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
- 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
- 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
- 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
- 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
- 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
- );
-
- $sbox1 = array();
- $sbox2 = array();
- $sbox3 = array();
-
- for ($i = 0; $i < 256; $i++)
- {
- $sbox1[$i << 8] = $sbox0[$i] << 8;
- $sbox2[$i << 16] = $sbox0[$i] << 16;
- $sbox3[$i << 24] = $sbox0[$i] << 24;
- }
- }
-
- return $sbox0[$word & 0x000000FF] |
- $sbox1[$word & 0x0000FF00] |
- $sbox2[$word & 0x00FF0000] |
- $sbox3[$word & 0xFF000000];
- }
-
- /**
- * Performs inverse S-Box substitutions
- *
- * @access private
- */
- function _inv_sub_word($word)
- {
- static $sbox0, $sbox1, $sbox2, $sbox3;
-
- if (empty($sbox0))
- {
- $sbox0 = array(
- 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
- 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
- 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
- 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
- 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
- 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
- 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
- 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
- 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
- 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
- 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
- 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
- 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
- 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
- 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
- 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
- );
-
- $sbox1 = array();
- $sbox2 = array();
- $sbox3 = array();
-
- for ($i = 0; $i < 256; $i++)
- {
- $sbox1[$i << 8] = $sbox0[$i] << 8;
- $sbox2[$i << 16] = $sbox0[$i] << 16;
- $sbox3[$i << 24] = $sbox0[$i] << 24;
- }
- }
-
- return $sbox0[$word & 0x000000FF] |
- $sbox1[$word & 0x0000FF00] |
- $sbox2[$word & 0x00FF0000] |
- $sbox3[$word & 0xFF000000];
- }
-
- /**
- * Pad "packets".
- *
- * Rijndael works by encrypting between sixteen and thirty-two bytes at a time, provided that number is also a multiple
- * of four. If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
- * pad the input so that it is of the proper length.
- *
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
- * transmitted separately)
- *
- * @see rijndael::disable_padding()
- * @access public
- */
- function enable_padding()
- {
- $this->padding = true;
- }
-
- /**
- * Do not pad packets.
- *
- * @see rijndael::enable_padding()
- * @access public
- */
- function disable_padding()
- {
- $this->padding = false;
- }
-
- /**
- * Pads a string
- *
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
- * $block_size - (strlen($text) % $block_size) bytes are added, each of which is equal to
- * chr($block_size - (strlen($text) % $block_size)
- *
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
- * and padding will, hence forth, be enabled.
- *
- * @see rijndael::_unpad()
- * @access private
- */
- function _pad($text)
- {
- $length = strlen($text);
-
- if (!$this->padding)
- {
- if ($length % $this->block_size == 0)
- {
- return $text;
- }
- else
- {
- $this->padding = true;
- }
- }
-
- $pad = $this->block_size - ($length % $this->block_size);
-
- return str_pad($text, $length + $pad, chr($pad));
- }
-
- /**
- * Unpads a string.
- *
- * If padding is enabled and the reported padding length exceeds the block size, padding will be, hence forth, disabled.
- *
- * @see rijndael::_pad()
- * @access private
- */
- function _unpad($text)
- {
- if (!$this->padding)
- {
- return $text;
- }
-
- $length = ord($text[strlen($text) - 1]);
-
- if ($length > $this->block_size)
- {
- $this->padding = false;
- return $text;
- }
-
- return substr($text, 0, -$length);
- }
-
- /**
- * Treat consecutive "packets" as if they are a continuous buffer.
- *
- * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
- * will yield different outputs:
- *
- * <code>
- * echo $rijndael->encrypt(substr($plaintext, 0, 16));
- * echo $rijndael->encrypt(substr($plaintext, 16, 16));
- * </code>
- * <code>
- * echo $rijndael->encrypt($plaintext);
- * </code>
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- * <code>
- * $rijndael->encrypt(substr($plaintext, 0, 16));
- * echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));
- * </code>
- * <code>
- * echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));
- * </code>
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the rijndael() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see rijndael::disable_continuous_buffer()
- * @access public
- */
- function enable_continuous_buffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see rijndael::enable_continuous_buffer()
- * @access public
- */
- function disable_continuous_buffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
- }
-
- /**
- * String Shift
- *
- * Inspired by array_shift
- *
- * @param String $string
- * @param optional Integer $index
- * @return String
- * @access private
- */
- function _string_shift(&$string, $index = 1)
- {
- $substr = substr($string, 0, $index);
- $string = substr($string, $index);
- return $substr;
- }
-}
-
-/**
- * Pure-PHP implementation of AES.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package aes
- */
-class aes extends rijndael {
- /**
- * MCrypt parameters
- *
- * @see aes::set_mcypt()
- * @var Array
- * @access private
- */
- var $mcrypt = array('', '');
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
- * CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used.
- *
- * @param optional Integer $mode
- * @return aes
- * @access public
- */
- function __construct($mode = CRYPT_AES_MODE_CBC)
- {
- if ( !defined('CRYPT_AES_MODE') )
- {
- switch (true)
- {
- case extension_loaded('mcrypt'):
- // i'd check to see if aes was supported, by doing in_array('des', mcrypt_list_algorithms('')),
- // but since that can be changed after the object has been created, there doesn't seem to be
- // a lot of point...
- define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
- break;
- default:
- define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
- }
- }
-
- switch ( CRYPT_AES_MODE )
- {
- case CRYPT_AES_MODE_MCRYPT:
- switch ($mode)
- {
- case CRYPT_AES_MODE_ECB:
- $this->mode = MCRYPT_MODE_ECB;
- break;
- case CRYPT_AES_MODE_CBC:
- default:
- $this->mode = MCRYPT_MODE_CBC;
- }
-
- break;
- default:
- switch ($mode)
- {
- case CRYPT_AES_MODE_ECB:
- $this->mode = CRYPT_RIJNDAEL_MODE_ECB;
- break;
- case CRYPT_AES_MODE_CBC:
- default:
- $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
- }
- }
-
- if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL)
- {
- parent::__construct($this->mode);
- }
- }
-
- /**
- * Dummy function
- *
- * Since aes extends rijndael, this function is, technically, available, but it doesn't do anything.
- *
- * @access public
- * @param Integer $length
- */
- function set_block_length($length)
- {
- return;
- }
-
- /**
- * Encrypts a message.
- *
- * $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the
- * same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
- * URL:
- *
- * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
- *
- * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
- * strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
- * length.
- *
- * @see aes::decrypt()
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT )
- {
- $this->_mcrypt_setup();
- $plaintext = $this->_pad($plaintext);
-
- $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->key, $this->encryptIV);
-
- $ciphertext = mcrypt_generic($td, $plaintext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->encryptIV = substr($ciphertext, -16);
- }
-
- return $ciphertext;
- }
-
- return parent::encrypt($plaintext);
- }
-
- /**
- * Decrypts a message.
- *
- * If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
- *
- * @see aes::encrypt()
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
-
- if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT )
- {
- $this->_mcryptSetup();
-
- $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->key, $this->decryptIV);
-
- $plaintext = mdecrypt_generic($td, $ciphertext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->decryptIV = substr($ciphertext, -16);
- }
-
- return $this->_unpad($plaintext);
- }
-
- return parent::decrypt($ciphertext);
- }
-
- /**
- * Sets MCrypt parameters. (optional)
- *
- * If MCrypt is being used, empty strings will be used, unless otherwise specified.
- *
- * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
- * @access public
- * @param optional Integer $algorithm_directory
- * @param optional Integer $mode_directory
- */
- function set_mcrypt($algorithm_directory = '', $mode_directory = '')
- {
- $this->mcrypt = array($algorithm_directory, $mode_directory);
- }
-
- /**
- * Setup mcrypt
- *
- * Validates all the variables.
- *
- * @access private
- */
- function _mcrypt_setup()
- {
- if (!$this->changed)
- {
- return;
- }
-
- if (!$this->explicit_key_length)
- {
- // this just copied from rijndael::_setup()
- $length = strlen($this->key) >> 2;
- if ($length > 8)
- {
- $length = 8;
- }
- else if ($length < 4)
- {
- $length = 4;
- }
- $this->Nk = $length;
- $this->key_size = $length << 2;
- }
-
- switch ($this->Nk)
- {
- case 4: // 128
- $this->key_size = 16;
- break;
- case 5: // 160
- case 6: // 192
- $this->key_size = 24;
- break;
- case 7: // 224
- case 8: // 256
- $this->key_size = 32;
- }
-
- $this->key = substr($this->key, 0, $this->key_size);
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
-
- $this->changed = false;
- }
-
- /**
- * Encrypts a block
- *
- * Optimized over rijndael's implementation by means of loop unrolling.
- *
- * @see rijndael::_encrypt_block()
- * @access private
- * @param String $in
- * @return String
- */
- function _encrypt_block($in)
- {
- // unpack starts it's indices at 1 - not 0.
- $state = unpack('N*', $in);
-
- // addRoundKey and reindex $state
- $state = array(
- $state[1] ^ $this->w[0][0],
- $state[2] ^ $this->w[0][1],
- $state[3] ^ $this->w[0][2],
- $state[4] ^ $this->w[0][3]
- );
-
- // shiftRows + subWord + mixColumns + addRoundKey
- // we could loop unroll this and use if statements to do more rounds as necessary, but, in my tests, that yields
- // only a marginal improvement. since that also, imho, hinders the readability of the code, i've opted not to do it.
- for ($round = 1; $round < $this->Nr; $round++)
- {
- $state = array(
- $this->t0[$state[0] & 0xFF000000] ^ $this->t1[$state[1] & 0x00FF0000] ^ $this->t2[$state[2] & 0x0000FF00] ^ $this->t3[$state[3] & 0x000000FF] ^ $this->w[$round][0],
- $this->t0[$state[1] & 0xFF000000] ^ $this->t1[$state[2] & 0x00FF0000] ^ $this->t2[$state[3] & 0x0000FF00] ^ $this->t3[$state[0] & 0x000000FF] ^ $this->w[$round][1],
- $this->t0[$state[2] & 0xFF000000] ^ $this->t1[$state[3] & 0x00FF0000] ^ $this->t2[$state[0] & 0x0000FF00] ^ $this->t3[$state[1] & 0x000000FF] ^ $this->w[$round][2],
- $this->t0[$state[3] & 0xFF000000] ^ $this->t1[$state[0] & 0x00FF0000] ^ $this->t2[$state[1] & 0x0000FF00] ^ $this->t3[$state[2] & 0x000000FF] ^ $this->w[$round][3]
- );
-
- }
-
- // subWord
- $state = array(
- $this->_sub_word($state[0]),
- $this->_sub_word($state[1]),
- $this->_sub_word($state[2]),
- $this->_sub_word($state[3])
- );
-
- // shiftRows + addRoundKey
- $state = array(
- ($state[0] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[3] & 0x000000FF) ^ $this->w[$this->Nr][0],
- ($state[1] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[0] & 0x000000FF) ^ $this->w[$this->Nr][1],
- ($state[2] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[1] & 0x000000FF) ^ $this->w[$this->Nr][2],
- ($state[3] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[2] & 0x000000FF) ^ $this->w[$this->Nr][3]
- );
-
- return pack('N*', $state[0], $state[1], $state[2], $state[3]);
- }
-
- /**
- * Decrypts a block
- *
- * Optimized over rijndael's implementation by means of loop unrolling.
- *
- * @see rijndael::_decrypt_block()
- * @access private
- * @param String $in
- * @return String
- */
- function _decrypt_block($in)
- {
- // unpack starts it's indices at 1 - not 0.
- $state = unpack('N*', $in);
-
- // addRoundKey and reindex $state
- $state = array(
- $state[1] ^ $this->dw[$this->Nr][0],
- $state[2] ^ $this->dw[$this->Nr][1],
- $state[3] ^ $this->dw[$this->Nr][2],
- $state[4] ^ $this->dw[$this->Nr][3]
- );
-
- // invShiftRows + invSubBytes + invMixColumns + addRoundKey
- for ($round = $this->Nr - 1; $round > 0; $round--)
- {
- $state = array(
- $this->dt0[$state[0] & 0xFF000000] ^ $this->dt1[$state[3] & 0x00FF0000] ^ $this->dt2[$state[2] & 0x0000FF00] ^ $this->dt3[$state[1] & 0x000000FF] ^ $this->dw[$round][0],
- $this->dt0[$state[1] & 0xFF000000] ^ $this->dt1[$state[0] & 0x00FF0000] ^ $this->dt2[$state[3] & 0x0000FF00] ^ $this->dt3[$state[2] & 0x000000FF] ^ $this->dw[$round][1],
- $this->dt0[$state[2] & 0xFF000000] ^ $this->dt1[$state[1] & 0x00FF0000] ^ $this->dt2[$state[0] & 0x0000FF00] ^ $this->dt3[$state[3] & 0x000000FF] ^ $this->dw[$round][2],
- $this->dt0[$state[3] & 0xFF000000] ^ $this->dt1[$state[2] & 0x00FF0000] ^ $this->dt2[$state[1] & 0x0000FF00] ^ $this->dt3[$state[0] & 0x000000FF] ^ $this->dw[$round][3]
- );
- }
-
- // invShiftRows + invSubWord + addRoundKey
- $state = array(
- $this->_inv_sub_word(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $this->dw[0][0],
- $this->_inv_sub_word(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $this->dw[0][1],
- $this->_inv_sub_word(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $this->dw[0][2],
- $this->_inv_sub_word(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $this->dw[0][3]
- );
-
- return pack('N*', $state[0], $state[1], $state[2], $state[3]);
- }
-}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/biginteger.php b/phpBB/includes/libraries/sftp/biginteger.php deleted file mode 100644 index d9b90dacb8..0000000000 --- a/phpBB/includes/libraries/sftp/biginteger.php +++ /dev/null @@ -1,2162 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP arbitrary precission integer arithmetic library
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access private
- * @see biginteger::_sliding_window()
- */
-/**
- * @see biginteger::_montgomery()
- * @see biginteger::_undo_montgomery()
- */
-define('MATH_BIGINTEGER_MONTGOMERY', 0);
-/**
- * @see biginteger::_barrett()
- */
-define('MATH_BIGINTEGER_BARRETT', 1);
-/**
- * @see biginteger::_mod2()
- */
-define('MATH_BIGINTEGER_POWEROF2', 2);
-/**
- * @see biginteger::_remainder()
- */
-define('MATH_BIGINTEGER_CLASSIC', 3);
-/**
- * @see biginteger::_copy()
- */
-define('MATH_BIGINTEGER_NONE', 4);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see biginteger::_montgomery()
- * @see biginteger::_barrett()
- */
-/**
- * $cache[MATH_BIGINTEGER_VARIABLE] tells us whether or not the cached data is still valid.
- */
-define('MATH_BIGINTEGER_VARIABLE', 0);
-/**
- * $cache[MATH_BIGINTEGER_DATA] contains the cached data.
- */
-define('MATH_BIGINTEGER_DATA', 1);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see biginteger::biginteger()
- */
-/**
- * To use the pure-PHP implementation
- */
-define('MATH_BIGINTEGER_MODE_INTERNAL', 1);
-/**
- * To use the BCMath library
- *
- * (if enabled; otherwise, the internal implementation will be used)
- */
-define('MATH_BIGINTEGER_MODE_BCMATH', 2);
-/**
- * To use the GMP library
- *
- * (if present; otherwise, either the BCMath or the internal implementation will be used)
- */
-define('MATH_BIGINTEGER_MODE_GMP', 3);
-/**#@-*/
-
-/**
- * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
- * numbers.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 1.0.0RC3
- * @access public
- * @package biginteger
- */
-class biginteger
-{
- /**
- * Holds the BigInteger's value.
- *
- * @var Array
- * @access private
- */
- var $value;
-
- /**
- * Holds the BigInteger's magnitude.
- *
- * @var Boolean
- * @access private
- */
- var $is_negative = false;
-
- /**
- * Converts base-2, base-10, base-16, and binary strings (eg. base-256) to BigIntegers.
- *
- * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
- * two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
- *
- * @param optional $x base-10 number or base-$base number if $base set.
- * @param optional integer $base
- * @return biginteger
- * @access public
- */
- function __construct($x = 0, $base = 10)
- {
- if ( !defined('MATH_BIGINTEGER_MODE') )
- {
- switch (true)
- {
- case extension_loaded('gmp'):
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
- break;
- case extension_loaded('bcmath'):
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH);
- break;
- default:
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL);
- }
- }
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $this->value = gmp_init(0);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $this->value = '0';
- break;
- default:
- $this->value = array();
- }
-
- if ($x === 0)
- {
- return;
- }
-
- switch ($base)
- {
- case -256:
- if (ord($x[0]) & 0x80)
- {
- $x = ~$x;
- $this->is_negative = true;
- }
- case 256:
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = unpack('H*hex', $x);
- $sign = $this->is_negative ? '-' : '';
- $this->value = gmp_init($sign . '0x' . $temp['hex']);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- // round $len to the nearest 4 (thanks, DavidMJ!)
- $len = (strlen($x) + 3) & 0xFFFFFFFC;
-
- $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);
-
- for ($i = 0; $i < $len; $i+= 4) {
- $this->value = bcmul($this->value, '4294967296'); // 4294967296 == 2**32
- $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])));
- }
-
- if ($this->is_negative) {
- $this->value = '-' . $this->value;
- }
-
- break;
- // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
- case MATH_BIGINTEGER_MODE_INTERNAL:
- while (strlen($x))
- {
- $this->value[] = $this->_bytes2int($this->_base256_rshift($x, 26));
- }
- }
-
- if ($this->is_negative)
- {
- if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL)
- {
- $this->is_negative = false;
- }
- $temp = $this->add(new biginteger('-1'));
- $this->value = $temp->value;
- }
- break;
- case 16:
- case -16:
- if ($base > 0 && $x[0] == '-')
- {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
-
- $is_negative = false;
- if ($base < 0 && hexdec($x[0]) >= 8)
- {
- $this->is_negative = $is_negative = true;
- $x = bin2hex(~pack('H*', $x));
- }
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
- $this->value = gmp_init($temp);
- $this->is_negative = false;
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
- $temp = new biginteger(pack('H*', $x), 256);
- $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
- $this->is_negative = false;
- break;
- case MATH_BIGINTEGER_MODE_INTERNAL:
- $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
- $temp = new biginteger(pack('H*', $x), 256);
- $this->value = $temp->value;
- }
-
- if ($is_negative)
- {
- $temp = $this->add(new biginteger('-1'));
- $this->value = $temp->value;
- }
- break;
- case 10:
- case -10:
- $x = preg_replace('#^(-?[0-9]*).*#', '$1', $x);
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $this->value = gmp_init($x);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
- // results then doing it on '-1' does (modInverse does $x[0])
- $this->value = (string) $x;
- break;
- case MATH_BIGINTEGER_MODE_INTERNAL:
- $temp = new biginteger();
-
- // array(10000000) is 10**7 in base-2**26. 10**7 is the closest to 2**26 we can get without passing it.
- $multiplier = new biginteger();
- $multiplier->value = array(10000000);
-
- if ($x[0] == '-')
- {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = str_pad($x, strlen($x) + (6 * strlen($x)) % 7, 0, STR_PAD_LEFT);
-
- while (strlen($x))
- {
- $temp = $temp->multiply($multiplier);
- $temp = $temp->add(new biginteger($this->_int2bytes(substr($x, 0, 7)), 256));
- $x = substr($x, 7);
- }
-
- $this->value = $temp->value;
- }
- break;
- case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
- case -2:
- if ($base > 0 && $x[0] == '-')
- {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = preg_replace('#^([01]*).*#', '$1', $x);
- $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
-
- $str = '0x';
- while (strlen($x))
- {
- $part = substr($x, 0, 4);
- $str.= dechex(bindec($part));
- $x = substr($x, 4);
- }
-
- if ($this->is_negative)
- {
- $str = '-' . $str;
- }
-
- $temp = new biginteger($str, 8 * $base); // ie. either -16 or +16
- $this->value = $temp->value;
- $this->is_negative = $temp->is_negative;
-
- break;
- default:
- // base not supported, so we'll let $this == 0
- }
- }
-
- /**
- * Converts a BigInteger to a byte string (eg. base-256).
- *
- * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
- * saved as two's compliment.
- *
- * @param Boolean $twos_compliment
- * @return String
- * @access public
- * @internal Converts a base-2**26 number to base-2**8
- */
- function to_bytes($twos_compliment = false)
- {
- if ($twos_compliment)
- {
- $comparison = $this->compare(new biginteger());
- if ($comparison == 0)
- {
- return '';
- }
-
- $temp = $comparison < 0 ? $this->add(new biginteger(1)) : $this->_copy();
- $bytes = $temp->to_bytes();
-
- if (empty($bytes)) // eg. if the number we're trying to convert is -1
- {
- $bytes = chr(0);
- }
-
- if (ord($bytes[0]) & 0x80)
- {
- $bytes = chr(0) . $bytes;
- }
-
- return $comparison < 0 ? ~$bytes : $bytes;
- }
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- if (gmp_cmp($this->value, gmp_init(0)) == 0)
- {
- return '';
- }
-
- $temp = gmp_strval(gmp_abs($this->value), 16);
- $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp;
-
- return ltrim(pack('H*', $temp), chr(0));
- case MATH_BIGINTEGER_MODE_BCMATH:
- if ($this->value === '0')
- {
- return '';
- }
-
- $value = '';
- $current = $this->value;
-
- if ($current[0] == '-')
- {
- $current = substr($current, 1);
- }
-
- // we don't do four bytes at a time because then numbers larger than 1<<31 would be negative
- // two's complimented numbers, which would break chr.
- while (bccomp($current, '0') > 0)
- {
- $temp = bcmod($current, 0x1000000);
- $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
- $current = bcdiv($current, 0x1000000);
- }
-
- return ltrim($value, chr(0));
- }
-
- if (!count($this->value))
- {
- return '';
- }
-
- $result = $this->_int2bytes($this->value[count($this->value) - 1]);
-
- $temp = $this->_copy();
-
- for ($i = count($temp->value) - 2; $i >= 0; $i--)
- {
- $temp->_base256_lshift($result, 26);
- $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
- }
-
- return $result;
- }
-
- /**
- * Converts a BigInteger to a base-10 number.
- *
- * @return String
- * @access public
- * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
- */
- function to_string()
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- return gmp_strval($this->value);
- case MATH_BIGINTEGER_MODE_BCMATH:
- if ($this->value === '0')
- {
- return '0';
- }
-
- return ltrim($this->value, '0');
- }
-
- if (!count($this->value))
- {
- return '0';
- }
-
- $temp = $this->_copy();
- $temp->is_negative = false;
-
- $divisor = new biginteger();
- $divisor->value = array(10000000); // eg. 10**7
- while (count($temp->value))
- {
- list($temp, $mod) = $temp->divide($divisor);
- $result = str_pad($this->_bytes2int($mod->to_bytes()), 7, '0', STR_PAD_LEFT) . $result;
- }
- $result = ltrim($result, '0');
-
- if ($this->is_negative)
- {
- $result = '-' . $result;
- }
-
- return $result;
- }
-
- /**
- * __toString() magic method
- *
- * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
- * toString().
- *
- * @access public
- * @internal Implemented per a suggestion by Techie-Michael - thanks!
- */
- function __toString()
- {
- return $this->to_string();
- }
-
- /**
- * Adds two BigIntegers.
- *
- * @param biginteger $y
- * @return biginteger
- * @access public
- * @internal Performs base-2**52 addition
- */
- function add($y)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_add($this->value, $y->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new biginteger();
- $temp->value = bcadd($this->value, $y->value);
-
- return $temp;
- }
-
- // subtract, if appropriate
- if ( $this->is_negative != $y->is_negative )
- {
- // is $y the negative number?
- $y_negative = $this->compare($y) > 0;
-
- $temp = $this->_copy();
- $y = $y->_copy();
- $temp->is_negative = $y->is_negative = false;
-
- $diff = $temp->compare($y);
- if ( !$diff )
- {
- return new biginteger();
- }
-
- $temp = $temp->subtract($y);
-
- $temp->is_negative = ($diff > 0) ? !$y_negative : $y_negative;
-
- return $temp;
- }
-
- $result = new biginteger();
- $carry = 0;
-
- $size = max(count($this->value), count($y->value));
- $size+= $size & 1; // rounds $size to the nearest 2.
-
- $x = array_pad($this->value, $size,0);
- $y = array_pad($y->value, $size, 0);
-
- for ($i = 0; $i < $size - 1; $i+=2)
- {
- $sum = $x[$i + 1] * 0x4000000 + $x[$i] + $y[$i + 1] * 0x4000000 + $y[$i] + $carry;
- $carry = $sum >= 4503599627370496; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
- $sum = $carry ? $sum - 4503599627370496 : $sum;
-
- $temp = floor($sum / 0x4000000);
-
- $result->value[] = $sum - 0x4000000 * $temp; // eg. a faster alternative to fmod($sum, 0x4000000)
- $result->value[] = $temp;
- }
-
- if ($carry)
- {
- $result->value[] = $carry;
- }
-
- $result->is_negative = $this->is_negative;
-
- return $result->_normalize();
- }
-
- /**
- * Subtracts two BigIntegers.
- *
- * @param biginteger $y
- * @return biginteger
- * @access public
- * @internal Performs base-2**52 subtraction
- */
- function subtract($y)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_sub($this->value, $y->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new biginteger();
- $temp->value = bcsub($this->value, $y->value);
-
- return $temp;
- }
-
- // add, if appropriate
- if ( $this->is_negative != $y->is_negative )
- {
- $is_negative = $y->compare($this) > 0;
-
- $temp = $this->_copy();
- $y = $y->_copy();
- $temp->is_negative = $y->is_negative = false;
-
- $temp = $temp->add($y);
-
- $temp->is_negative = $is_negative;
-
- return $temp;
- }
-
- $diff = $this->compare($y);
-
- if ( !$diff )
- {
- return new biginteger();
- }
-
- // switch $this and $y around, if appropriate.
- if ( (!$this->is_negative && $diff < 0) || ($this->is_negative && $diff > 0) )
- {
- $is_negative = $y->is_negative;
-
- $temp = $this->_copy();
- $y = $y->_copy();
- $temp->is_negative = $y->is_negative = false;
-
- $temp = $y->subtract($temp);
- $temp->is_negative = !$is_negative;
-
- return $temp;
- }
-
- $result = new biginteger();
- $carry = 0;
-
- $size = max(count($this->value), count($y->value));
- $size+= $size % 2;
-
- $x = array_pad($this->value, $size, 0);
- $y = array_pad($y->value, $size, 0);
-
- for ($i = 0; $i < $size - 1; $i+=2)
- {
- $sum = $x[$i + 1] * 0x4000000 + $x[$i] - $y[$i + 1] * 0x4000000 - $y[$i] + $carry;
- $carry = $sum < 0 ? -1 : 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
- $sum = $carry ? $sum + 4503599627370496 : $sum;
-
- $temp = floor($sum / 0x4000000);
-
- $result->value[] = $sum - 0x4000000 * $temp;
- $result->value[] = $temp;
- }
-
- // $carry shouldn't be anything other than zero, at this point, since we already made sure that $this
- // was bigger than $y.
-
- $result->is_negative = $this->is_negative;
-
- return $result->_normalize();
- }
-
- /**
- * Multiplies two BigIntegers
- *
- * @param biginteger $x
- * @return biginteger
- * @access public
- * @internal Modeled after 'multiply' in MutableBigInteger.java.
- */
- function multiply($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_mul($this->value, $x->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new biginteger();
- $temp->value = bcmul($this->value, $x->value);
-
- return $temp;
- }
-
- if ( !$this->compare($x) )
- {
- return $this->_square();
- }
-
- $this_length = count($this->value);
- $x_length = count($x->value);
-
- if ( !$this_length || !$x_length ) // a 0 is being multiplied
- {
- return new biginteger();
- }
-
- $product = new biginteger();
- $product->value = $this->_array_repeat(0, $this_length + $x_length);
-
- // the following for loop could be removed if the for loop following it
- // (the one with nested for loops) initially set $i to 0, but
- // doing so would also make the result in one set of unnecessary adds,
- // since on the outermost loops first pass, $product->value[$k] is going
- // to always be 0
-
- $carry = 0;
- $i = 0;
-
- for ($j = 0, $k = $i; $j < $this_length; $j++, $k++)
- {
- $temp = $product->value[$k] + $this->value[$j] * $x->value[$i] + $carry;
- $carry = floor($temp / 0x4000000);
- $product->value[$k] = $temp - 0x4000000 * $carry;
- }
-
- $product->value[$k] = $carry;
-
- // the above for loop is what the previous comment was talking about. the
- // following for loop is the "one with nested for loops"
-
- for ($i = 1; $i < $x_length; $i++)
- {
- $carry = 0;
-
- for ($j = 0, $k = $i; $j < $this_length; $j++, $k++)
- {
- $temp = $product->value[$k] + $this->value[$j] * $x->value[$i] + $carry;
- $carry = floor($temp / 0x4000000);
- $product->value[$k] = $temp - 0x4000000 * $carry;
- }
-
- $product->value[$k] = $carry;
- }
-
- $product->is_negative = $this->is_negative != $x->is_negative;
-
- return $product->_normalize();
- }
-
- /**
- * Squares a BigInteger
- *
- * Squaring can be done faster than multiplying a number by itself can be. See
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
- *
- * @return biginteger
- * @access private
- */
- function _square()
- {
- if ( empty($this->value) )
- {
- return new biginteger();
- }
-
- $max_index = count($this->value) - 1;
-
- $square = new biginteger();
- $square->value = $this->_array_repeat(0, 2 * $max_index);
-
- for ($i = 0; $i <= $max_index; $i++)
- {
- $temp = $square->value[2 * $i] + $this->value[$i] * $this->value[$i];
- $carry = floor($temp / 0x4000000);
- $square->value[2 * $i] = $temp - 0x4000000 * $carry;
-
- // note how we start from $i+1 instead of 0 as we do in multiplication.
- for ($j = $i + 1; $j <= $max_index; $j++)
- {
- $temp = $square->value[$i + $j] + 2 * $this->value[$j] * $this->value[$i] + $carry;
- $carry = floor($temp / 0x4000000);
- $square->value[$i + $j] = $temp - 0x4000000 * $carry;
- }
-
- // the following line can yield values larger 2**15. at this point, PHP should switch
- // over to floats.
- $square->value[$i + $max_index + 1] = $carry;
- }
-
- return $square->_normalize();
- }
-
- /**
- * Divides two BigIntegers.
- *
- * Returns an array whose first element contains the quotient and whose second element contains the
- * "common residue". If the remainder would be positive, the "common residue" and the remainder are the
- * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder
- * and the divisor (basically, the "common residue" is the first positive modulo).
- *
- * @param biginteger $y
- * @return Array
- * @access public
- * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}
- * with a slight variation due to the fact that this script, initially, did not support negative numbers. Now,
- * it does, but I don't want to change that which already works.
- */
- function divide($y)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $quotient = new biginteger();
- $remainder = new biginteger();
-
- list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
-
- if (gmp_sign($remainder->value) < 0)
- {
- $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
- }
-
- return array($quotient, $remainder);
- case MATH_BIGINTEGER_MODE_BCMATH:
- $quotient = new biginteger();
- $remainder = new biginteger();
-
- $quotient->value = bcdiv($this->value, $y->value);
- $remainder->value = bcmod($this->value, $y->value);
-
- if ($remainder->value[0] == '-')
- {
- $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value);
- }
-
- return array($quotient, $remainder);
- }
-
- $x = $this->_copy();
- $y = $y->_copy();
-
- $x_sign = $x->is_negative;
- $y_sign = $y->is_negative;
-
- $x->is_negative = $y->is_negative = false;
-
- $diff = $x->compare($y);
-
- if ( !$diff )
- {
- $temp = new biginteger();
- $temp->value = array(1);
- $temp->is_negative = $x_sign != $y_sign;
- return array($temp, new biginteger());
- }
-
- if ( $diff < 0 )
- {
- // if $x is negative, "add" $y.
- if ( $x_sign )
- {
- $x = $y->subtract($x);
- }
- return array(new biginteger(), $x);
- }
-
- // normalize $x and $y as described in HAC 14.23 / 14.24
- // (incidently, i haven't been able to find a definitive example showing that this
- // results in worth-while speedup, but whatever)
- $msb = $y->value[count($y->value) - 1];
- for ($shift = 0; !($msb & 0x2000000); $shift++)
- {
- $msb <<= 1;
- }
- $x->_lshift($shift);
- $y->_lshift($shift);
-
- $x_max = count($x->value) - 1;
- $y_max = count($y->value) - 1;
-
- $quotient = new biginteger();
- $quotient->value = $this->_array_repeat(0, $x_max - $y_max + 1);
-
- // $temp = $y << ($x_max - $y_max-1) in base 2**26
- $temp = new biginteger();
- $temp->value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y->value);
-
- while ( $x->compare($temp) >= 0 )
- {
- // calculate the "common residue"
- $quotient->value[$x_max - $y_max]++;
- $x = $x->subtract($temp);
- $x_max = count($x->value) - 1;
- }
-
- for ($i = $x_max; $i >= $y_max + 1; $i--)
- {
- $x_value = array(
- $x->value[$i],
- ( $i > 0 ) ? $x->value[$i - 1] : 0,
- ( $i - 1 > 0 ) ? $x->value[$i - 2] : 0
- );
- $y_value = array(
- $y->value[$y_max],
- ( $y_max > 0 ) ? $y_max - 1 : 0
- );
-
-
- $q_index = $i - $y_max - 1;
- if ($x_value[0] == $y_value[0])
- {
- $quotient->value[$q_index] = 0x3FFFFFF;
- }
- else
- {
- $quotient->value[$q_index] = floor(
- ($x_value[0] * 0x4000000 + $x_value[1])
- /
- $y_value[0]
- );
- }
-
- $temp = new biginteger();
- $temp->value = array($y_value[1], $y_value[0]);
-
- $lhs = new biginteger();
- $lhs->value = array($quotient->value[$q_index]);
- $lhs = $lhs->multiply($temp);
-
- $rhs = new biginteger();
- $rhs->value = array($x_value[2], $x_value[1], $x_value[0]);
-
- while ( $lhs->compare($rhs) > 0 )
- {
- $quotient->value[$q_index]--;
-
- $lhs = new biginteger();
- $lhs->value = array($quotient->value[$q_index]);
- $lhs = $lhs->multiply($temp);
- }
-
- $corrector = new biginteger();
- $temp = new biginteger();
- $corrector->value = $temp->value = $this->_array_repeat(0, $q_index);
- $temp->value[] = $quotient->value[$q_index];
-
- $temp = $temp->multiply($y);
-
- if ( $x->compare($temp) < 0 )
- {
- $corrector->value[] = 1;
- $x = $x->add($corrector->multiply($y));
- $quotient->value[$q_index]--;
- }
-
- $x = $x->subtract($temp);
- $x_max = count($x->value) - 1;
- }
-
- // unnormalize the remainder
- $x->_rshift($shift);
-
- $quotient->is_negative = $x_sign != $y_sign;
-
- // calculate the "common residue", if appropriate
- if ( $x_sign )
- {
- $y->_rshift($shift);
- $x = $y->subtract($x);
- }
-
- return array($quotient->_normalize(), $x);
- }
-
- /**
- * Performs modular exponentiation.
- *
- * @param biginteger $e
- * @param biginteger $n
- * @return biginteger
- * @access public
- * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and
- * and although the approach involving repeated squaring does vastly better, it, too, is impractical
- * for our purposes. The reason being that division - by far the most complicated and time-consuming
- * of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
- *
- * Modular reductions resolve this issue. Although an individual modular reduction takes more time
- * then an individual division, when performed in succession (with the same modulo), they're a lot faster.
- *
- * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction,
- * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the
- * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
- * the product of two odd numbers is odd), but what about when RSA isn't used?
- *
- * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a
- * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the
- * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however,
- * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
- * the other, a power of two - and recombine them, later. This is the method that this modPow function uses.
- * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
- */
- function mod_pow($e, $n)
- {
- $n = $n->abs();
- if ($e->compare(new biginteger()) < 0)
- {
- $e = $e->abs();
-
- $temp = $this->modInverse($n);
- if ($temp === false)
- {
- return false;
- }
-
- return $temp->modPow($e, $n);
- }
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_powm($this->value, $e->value, $n->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new biginteger();
- $temp->value = bcpowmod($this->value, $e->value, $n->value);
-
- return $temp;
- }
-
- if ( empty($e->value) )
- {
- $temp = new biginteger();
- $temp->value = array(1);
- return $temp;
- }
-
- if ( $e->value == array(1) )
- {
- list(, $temp) = $this->divide($n);
- return $temp;
- }
-
- if ( $e->value == array(2) )
- {
- $temp = $this->_square();
- list(, $temp) = $temp->divide($n);
- return $temp;
- }
-
- // is the modulo odd?
- if ( $n->value[0] & 1 )
- {
- return $this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY);
- }
- // if it's not, it's even
-
- // find the lowest set bit (eg. the max pow of 2 that divides $n)
- for ($i = 0; $i < count($n->value); $i++)
- {
- if ( $n->value[$i] )
- {
- $temp = decbin($n->value[$i]);
- $j = strlen($temp) - strrpos($temp, '1') - 1;
- $j+= 26 * $i;
- break;
- }
- }
- // at this point, 2^$j * $n/(2^$j) == $n
-
- $mod1 = $n->_copy();
- $mod1->_rshift($j);
- $mod2 = new biginteger();
- $mod2->value = array(1);
- $mod2->_lshift($j);
-
- $part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new biginteger();
- $part2 = $this->_sliding_window($e, $mod2, MATH_BIGINTEGER_POWEROF2);
-
- $y1 = $mod2->mod_inverse($mod1);
- $y2 = $mod1->mod_inverse($mod2);
-
- $result = $part1->multiply($mod2);
- $result = $result->multiply($y1);
-
- $temp = $part2->multiply($mod1);
- $temp = $temp->multiply($y2);
-
- $result = $result->add($temp);
- list(, $result) = $result->divide($n);
-
- return $result;
- }
-
- /**
- * Sliding Window k-ary Modular Exponentiation
- *
- * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims,
- * however, this function performs a modular reduction after every multiplication and squaring operation.
- * As such, this function has the same preconditions that the reductions being used do.
- *
- * @param biginteger $e
- * @param biginteger $n
- * @param Integer $mode
- * @return biginteger
- * @access private
- */
- function _sliding_window($e, $n, $mode)
- {
- static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function
- //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1
-
- $e_length = count($e->value) - 1;
- $e_bits = decbin($e->value[$e_length]);
- for ($i = $e_length - 1; $i >= 0; $i--)
- {
- $e_bits.= str_pad(decbin($e->value[$i]), 26, '0', STR_PAD_LEFT);
- }
- $e_length = strlen($e_bits);
-
- // calculate the appropriate window size.
- // $window_size == 3 if $window_ranges is between 25 and 81, for example.
- for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); $window_size++, $i++);
-
- switch ($mode)
- {
- case MATH_BIGINTEGER_MONTGOMERY:
- $reduce = '_montgomery';
- $undo = '_undo_montgomery';
- break;
- case MATH_BIGINTEGER_BARRETT:
- $reduce = '_barrett';
- $undo = '_barrett';
- break;
- case MATH_BIGINTEGER_POWEROF2:
- $reduce = '_mod2';
- $undo = '_mod2';
- break;
- case MATH_BIGINTEGER_CLASSIC:
- $reduce = '_remainder';
- $undo = '_remainder';
- break;
- case MATH_BIGINTEGER_NONE:
- // ie. do no modular reduction. useful if you want to just do pow as opposed to modPow.
- $reduce = '_copy';
- $undo = '_copy';
- break;
- default:
- // an invalid $mode was provided
- }
-
- // precompute $this^0 through $this^$window_size
- $powers = array();
- $powers[1] = $this->$undo($n);
- $powers[2] = $powers[1]->_square();
- $powers[2] = $powers[2]->$reduce($n);
-
- // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end
- // in a 1. ie. it's supposed to be odd.
- $temp = 1 << ($window_size - 1);
- for ($i = 1; $i < $temp; $i++)
- {
- $powers[2 * $i + 1] = $powers[2 * $i - 1]->multiply($powers[2]);
- $powers[2 * $i + 1] = $powers[2 * $i + 1]->$reduce($n);
- }
-
- $result = new biginteger();
- $result->value = array(1);
- $result = $result->$undo($n);
-
- for ($i = 0; $i < $e_length; )
- {
- if ( !$e_bits[$i] )
- {
- $result = $result->_square();
- $result = $result->$reduce($n);
- $i++;
- }
- else
- {
- for ($j = $window_size - 1; $j >= 0; $j--)
- {
- if ( $e_bits[$i + $j] )
- {
- break;
- }
- }
-
- for ($k = 0; $k <= $j; $k++) // eg. the length of substr($e_bits, $i, $j+1)
- {
- $result = $result->_square();
- $result = $result->$reduce($n);
- }
-
- $result = $result->multiply($powers[bindec(substr($e_bits, $i, $j + 1))]);
- $result = $result->$reduce($n);
-
- $i+=$j + 1;
- }
- }
-
- $result = $result->$reduce($n);
- return $result->_normalize();
- }
-
- /**
- * Remainder
- *
- * A wrapper for the divide function.
- *
- * @see divide()
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _remainder($n)
- {
- list(, $temp) = $this->divide($n);
- return $temp;
- }
-
- /**
- * Modulos for Powers of Two
- *
- * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1),
- * we'll just use this function as a wrapper for doing that.
- *
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _mod2($n)
- {
- $temp = new biginteger();
- $temp->value = array(1);
- return $this->bitwise_and($n->subtract($temp));
- }
-
- /**
- * Barrett Modular Reduction
- *
- * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly,
- * so as not to require negative numbers (initially, this script didn't support negative numbers).
- *
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _barrett($n)
- {
- static $cache;
-
- $n_length = count($n->value);
-
- if ( !isset($cache[MATH_BIGINTEGER_VARIABLE]) || $n->compare($cache[MATH_BIGINTEGER_VARIABLE]) )
- {
- $cache[MATH_BIGINTEGER_VARIABLE] = $n;
- $temp = new biginteger();
- $temp->value = $this->_array_repeat(0, 2 * $n_length);
- $temp->value[] = 1;
- list($cache[MATH_BIGINTEGER_DATA], ) = $temp->divide($n);
- }
-
- $temp = new biginteger();
- $temp->value = array_slice($this->value, $n_length - 1);
- $temp = $temp->multiply($cache[MATH_BIGINTEGER_DATA]);
- $temp->value = array_slice($temp->value, $n_length + 1);
-
- $result = new biginteger();
- $result->value = array_slice($this->value, 0, $n_length + 1);
- $temp = $temp->multiply($n);
- $temp->value = array_slice($temp->value, 0, $n_length + 1);
-
- if ($result->compare($temp) < 0)
- {
- $corrector = new biginteger();
- $corrector->value = $this->_array_repeat(0, $n_length + 1);
- $corrector->value[] = 1;
- $result = $result->add($corrector);
- }
-
- $result = $result->subtract($temp);
- while ($result->compare($n) > 0)
- {
- $result = $result->subtract($n);
- }
-
- return $result;
- }
-
- /**
- * Montgomery Modular Reduction
- *
- * ($this->_montgomery($n))->_undoMontgomery($n) yields $x%$n.
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be
- * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function
- * to work correctly.
- *
- * @see _undoMontgomery()
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _montgomery($n)
- {
- static $cache;
-
- if ( !isset($cache[MATH_BIGINTEGER_VARIABLE]) || $n->compare($cache[MATH_BIGINTEGER_VARIABLE]) )
- {
- $cache[MATH_BIGINTEGER_VARIABLE] = $n;
- $cache[MATH_BIGINTEGER_DATA] = $n->_mod_inverse67108864();
- }
-
- $result = $this->_copy();
-
- $n_length = count($n->value);
-
- for ($i = 0; $i < $n_length; $i++)
- {
- $temp = new biginteger();
- $temp->value = array(
- ($result->value[$i] * $cache[MATH_BIGINTEGER_DATA]) & 0x3FFFFFF
- );
- $temp = $temp->multiply($n);
- $temp->value = array_merge($this->_array_repeat(0, $i), $temp->value);
- $result = $result->add($temp);
- }
-
- $result->value = array_slice($result->value, $n_length);
-
- if ($result->compare($n) >= 0)
- {
- $result = $result->subtract($n);
- }
-
- return $result->_normalize();
- }
-
- /**
- * Undo Montgomery Modular Reduction
- *
- * @see _montgomery()
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _undo_montgomery($n)
- {
- $temp = new biginteger();
- $temp->value = array_merge($this->_array_repeat(0, count($n->value)), $this->value);
- list(, $temp) = $temp->divide($n);
- return $temp->_normalize();
- }
-
- /**
- * Modular Inverse of a number mod 2**26 (eg. 67108864)
- *
- * Based off of the bnpInvDigit function implemented and justified in the following URL:
- *
- * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
- *
- * The following URL provides more info:
- *
- * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
- *
- * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For
- * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
- * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
- * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that
- * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the
- * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to
- * 40 bits, which only 64-bit floating points will support.
- *
- * Thanks to Pedro Gimeno Fortea for input!
- *
- * @see _montgomery()
- * @access private
- * @return Integer
- */
- function _mod_inverse67108864() // 2**26 == 67108864
- {
- $x = -$this->value[0];
- $result = $x & 0x3; // x**-1 mod 2**2
- $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
- $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8
- $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
- $result = fmod($result * (2 - fmod($x * $result, 0x4000000)), 0x4000000); // x**-1 mod 2**26
- return $result & 0x3FFFFFF;
- }
-
- /**
- * Calculates modular inverses.
- *
- * @param biginteger $n
- * @return mixed false, if no modular inverse exists, biginteger, otherwise.
- * @access public
- * @internal Calculates the modular inverse of $this mod $n using the binary xGCD algorithim described in
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes,
- * the more traditional algorithim requires "relatively costly multiple-precision divisions". See
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
- */
- function mod_inverse($n)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_invert($this->value, $n->value);
-
- return ( $temp->value === false ) ? false : $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
- // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is,
- // the basic extended euclidean algorithim is what we're using.
-
- // if $x is less than 0, the first character of $x is a '-', so we'll remove it. we can do this because
- // $x mod $n == $x mod -$n.
- $n = (bccomp($n->value, '0') < 0) ? substr($n->value, 1) : $n->value;
-
- if (bccomp($this->value,'0') < 0)
- {
- $negated_this = new biginteger();
- $negated_this->value = substr($this->value, 1);
-
- $temp = $negated_this->mod_inverse(new biginteger($n));
-
- if ($temp === false)
- {
- return false;
- }
-
- $temp->value = bcsub($n, $temp->value);
-
- return $temp;
- }
-
- $u = $this->value;
- $v = $n;
-
- $a = '1';
- $c = '0';
-
- while (true)
- {
- $q = bcdiv($u, $v);
- $temp = $u;
- $u = $v;
- $v = bcsub($temp, bcmul($v, $q));
-
- if (bccomp($v, '0') == 0) {
- break;
- }
-
- $temp = $a;
- $a = $c;
- $c = bcsub($temp, bcmul($c, $q));
- }
-
- $temp = new biginteger();
- $temp->value = (bccomp($c, '0') < 0) ? bcadd($c, $n) : $c;
-
- // $u contains the gcd of $this and $n
- return (bccomp($u,'1') == 0) ? $temp : false;
- }
-
- // if $this and $n are even, return false.
- if ( !($this->value[0]&1) && !($n->value[0]&1) )
- {
- return false;
- }
-
- $n = $n->_copy();
- $n->is_negative = false;
-
- if ($this->compare(new biginteger()) < 0)
- {
- // is_negative is currently true. since we need it to be false, we'll just set it to false, temporarily,
- // and reset it as true, later.
- $this->is_negative = false;
-
- $temp = $this->mod_inverse($n);
-
- if ($temp === false)
- {
- return false;
- }
-
- $temp = $n->subtract($temp);
-
- $this->is_negative = true;
-
- return $temp;
- }
-
- $u = $n->_copy();
- $x = $this;
- //list(, $x) = $this->divide($n);
- $v = $x->_copy();
-
- $a = new biginteger();
- $b = new biginteger();
- $c = new biginteger();
- $d = new biginteger();
-
- $a->value = $d->value = array(1);
-
- while ( !empty($u->value) )
- {
- while ( !($u->value[0] & 1) )
- {
- $u->_rshift(1);
- if ( ($a->value[0] & 1) || ($b->value[0] & 1) )
- {
- $a = $a->add($x);
- $b = $b->subtract($n);
- }
- $a->_rshift(1);
- $b->_rshift(1);
- }
-
- while ( !($v->value[0] & 1) )
- {
- $v->_rshift(1);
- if ( ($c->value[0] & 1) || ($d->value[0] & 1) )
- {
- $c = $c->add($x);
- $d = $d->subtract($n);
- }
- $c->_rshift(1);
- $d->_rshift(1);
- }
-
- if ($u->compare($v) >= 0)
- {
- $u = $u->subtract($v);
- $a = $a->subtract($c);
- $b = $b->subtract($d);
- }
- else
- {
- $v = $v->subtract($u);
- $c = $c->subtract($a);
- $d = $d->subtract($b);
- }
-
- $u->_normalize();
- }
-
- // at this point, $v == gcd($this, $n). if it's not equal to 1, no modular inverse exists.
- if ( $v->value != array(1) )
- {
- return false;
- }
-
- $d = ($d->compare(new biginteger()) < 0) ? $d->add($n) : $d;
-
- return ($this->is_negative) ? $n->subtract($d) : $d;
- }
-
- /**
- * Absolute value.
- *
- * @return biginteger
- * @access public
- */
- function abs()
- {
- $temp = new biginteger();
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp->value = gmp_abs($this->value);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp->value = (bccomp($this->value, '0') < 0) ? substr($this->value, 1) : $this->value;
- break;
- default:
- $temp->value = $this->value;
- }
-
- return $temp;
- }
-
- /**
- * Compares two numbers.
- *
- * @param biginteger $x
- * @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal.
- * @access public
- * @internal Could return $this->sub($x), but that's not as fast as what we do do.
- */
- function compare($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- return gmp_cmp($this->value, $x->value);
- case MATH_BIGINTEGER_MODE_BCMATH:
- return bccomp($this->value, $x->value);
- }
-
- $this->_normalize();
- $x->_normalize();
-
- if ( $this->is_negative != $x->is_negative )
- {
- return ( !$this->is_negative && $x->is_negative ) ? 1 : -1;
- }
-
- $result = $this->is_negative ? -1 : 1;
-
- if ( count($this->value) != count($x->value) )
- {
- return ( count($this->value) > count($x->value) ) ? $result : -$result;
- }
-
- for ($i = count($this->value) - 1; $i >= 0; $i--)
- {
- if ($this->value[$i] != $x->value[$i])
- {
- return ( $this->value[$i] > $x->value[$i] ) ? $result : -$result;
- }
- }
-
- return 0;
- }
-
- /**
- * Returns a copy of $this
- *
- * PHP5 passes objects by reference while PHP4 passes by value. As such, we need a function to guarantee
- * that all objects are passed by value, when appropriate. More information can be found here:
- *
- * {@link http://www.php.net/manual/en/language.oop5.basic.php#51624}
- *
- * @access private
- * @return biginteger
- */
- function _copy()
- {
- $temp = new biginteger();
- $temp->value = $this->value;
- $temp->is_negative = $this->is_negative;
- return $temp;
- }
-
- /**
- * Logical And
- *
- * @param biginteger $x
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
- * @return biginteger
- */
- function bitwise_and($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_and($this->value, $x->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- return new biginteger($this->to_bytes() & $x->to_bytes(), 256);
- }
-
- $result = new biginteger();
-
- $x_length = count($x->value);
- for ($i = 0; $i < $x_length; $i++)
- {
- $result->value[] = $this->value[$i] & $x->value[$i];
- }
-
- return $result->_normalize();
- }
-
- /**
- * Logical Or
- *
- * @param biginteger $x
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
- * @return biginteger
- */
- function bitwise_or($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_or($this->value, $x->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- return new biginteger($this->to_bytes() | $x->to_bytes(), 256);
- }
-
- $result = $this->_copy();
-
- $x_length = count($x->value);
- for ($i = 0; $i < $x_length; $i++)
- {
- $result->value[$i] = $this->value[$i] | $x->value[$i];
- }
-
- return $result->_normalize();
- }
-
- /**
- * Logical Exclusive-Or
- *
- * @param biginteger $x
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
- * @return biginteger
- */
- function bitwise_xor($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_xor($this->value, $x->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- return new biginteger($this->to_bytes() ^ $x->to_bytes(), 256);
- }
-
- $result = $this->_copy();
-
- $x_length = count($x->value);
- for ($i = 0; $i < $x_length; $i++)
- {
- $result->value[$i] = $this->value[$i] ^ $x->value[$i];
- }
-
- return $result->_normalize();
- }
-
- /**
- * Logical Not
- *
- * Although integers can be converted to and from various bases with relative ease, there is one piece
- * of information that is lost during such conversions. The number of leading zeros that number had
- * or should have in any given base. Per that, if you convert 1 from decimal to binary, there's no
- * way to know just how many leading zero's there should be. In truth, there could be any number.
- *
- * Normally, the number of leading zero's is unimportant. When doing "not", however, it is. The "not"
- * of 1 on an 8-bit representation of 1 is 1111 1110. The "not" of 1 on a 16-bit representation of 1 is
- * 1111 1111 1111 1110. When doing it on a number that's preceeded by an infinite number of zero's, it's
- * infinite.
- *
- * This function assumes that there are no leading zero's - that the bit-representation being used is
- * equal to the minimum number of required bits, unless otherwise specified in the optional parameter,
- * where the optional parameter represents the bit-representation being used. If the specified
- * bit-representation is smaller than the minimum number of bits required to represent the number, the
- * latter will be used as the bit-representation.
- *
- * @param $bits Integer
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
- * @return biginteger
- */
- function bitwise_not($bits = -1)
- {
- // calculuate "not" without regard to $bits
- $temp = ~$this->to_bytes();
- $msb = decbin(ord($temp[0]));
- $msb = substr($msb, strpos($msb, '0'));
- $temp[0] = chr(bindec($msb));
-
- // see if we need to add extra leading 1's
- $current_bits = strlen($msb) + 8 * strlen($temp) - 8;
- $new_bits = $bits - $current_bits;
- if ($new_bits <= 0)
- {
- return new biginteger($temp, 256);
- }
-
- // generate as many leading 1's as we need to.
- $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3);
- $this->_base256_lshift($leading_ones, $current_bits);
-
- $temp = str_pad($temp, ceil($bits / 8), chr(0), STR_PAD_LEFT);
-
- return new biginteger($leading_ones | $temp, 256);
- }
-
- /**
- * Logical Right Shift
- *
- * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
- *
- * @param Integer $shift
- * @return biginteger
- * @access public
- * @internal The only version that yields any speed increases is the internal version.
- */
- function bitwise_right_shift($shift)
- {
- $temp = new biginteger();
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- static $two;
-
- if (empty($two))
- {
- $two = gmp_init('2');
- }
-
- $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift));
-
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp->value = bcdiv($this->value, bcpow('2', $shift));
-
- break;
- default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten
- // and I don't want to do that...
- $temp->value = $this->value;
- $temp->_rshift($shift);
- }
-
- return $temp;
- }
-
- /**
- * Logical Left Shift
- *
- * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
- *
- * @param Integer $shift
- * @return biginteger
- * @access public
- * @internal The only version that yields any speed increases is the internal version.
- */
- function bitwise_left_shift($shift)
- {
- $temp = new biginteger();
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- static $two;
-
- if (empty($two))
- {
- $two = gmp_init('2');
- }
-
- $temp->value = gmp_mul($this->value, gmp_pow($two, $shift));
-
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp->value = bcmul($this->value, bcpow('2', $shift));
-
- break;
- default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten
- // and I don't want to do that...
- $temp->value = $this->value;
- $temp->_lshift($shift);
- }
-
- return $temp;
- }
-
- /**
- * Generate a random number
- *
- * $generator should be the name of a random number generating function whose first parameter is the minimum
- * value and whose second parameter is the maximum value. If this function needs to be seeded, it should be
- * done before this function is called.
- *
- * @param optional Integer $min
- * @param optional Integer $max
- * @param optional String $generator
- * @return biginteger
- * @access public
- */
- function random($min = false, $max = false, $generator = 'mt_rand')
- {
- if ($min === false)
- {
- $min = new biginteger(0);
- }
-
- if ($max === false)
- {
- $max = new biginteger(0x7FFFFFFF);
- }
-
- $compare = $max->compare($min);
-
- if (!$compare)
- {
- return $min;
- }
- else if ($compare < 0)
- {
- // if $min is bigger then $max, swap $min and $max
- $temp = $max;
- $max = $min;
- $min = $temp;
- }
-
- $max = $max->subtract($min);
- $max = ltrim($max->to_bytes(), chr(0));
- $size = strlen($max) - 1;
- $random = '';
-
- $bytes = $size & 3;
- for ($i = 0; $i < $bytes; $i++)
- {
- $random.= chr($generator(0, 255));
- }
-
- $blocks = $size >> 2;
- for ($i = 0; $i < $blocks; $i++)
- {
- $random.= pack('N', $generator(-2147483648, 0x7FFFFFFF));
- }
-
- $temp = new biginteger($random, 256);
- if ($temp->compare(new biginteger(substr($max, 1), 256)) > 0)
- {
- $random = chr($generator(0, ord($max[0]) - 1)) . $random;
- }
- else
- {
- $random = chr($generator(0, ord($max[0]) )) . $random;
- }
-
- $random = new biginteger($random, 256);
-
- return $random->add($min);
- }
-
- /**
- * Logical Left Shift
- *
- * Shifts BigInteger's by $shift bits.
- *
- * @param Integer $shift
- * @access private
- */
- function _lshift($shift)
- {
- if ( $shift == 0 )
- {
- return;
- }
-
- $num_digits = floor($shift / 26);
- $shift %= 26;
- $shift = 1 << $shift;
-
- $carry = 0;
-
- for ($i = 0; $i < count($this->value); $i++)
- {
- $temp = $this->value[$i] * $shift + $carry;
- $carry = floor($temp / 0x4000000);
- $this->value[$i] = $temp - $carry * 0x4000000;
- }
-
- if ( $carry )
- {
- $this->value[] = $carry;
- }
-
- while ($num_digits--)
- {
- array_unshift($this->value, 0);
- }
- }
-
- /**
- * Logical Right Shift
- *
- * Shifts BigInteger's by $shift bits.
- *
- * @param Integer $shift
- * @access private
- */
- function _rshift($shift)
- {
- if ($shift == 0)
- {
- $this->_normalize();
- }
-
- $num_digits = floor($shift / 26);
- $shift %= 26;
- $carry_shift = 26 - $shift;
- $carry_mask = (1 << $shift) - 1;
-
- if ( $num_digits )
- {
- $this->value = array_slice($this->value, $num_digits);
- }
-
- $carry = 0;
-
- for ($i = count($this->value) - 1; $i >= 0; $i--)
- {
- $temp = $this->value[$i] >> $shift | $carry;
- $carry = ($this->value[$i] & $carry_mask) << $carry_shift;
- $this->value[$i] = $temp;
- }
-
- $this->_normalize();
- }
-
- /**
- * Normalize
- *
- * Deletes leading zeros.
- *
- * @see divide()
- * @return Math_BigInteger
- * @access private
- */
- function _normalize()
- {
- if ( !count($this->value) )
- {
- return $this;
- }
-
- for ($i=count($this->value) - 1; $i >= 0; $i--)
- {
- if ( $this->value[$i] )
- {
- break;
- }
- unset($this->value[$i]);
- }
-
- return $this;
- }
-
- /**
- * Array Repeat
- *
- * @param $input Array
- * @param $multiplier mixed
- * @return Array
- * @access private
- */
- function _array_repeat($input, $multiplier)
- {
- return ($multiplier) ? array_fill(0, $multiplier, $input) : array();
- }
-
- /**
- * Logical Left Shift
- *
- * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
- *
- * @param $x String
- * @param $shift Integer
- * @return String
- * @access private
- */
- function _base256_lshift(&$x, $shift)
- {
- if ($shift == 0)
- {
- return;
- }
-
- $num_bytes = $shift >> 3; // eg. floor($shift/8)
- $shift &= 7; // eg. $shift % 8
-
- $carry = 0;
- for ($i = strlen($x) - 1; $i >= 0; $i--)
- {
- $temp = ord($x[$i]) << $shift | $carry;
- $x[$i] = chr($temp);
- $carry = $temp >> 8;
- }
- $carry = ($carry != 0) ? chr($carry) : '';
- $x = $carry . $x . str_repeat(chr(0), $num_bytes);
- }
-
- /**
- * Logical Right Shift
- *
- * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder.
- *
- * @param $x String
- * @param $shift Integer
- * @return String
- * @access private
- */
- function _base256_rshift(&$x, $shift)
- {
- if ($shift == 0)
- {
- $x = ltrim($x, chr(0));
- return '';
- }
-
- $num_bytes = $shift >> 3; // eg. floor($shift/8)
- $shift &= 7; // eg. $shift % 8
-
- $remainder = '';
- if ($num_bytes)
- {
- $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes;
- $remainder = substr($x, $start);
- $x = substr($x, 0, -$num_bytes);
- }
-
- $carry = 0;
- $carry_shift = 8 - $shift;
- for ($i = 0; $i < strlen($x); $i++)
- {
- $temp = (ord($x[$i]) >> $shift) | $carry;
- $carry = (ord($x[$i]) << $carry_shift) & 0xFF;
- $x[$i] = chr($temp);
- }
- $x = ltrim($x, chr(0));
-
- $remainder = chr($carry >> $carry_shift) . $remainder;
-
- return ltrim($remainder, chr(0));
- }
-
- // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long
- // at 32-bits, while java's longs are 64-bits.
-
- /**
- * Converts 32-bit integers to bytes.
- *
- * @param Integer $x
- * @return String
- * @access private
- */
- function _int2bytes($x)
- {
- return ltrim(pack('N', $x), chr(0));
- }
-
- /**
- * Converts bytes to 32-bit integers
- *
- * @param String $x
- * @return Integer
- * @access private
- */
- function _bytes2int($x)
- {
- $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT));
- return $temp['int'];
- }
-}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/des.php b/phpBB/includes/libraries/sftp/des.php deleted file mode 100644 index 278de64a01..0000000000 --- a/phpBB/includes/libraries/sftp/des.php +++ /dev/null @@ -1,1428 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementation of DES.
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access private
- * @see des::_prepare_key()
- * @see des::_process_block()
- */
-/**
- * Contains array_reverse($keys[CRYPT_DES_DECRYPT])
- */
-define('CRYPT_DES_ENCRYPT', 0);
-/**
- * Contains array_reverse($keys[CRYPT_DES_ENCRYPT])
- */
-define('CRYPT_DES_DECRYPT', 1);
-/**#@-*/
-
-/**#@+
- * @access public
- * @see des::encrypt()
- * @see des::decrypt()
- */
-/**
- * Encrypt / decrypt using the Electronic Code Book mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
- */
-define('CRYPT_DES_MODE_ECB', 1);
-/**
- * Encrypt / decrypt using the Code Book Chaining mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
- */
-define('CRYPT_DES_MODE_CBC', 2);
-/**#@-*/
-
-/**
- * Encrypt / decrypt using inner chaining
- *
- * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
- */
-define('CRYPT_DES_MODE_3CBC', 3);
-
-/**
- * Encrypt / decrypt using outer chaining
- *
- * Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
- */
-define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
-
-/**#@+
- * @access private
- * @see des::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_DES_MODE_INTERNAL', 1);
-/**
- * Toggles the mcrypt implementation
- */
-define('CRYPT_DES_MODE_MCRYPT', 2);
-/**#@-*/
-
-/**
- * Pure-PHP implementation of DES.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package des
- */
-class des
-{
- /**
- * The Key Schedule
- *
- * @see des::setKey()
- * @var Array
- * @access private
- */
- var $keys = "\0\0\0\0\0\0\0\0";
-
- /**
- * The Encryption Mode
- *
- * @see des::des()
- * @var Integer
- * @access private
- */
- var $mode;
-
- /**
- * Continuous Buffer status
- *
- * @see des::enableContinuousBuffer()
- * @var Boolean
- * @access private
- */
- var $continuousBuffer = false;
-
- /**
- * Padding status
- *
- * @see des::enablePadding()
- * @var Boolean
- * @access private
- */
- var $padding = true;
-
- /**
- * The Initialization Vector
- *
- * @see des::setIV()
- * @var String
- * @access private
- */
- var $iv = "\0\0\0\0\0\0\0\0";
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see des::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $encryptIV = "\0\0\0\0\0\0\0\0";
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see des::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $decryptIV = "\0\0\0\0\0\0\0\0";
-
- /**
- * MCrypt parameters
- *
- * @see des::setMCrypt()
- * @var Array
- * @access private
- */
- var $mcrypt = array('', '');
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
- * CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC. If not explictly set, CRYPT_DES_MODE_CBC will be used.
- *
- * @param optional Integer $mode
- * @return des
- * @access public
- */
- function __construct($mode = CRYPT_MODE_DES_CBC)
- {
- if ( !defined('CRYPT_DES_MODE') )
- {
- switch (true)
- {
- case extension_loaded('mcrypt'):
- // i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),
- // but since that can be changed after the object has been created, there doesn't seem to be
- // a lot of point...
- define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
- break;
- default:
- define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);
- }
- }
-
- switch ( CRYPT_DES_MODE )
- {
- case CRYPT_DES_MODE_MCRYPT:
- switch ($mode)
- {
- case CRYPT_DES_MODE_ECB:
- $this->mode = MCRYPT_MODE_ECB;
- break;
- case CRYPT_DES_MODE_CBC:
- default:
- $this->mode = MCRYPT_MODE_CBC;
- }
-
- break;
- default:
- switch ($mode)
- {
- case CRYPT_DES_MODE_ECB:
- case CRYPT_DES_MODE_CBC:
- $this->mode = $mode;
- break;
- default:
- $this->mode = CRYPT_DES_MODE_CBC;
- }
- }
- }
-
- /**
- * Sets the key.
- *
- * Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
- * only use the first eight, if $key has more then eight characters in it, and pad $key with the
- * null byte if it is less then eight characters long.
- *
- * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
- *
- * If the key is not explicitly set, it'll be assumed to be all zero's.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $this->keys = ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) ? substr($key, 0, 8) : $this->_prepare_key($key);
- }
-
- /**
- * Sets the initialization vector. (optional)
- *
- * SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explictly set, it'll be assumed
- * to be all zero's.
- *
- * @access public
- * @param String $iv
- */
- function set_iv($iv)
- {
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));;
- }
-
- /**
- * Sets MCrypt parameters. (optional)
- *
- * If MCrypt is being used, empty strings will be used, unless otherwise specified.
- *
- * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
- * @access public
- * @param optional Integer $algorithm_directory
- * @param optional Integer $mode_directory
- */
- function set_mcrypt($algorithm_directory = '', $mode_directory = '')
- {
- $this->mcrypt = array($algorithm_directory, $mode_directory);
- }
-
- /**
- * Encrypts a message.
- *
- * $plaintext will be padded with up to 8 additional bytes. Other DES implementations may or may not pad in the
- * same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
- * URL:
- *
- * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
- *
- * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
- * strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
- * length.
- *
- * @see des::decrypt()
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- $plaintext = $this->_pad($plaintext);
-
- if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT )
- {
- $td = mcrypt_module_open(MCRYPT_DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->keys, $this->encryptIV);
-
- $ciphertext = mcrypt_generic($td, $plaintext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->encryptIV = substr($ciphertext, -8);
- }
-
- return $ciphertext;
- }
-
- if (!is_array($this->keys))
- {
- $this->keys = $this->_prepare_key("\0\0\0\0\0\0\0\0");
- }
-
- $ciphertext = '';
- switch ($this->mode)
- {
- case CRYPT_DES_MODE_ECB:
- for ($i = 0; $i < strlen($plaintext); $i+=8)
- {
- $ciphertext.= $this->_process_block(substr($plaintext, $i, 8), CRYPT_DES_ENCRYPT);
- }
- break;
- case CRYPT_DES_MODE_CBC:
- $xor = $this->encryptIV;
- for ($i = 0; $i < strlen($plaintext); $i+=8)
- {
- $block = substr($plaintext, $i, 8);
- $block = $this->_process_block($block ^ $xor, CRYPT_DES_ENCRYPT);
- $xor = $block;
- $ciphertext.= $block;
- }
- if ($this->continuousBuffer)
- {
- $this->encryptIV = $xor;
- }
- }
-
- return $ciphertext;
- }
-
- /**
- * Decrypts a message.
- *
- * If strlen($ciphertext) is not a multiple of 8, null bytes will be added to the end of the string until it is.
- *
- * @see des::encrypt()
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
-
- if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT )
- {
- $td = mcrypt_module_open(MCRYPT_DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->keys, $this->decryptIV);
-
- $plaintext = mdecrypt_generic($td, $ciphertext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->decryptIV = substr($ciphertext, -8);
- }
-
- return $this->_unpad($plaintext);
- }
-
- if (!is_array($this->keys))
- {
- $this->keys = $this->_prepare_key("\0\0\0\0\0\0\0\0");
- }
-
- $plaintext = '';
- switch ($this->mode)
- {
- case CRYPT_DES_MODE_ECB:
- for ($i = 0; $i < strlen($ciphertext); $i+=8)
- {
- $plaintext.= $this->_process_block(substr($ciphertext, $i, 8), CRYPT_DES_DECRYPT);
- }
- break;
- case CRYPT_DES_MODE_CBC:
- $xor = $this->decryptIV;
- for ($i = 0; $i < strlen($ciphertext); $i+=8)
- {
- $block = substr($ciphertext, $i, 8);
- $plaintext.= $this->_process_block($block, CRYPT_DES_DECRYPT) ^ $xor;
- $xor = $block;
- }
- if ($this->continuousBuffer)
- {
- $this->decryptIV = $xor;
- }
- }
-
- return $this->_unpad($plaintext);
- }
-
- /**
- * Treat consecutive "packets" as if they are a continuous buffer.
- *
- * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
- * will yield different outputs:
- *
- * <code>
- * echo $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->encrypt(substr($plaintext, 8, 8));
- * </code>
- * <code>
- * echo $des->encrypt($plaintext);
- * </code>
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- * <code>
- * $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- * <code>
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the des() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see des::disableContinuousBuffer()
- * @access public
- */
- function enable_continuous_buffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see des::enableContinuousBuffer()
- * @access public
- */
- function disable_continuous_buffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
- }
-
- /**
- * Pad "packets".
- *
- * DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
- * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
- *
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
- * transmitted separately)
- *
- * @see des::disablePadding()
- * @access public
- */
- function enable_padding()
- {
- $this->padding = true;
- }
-
- /**
- * Do not pad packets.
- *
- * @see des::enablePadding()
- * @access public
- */
- function disable_padding()
- {
- $this->padding = false;
- }
-
- /**
- * Pads a string
- *
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
- * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
- *
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
- * and padding will, hence forth, be enabled.
- *
- * @see des::_unpad()
- * @access private
- */
- function _pad($text)
- {
- $length = strlen($text);
-
- if (!$this->padding)
- {
- if (($length & 7) == 0)
- {
- return $text;
- }
- else
- {
- $this->padding = true;
- }
- }
-
- $pad = 8 - ($length & 7);
- return str_pad($text, $length + $pad, chr($pad));
- }
-
- /**
- * Unpads a string
- *
- * If padding is enabled and the reported padding length exceeds the block size, padding will be, hence forth, disabled.
- *
- * @see des::_pad()
- * @access private
- */
- function _unpad($text)
- {
- if (!$this->padding)
- {
- return $text;
- }
-
- $length = ord($text[strlen($text) - 1]);
-
- if ($length > 8)
- {
- $this->padding = false;
- return $text;
- }
-
- return substr($text, 0, -$length);
- }
-
- /**
- * Encrypts or decrypts a 64-bit block
- *
- * $mode should be either CRYPT_DES_ENCRYPT or CRYPT_DES_DECRYPT. See
- * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
- * idea of what this function does.
- *
- * @access private
- * @param String $block
- * @param Integer $mode
- * @return String
- */
- function _process_block($block, $mode)
- {
- // s-boxes. in the official DES docs, they're described as being matrices that
- // one accesses by using the first and last bits to determine the row and the
- // middle four bits to determine the column. in this implementation, they've
- // been converted to vectors
- static $sbox = array(
- array(
- 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
- 3, 10 ,10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
- 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
- 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
- ),
- array(
- 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
- 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
- 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
- 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
- ),
- array(
- 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
- 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
- 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
- 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
- ),
- array(
- 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
- 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
- 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
- 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
- ),
- array(
- 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
- 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
- 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
- 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
- ),
- array(
- 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
- 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
- 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
- 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
- ),
- array(
- 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
- 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
- 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
- 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12
- ),
- array(
- 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
- 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
- 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
- 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
- )
- );
-
- $temp = unpack('Na/Nb', $block);
- $block = array($temp['a'], $temp['b']);
-
- // because php does arithmetic right shifts, if the most significant bits are set, right
- // shifting those into the correct position will add 1's - not 0's. this will intefere
- // with the | operation unless a second & is done. so we isolate these bits and left shift
- // them into place. we then & each block with 0x7FFFFFFF to prevennt 1's from being added
- // for any other shifts.
- $msb = array(
- ($block[0] >> 31) & 1,
- ($block[1] >> 31) & 1
- );
- $block[0] &= 0x7FFFFFFF;
- $block[1] &= 0x7FFFFFFF;
-
- // we isolate the appropriate bit in the appropriate integer and shift as appropriate. in
- // some cases, there are going to be multiple bits in the same integer that need to be shifted
- // in the same way. we combine those into one shift operation.
- $block = array(
- (($block[1] & 0x00000040) << 25) | (($block[1] & 0x00004000) << 16) |
- (($block[1] & 0x00400001) << 7) | (($block[1] & 0x40000100) >> 2) |
- (($block[0] & 0x00000040) << 21) | (($block[0] & 0x00004000) << 12) |
- (($block[0] & 0x00400001) << 3) | (($block[0] & 0x40000100) >> 6) |
- (($block[1] & 0x00000010) << 19) | (($block[1] & 0x00001000) << 10) |
- (($block[1] & 0x00100000) << 1) | (($block[1] & 0x10000000) >> 8) |
- (($block[0] & 0x00000010) << 15) | (($block[0] & 0x00001000) << 6) |
- (($block[0] & 0x00100000) >> 3) | (($block[0] & 0x10000000) >> 12) |
- (($block[1] & 0x00000004) << 13) | (($block[1] & 0x00000400) << 4) |
- (($block[1] & 0x00040000) >> 5) | (($block[1] & 0x04000000) >> 14) |
- (($block[0] & 0x00000004) << 9) | ( $block[0] & 0x00000400 ) |
- (($block[0] & 0x00040000) >> 9) | (($block[0] & 0x04000000) >> 18) |
- (($block[1] & 0x00010000) >> 11) | (($block[1] & 0x01000000) >> 20) |
- (($block[0] & 0x00010000) >> 15) | (($block[0] & 0x01000000) >> 24)
- ,
- (($block[1] & 0x00000080) << 24) | (($block[1] & 0x00008000) << 15) |
- (($block[1] & 0x00800002) << 6) | (($block[0] & 0x00000080) << 20) |
- (($block[0] & 0x00008000) << 11) | (($block[0] & 0x00800002) << 2) |
- (($block[1] & 0x00000020) << 18) | (($block[1] & 0x00002000) << 9) |
- ( $block[1] & 0x00200000 ) | (($block[1] & 0x20000000) >> 9) |
- (($block[0] & 0x00000020) << 14) | (($block[0] & 0x00002000) << 5) |
- (($block[0] & 0x00200000) >> 4) | (($block[0] & 0x20000000) >> 13) |
- (($block[1] & 0x00000008) << 12) | (($block[1] & 0x00000800) << 3) |
- (($block[1] & 0x00080000) >> 6) | (($block[1] & 0x08000000) >> 15) |
- (($block[0] & 0x00000008) << 8) | (($block[0] & 0x00000800) >> 1) |
- (($block[0] & 0x00080000) >> 10) | (($block[0] & 0x08000000) >> 19) |
- (($block[1] & 0x00000200) >> 3) | (($block[0] & 0x00000200) >> 7) |
- (($block[1] & 0x00020000) >> 12) | (($block[1] & 0x02000000) >> 21) |
- (($block[0] & 0x00020000) >> 16) | (($block[0] & 0x02000000) >> 25) |
- ($msb[1] << 28) | ($msb[0] << 24)
- );
-
- for ($i = 0; $i < 16; $i++)
- {
- // start of "the Feistel (F) function" - see the following URL:
- // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
- $temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $this->keys[$mode][$i][0]]) << 28)
- | (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $this->keys[$mode][$i][1]]) << 24)
- | (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $this->keys[$mode][$i][2]]) << 20)
- | (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $this->keys[$mode][$i][3]]) << 16)
- | (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $this->keys[$mode][$i][4]]) << 12)
- | (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $this->keys[$mode][$i][5]]) << 8)
- | (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $this->keys[$mode][$i][6]]) << 4)
- | ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $this->keys[$mode][$i][7]]);
-
- $msb = ($temp >> 31) & 1;
- $temp &= 0x7FFFFFFF;
- $newBlock = (($temp & 0x00010000) << 15) | (($temp & 0x02020120) << 5)
- | (($temp & 0x00001800) << 17) | (($temp & 0x01000000) >> 10)
- | (($temp & 0x00000008) << 24) | (($temp & 0x00100000) << 6)
- | (($temp & 0x00000010) << 21) | (($temp & 0x00008000) << 9)
- | (($temp & 0x00000200) << 12) | (($temp & 0x10000000) >> 27)
- | (($temp & 0x00000040) << 14) | (($temp & 0x08000000) >> 8)
- | (($temp & 0x00004000) << 4) | (($temp & 0x00000002) << 16)
- | (($temp & 0x00442000) >> 6) | (($temp & 0x40800000) >> 15)
- | (($temp & 0x00000001) << 11) | (($temp & 0x20000000) >> 20)
- | (($temp & 0x00080000) >> 13) | (($temp & 0x00000004) << 3)
- | (($temp & 0x04000000) >> 22) | (($temp & 0x00000480) >> 7)
- | (($temp & 0x00200000) >> 19) | ($msb << 23);
- // end of "the Feistel (F) function" - $newBlock is F's output
-
- $temp = $block[1];
- $block[1] = $block[0] ^ $newBlock;
- $block[0] = $temp;
- }
-
- $msb = array(
- ($block[0] >> 31) & 1,
- ($block[1] >> 31) & 1
- );
- $block[0] &= 0x7FFFFFFF;
- $block[1] &= 0x7FFFFFFF;
-
- $block = array(
- (($block[0] & 0x01000004) << 7) | (($block[1] & 0x01000004) << 6) |
- (($block[0] & 0x00010000) << 13) | (($block[1] & 0x00010000) << 12) |
- (($block[0] & 0x00000100) << 19) | (($block[1] & 0x00000100) << 18) |
- (($block[0] & 0x00000001) << 25) | (($block[1] & 0x00000001) << 24) |
- (($block[0] & 0x02000008) >> 2) | (($block[1] & 0x02000008) >> 3) |
- (($block[0] & 0x00020000) << 4) | (($block[1] & 0x00020000) << 3) |
- (($block[0] & 0x00000200) << 10) | (($block[1] & 0x00000200) << 9) |
- (($block[0] & 0x00000002) << 16) | (($block[1] & 0x00000002) << 15) |
- (($block[0] & 0x04000000) >> 11) | (($block[1] & 0x04000000) >> 12) |
- (($block[0] & 0x00040000) >> 5) | (($block[1] & 0x00040000) >> 6) |
- (($block[0] & 0x00000400) << 1) | ( $block[1] & 0x00000400 ) |
- (($block[0] & 0x08000000) >> 20) | (($block[1] & 0x08000000) >> 21) |
- (($block[0] & 0x00080000) >> 14) | (($block[1] & 0x00080000) >> 15) |
- (($block[0] & 0x00000800) >> 8) | (($block[1] & 0x00000800) >> 9)
- ,
- (($block[0] & 0x10000040) << 3) | (($block[1] & 0x10000040) << 2) |
- (($block[0] & 0x00100000) << 9) | (($block[1] & 0x00100000) << 8) |
- (($block[0] & 0x00001000) << 15) | (($block[1] & 0x00001000) << 14) |
- (($block[0] & 0x00000010) << 21) | (($block[1] & 0x00000010) << 20) |
- (($block[0] & 0x20000080) >> 6) | (($block[1] & 0x20000080) >> 7) |
- ( $block[0] & 0x00200000 ) | (($block[1] & 0x00200000) >> 1) |
- (($block[0] & 0x00002000) << 6) | (($block[1] & 0x00002000) << 5) |
- (($block[0] & 0x00000020) << 12) | (($block[1] & 0x00000020) << 11) |
- (($block[0] & 0x40000000) >> 15) | (($block[1] & 0x40000000) >> 16) |
- (($block[0] & 0x00400000) >> 9) | (($block[1] & 0x00400000) >> 10) |
- (($block[0] & 0x00004000) >> 3) | (($block[1] & 0x00004000) >> 4) |
- (($block[0] & 0x00800000) >> 18) | (($block[1] & 0x00800000) >> 19) |
- (($block[0] & 0x00008000) >> 12) | (($block[1] & 0x00008000) >> 13) |
- ($msb[0] << 7) | ($msb[1] << 6)
- );
-
- return pack('NN', $block[0], $block[1]);
- }
-
- /**
- * Creates the key schedule.
- *
- * @access private
- * @param String $key
- * @return Array
- */
- function _prepare_key($key)
- {
- static $shifts = array( // number of key bits shifted per round
- 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
- );
-
- // pad the key and remove extra characters as appropriate.
- $key = str_pad(substr($key, 0, 8), 8, chr(0));
-
- $temp = unpack('Na/Nb', $key);
- $key = array($temp['a'], $temp['b']);
- $msb = array(
- ($key[0] >> 31) & 1,
- ($key[1] >> 31) & 1
- );
- $key[0] &= 0x7FFFFFFF;
- $key[1] &= 0x7FFFFFFF;
-
- $key = array(
- (($key[1] & 0x00000002) << 26) | (($key[1] & 0x00000204) << 17) |
- (($key[1] & 0x00020408) << 8) | (($key[1] & 0x02040800) >> 1) |
- (($key[0] & 0x00000002) << 22) | (($key[0] & 0x00000204) << 13) |
- (($key[0] & 0x00020408) << 4) | (($key[0] & 0x02040800) >> 5) |
- (($key[1] & 0x04080000) >> 10) | (($key[0] & 0x04080000) >> 14) |
- (($key[1] & 0x08000000) >> 19) | (($key[0] & 0x08000000) >> 23) |
- (($key[0] & 0x00000010) >> 1) | (($key[0] & 0x00001000) >> 10) |
- (($key[0] & 0x00100000) >> 19) | (($key[0] & 0x10000000) >> 28)
- ,
- (($key[1] & 0x00000080) << 20) | (($key[1] & 0x00008000) << 11) |
- (($key[1] & 0x00800000) << 2) | (($key[0] & 0x00000080) << 16) |
- (($key[0] & 0x00008000) << 7) | (($key[0] & 0x00800000) >> 2) |
- (($key[1] & 0x00000040) << 13) | (($key[1] & 0x00004000) << 4) |
- (($key[1] & 0x00400000) >> 5) | (($key[1] & 0x40000000) >> 14) |
- (($key[0] & 0x00000040) << 9) | ( $key[0] & 0x00004000 ) |
- (($key[0] & 0x00400000) >> 9) | (($key[0] & 0x40000000) >> 18) |
- (($key[1] & 0x00000020) << 6) | (($key[1] & 0x00002000) >> 3) |
- (($key[1] & 0x00200000) >> 12) | (($key[1] & 0x20000000) >> 21) |
- (($key[0] & 0x00000020) << 2) | (($key[0] & 0x00002000) >> 7) |
- (($key[0] & 0x00200000) >> 16) | (($key[0] & 0x20000000) >> 25) |
- (($key[1] & 0x00000010) >> 1) | (($key[1] & 0x00001000) >> 10) |
- (($key[1] & 0x00100000) >> 19) | (($key[1] & 0x10000000) >> 28) |
- ($msb[1] << 24) | ($msb[0] << 20)
- );
-
- $keys = array();
- for ($i = 0; $i < 16; $i++)
- {
- $key[0] <<= $shifts[$i];
- $temp = ($key[0] & 0xF0000000) >> 28;
- $key[0] = ($key[0] | $temp) & 0x0FFFFFFF;
-
- $key[1] <<= $shifts[$i];
- $temp = ($key[1] & 0xF0000000) >> 28;
- $key[1] = ($key[1] | $temp) & 0x0FFFFFFF;
-
- $temp = array(
- (($key[1] & 0x00004000) >> 9) | (($key[1] & 0x00000800) >> 7) |
- (($key[1] & 0x00020000) >> 14) | (($key[1] & 0x00000010) >> 2) |
- (($key[1] & 0x08000000) >> 26) | (($key[1] & 0x00800000) >> 23)
- ,
- (($key[1] & 0x02400000) >> 20) | (($key[1] & 0x00000001) << 4) |
- (($key[1] & 0x00002000) >> 10) | (($key[1] & 0x00040000) >> 18) |
- (($key[1] & 0x00000080) >> 6)
- ,
- ( $key[1] & 0x00000020 ) | (($key[1] & 0x00000200) >> 5) |
- (($key[1] & 0x00010000) >> 13) | (($key[1] & 0x01000000) >> 22) |
- (($key[1] & 0x00000004) >> 1) | (($key[1] & 0x00100000) >> 20)
- ,
- (($key[1] & 0x00001000) >> 7) | (($key[1] & 0x00200000) >> 17) |
- (($key[1] & 0x00000002) << 2) | (($key[1] & 0x00000100) >> 6) |
- (($key[1] & 0x00008000) >> 14) | (($key[1] & 0x04000000) >> 26)
- ,
- (($key[0] & 0x00008000) >> 10) | ( $key[0] & 0x00000010 ) |
- (($key[0] & 0x02000000) >> 22) | (($key[0] & 0x00080000) >> 17) |
- (($key[0] & 0x00000200) >> 8) | (($key[0] & 0x00000002) >> 1)
- ,
- (($key[0] & 0x04000000) >> 21) | (($key[0] & 0x00010000) >> 12) |
- (($key[0] & 0x00000020) >> 2) | (($key[0] & 0x00000800) >> 9) |
- (($key[0] & 0x00800000) >> 22) | (($key[0] & 0x00000100) >> 8)
- ,
- (($key[0] & 0x00001000) >> 7) | (($key[0] & 0x00000088) >> 3) |
- (($key[0] & 0x00020000) >> 14) | (($key[0] & 0x00000001) << 2) |
- (($key[0] & 0x00400000) >> 21)
- ,
- (($key[0] & 0x00000400) >> 5) | (($key[0] & 0x00004000) >> 10) |
- (($key[0] & 0x00000040) >> 3) | (($key[0] & 0x00100000) >> 18) |
- (($key[0] & 0x08000000) >> 26) | (($key[0] & 0x01000000) >> 24)
- );
-
- $keys[] = $temp;
- }
-
- $temp = array(
- CRYPT_DES_ENCRYPT => $keys,
- CRYPT_DES_DECRYPT => array_reverse($keys)
- );
-
- return $temp;
- }
-}
-
-
-
-/**
- * Pure-PHP implementation of Triple DES.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package Crypt_TerraDES
- */
-class tripledes
-{
- /**
- * The Three Keys
- *
- * @see tripledes::setKey()
- * @var String
- * @access private
- */
- var $key = "\0\0\0\0\0\0\0\0";
-
- /**
- * The Encryption Mode
- *
- * @see tripledes::tripledes()
- * @var Integer
- * @access private
- */
- var $mode = CRYPT_DES_MODE_CBC;
-
- /**
- * Continuous Buffer status
- *
- * @see tripledes::enableContinuousBuffer()
- * @var Boolean
- * @access private
- */
- var $continuousBuffer = false;
-
- /**
- * Padding status
- *
- * @see tripledes::enablePadding()
- * @var Boolean
- * @access private
- */
- var $padding = true;
-
- /**
- * The Initialization Vector
- *
- * @see tripledes::setIV()
- * @var String
- * @access private
- */
- var $iv = "\0\0\0\0\0\0\0\0";
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see tripledes::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $encryptIV = "\0\0\0\0\0\0\0\0";
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see tripledes::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $decryptIV = "\0\0\0\0\0\0\0\0";
-
- /**
- * MCrypt parameters
- *
- * @see tripledes::setMCrypt()
- * @var Array
- * @access private
- */
- var $mcrypt = array('', '');
-
- /**
- * The des objects
- *
- * @var Array
- * @access private
- */
- var $des;
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
- * CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC. If not explictly set, CRYPT_DES_MODE_CBC will be used.
- *
- * @param optional Integer $mode
- * @return tripledes
- * @access public
- */
- function __construct($mode = CRYPT_DES_MODE_CBC)
- {
- if ( !defined('CRYPT_DES_MODE') )
- {
- switch (true)
- {
- case extension_loaded('mcrypt'):
- // i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),
- // but since that can be changed after the object has been created, there doesn't seem to be
- // a lot of point...
- define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
- break;
- default:
- define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);
- }
- }
-
- if ( $mode == CRYPT_DES_MODE_3CBC )
- {
- $this->mode = CRYPT_DES_MODE_3CBC;
- $this->des = array(
- new des(CRYPT_DES_MODE_CBC),
- new des(CRYPT_DES_MODE_CBC),
- new des(CRYPT_DES_MODE_CBC)
- );
-
- // we're going to be doing the padding, ourselves, so disable it in the des objects
- $this->des[0]->disable_padding();
- $this->des[1]->disable_padding();
- $this->des[2]->disable_padding();
-
- return;
- }
-
- switch ( CRYPT_DES_MODE )
- {
- case CRYPT_DES_MODE_MCRYPT:
- switch ($mode)
- {
- case CRYPT_DES_MODE_ECB:
- $this->mode = MCRYPT_MODE_ECB; break;
- case CRYPT_DES_MODE_CBC:
- default:
- $this->mode = MCRYPT_MODE_CBC;
- }
-
- break;
- default:
- $this->des = array(
- new des(CRYPT_DES_MODE_ECB),
- new des(CRYPT_DES_MODE_ECB),
- new des(CRYPT_DES_MODE_ECB)
- );
-
- // we're going to be doing the padding, ourselves, so disable it in the des objects
- $this->des[0]->disable_padding();
- $this->des[1]->disable_padding();
- $this->des[2]->disable_padding();
-
- switch ($mode)
- {
- case CRYPT_DES_MODE_ECB:
- case CRYPT_DES_MODE_CBC:
- $this->mode = $mode;
- break;
- default:
- $this->mode = CRYPT_DES_MODE_CBC;
- }
- }
- }
-
- /**
- * Sets the key.
- *
- * Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
- * 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
- *
- * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
- *
- * If the key is not explicitly set, it'll be assumed to be all zero's.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $length = strlen($key);
- if ($length > 8)
- {
- $key = str_pad($key, 24, chr(0));
- // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
- // http://php.net/function.mcrypt-encrypt#47973
- $key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
- }
- $this->key = $key;
- switch (true)
- {
- case CRYPT_DES_MODE == CRYPT_DES_MODE_INTERNAL:
- case $this->mode == CRYPT_DES_MODE_3CBC:
- $this->des[0]->set_key(substr($key, 0, 8));
- $this->des[1]->set_key(substr($key, 8, 8));
- $this->des[2]->set_key(substr($key, 16, 8));
- }
- }
-
- /**
- * Sets the initialization vector. (optional)
- *
- * SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explictly set, it'll be assumed
- * to be all zero's.
- *
- * @access public
- * @param String $iv
- */
- function set_iv($iv)
- {
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));
- if ($this->mode == CRYPT_DES_MODE_3CBC)
- {
- $this->des[0]->set_iv($iv);
- $this->des[1]->set_iv($iv);
- $this->des[2]->set_iv($iv);
- }
- }
-
- /**
- * Sets MCrypt parameters. (optional)
- *
- * If MCrypt is being used, empty strings will be used, unless otherwise specified.
- *
- * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
- * @access public
- * @param optional Integer $algorithm_directory
- * @param optional Integer $mode_directory
- */
- function set_mcrypt($algorithm_directory = '', $mode_directory = '')
- {
- $this->mcrypt = array($algorithm_directory, $mode_directory);
- if ( $this->mode == CRYPT_DES_MODE_3CBC )
- {
- $this->des[0]->set_mcrypt($algorithm_directory, $mode_directory);
- $this->des[1]->set_mcrypt($algorithm_directory, $mode_directory);
- $this->des[2]->set_mcrypt($algorithm_directory, $mode_directory);
- }
- }
-
- /**
- * Encrypts a message.
- *
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- $plaintext = $this->_pad($plaintext);
-
- // if the key is smaller then 8, do what we'd normally do
- if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8)
- {
- $ciphertext = $this->des[2]->encrypt($this->des[1]->decrypt($this->des[0]->encrypt($plaintext)));
-
- return $ciphertext;
- }
-
- if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT )
- {
- $td = mcrypt_module_open(MCRYPT_3DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->key, $this->encryptIV);
-
- $ciphertext = mcrypt_generic($td, $plaintext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->encryptIV = substr($ciphertext, -8);
- }
-
- return $ciphertext;
- }
-
- if (strlen($this->key) <= 8)
- {
- $this->des[0]->mode = $this->mode;
-
- return $this->des[0]->encrypt($plaintext);
- }
-
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $plaintext = str_pad($plaintext, ceil(strlen($plaintext) / 8) * 8, chr(0));
-
- $ciphertext = '';
- switch ($this->mode)
- {
- case CRYPT_DES_MODE_ECB:
- for ($i = 0; $i < strlen($plaintext); $i+=8)
- {
- $block = substr($plaintext, $i, 8);
- $block = $this->des[0]->_process_block($block, CRYPT_DES_ENCRYPT);
- $block = $this->des[1]->_process_block($block, CRYPT_DES_DECRYPT);
- $block = $this->des[2]->_process_block($block, CRYPT_DES_ENCRYPT);
- $ciphertext.= $block;
- }
- break;
- case CRYPT_DES_MODE_CBC:
- $xor = $this->encryptIV;
- for ($i = 0; $i < strlen($plaintext); $i+=8)
- {
- $block = substr($plaintext, $i, 8) ^ $xor;
- $block = $this->des[0]->_process_block($block, CRYPT_DES_ENCRYPT);
- $block = $this->des[1]->_process_block($block, CRYPT_DES_DECRYPT);
- $block = $this->des[2]->_process_block($block, CRYPT_DES_ENCRYPT);
- $xor = $block;
- $ciphertext.= $block;
- }
- if ($this->continuousBuffer)
- {
- $this->encryptIV = $xor;
- }
- }
-
- return $ciphertext;
- }
-
- /**
- * Decrypts a message.
- *
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8)
- {
- $plaintext = $this->des[0]->decrypt($this->des[1]->encrypt($this->des[2]->decrypt($ciphertext)));
-
- return $this->_unpad($plaintext);
- }
-
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
-
- if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT )
- {
- $td = mcrypt_module_open(MCRYPT_3DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->key, $this->decryptIV);
-
- $plaintext = mdecrypt_generic($td, $ciphertext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->decryptIV = substr($ciphertext, -8);
- }
-
- return $this->_unpad($plaintext);
- }
-
- if (strlen($this->key) <= 8)
- {
- $this->des[0]->mode = $this->mode;
-
- return $this->_unpad($this->des[0]->decrypt($plaintext));
- }
-
- $plaintext = '';
- switch ($this->mode)
- {
- case CRYPT_DES_MODE_ECB:
- for ($i = 0; $i < strlen($ciphertext); $i+=8)
- {
- $block = substr($ciphertext, $i, 8);
- $block = $this->des[2]->_process_block($block, CRYPT_DES_DECRYPT);
- $block = $this->des[1]->_process_block($block, CRYPT_DES_ENCRYPT);
- $block = $this->des[0]->_process_block($block, CRYPT_DES_DECRYPT);
- $plaintext.= $block;
- }
- break;
- case CRYPT_DES_MODE_CBC:
- $xor = $this->decryptIV;
- for ($i = 0; $i < strlen($ciphertext); $i+=8)
- {
- $orig = $block = substr($ciphertext, $i, 8);
- $block = $this->des[2]->_process_block($block, CRYPT_DES_DECRYPT);
- $block = $this->des[1]->_process_block($block, CRYPT_DES_ENCRYPT);
- $block = $this->des[0]->_process_block($block, CRYPT_DES_DECRYPT);
- $plaintext.= $block ^ $xor;
- $xor = $orig;
- }
- if ($this->continuousBuffer)
- {
- $this->decryptIV = $xor;
- }
- }
-
- return $this->_unpad($plaintext);
- }
-
- /**
- * Treat consecutive "packets" as if they are a continuous buffer.
- *
- * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
- * will yield different outputs:
- *
- * <code>
- * echo $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->encrypt(substr($plaintext, 8, 8));
- * </code>
- * <code>
- * echo $des->encrypt($plaintext);
- * </code>
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- * <code>
- * $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- * <code>
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the des() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see tripledes::disableContinuousBuffer()
- * @access public
- */
- function enable_continuous_buffer()
- {
- $this->continuousBuffer = true;
- if ($this->mode == CRYPT_DES_MODE_3CBC)
- {
- $this->des[0]->enable_continuous_buffer();
- $this->des[1]->enable_continuous_buffer();
- $this->des[2]->enable_continuous_buffer();
- }
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see tripledes::enableContinuousBuffer()
- * @access public
- */
- function disable_continuous_buffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
-
- if ($this->mode == CRYPT_DES_MODE_3CBC)
- {
- $this->des[0]->disable_continuous_buffer();
- $this->des[1]->disable_continuous_buffer();
- $this->des[2]->disable_continuous_buffer();
- }
- }
-
- /**
- * Pad "packets".
- *
- * DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
- * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
- *
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
- * transmitted separately)
- *
- * @see tripledes::disable_padding()
- * @access public
- */
- function enable_padding()
- {
- $this->padding = true;
- }
-
- /**
- * Do not pad packets.
- *
- * @see tripledes::enablePadding()
- * @access public
- */
- function disable_padding()
- {
- $this->padding = false;
- }
-
- /**
- * Pads a string
- *
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
- * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
- *
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
- * and padding will, hence forth, be enabled.
- *
- * @see tripledes::_unpad()
- * @access private
- */
- function _pad($text)
- {
- $length = strlen($text);
-
- if (!$this->padding)
- {
- if (($length & 7) == 0)
- {
- return $text;
- }
- else
- {
- $this->padding = true;
- }
- }
-
- $pad = 8 - ($length & 7);
- return str_pad($text, $length + $pad, chr($pad));
- }
-
- /**
- * Unpads a string
- *
- * If padding is enabled and the reported padding length exceeds the block size, padding will be, hence forth, disabled.
- *
- * @see tripledes::_pad()
- * @access private
- */
- function _unpad($text)
- {
- if (!$this->padding)
- {
- return $text;
- }
-
- $length = ord($text[strlen($text) - 1]);
-
- if ($length > 8)
- {
- $this->padding = false;
- return $text;
- }
-
- return substr($text, 0, -$length);
- }
-}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/hash.php b/phpBB/includes/libraries/sftp/hash.php deleted file mode 100644 index eb048f5d28..0000000000 --- a/phpBB/includes/libraries/sftp/hash.php +++ /dev/null @@ -1,278 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access private
- * @see hash::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_HASH_MODE_INTERNAL', 1);
-/**
- * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
- */
-define('CRYPT_HASH_MODE_MHASH', 2);
-/**
- * Toggles the hash() implementation, which works on PHP 5.1.2+.
- */
-define('CRYPT_HASH_MODE_HASH', 3);
-/**#@-*/
-
-/**
- * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package hash
- */
-class hash
-{
- /**
- * Byte-length of compression blocks / key (Internal HMAC)
- *
- * @see hash::set_algorithm()
- * @var Integer
- * @access private
- */
- var $b;
-
- /**
- * Byte-length of hash output (Internal HMAC)
- *
- * @see hash::set_hash()
- * @var Integer
- * @access private
- */
- var $l;
-
- /**
- * Hash Algorithm
- *
- * @see hash::set_hash()
- * @var String
- * @access private
- */
- var $hash;
-
- /**
- * Key
- *
- * @see hash::setKey()
- * @var String
- * @access private
- */
- var $key = '';
-
- /**
- * Outer XOR (Internal HMAC)
- *
- * @see hash::setKey()
- * @var String
- * @access private
- */
- var $opad;
-
- /**
- * Inner XOR (Internal HMAC)
- *
- * @see hash::setKey()
- * @var String
- * @access private
- */
- var $ipad;
-
- /**
- * Default Constructor.
- *
- * @param optional String $hash
- * @return hash
- * @access public
- */
- function __construct($hash = 'sha1')
- {
- if ( !defined('CRYPT_HASH_MODE') )
- {
- switch (true)
- {
- case extension_loaded('hash'):
- define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
- break;
- case extension_loaded('mhash'):
- define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
- break;
- default:
- define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
- }
- }
-
- $this->set_hash($hash);
- }
-
- /**
- * Sets the key for HMACs
- *
- * Keys can be of any length.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $this->key = $key;
- }
-
- /**
- * Sets the hash function.
- *
- * @access public
- * @param String $hash
- */
- function set_hash($hash)
- {
- switch ($hash)
- {
- case 'md5-96':
- case 'sha1-96':
- $this->l = 12; // 96 / 8 = 12
- break;
- case 'md5':
- $this->l = 16;
- break;
- case 'sha1':
- $this->l = 20;
- }
-
- switch (CRYPT_HASH_MODE)
- {
- case CRYPT_HASH_MODE_MHASH:
- switch ($hash)
- {
- case 'md5':
- case 'md5-96':
- $this->hash = MHASH_MD5;
- break;
- case 'sha1':
- case 'sha1-96':
- default:
- $this->hash = MHASH_SHA1;
- }
- return;
- case CRYPT_HASH_MODE_HASH:
- switch ($hash)
- {
- case 'md5':
- case 'md5-96':
- $this->hash = 'md5';
- return;
- case 'sha1':
- case 'sha1-96':
- default:
- $this->hash = 'sha1';
- }
- return;
- }
-
- switch ($hash)
- {
- case 'md5':
- case 'md5-96':
- $this->b = 64;
- $this->hash = 'md5';
- break;
- case 'sha1':
- case 'sha1-96':
- default:
- $this->b = 64;
- $this->hash = 'sha1';
- }
-
- $this->ipad = str_repeat(chr(0x36), $this->b);
- $this->opad = str_repeat(chr(0x5C), $this->b);
- }
-
- /**
- * Compute the HMAC.
- *
- * @access public
- * @param String $text
- */
- function create($text)
- {
- if (!empty($this->key))
- {
- switch (CRYPT_HASH_MODE)
- {
- case CRYPT_HASH_MODE_MHASH:
- $output = mhash($this->hash, $text, $this->key);
- break;
- case CRYPT_HASH_MODE_HASH:
- $output = hash_hmac($this->hash, $text, $this->key, true);
- break;
- case CRYPT_HASH_MODE_INTERNAL:
- $hash = $this->hash;
- /* "Applications that use keys longer than B bytes will first hash the key using H and then use the
- resultant L byte string as the actual key to HMAC."
-
- -- http://tools.ietf.org/html/rfc2104#section-2 */
- $key = strlen($this->key) > $this->b ? $hash($this->key) : $this->key;
-
- $key = str_pad($key, $this->b, chr(0));// step 1
- $temp = $this->ipad ^ $key; // step 2
- $temp .= $text; // step 3
- $temp = pack('H*', $hash($temp)); // step 4
- $output = $this->opad ^ $key; // step 5
- $output.= $temp; // step 6
- $output = pack('H*', $hash($output)); // step 7
- }
- }
- else
- {
- switch (CRYPT_HASH_MODE)
- {
- case CRYPT_HASH_MODE_MHASH:
- $output = mhash($this->hash, $text);
- break;
- case CRYPT_HASH_MODE_MHASH:
- $output = hash($this->hash, $text, true);
- break;
- case CRYPT_HASH_MODE_INTERNAL:
- $hash = $this->hash;
- $output = pack('H*', $hash($output));
- }
- }
-
- return substr($output, 0, $this->l);
- }
-}
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/random.php b/phpBB/includes/libraries/sftp/random.php deleted file mode 100644 index cfc7ef0bc7..0000000000 --- a/phpBB/includes/libraries/sftp/random.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**
- * Generate a random value. Feel free to replace this function with a cryptographically secure PRNG.
- *
- * @param optional Integer $min
- * @param optional Integer $max
- * @param optional String $randomness_path
- * @return Integer
- * @access public
- */
-function crypt_random($min = 0, $max = 0x7FFFFFFF, $randomness_path = '/dev/urandom')
-{
- static $seeded = false;
-
- if (!$seeded)
- {
- $seeded = true;
- if (file_exists($randomness_path))
- {
- $fp = fopen($randomness_path, 'r');
- $temp = unpack('Nint', fread($fp, 4));
- mt_srand($temp['int']);
- fclose($fp);
- }
- else
- {
- list($sec, $usec) = explode(' ', microtime());
- mt_srand((float) $sec + ((float) $usec * 100000));
- }
- }
-
- return mt_rand($min, $max);
-}
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/rc4.php b/phpBB/includes/libraries/sftp/rc4.php deleted file mode 100644 index 88a5c2f345..0000000000 --- a/phpBB/includes/libraries/sftp/rc4.php +++ /dev/null @@ -1,490 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementation of RC4
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access private
- * @see rc4::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_RC4_MODE_INTERNAL', 1);
-/**
- * Toggles the mcrypt implementation
- */
-define('CRYPT_RC4_MODE_MCRYPT', 2);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see rc4::_crypt()
- */
-define('CRYPT_RC4_ENCRYPT', 0);
-define('CRYPT_RC4_DECRYPT', 1);
-/**#@-*/
-
-/**
- * Pure-PHP implementation of RC4.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package rc4
- */
-class rc4
-{
- /**
- * The Key
- *
- * @see rc4::set_key()
- * @var String
- * @access private
- */
- var $key = "\0";
-
- /**
- * The Key Stream for encryption
- *
- * If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
- *
- * @see rc4::set_key()
- * @var Array
- * @access private
- */
- var $encryptStream = false;
-
- /**
- * The Key Stream for decryption
- *
- * If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
- *
- * @see rc4::set_key()
- * @var Array
- * @access private
- */
- var $decryptStream = false;
-
- /**
- * The $i and $j indexes for encryption
- *
- * @see rc4::_crypt()
- * @var Integer
- * @access private
- */
- var $encryptIndex = 0;
-
- /**
- * The $i and $j indexes for decryption
- *
- * @see rc4::_crypt()
- * @var Integer
- * @access private
- */
- var $decryptIndex = 0;
-
- /**
- * MCrypt parameters
- *
- * @see rc4::set_mcrypt()
- * @var Array
- * @access private
- */
- var $mcrypt = array('', '');
-
- /**
- * The Encryption Algorithm
- *
- * Only used if CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT. Only possible values are MCRYPT_RC4 or MCRYPT_ARCFOUR.
- *
- * @see rc4::__construct()
- * @var Integer
- * @access private
- */
- var $mode;
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used.
- *
- * @param optional Integer $mode
- * @return rc4
- * @access public
- */
- function __construct()
- {
- if ( !defined('CRYPT_RC4_MODE') )
- {
- switch (true)
- {
- case extension_loaded('mcrypt') && (defined('MCRYPT_ARCFOUR') || defined('MCRYPT_RC4')):
- // i'd check to see if rc4 was supported, by doing in_array('arcfour', mcrypt_list_algorithms('')),
- // but since that can be changed after the object has been created, there doesn't seem to be
- // a lot of point...
- define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_MCRYPT);
- break;
- default:
- define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_INTERNAL);
- }
- }
-
- switch ( CRYPT_RC4_MODE )
- {
- case CRYPT_RC4_MODE_MCRYPT:
- switch (true)
- {
- case defined('MCRYPT_ARCFOUR'):
- $this->mode = MCRYPT_ARCFOUR;
- break;
- case defined('MCRYPT_RC4');
- $this->mode = MCRYPT_RC4;
- }
- }
- }
-
- /**
- * Sets the key.
- *
- * Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
- * be used. If no key is explicitly set, it'll be assumed to be a single null byte.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $this->key = $key;
-
- if (CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT)
- {
- return;
- }
-
- $keyLength = strlen($key);
- $keyStream = array();
- for ($i = 0; $i < 256; $i++)
- {
- $keyStream[$i] = $i;
- }
- $j = 0;
- for ($i = 0; $i < 256; $i++)
- {
- $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
- $temp = $keyStream[$i];
- $keyStream[$i] = $keyStream[$j];
- $keyStream[$j] = $temp;
- }
-
- $this->encryptIndex = $this->decryptIndex = array(0, 0);
- $this->encryptStream = $this->decryptStream = $keyStream;
- }
-
- /**
- * Dummy function.
- *
- * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
- * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
- * calling set_key().
- *
- * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
- * the IV's are relatively easy to predict, an attack described by
- * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
- * can be used to quickly guess at the rest of the key. The following links elaborate:
- *
- * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
- * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
- *
- * @param String $iv
- * @see rc4::set_key()
- * @access public
- */
- function setIV($iv)
- {
- }
-
- /**
- * Sets MCrypt parameters. (optional)
- *
- * If MCrypt is being used, empty strings will be used, unless otherwise specified.
- *
- * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
- * @access public
- * @param optional Integer $algorithm_directory
- * @param optional Integer $mode_directory
- */
- function set_mcrypt($algorithm_directory = '', $mode_directory = '')
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT )
- {
- $this->mcrypt = array($algorithm_directory, $mode_directory);
- $this->_close_mcrypt();
- }
- }
-
- /**
- * Encrypts a message.
- *
- * @see rc4::_crypt()
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
- }
-
- /**
- * Decrypts a message.
- *
- * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
- * Atleast if the continuous buffer is disabled.
- *
- * @see rc4::_crypt()
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
- }
-
- /**
- * Encrypts or decrypts a message.
- *
- * @see rc4::encrypt()
- * @see rc4::decrypt()
- * @access private
- * @param String $text
- * @param Integer $mode
- */
- function _crypt($text, $mode)
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT )
- {
- $keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream';
-
- if ($this->$keyStream === false)
- {
- $this->$keyStream = mcrypt_module_open($this->mode, $this->mcrypt[0], MCRYPT_MODE_STREAM, $this->mcrypt[1]);
- mcrypt_generic_init($this->$keyStream, $this->key, '');
- }
- else if (!$this->continuousBuffer)
- {
- mcrypt_generic_init($this->$keyStream, $this->key, '');
- }
- $newText = mcrypt_generic($this->$keyStream, $text);
- if (!$this->continuousBuffer)
- {
- mcrypt_generic_deinit($this->$keyStream);
- }
-
- return $newText;
- }
-
- if ($this->encryptStream === false)
- {
- $this->set_key($this->key);
- }
-
- switch ($mode)
- {
- case CRYPT_RC4_ENCRYPT:
- $keyStream = $this->encryptStream;
- list($i, $j) = $this->encryptIndex;
- break;
- case CRYPT_RC4_DECRYPT:
- $keyStream = $this->decryptStream;
- list($i, $j) = $this->decryptIndex;
- }
-
- $newText = '';
- for ($k = 0; $k < strlen($text); $k++)
- {
- $i = ($i + 1) & 255;
- $j = ($j + $keyStream[$i]) & 255;
- $temp = $keyStream[$i];
- $keyStream[$i] = $keyStream[$j];
- $keyStream[$j] = $temp;
- $temp = $keyStream[($keyStream[$i] + $keyStream[$j]) & 255];
- $newText.= chr(ord($text[$k]) ^ $temp);
- }
-
- if ($this->continuousBuffer)
- {
- switch ($mode)
- {
- case CRYPT_RC4_ENCRYPT:
- $this->encryptStream = $keyStream;
- $this->encryptIndex = array($i, $j);
- break;
- case CRYPT_RC4_DECRYPT:
- $this->decryptStream = $keyStream;
- $this->decryptIndex = array($i, $j);
- }
- }
-
- return $newText;
- }
-
- /**
- * Treat consecutive "packets" as if they are a continuous buffer.
- *
- * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
- * will yield different outputs:
- *
- * <code>
- * echo $rc4->encrypt(substr($plaintext, 0, 8));
- * echo $rc4->encrypt(substr($plaintext, 8, 8));
- * </code>
- * <code>
- * echo $rc4->encrypt($plaintext);
- * </code>
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- * <code>
- * $rc4->encrypt(substr($plaintext, 0, 8));
- * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- * <code>
- * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see rc4::disable_continuous_buffer()
- * @access public
- */
- function enable_continuous_buffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see rc4::enable_continuous_buffer()
- * @access public
- */
- function disable_continuous_buffer()
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL )
- {
- $this->encryptIndex = $this->decryptIndex = array(0, 0);
- $this->set_key($this->key);
- }
-
- $this->continuousBuffer = false;
- }
-
- /**
- * Dummy function.
- *
- * Since RC4 is a stream cipher and not a block cipher, no padding is necessary. The only reason this function is
- * included is so that you can switch between a block cipher and a stream cipher transparently.
- *
- * @see rc4::disable_padding()
- * @access public
- */
- function enable_padding()
- {
- }
-
- /**
- * Dummy function.
- *
- * @see rc4::enable_padding()
- * @access public
- */
- function disable_padding()
- {
- }
-
- /**
- * Class destructor.
- *
- * Will be called, automatically, if you're using PHP5. If you're using PHP4, call it yourself. Only really
- * needs to be called if mcrypt is being used.
- *
- * @access public
- */
- function __destruct()
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT )
- {
- $this->_close_mcrypt();
- }
- }
-
- /**
- * Properly close the MCrypt objects.
- *
- * @access prviate
- */
- function _close_mcrypt()
- {
- if ( $this->encryptStream !== false )
- {
- if ( $this->continuousBuffer )
- {
- mcrypt_generic_deinit($this->encryptStream);
- }
-
- mcrypt_module_close($this->encryptStream);
-
- $this->encryptStream = false;
- }
-
- if ( $this->decryptStream !== false )
- {
- if ( $this->continuousBuffer )
- {
- mcrypt_generic_deinit($this->decryptStream);
- }
-
- mcrypt_module_close($this->decryptStream);
-
- $this->decryptStream = false;
- }
- }
-}
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/sftp.php b/phpBB/includes/libraries/sftp/sftp.php deleted file mode 100644 index 41915c5ea9..0000000000 --- a/phpBB/includes/libraries/sftp/sftp.php +++ /dev/null @@ -1,3247 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementation of ssh2
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-include('biginteger.' . PHP_EXT);
-include('random.' . PHP_EXT);
-include('hash.' . PHP_EXT);
-include('rc4.' . PHP_EXT);
-include('aes.' . PHP_EXT);
-include('des.' . PHP_EXT);
-
-/**#@+
- * Execution Bitmap Masks
- *
- * @see ssh2::bitmap
- * @access private
- */
-define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
-define('NET_SSH2_MASK_LOGIN', 0x00000002);
-/**#@-*/
-
-/**#@+
- * @access public
- * @see ssh2::getLog()
- */
-/**
- * Returns the message numbers
- */
-define('NET_SSH2_LOG_SIMPLE', 1);
-/**
- * Returns the message content
- */
-define('NET_SSH2_LOG_COMPLEX', 2);
-/**#@-*/
-
-/**#@+
- * @access public
- * @see ssh2_sftp::get_log()
- */
-/**
- * Returns the message numbers
- */
-define('NET_SFTP_LOG_SIMPLE', NET_SSH2_LOG_SIMPLE);
-/**
- * Returns the message content
- */
-define('NET_SFTP_LOG_COMPLEX', NET_SSH2_LOG_COMPLEX);
-/**#@-*/
-
-/**
- * Pure-PHP implementation of SSHv2.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package ssh2
- */
-class ssh2
-{
- /**
- * The SSH identifier
- *
- * @var String
- * @access private
- */
- var $identifier = 'SSH-2.0-phpseclib_0.1';
-
- /**
- * The Socket Object
- *
- * @var Object
- * @access private
- */
- var $fsock;
-
- /**
- * Execution Bitmap
- *
- * The bits that are set reprsent functions that have been called already. This is used to determine
- * if a requisite function has been successfully executed. If not, an error should be thrown.
- *
- * @var Integer
- * @access private
- */
- var $bitmap = 0;
-
- /**
- * Debug Info
- *
- * @see ssh2::get_debug_info()
- * @var String
- * @access private
- */
- var $debug_info = '';
-
- /**
- * Server Identifier
- *
- * @see ssh2::get_server_identification()
- * @var String
- * @access private
- */
- var $server_identifier = '';
-
- /**
- * Key Exchange Algorithms
- *
- * @see ssh2::get_kex_algorithims()
- * @var Array
- * @access private
- */
- var $kex_algorithms;
-
- /**
- * Server Host Key Algorithms
- *
- * @see ssh2::get_server_host_key_algorithms()
- * @var Array
- * @access private
- */
- var $server_host_key_algorithms;
-
- /**
- * Encryption Algorithms: Client to Server
- *
- * @see ssh2::get_encryption_algorithms_client_to_server()
- * @var Array
- * @access private
- */
- var $encryption_algorithms_client_to_server;
-
- /**
- * Encryption Algorithms: Server to Client
- *
- * @see ssh2::get_encryption_algorithms_server_to_client()
- * @var Array
- * @access private
- */
- var $encryption_algorithms_server_to_client;
-
- /**
- * MAC Algorithms: Client to Server
- *
- * @see ssh2::get_mac_algorithms_client_to_server()
- * @var Array
- * @access private
- */
- var $mac_algorithms_client_to_server;
-
- /**
- * MAC Algorithms: Server to Client
- *
- * @see ssh2::get_mac_algorithms_server_to_client()
- * @var Array
- * @access private
- */
- var $mac_algorithms_server_to_client;
-
- /**
- * Compression Algorithms: Client to Server
- *
- * @see ssh2::get_compression_algorithms_client_to_server()
- * @var Array
- * @access private
- */
- var $compression_algorithms_client_to_server;
-
- /**
- * Compression Algorithms: Server to Client
- *
- * @see ssh2::get_compression_algorithms_server_to_client()
- * @var Array
- * @access private
- */
- var $compression_algorithms_server_to_client;
-
- /**
- * Languages: Server to Client
- *
- * @see ssh2::get_languages_server_to_client()
- * @var Array
- * @access private
- */
- var $languages_server_to_client;
-
- /**
- * Languages: Client to Server
- *
- * @see ssh2::get_languages_client_to_server()
- * @var Array
- * @access private
- */
- var $languages_client_to_server;
-
- /**
- * Block Size for Server to Client Encryption
- *
- * "Note that the length of the concatenation of 'packet_length',
- * 'padding_length', 'payload', and 'random padding' MUST be a multiple
- * of the cipher block size or 8, whichever is larger. This constraint
- * MUST be enforced, even when using stream ciphers."
- *
- * -- http://tools.ietf.org/html/rfc4253#section-6
- *
- * @see ssh2::__constructor()
- * @see ssh2::_send_binary_packet()
- * @var Integer
- * @access private
- */
- var $encrypt_block_size = 8;
-
- /**
- * Block Size for Client to Server Encryption
- *
- * @see ssh2::ssh2()
- * @see ssh2::_get_binary_packet()
- * @var Integer
- * @access private
- */
- var $decrypt_block_size = 8;
-
- /**
- * Server to Client Encryption Object
- *
- * @see ssh2::_get_binary_packet()
- * @var Object
- * @access private
- */
- var $decrypt = false;
-
- /**
- * Client to Server Encryption Object
- *
- * @see ssh2::_send_binary_packet()
- * @var Object
- * @access private
- */
- var $encrypt = false;
-
- /**
- * Client to Server HMAC Object
- *
- * @see ssh2::_send_binary_packet()
- * @var Object
- * @access private
- */
- var $hmac_create = false;
-
- /**
- * Server to Client HMAC Object
- *
- * @see ssh2::_get_binary_packet()
- * @var Object
- * @access private
- */
- var $hmac_check = false;
-
- /**
- * Size of server to client HMAC
- *
- * We need to know how big the HMAC will be for the server to client direction so that we know how many bytes to read.
- * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is
- * append it.
- *
- * @see ssh2::_get_binary_packet()
- * @var Integer
- * @access private
- */
- var $hmac_size = false;
-
- /**
- * Server Public Host Key
- *
- * @see ssh2::getServerPublicHostKey()
- * @var String
- * @access private
- */
- var $server_public_host_key;
-
- /**
- * Session identifer
- *
- * "The exchange hash H from the first key exchange is additionally
- * used as the session identifier, which is a unique identifier for
- * this connection."
- *
- * -- http://tools.ietf.org/html/rfc4253#section-7.2
- *
- * @see ssh2::_key_exchange()
- * @var String
- * @access private
- */
- var $session_id = false;
-
- /**
- * Message Numbers
- *
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $message_numbers = array();
-
- /**
- * Disconnection Message 'reason codes' defined in RFC4253
- *
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $disconnect_reasons = array();
-
- /**
- * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
- *
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $channel_open_failure_reasons = array();
-
- /**
- * Terminal Modes
- *
- * @link http://tools.ietf.org/html/rfc4254#section-8
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $terminal_modes = array();
-
- /**
- * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
- *
- * @link http://tools.ietf.org/html/rfc4254#section-5.2
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $channel_extended_data_type_codes = array();
-
- /**
- * Send Sequence Number
- *
- * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
- *
- * @see ssh2::_send_binary_packet()
- * @var Integer
- * @access private
- */
- var $send_seq_no = 0;
-
- /**
- * Get Sequence Number
- *
- * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
- *
- * @see ssh2::_get_binary_packet()
- * @var Integer
- * @access private
- */
- var $get_seq_no = 0;
-
- /**
- * Message Number Log
- *
- * @see ssh2::getLog()
- * @var Array
- * @access private
- */
- var $message_number_log = array();
-
- /**
- * Message Log
- *
- * @see ssh2::getLog()
- * @var Array
- * @access private
- */
- var $message_log = array();
-
- /**
- * Default Constructor.
- *
- * Connects to an SSHv2 server
- *
- * @param String $host
- * @param optional Integer $port
- * @param optional Integer $timeout
- * @return ssh2
- * @access public
- */
- function __construct($host, $port = 22, $timeout = 10)
- {
- $this->message_numbers = array(
- 1 => 'NET_SSH2_MSG_DISCONNECT',
- 2 => 'NET_SSH2_MSG_IGNORE',
- 3 => 'NET_SSH2_MSG_UNIMPLEMENTED',
- 4 => 'NET_SSH2_MSG_DEBUG',
- 5 => 'NET_SSH2_MSG_SERVICE_REQUEST',
- 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT',
- 20 => 'NET_SSH2_MSG_KEXINIT',
- 21 => 'NET_SSH2_MSG_NEWKEYS',
- 30 => 'NET_SSH2_MSG_KEXDH_INIT',
- 31 => 'NET_SSH2_MSG_KEXDH_REPLY',
- 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST',
- 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE',
- 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS',
- 53 => 'NET_SSH2_MSG_USERAUTH_BANNER',
- 60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ',
-
- 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST',
- 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS',
- 82 => 'NET_SSH2_MSG_REQUEST_FAILURE',
- 90 => 'NET_SSH2_MSG_CHANNEL_OPEN',
- 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION',
- 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE',
- 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST',
- 94 => 'NET_SSH2_MSG_CHANNEL_DATA',
- 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA',
- 96 => 'NET_SSH2_MSG_CHANNEL_EOF',
- 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE',
- 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST',
- 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS',
- 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'
- );
- $this->disconnect_reasons = array(
- 1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
- 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
- 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
- 4 => 'NET_SSH2_DISCONNECT_RESERVED',
- 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
- 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
- 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
- 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
- 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
- 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
- 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
- 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
- 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
- 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
- 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
- );
- $this->channel_open_failure_reasons = array(
- 1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'
- );
- $this->terminal_modes = array(
- 0 => 'NET_SSH2_TTY_OP_END'
- );
- $this->channel_extended_data_type_codes = array(
- 1 => 'NET_SSH2_EXTENDED_DATA_STDERR'
- );
-
- $this->_define_array(
- $this->message_numbers,
- $this->disconnect_reasons,
- $this->channel_open_failure_reasons,
- $this->terminal_modes,
- $this->channel_extended_data_type_codes
- );
-
- $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
- if (!$this->fsock)
- {
- return;
- }
-
- /* According to the SSH2 specs,
-
- "The server MAY send other lines of data before sending the version
- string. Each line SHOULD be terminated by a Carriage Return and Line
- Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
- in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients
- MUST be able to process such lines." */
- $temp = '';
- while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches))
- {
- if (substr($temp, -2) == "\r\n")
- {
- $this->debug_info.= $temp;
- $temp = '';
- }
- $temp.= fgets($this->fsock, 255);
- }
- $this->server_identifier = trim($temp);
- $this->debug_info = utf8_decode($this->debug_info);
-
- if ($matches[1] != '1.99' && $matches[1] != '2.0')
- {
- return;
- }
-
- fputs($this->fsock, $this->identifier . "\r\n");
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return;
- }
-
- if (ord($response[0]) != NET_SSH2_MSG_KEXINIT)
- {
- return;
- }
-
- if (!$this->_key_exchange($response))
- {
- return;
- }
-
- $this->bitmap = NET_SSH2_MASK_CONSTRUCTOR;
- }
-
- /**
- * Key Exchange
- *
- * @param String $kexinit_payload_server
- * @access private
- */
- function _key_exchange($kexinit_payload_server)
- {
- static $kex_algorithms = array(
- 'diffie-hellman-group1-sha1', // REQUIRED
- 'diffie-hellman-group14-sha1' // REQUIRED
- );
-
- static $server_host_key_algorithms = array(
- 'ssh-rsa', // RECOMMENDED sign Raw RSA Key
- 'ssh-dss' // REQUIRED sign Raw DSS Key
- );
-
- static $encryption_algorithms = array(
- 'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
- 'aes128-cbc', // RECOMMENDED AES with a 128-bit key
- 'aes192-cbc', // OPTIONAL AES with a 192-bit key
- 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
- '3des-cbc', // REQUIRED three-key 3DES in CBC mode
- 'none' // OPTIONAL no encryption; NOT RECOMMENDED
- );
-
- static $mac_algorithms = array(
- 'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
- 'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20)
- 'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
- 'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16)
- 'none' // OPTIONAL no MAC; NOT RECOMMENDED
- );
-
- static $compression_algorithms = array(
- 'none' // REQUIRED no compression
- //'zlib' // OPTIONAL ZLIB (LZ77) compression
- );
-
- static $str_kex_algorithms, $str_server_host_key_algorithms,
- $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client,
- $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server;
-
- if (empty($str_kex_algorithms)) {
- $str_kex_algorithms = implode(',', $kex_algorithms);
- $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
- $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
- $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
- $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
- }
-
- $client_cookie = '';
- for ($i = 0; $i < 16; $i++)
- {
- $client_cookie.= chr(crypt_random(0, 255));
- }
-
- $response = $kexinit_payload_server;
- $this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT)
- list(, $server_cookie) = unpack('a16', $this->_string_shift($response, 16));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
-
- list(, $first_kex_packet_follows) = unpack('C', $this->_string_shift($response, 1));
- $first_kex_packet_follows = $first_kex_packet_follows != 0;
-
- // the sending of NET_SSH2_MSG_KEXINIT could go in one of two places. this is the second place.
- $kexinit_payload_client = pack('Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
- NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms,
- strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server),
- $encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client,
- strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client),
- $mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server,
- strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '',
- 0, 0
- );
-
- if (!$this->_send_binary_packet($kexinit_payload_client))
- {
- return false;
- }
- // here ends the second place.
-
- // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
- for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++);
- if ($i == count($encryption_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
- // diffie-hellman key exchange as fast as possible
- $decrypt = $encryption_algorithms[$i];
- switch ($decrypt)
- {
- case '3des-cbc':
- $decryptKeyLength = 24; // eg. 192 / 8
- break;
- case 'aes256-cbc':
- $decryptKeyLength = 32; // eg. 256 / 8
- break;
- case 'aes192-cbc':
- $decryptKeyLength = 24; // eg. 192 / 8
- break;
- case 'aes128-cbc':
- $decryptKeyLength = 16; // eg. 128 / 8
- break;
- case 'arcfour':
- $decryptKeyLength = 16; // eg. 128 / 8
- break;
- case 'none';
- $decryptKeyLength = 0;
- }
-
- for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++);
- if ($i == count($encryption_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $encrypt = $encryption_algorithms[$i];
- switch ($encrypt)
- {
- case '3des-cbc':
- $encryptKeyLength = 24;
- break;
- case 'aes256-cbc':
- $encryptKeyLength = 32;
- break;
- case 'aes192-cbc':
- $encryptKeyLength = 24;
- break;
- case 'aes128-cbc':
- $encryptKeyLength = 16;
- break;
- case 'arcfour':
- $encryptKeyLength = 16;
- break;
- case 'none';
- $encryptKeyLength = 0;
- }
-
- $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
-
- // through diffie-hellman key exchange a symmetric key is obtained
- for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++);
- if ($i == count($kex_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- switch ($kex_algorithms[$i])
- {
- // see http://tools.ietf.org/html/rfc2409#section-6.2 and
- // http://tools.ietf.org/html/rfc2412, appendex E
- case 'diffie-hellman-group1-sha1':
- $p = pack('N32', 0xFFFFFFFF, 0xFFFFFFFF, 0xC90FDAA2, 0x2168C234, 0xC4C6628B, 0x80DC1CD1,
- 0x29024E08, 0x8A67CC74, 0x020BBEA6, 0x3B139B22, 0x514A0879, 0x8E3404DD,
- 0xEF9519B3, 0xCD3A431B, 0x302B0A6D, 0xF25F1437, 0x4FE1356D, 0x6D51C245,
- 0xE485B576, 0x625E7EC6, 0xF44C42E9, 0xA637ED6B, 0x0BFF5CB6, 0xF406B7ED,
- 0xEE386BFB, 0x5A899FA5, 0xAE9F2411, 0x7C4B1FE6, 0x49286651, 0xECE65381,
- 0xFFFFFFFF, 0xFFFFFFFF);
- $keyLength = $keyLength < 160 ? $keyLength : 160;
- $hash = 'sha1';
- break;
- // see http://tools.ietf.org/html/rfc3526#section-3
- case 'diffie-hellman-group14-sha1':
- $p = pack('N64', 0xFFFFFFFF, 0xFFFFFFFF, 0xC90FDAA2, 0x2168C234, 0xC4C6628B, 0x80DC1CD1,
- 0x29024E08, 0x8A67CC74, 0x020BBEA6, 0x3B139B22, 0x514A0879, 0x8E3404DD,
- 0xEF9519B3, 0xCD3A431B, 0x302B0A6D, 0xF25F1437, 0x4FE1356D, 0x6D51C245,
- 0xE485B576, 0x625E7EC6, 0xF44C42E9, 0xA637ED6B, 0x0BFF5CB6, 0xF406B7ED,
- 0xEE386BFB, 0x5A899FA5, 0xAE9F2411, 0x7C4B1FE6, 0x49286651, 0xECE45B3D,
- 0xC2007CB8, 0xA163BF05, 0x98DA4836, 0x1C55D39A, 0x69163FA8, 0xFD24CF5F,
- 0x83655D23, 0xDCA3AD96, 0x1C62F356, 0x208552BB, 0x9ED52907, 0x7096966D,
- 0x670C354E, 0x4ABC9804, 0xF1746C08, 0xCA18217C, 0x32905E46, 0x2E36CE3B,
- 0xE39E772C, 0x180E8603, 0x9B2783A2, 0xEC07A28F, 0xB5C55DF0, 0x6F4C52C9,
- 0xDE2BCBF6, 0x95581718, 0x3995497C, 0xEA956AE5, 0x15D22618, 0x98FA0510,
- 0x15728E5A, 0x8AACAA68, 0xFFFFFFFF, 0xFFFFFFFF);
- $keyLength = $keyLength < 160 ? $keyLength : 160;
- $hash = 'sha1';
- }
-
- $p = new biginteger($p, 256);
- //$q = $p->bitwise_right_shift(1);
-
- /* To increase the speed of the key exchange, both client and server may
- reduce the size of their private exponents. It should be at least
- twice as long as the key material that is generated from the shared
- secret. For more details, see the paper by van Oorschot and Wiener
- [VAN-OORSCHOT].
-
- -- http://tools.ietf.org/html/rfc4419#section-6.2 */
- $q = new biginteger(1);
- $q = $q->bitwise_left_shift(2 * $keyLength);
- $q = $q->subtract(new biginteger(1));
-
- $g = new biginteger(2);
- $x = new biginteger();
- $x = $x->random(new biginteger(1), $q, 'crypt_random');
- $e = $g->mod_pow($x, $p);
-
- $eBytes = $e->to_bytes(true);
- $data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes);
-
- if (!$this->_send_binary_packet($data))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- if ($type != NET_SSH2_MSG_KEXDH_REPLY)
- {
- return false;
- }
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $fBytes = $this->_string_shift($response, $temp['length']);
- $f = new biginteger($fBytes, -256);
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $signature = $this->_string_shift($response, $temp['length']);
-
- $temp = unpack('Nlength', $this->_string_shift($signature, 4));
- $signature_format = $this->_string_shift($signature, $temp['length']);
-
- $key = $f->mod_pow($x, $p);
- $keyBytes = $key->to_bytes(true);
-
- $source = pack('Na*Na*Na*Na*Na*Na*Na*Na*',
- strlen($this->identifier), $this->identifier, strlen($this->server_identifier), $this->server_identifier,
- strlen($kexinit_payload_client), $kexinit_payload_client, strlen($kexinit_payload_server),
- $kexinit_payload_server, strlen($this->server_public_host_key), $this->server_public_host_key, strlen($eBytes),
- $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes
- );
-
- $source = pack('H*', $hash($source));
-
- if ($this->session_id === false)
- {
- $this->session_id = $source;
- }
-
- // if you the server's assymetric key matches the one you have on file, then you should be able to decrypt the
- // "signature" and get something that should equal the "exchange hash", as defined in the SSH-2 specs.
- // here, we just check to see if the "signature" is good. you can verify whether or not the assymetric key is good,
- // later, with the getServerHostKeyAlgorithm() function
- for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++);
- if ($i == count($server_host_key_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- if ($public_key_format != $server_host_key_algorithms[$i] || $signature_format != $server_host_key_algorithms[$i])
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- switch ($server_host_key_algorithms[$i])
- {
- case 'ssh-dss':
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $p = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $q = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $g = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $y = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- /* The value for 'dss_signature_blob' is encoded as a string containing
- r, followed by s (which are 160-bit integers, without lengths or
- padding, unsigned, and in network byte order). */
- $temp = unpack('Nlength', $this->_string_shift($signature, 4));
- if ($temp['length'] != 40)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $r = new biginteger($this->_string_shift($signature, 20), 256);
- $s = new biginteger($this->_string_shift($signature, 20), 256);
-
- if ($r->compare($q) >= 0 || $s->compare($q) >= 0)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $w = $s->mod_inverse($q);
-
- $u1 = $w->multiply(new biginteger(sha1($source), 16));
- list(, $u1) = $u1->divide($q);
-
- $u2 = $w->multiply($r);
- list(, $u2) = $u2->divide($q);
-
- $g = $g->mod_pow($u1, $p);
- $y = $y->mod_pow($u2, $p);
-
- $v = $g->multiply($y);
- list(, $v) = $v->divide($p);
- list(, $v) = $v->divide($q);
-
- if ($v->compare($r) != 0)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
- }
-
- break;
- case 'ssh-rsa':
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $e = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $n = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
- $nLength = $temp['length'];
-
- $temp = unpack('Nlength', $this->_string_shift($signature, 4));
- $s = new biginteger($this->_string_shift($signature, $temp['length']), 256);
-
- // validate an RSA signature per "8.2 RSASSA-PKCS1-v1_5", "5.2.2 RSAVP1", and "9.1 EMSA-PSS" in the
- // following URL:
- // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
-
- // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
-
- if ($s->compare(new biginteger()) < 0 || $s->compare($n->subtract(new biginteger(1))) > 0)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $s = $s->mod_pow($e, $n);
- $s = $s->to_bytes();
-
- $h = pack('N4H*', 0x00302130, 0x0906052B, 0x0E03021A, 0x05000414, sha1($source));
- $h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 3 - strlen($h)) . $h;
-
- if ($s != $h)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
- }
- }
-
- $packet = pack('C',
- NET_SSH2_MSG_NEWKEYS
- );
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
-
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- if ($type != NET_SSH2_MSG_NEWKEYS)
- {
- return false;
- }
-
- switch ($encrypt)
- {
- case '3des-cbc':
- $this->encrypt = new tripledes();
- // $this->encrypt_block_size = 64 / 8 == the default
- break;
- case 'aes256-cbc':
- $this->encrypt = new aes();
- $this->encrypt_block_size = 16; // eg. 128 / 8
- break;
- case 'aes192-cbc':
- $this->encrypt = new aes();
- $this->encrypt_block_size = 16;
- break;
- case 'aes128-cbc':
- $this->encrypt = new aes();
- $this->encrypt_block_size = 16;
- break;
- case 'arcfour':
- $this->encrypt = new rc4();
- }
-
- switch ($decrypt)
- {
- case '3des-cbc':
- $this->decrypt = new tripledes();
- break;
- case 'aes256-cbc':
- $this->decrypt = new aes();
- $this->decrypt_block_size = 16;
- break;
- case 'aes192-cbc':
- $this->decrypt = new aes();
- $this->decrypt_block_size = 16;
- break;
- case 'aes128-cbc':
- $this->decrypt = new aes();
- $this->decrypt_block_size = 16;
- break;
- case 'arcfour':
- $this->decrypt = new rc4();
- }
-
- $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
-
- if ($this->encrypt)
- {
- $this->encrypt->enable_continuous_buffer();
- $this->encrypt->disable_padding();
-
- $iv = pack('H*', $hash($keyBytes . $source . 'A' . $this->session_id));
- while ($this->encrypt_block_size > strlen($iv)) {
- $iv.= pack('H*', $hash($keyBytes . $source . $iv));
- }
- $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
-
- $key = pack('H*', $hash($keyBytes . $source . 'C' . $this->session_id));
- while ($encryptKeyLength > strlen($key))
- {
- $key.= pack('H*', $hash($keyBytes . $source . $key));
- }
- $this->encrypt->set_key(substr($key, 0, $encryptKeyLength));
- }
-
- if ($this->decrypt)
- {
- $this->decrypt->enable_continuous_buffer();
- $this->decrypt->disable_padding();
-
- $iv = pack('H*', $hash($keyBytes . $source . 'B' . $this->session_id));
- while ($this->decrypt_block_size > strlen($iv))
- {
- $iv.= pack('H*', $hash($keyBytes . $source . $iv));
- }
- $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
-
- $key = pack('H*', $hash($keyBytes . $source . 'D' . $this->session_id));
- while ($decryptKeyLength > strlen($key))
- {
- $key.= pack('H*', $hash($keyBytes . $source . $key));
- }
- $this->decrypt->set_key(substr($key, 0, $decryptKeyLength));
- }
-
- for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++);
- if ($i == count($mac_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none'
- switch ($mac_algorithms[$i])
- {
- case 'hmac-sha1':
- $this->hmac_create = new hash('sha1');
- $createKeyLength = 20;
- break;
- case 'hmac-sha1-96':
- $this->hmac_create = new hash('sha1-96');
- $createKeyLength = 20;
- break;
- case 'hmac-md5':
- $this->hmac_create = new hash('md5');
- $createKeyLength = 16;
- break;
- case 'hmac-md5-96':
- $this->hmac_create = new hash('md5-96');
- $createKeyLength = 16;
- }
-
- for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++);
- if ($i == count($mac_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $checkKeyLength = 0;
- $this->hmac_size = 0;
- switch ($mac_algorithms[$i])
- {
- case 'hmac-sha1':
- $this->hmac_check = new hash('sha1');
- $checkKeyLength = 20;
- $this->hmac_size = 20;
- break;
- case 'hmac-sha1-96':
- $this->hmac_check = new hash('sha1-96');
- $checkKeyLength = 20;
- $this->hmac_size = 12;
- break;
- case 'hmac-md5':
- $this->hmac_check = new hash('md5');
- $checkKeyLength = 16;
- $this->hmac_size = 16;
- break;
- case 'hmac-md5-96':
- $this->hmac_check = new hash('md5-96');
- $checkKeyLength = 16;
- $this->hmac_size = 12;
- }
-
- $key = pack('H*', $hash($keyBytes . $source . 'E' . $this->session_id));
- while ($createKeyLength > strlen($key))
- {
- $key.= pack('H*', $hash($keyBytes . $source . $key));
- }
- $this->hmac_create->set_key(substr($key, 0, $createKeyLength));
-
- $key = pack('H*', $hash($keyBytes . $source . 'F' . $this->session_id));
- while ($checkKeyLength > strlen($key))
- {
- $key.= pack('H*', $hash($keyBytes . $source . $key));
- }
- $this->hmac_check->set_key(substr($key, 0, $checkKeyLength));
-
- for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++);
- if ($i == count($compression_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
- $this->decompress = $compression_algorithms[$i] == 'zlib';
-
- for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++);
- if ($i == count($compression_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
- $this->compress = $compression_algorithms[$i] == 'zlib';
-
- return true;
- }
-
- /**
- * Login
- *
- * @param String $username
- * @param optional String $password
- * @return Boolean
- * @access public
- * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
- by sending dummy SSH_MSG_IGNORE messages.
- */
- function login($username, $password = '')
- {
- if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR))
- {
- return false;
- }
-
- $packet = pack('CNa*',
- NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth'
- );
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- if ($type != NET_SSH2_MSG_SERVICE_ACCEPT)
- {
- return false;
- }
-
- // publickey authentication is required, per the SSH-2 specs, however, we don't support it.
- $utf8_password = utf8_encode($password);
- $packet = pack('CNa*Na*Na*CNa*',
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
- strlen('password'), 'password', 0, strlen($utf8_password), $utf8_password
- );
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- // remove the username and password from the last logged packet
- if (defined('NET_SSH2_LOGGING'))
- {
- $packet = pack('CNa*Na*Na*CNa*',
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen('username'), 'username', strlen('ssh-connection'), 'ssh-connection',
- strlen('password'), 'password', 0, strlen('password'), 'password'
- );
- $this->message_log[count($this->message_log) - 1] = $packet;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // in theory, the password can be changed
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_PASSWD_CHANGEREQ:\r\n" . utf8_decode($this->_string_shift($response, $length));
- return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
- case NET_SSH2_MSG_USERAUTH_FAILURE:
- list(, $length) = unpack('Nlength', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_FAILURE:\r\n" . $this->_string_shift($response, $length);
- return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
- case NET_SSH2_MSG_USERAUTH_SUCCESS:
- $this->bitmap |= NET_SSH2_MASK_LOGIN;
- return true;
- }
-
- return false;
- }
-
- /**
- * Execute Command
- *
- * @param String $command
- * @return String
- * @access public
- */
- function exec($command)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $client_channel = 0; // PuTTy uses 0x100
- // RFC4254 defines the window size as "bytes the other party can send before it must wait for the window to be
- // adjusted". 0x7FFFFFFF is, at 4GB, the max size. technically, it should probably be decremented, but, honestly,
- // if you're transfering more than 4GB, you probably shouldn't be using phpseclib, anyway.
- // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
- $window_size = 0x7FFFFFFF;
- // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
- // uses 0x4000, that's what will be used here, as well. 0x7FFFFFFF could be used, as well (i've not encountered
- // any problems, using it, myself), but that's not what the specs say, so whatever.
- $packet_size = 0x4000;
-
- $packet = pack('CNa*N3',
- NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', $client_channel, $window_size, $packet_size);
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
- $this->_string_shift($response, 4);
- list(, $server_channel) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
- $packet = pack('CNNa*CNa*N5a*',
- NET_SSH2_MSG_CHANNEL_REQUEST, $server_channel, strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100',
- 80, 24, 0, 0, strlen($terminal_modes), $terminal_modes);
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_SUCCESS:
- break;
- case NET_SSH2_MSG_CHANNEL_FAILURE:
- default:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $packet = pack('CNNa*CNa*',
- NET_SSH2_MSG_CHANNEL_REQUEST, $server_channel, strlen('exec'), 'exec', 1, strlen($command), $command);
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_SUCCESS:
- break;
- case NET_SSH2_MSG_CHANNEL_FAILURE:
- default:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $output = '';
- while (true)
- {
- $temp = $this->_get_channel_packet();
- switch (true)
- {
- case $temp === true:
- return $output;
- case $temp === false:
- return false;
- default:
- $output.= $temp;
- }
- }
- }
-
- /**
- * Disconnect
- *
- * @access public
- */
- function disconnect()
- {
- $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- /**
- * Destructor.
- *
- * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
- * disconnect().
- *
- * @access public
- */
- function __destruct()
- {
- $this->disconnect();
- }
-
- /**
- * Gets Binary Packets
- *
- * See '6. Binary Packet Protocol' of rfc4253 for more info.
- *
- * @see ssh2::_send_binary_packet()
- * @return String
- * @access private
- */
- function _get_binary_packet()
- {
- if (feof($this->fsock))
- {
- return false;
- }
-
- $raw = fread($this->fsock, $this->decrypt_block_size);
-
- if ($this->decrypt !== false)
- {
- $raw = $this->decrypt->decrypt($raw);
- }
-
- $temp = unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5));
- $packet_length = $temp['packet_length'];
- $padding_length = $temp['padding_length'];
-
- $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
- $buffer = '';
- while ($remaining_length > 0)
- {
- $temp = fread($this->fsock, $remaining_length);
- $buffer.= $temp;
- $remaining_length-= strlen($temp);
- }
- if (!empty($buffer))
- {
- $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
- $buffer = $temp = '';
- }
-
- $payload = $this->_string_shift($raw, $packet_length - $padding_length - 1);
- $padding = $this->_string_shift($raw, $padding_length); // should leave $raw empty
-
- if ($this->hmac_check !== false)
- {
- $hmac = fread($this->fsock, $this->hmac_size);
- if ($hmac != $this->hmac_check->create(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding)))
- {
- return false;
- }
- }
-
- //if ($this->decompress)
- //{
- // $payload = gzinflate(substr($payload, 2));
- //}
-
- $this->get_seq_no++;
-
- if (defined('NET_SSH2_LOGGING'))
- {
- $this->message_number_log[] = '<- ' . $this->message_numbers[ord($payload[0])];
- $this->message_log[] = $payload;
- }
-
- return $this->_filter($payload);
- }
-
- /**
- * Filter Binary Packets
- *
- * Because some binary packets need to be ignored...
- *
- * @see ssh2::_get_binary_packet()
- * @return String
- * @access private
- */
- function _filter($payload)
- {
- switch (ord($payload[0]))
- {
- case NET_SSH2_MSG_DISCONNECT:
- $this->_string_shift($payload, 1);
- list(, $reason_code, $length) = unpack('N2', $this->_string_shift($payload, 8));
- $this->debug_info.= "\r\n\r\nSSH_MSG_DISCONNECT:\r\n" . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode($this->_string_shift($payload, $temp['length']));
- $this->bitmask = 0;
- return false;
- case NET_SSH2_MSG_IGNORE:
- $payload = $this->_get_binary_packet();
- break;
- case NET_SSH2_MSG_DEBUG:
- $this->_string_shift($payload, 2);
- list(, $length) = unpack('N', $payload);
- $this->debug_info.= "\r\n\r\nSSH_MSG_DEBUG:\r\n" . utf8_decode($this->_string_shift($payload, $length));
- $payload = $this->_get_binary_packet();
- break;
- case NET_SSH2_MSG_UNIMPLEMENTED:
- return false;
- case NET_SSH2_MSG_KEXINIT:
- if ($this->session_id !== false)
- {
- if (!$this->_key_exchange($payload))
- {
- $this->bitmask = 0;
- return false;
- }
- $payload = $this->_get_binary_packet();
- }
- }
-
- // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
- if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER)
- {
- $this->_string_shift($payload, 1);
- list(, $length) = unpack('N', $payload);
- $this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_BANNER:\r\n" . utf8_decode($this->_string_shift($payload, $length));
- $payload = $this->_get_binary_packet();
- }
-
- // only called when we've already logged in
- if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && ($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- switch (ord($payload[0]))
- {
- case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
- $this->_string_shift($payload, 1);
- list(, $length) = unpack('N', $payload);
- $this->debug_info.= "\r\n\r\nSSH_MSG_GLOBAL_REQUEST:\r\n" . utf8_decode($this->_string_shift($payload, $length));
-
- if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE)))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $payload = $this->_get_binary_packet();
- break;
- case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
- $this->_string_shift($payload, 1);
- list(, $length) = unpack('N', $payload);
- $this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_OPEN:\r\n" . utf8_decode($this->_string_shift($payload, $length));
-
- list(, $recipient_channel) = unpack('N', $this->_string_shift($payload, 4));
-
- $packet = pack('CN3a*Na*',
- NET_SSH2_MSG_REQUEST_FAILURE, $recipient_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, '');
-
- if (!$this->_send_binary_packet($packet))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $payload = $this->_get_binary_packet();
- break;
- case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
- $payload = $this->_get_binary_packet();
- }
- }
-
- return $payload;
- }
-
- /**
- * Gets channel data
- *
- * Returns the data as a string if it's available and false if not.
- *
- * @return Mixed
- * @access private
- */
- function _get_channel_packet()
- {
- while (true)
- {
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_DATA:
- $this->_string_shift($response, 4); // skip over server channel
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- return $this->_string_shift($response, $length);
- case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
- $this->_string_shift($response, 4); // skip over server channel
- list(, $data_type_code, $length) = unpack('N2', $this->_string_shift($response, 8));
- $data = $this->_string_shift($response, $length);
- switch ($data_type_code)
- {
- case NET_SSH2_EXTENDED_DATA_STDERR:
- $this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_EXTENDED_DATA (SSH_EXTENDED_DATA_STDERR):\r\n" . $data;
- }
- break;
- case NET_SSH2_MSG_CHANNEL_REQUEST:
- $this->_string_shift($response, 4); // skip over server channel
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $value = $this->_string_shift($response, $length);
- switch ($value)
- {
- case 'exit-signal':
- $this->_string_shift($response, 1);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_REQUEST (exit-signal):\r\nSIG" . $this->_string_shift($response, $length);
- $this->_string_shift($response, 1);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n" . $this->_string_shift($response, $length);
- case 'exit-status':
- default:
- // "Some systems may not implement signals, in which case they SHOULD ignore this message."
- // -- http://tools.ietf.org/html/rfc4254#section-6.9
- //break 2;
- break;
- }
- break;
- case NET_SSH2_MSG_CHANNEL_CLOSE:
- $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $server_channel));
- return true;
- case NET_SSH2_MSG_CHANNEL_EOF:
- break;
- default:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
- }
- }
-
- /**
- * Sends Binary Packets
- *
- * See '6. Binary Packet Protocol' of rfc4253 for more info.
- *
- * @param String $data
- * @see ssh2::_get_binary_packet()
- * @return Boolean
- * @access private
- */
- function _send_binary_packet($data)
- {
- if (feof($this->fsock))
- {
- return false;
- }
-
- if (defined('NET_SSH2_LOGGING'))
- {
- $this->message_number_log[] = '-> ' . $this->message_numbers[ord($data[0])];
- $this->message_log[] = $data;
- }
-
- //if ($this->compress)
- //{
- // // the -4 removes the checksum:
- // // http://php.net/function.gzcompress#57710
- // $data = substr(gzcompress($data), 0, -4);
- //}
-
- // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
- $packet_length = strlen($data) + 9;
- // round up to the nearest $this->encrypt_block_size
- $packet_length+= (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size;
- // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length
- $padding_length = $packet_length - strlen($data) - 5;
-
- $padding = '';
- for ($i = 0; $i < $padding_length; $i++)
- {
- $padding.= chr(crypt_random(0, 255));
- }
-
- // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself
- $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding);
-
- $hmac = $this->hmac_create !== false ? $this->hmac_create->create(pack('Na*', $this->send_seq_no, $packet)) : '';
- $this->send_seq_no++;
-
- if ($this->encrypt !== false)
- {
- $packet = $this->encrypt->encrypt($packet);
- }
-
- $packet.= $hmac;
-
- return strlen($packet) == fputs($this->fsock, $packet);
- }
-
- /**
- * Disconnect
- *
- * @param Integer $reason
- * @return Boolean
- * @access private
- */
- function _disconnect($reason)
- {
- if ($this->bitmap)
- {
- $data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, '');
- $this->_send_binary_packet($data);
- $this->bitmap = 0;
- fclose($this->fsock);
- return false;
- }
- }
-
- /**
- * String Shift
- *
- * Inspired by array_shift
- *
- * @param String $string
- * @param optional Integer $index
- * @return String
- * @access private
- */
- function _string_shift(&$string, $index = 1)
- {
- $substr = substr($string, 0, $index);
- $string = substr($string, $index);
- return $substr;
- }
-
- /**
- * Define Array
- *
- * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of
- * named constants from it, using the value as the name of the constant and the index as the value of the constant.
- * If any of the constants that would be defined already exists, none of the constants will be defined.
- *
- * @param Array $array
- * @access private
- */
- function _define_array()
- {
- $args = func_get_args();
- foreach ($args as $arg)
- {
- foreach ($arg as $key=>$value)
- {
- if (!defined($value))
- {
- define($value, $key);
- }
- else
- {
- break 2;
- }
- }
- }
- }
-
- /**
- * Returns a log of the packets that have been sent and received.
- *
- * $type can be either NET_SSH2_LOG_SIMPLE or NET_SSH2_LOG_COMPLEX. Enable by defining NET_SSH2_LOGGING.
- *
- * @param Integer $type
- * @access public
- * @return String or Array
- */
- function get_log($type = NET_SSH2_LOG_COMPLEX)
- {
- if ($type == NET_SSH2_LOG_SIMPLE)
- {
- return $this->message_number_log;
- }
-
- static $boundary = ':', $long_width = 65, $short_width = 15;
-
- $output = '';
- for ($i = 0; $i < count($this->message_log); $i++)
- {
- $output.= $this->message_number_log[$i] . "\r\n";
- $current_log = $this->message_log[$i];
- do
- {
- $fragment = $this->_string_shift($current_log, $short_width);
- $hex = substr(
- preg_replace(
- '#(.)#es',
- '"' . $boundary . '" . str_pad(dechex(ord(substr("\\1", -1))), 2, "0", STR_PAD_LEFT)',
- $fragment),
- strlen($boundary)
- );
- // replace non ASCII printable characters with dots
- // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
- $raw = preg_replace('#[^\x20-\x7E]#', '.', $fragment);
- $output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n";
- }
- while (!empty($current_log));
- $output.= "\r\n";
- }
-
- return $output;
- }
-
- /**
- * Returns Debug Information
- *
- * If any debug information is sent by the server, this function can be used to access it.
- *
- * @return String
- * @access public
- */
- function get_debug_info()
- {
- return $this->debug_info;
- }
-
- /**
- * Return the server identification.
- *
- * @return String
- * @access public
- */
- function get_server_identification()
- {
- return $this->server_identifier;
- }
-
- /**
- * Return a list of the key exchange algorithms the server supports.
- *
- * @return Array
- * @access public
- */
- function get_kex_algorithms()
- {
- return $this->kex_algorithms;
- }
-
- /**
- * Return a list of the host key (public key) algorithms the server supports.
- *
- * @return Array
- * @access public
- */
- function get_server_host_key_algorithms()
- {
- return $this->server_host_key_algorithms;
- }
-
- /**
- * Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client.
- *
- * @return Array
- * @access public
- */
- function get_encryption_algorithms_client_to_server()
- {
- return $this->encryption_algorithms_client_to_server;
- }
-
- /**
- * Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client.
- *
- * @return Array
- * @access public
- */
- function get_encryption_algorithms_server_to_client()
- {
- return $this->encryption_algorithms_server_to_client;
- }
-
- /**
- * Return a list of the MAC algorithms the server supports, when receiving stuff from the client.
- *
- * @return Array
- * @access public
- */
- function get_mac_algorithms_client_to_server()
- {
- return $this->mac_algorithms_client_to_server;
- }
-
- /**
- * Return a list of the MAC algorithms the server supports, when sending stuff to the client.
- *
- * @return Array
- * @access public
- */
- function get_mac_algorithms_server_to_client()
- {
- return $this->mac_algorithms_server_to_client;
- }
-
- /**
- * Return a list of the compression algorithms the server supports, when receiving stuff from the client.
- *
- * @return Array
- * @access public
- */
- function get_compression_algorithms_client_to_server()
- {
- return $this->compression_algorithms_client_to_server;
- }
-
- /**
- * Return a list of the compression algorithms the server supports, when sending stuff to the client.
- *
- * @return Array
- * @access public
- */
- function get_compression_algorithms_server_to_client()
- {
- return $this->compression_algorithms_server_to_client;
- }
-
- /**
- * Return a list of the languages the server supports, when sending stuff to the client.
- *
- * @return Array
- * @access public
- */
- function get_languages_server_to_client()
- {
- return $this->languages_server_to_client;
- }
-
- /**
- * Return a list of the languages the server supports, when receiving stuff from the client.
- *
- * @return Array
- * @access public
- */
- function get_languages_client_to_server()
- {
- return $this->languages_client_to_server;
- }
-
- /**
- * Returns the server public host key.
- *
- * Caching this the first time you connect to a server and checking the result on subsequent connections
- * is recommended.
- *
- * @return Array
- * @access public
- */
- function get_server_public_host_key()
- {
- return $this->server_public_host_key;
- }
-}
-
-/**
- * Pure-PHP implementation of SFTP.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package sftp
- */
-class ssh2_sftp extends ssh2
-{
- /**
- * Packet Types
- *
- * @see ssh2_sftp::__construct()
- * @var Array
- * @access private
- */
- var $packet_types = array();
-
- /**
- * Status Codes
- *
- * @see ssh2_sftp::__construct()
- * @var Array
- * @access private
- */
- var $status_codes = array();
-
- /**
- * The Window Size
- *
- * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 4GB)
- *
- * @var Integer
- * @see ssh2::exec()
- * @access private
- */
- var $window_size = 0x7FFFFFFF;
-
- /**
- * The Packet Size
- *
- * Maximum max packet size
- *
- * @var Integer
- * @see ssh2::exec()
- * @access private
- */
- var $packet_size = 0x4000;
-
- /**
- * The Client Channel
- *
- * Net_SSH2::exec() uses 0
- *
- * @var Integer
- * @see ssh2::exec()
- * @access private
- */
- var $client_channel = 1;
-
- /**
- * The Server Channel
- *
- * @var Integer
- * @see ssh2_sftp::_init_channel()
- * @access private
- */
- var $server_channel = -1;
-
- /**
- * The Request ID
- *
- * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
- * concurrent actions, so it's somewhat academic, here.
- *
- * @var Integer
- * @see ssh2_sftp::_send_sftp_packet()
- * @access private
- */
- var $request_id = false;
-
- /**
- * The Packet Type
- *
- * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
- * concurrent actions, so it's somewhat academic, here.
- *
- * @var Integer
- * @see ssh2_sftp::_send_sftp_packet()
- * @access private
- */
- var $packet_type = -1;
-
- /**
- * Extensions supported by the server
- *
- * @var Array
- * @see ssh2_sftp::_init_channel()
- * @access private
- */
- var $extensions = array();
-
- /**
- * Server SFTP version
- *
- * @var Integer
- * @see ssh2_sftp::_init_channel()
- * @access private
- */
- var $version;
-
- /**
- * Current working directory
- *
- * @var String
- * @see ssh2_sftp::_realpath()
- * @see ssh2_sftp::chdir()
- * @access private
- */
- var $pwd = false;
-
- /**
- * Packet Type Log
- *
- * @see ssh2_sftp::get_log()
- * @var Array
- * @access private
- */
- var $packet_type_log = array();
-
- /**
- * Packet Log
- *
- * @see ssh2_sftp::get_log()
- * @var Array
- * @access private
- */
- var $packet_log = array();
-
- /**
- * Default Constructor.
- *
- * Connects to an SFTP server
- *
- * @param String $host
- * @param optional Integer $port
- * @param optional Integer $timeout
- * @return sftp
- * @access public
- */
- function __construct($host, $port = 22, $timeout = 10)
- {
- parent::__construct($host, $port, $timeout);
- $this->packet_types = array(
- 1 => 'NET_SFTP_INIT',
- 2 => 'NET_SFTP_VERSION',
- /* the format of SSH_FXP_OPEN changed between SFTPv4 and SFTPv5+:
- SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.1
- pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3 */
- 3 => 'NET_SFTP_OPEN',
- 4 => 'NET_SFTP_CLOSE',
- 5 => 'NET_SFTP_READ',
- 6 => 'NET_SFTP_WRITE',
- 8 => 'NET_SFTP_FSTAT',
- 9 => 'NET_SFTP_SETSTAT',
- 11 => 'NET_SFTP_OPENDIR',
- 12 => 'NET_SFTP_READDIR',
- 13 => 'NET_SFTP_REMOVE',
- 14 => 'NET_SFTP_MKDIR',
- 15 => 'NET_SFTP_RMDIR',
- 16 => 'NET_SFTP_REALPATH',
- 17 => 'NET_SFTP_STAT',
- /* the format of SSH_FXP_RENAME changed between SFTPv4 and SFTPv5+:
- SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
- pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.5 */
- 18 => 'NET_SFTP_RENAME',
-
- 101=> 'NET_SFTP_STATUS',
- 102=> 'NET_SFTP_HANDLE',
- /* the format of SSH_FXP_NAME changed between SFTPv3 and SFTPv4+:
- SFTPv4+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4
- pre-SFTPv4 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7 */
- 103=> 'NET_SFTP_DATA',
- 104=> 'NET_SFTP_NAME',
- 105=> 'NET_SFTP_ATTRS',
-
- 200=> 'NET_SFTP_EXTENDED'
- );
- $this->status_codes = array(
- 0 => 'NET_SFTP_STATUS_OK',
- 1 => 'NET_SFTP_STATUS_EOF'
- );
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
- // the order, in this case, matters quite a lot - see ssh2_sftp::_parse_attributes() to understand why
- $this->attributes = array(
- 0x00000001 => 'NET_SFTP_ATTR_SIZE',
- 0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
- 0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
- 0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
- 0x80000000 => 'NET_SFTP_ATTR_EXTENDED'
- );
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
- // the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
- // the array for that $this->open5_flags and similarily alter the constant names.
- $this->open_flags = array(
- 0x00000001 => 'NET_SFTP_OPEN_READ',
- 0x00000002 => 'NET_SFTP_OPEN_WRITE',
- 0x00000008 => 'NET_SFTP_OPEN_CREATE'
- );
- $this->_define_array(
- $this->packet_types,
- $this->status_codes,
- $this->attributes,
- $this->open_flags
- );
- }
-
- /**
- * Login
- *
- * @param String $username
- * @param optional String $password
- * @return Boolean
- * @access public
- */
- function login($username, $password = '')
- {
- if (!parent::login($username, $password))
- {
- return false;
- }
-
- $packet = pack('CNa*N3',
- NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', $this->client_channel, $this->window_size, $this->packet_size);
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
- $this->_string_shift($response, 4);
- list(, $this->server_channel) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $packet = pack('CNNa*CNa*',
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channel, strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp');
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_SUCCESS:
- break;
- case NET_SSH2_MSG_CHANNEL_FAILURE:
- default:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3"))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_VERSION)
- {
- return false;
- }
-
- list(, $this->version) = unpack('N', $this->_string_shift($response, 4));
- while (!empty($response))
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $key = $this->_string_shift($response, $length);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $value = $this->_string_shift($response, $length);
- $this->extensions[$key] = $value;
- }
-
- /*
- SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com',
- however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's
- not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for
- one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
- 'newline@vandyke.com' would.
- */
- /*
- if (isset($this->extensions['newline@vandyke.com']))
- {
- $this->extensions['newline'] = $this->extensions['newline@vandyke.com'];
- unset($this->extensions['newline@vandyke.com']);
- }
- */
-
- $this->request_id = 1;
-
- /*
- A Note on SFTPv4/5/6 support:
- <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.1> states the following:
-
- "If the client wishes to interoperate with servers that support noncontiguous version
- numbers it SHOULD send '3'"
-
- Given that the server only sends its version number after the client has already done so, the above
- seems to be suggesting that v3 should be the default version. This makes sense given that v3 is the
- most popular.
-
- <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.5> states the following;
-
- "If the server did not send the "versions" extension, or the version-from-list was not included, the
- server MAY send a status response describing the failure, but MUST then close the channel without
- processing any further requests."
-
- So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
- a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4? If it only implements
- v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
- in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what sftp would do is close the
- channel and reopen it with a new and updated SSH_FXP_INIT packet.
- */
- if ($this->version != 3)
- {
- return false;
- }
-
- $this->pwd = $this->_realpath('.');
-
- return true;
- }
-
- /**
- * Returns the current directory name
- *
- * @return Mixed
- * @access public
- */
- function pwd()
- {
- return $this->pwd;
- }
-
- /**
- * Canonicalize the Server-Side Path Name
- *
- * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns
- * the absolute (canonicalized) path. If $mode is set to NET_SFTP_CONFIRM_DIR (as opposed to NET_SFTP_CONFIRM_NONE,
- * which is what it is set to by default), false is returned if $dir is not a valid directory.
- *
- * @see ssh2_sftp::chdir()
- * @param String $dir
- * @param optional Integer $mode
- * @return Mixed
- * @access private
- */
- function _realpath($dir)
- {
- /*
- "This protocol represents file names as strings. File names are
- assumed to use the slash ('/') character as a directory separator.
-
- File names starting with a slash are "absolute", and are relative to
- the root of the file system. Names starting with any other character
- are relative to the user's default directory (home directory). Note
- that identifying the user is assumed to take place outside of this
- protocol."
-
- -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-6
- */
- $file = '';
- if ($this->pwd !== false)
- {
- // if the SFTP server returned the canonicalized path even for non-existant files this wouldn't be necessary
- // on OpenSSH it isn't necessary but on other SFTP servers it is. that and since the specs say nothing on
- // the subject, we'll go ahead and work around it with the following.
- if ($dir[strlen($dir) - 1] != '/')
- {
- $file = basename($dir);
- $dir = dirname($dir);
- }
-
- if ($dir == '.' || $dir == $this->pwd)
- {
- return $this->pwd . $file;
- }
-
- if ($dir[0] != '/')
- {
- $dir = $this->pwd . '/' . $dir;
- }
- // on the surface it seems like maybe resolving a path beginning with / is unnecessary, but such paths
- // can contain .'s and ..'s just like any other. we could parse those out as appropriate or we can let
- // the server do it. we'll do the latter.
- }
-
- /*
- that SSH_FXP_REALPATH returns SSH_FXP_NAME does not necessarily mean that anything actually exists at the
- specified path. generally speaking, no attributes are returned with this particular SSH_FXP_NAME packet
- regardless of whether or not a file actually exists. and in SFTPv3, the longname field and the filename
- field match for this particular SSH_FXP_NAME packet. for other SSH_FXP_NAME packets, this will likely
- not be the case, but for this one, it is.
- */
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
- if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($dir), $dir)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_NAME:
- // although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following
- // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
- // at is the first part and that part is defined the same in SFTP versions 3 through 6.
- $this->_string_shift($response, 4); // skip over the count - it should be 1, anyway
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $realpath = $this->_string_shift($response, $length);
- break;
- case NET_SFTP_STATUS:
- // skip over the status code - hopefully the error message will give us all the info we need, anyway
- $this->_string_shift($response, 4);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- default:
- return false;
- }
-
- // if $this->pwd isn't set than the only thing $realpath could be is for '.', which is pretty much guaranteed to
- // be a bonafide directory
- return $realpath . '/' . $file;
- }
-
- /**
- * Changes the current directory
- *
- * @param String $dir
- * @return Boolean
- * @access public
- */
- function chdir($dir)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- if ($dir[strlen($dir) - 1] != '/')
- {
- $dir.= '/';
- }
- $dir = $this->_realpath($dir);
-
- // confirm that $dir is, in fact, a valid directory
- if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir)))
- {
- return false;
- }
-
- // see ssh2_sftp::nlist() for a more thorough explanation of the following
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_HANDLE:
- $handle = substr($response, 4);
- break;
- case NET_SFTP_STATUS:
- return false;
- default:
- return false;
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- $this->pwd = $dir;
- return true;
- }
-
- /**
- * Returns a list of files in the given directory
- *
- * @param optional String $dir
- * @return Mixed
- * @access public
- */
- function nlist($dir = '.')
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $dir = $this->_realpath($dir);
- if ($dir === false)
- {
- return false;
- }
-
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
- if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_HANDLE:
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2
- // since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that
- // represent the length of the string and leave it at that
- $handle = substr($response, 4);
- break;
- case NET_SFTP_STATUS:
- // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
- return false;
- default:
- return false;
- }
-
- $contents = array();
- while (true)
- {
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
- // why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
- // SSH_MSG_CHANNEL_DATA messages is not known to me.
- if (!$this->_send_sftp_packet(NET_SFTP_READDIR, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_NAME:
- list(, $count) = unpack('N', $this->_string_shift($response, 4));
- for ($i = 0; $i < $count; $i++)
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $contents[] = $this->_string_shift($response, $length);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->_string_shift($response, $length); // we don't care about the longname
- $this->_parse_attributes($response); // we also don't care about the attributes
- // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
- // final SSH_FXP_STATUS packet should tell us that, already.
- }
- break;
- case NET_SFTP_STATUS:
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
- if ($status != NET_SFTP_STATUS_EOF)
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- }
- break 2;
- default:
- return false;
- }
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- // "The client MUST release all resources associated with the handle regardless of the status."
- // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- return $contents;
- }
-
- /**
- * Set permissions on a file.
- *
- * Returns the new file permissions on success or FALSE on error.
- *
- * @param Integer $mode
- * @param String $filename
- * @return Mixed
- * @access public
- */
- function chmod($mode, $filename)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $filename = $this->_realpath($filename);
- if ($filename === false)
- {
- return false;
- }
-
- // SFTPv4+ has an additional byte field - type - that would need to be sent, as well. setting it to
- // SSH_FILEXFER_TYPE_UNKNOWN might work. if not, we'd have to do an SSH_FXP_STAT before doing an SSH_FXP_SETSTAT.
- $attr = pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
- if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($filename), $filename, $attr)))
- {
- return false;
- }
-
- /*
- "Because some systems must use separate system calls to set various attributes, it is possible that a failure
- response will be returned, but yet some of the attributes may be have been successfully modified. If possible,
- servers SHOULD avoid this situation; however, clients MUST be aware that this is possible."
-
- -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6
- */
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- // rather than return what the permissions *should* be, we'll return what they actually are. this will also
- // tell us if the file actually exists.
- // incidentally ,SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
- $packet = pack('Na*', strlen($filename), $filename);
- if (!$this->_send_sftp_packet(NET_SFTP_STAT, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_ATTRS:
- $attrs = $this->_parse_attributes($response);
- return $attrs['permissions'];
- case NET_SFTP_STATUS:
- return false;
- }
-
- return false;
- }
-
- /**
- * Creates a directory.
- *
- * @param String $dir
- * @return Boolean
- * @access public
- */
- function mkdir($dir)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $dir = $this->_realpath(rtrim($dir, '/'));
- if ($dir === false)
- {
- return false;
- }
-
- // by not providing any permissions, hopefully the server will use the logged in users umask - their
- // default permissions.
- if (!$this->_send_sftp_packet(NET_SFTP_MKDIR, pack('Na*N', strlen($dir), $dir, 0)))
- {
- return false;
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
- if ($status != NET_SFTP_STATUS_OK)
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- }
-
- return true;
- }
-
- /**
- * Removes a directory.
- *
- * @param String $dir
- * @return Boolean
- * @access public
- */
- function rmdir($dir)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $dir = $this->_realpath($dir);
- if ($dir === false)
- {
- return false;
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($dir), $dir)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
- if ($status != NET_SFTP_STATUS_OK)
- {
- // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
- return false;
- }
-
- return true;
- }
-
- /**
- * Uploads a file to the SFTP server.
- *
- * By default, ssh2_sftp::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
- * So, for example, if you set $data to 'filename.ext' and then do ssh2_sftp::get(), you will get a file, twelve bytes
- * long, containing 'filename.ext' as its contents.
- *
- * Setting $mode to NET_SFTP_LOCAL_FILE will change the above behavior. With NET_SFTP_LOCAL_FILE, $remote_file will
- * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
- * large $remote_file will be, as well.
- *
- * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
- * care of that, yourself.
- *
- * @param String $remote_file
- * @param String $data
- * @param optional Integer $flags
- * @return Boolean
- * @access public
- * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - ssh2_sftp::setMode().
- */
- function put($remote_file, $data, $mode = NET_SFTP_STRING)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $remote_file = $this->_realpath($remote_file);
- if ($remote_file === false)
- {
- return false;
- }
-
- $packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE, 0);
- if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_HANDLE:
- $handle = substr($response, 4);
- break;
- case NET_SFTP_STATUS:
- $this->_string_shift($response, 4);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- default:
- return false;
- }
-
- $initialize = true;
-
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
- if ($mode == NET_SFTP_LOCAL_FILE)
- {
- if (!is_file($data))
- {
- return false;
- }
- $fp = fopen($data, 'r');
- if (!$fp)
- {
- return false;
- }
- $sent = 0;
- $size = filesize($data);
- while ($sent < $size)
- {
- /*
- "The 'maximum packet size' specifies the maximum size of an individual data packet that can be sent to the
- sender. For example, one might want to use smaller packets for interactive connections to get better
- interactive response on slow links."
-
- -- http://tools.ietf.org/html/rfc4254#section-5.1
-
- per that, we're going to assume that the 'maximum packet size' field of the SSH_MSG_CHANNEL_OPEN message
- does not apply to the client. the client is the one who sends the SSH_MSG_CHANNEL_OPEN message, anyway,
- so it's not as if the above could be referring to the server.
-
- the reason that's mentioned is because sending $this->packet_size as the payload will result in a packet
- that's larger than $this->packet_size, but that's not a problem, as per the above.
- */
- if ($initialize)
- {
- $temp = fread($fp, $this->packet_size);
- $sent+= strlen($temp);
- $packet = pack('NCN2a*N3a*',
- $size + strlen($handle) + 21, NET_SFTP_WRITE, $this->request_id, strlen($handle), $handle, 0, 0, $size, $temp
- );
- $initialize = false;
- if (defined('NET_SFTP_LOGGING'))
- {
- $log_index = count($this->packet_type_log);
- $this->packet_type_log[] = '<- ' . $this->packet_types[$packet_type];
- $this->packet_log[] = $packet;
- }
- }
- else
- {
- $packet = fread($fp, $this->packet_size);
- $sent+= strlen($packet);
- if (defined('NET_SFTP_LOGGING'))
- {
- $this->packet_log[$log_index].= $packet;
- }
- }
- if (!$this->_send_channel_packet($packet))
- {
- fclose($fp);
- return false;
- }
- }
- fclose($fp);
- }
- else
- {
- while (strlen($data))
- {
- if ($initialize)
- {
- $packet = pack('NCN2a*N3a*',
- strlen($data) + strlen($handle) + 21, NET_SFTP_WRITE, $this->request_id, strlen($handle), $handle, 0, 0, strlen($data),
- $this->_string_shift($data, $this->packet_size)
- );
- $initialize = false;
- }
- else
- {
- $packet = $this->_string_shift($data, $this->packet_size);
- }
- if (!$this->_send_channel_packet($packet))
- {
- return false;
- }
- }
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * Downloads a file from the SFTP server.
- *
- * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
- * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
- * operation
- *
- * @param String $remote_file
- * @param optional String $local_file
- * @return Mixed
- * @access public
- */
- function get($remote_file, $local_file = false)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $remote_file = $this->_realpath($remote_file);
- if ($remote_file === false)
- {
- return false;
- }
-
- $packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_READ, 0);
- if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_HANDLE:
- $handle = substr($response, 4);
- break;
- case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
- return false;
- default:
- return false;
- }
-
- $packet = pack('Na*', strlen($handle), $handle);
- if (!$this->_send_sftp_packet(NET_SFTP_FSTAT, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_ATTRS:
- $attrs = $this->_parse_attributes($response);
- break;
- case NET_SFTP_STATUS:
- return false;
- default:
- return false;
- }
-
-
- if ($local_file !== false)
- {
- $fp = fopen($local_file, 'w');
- if (!$fp)
- {
- return false;
- }
- }
- else
- {
- $content = '';
- }
-
- $read = 0;
- while ($read < $attrs['size'])
- {
- $packet = pack('Na*N3', strlen($handle), $handle, 0, $read, 100000); // 100000 is completely arbitrarily chosen
- if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_DATA:
- $temp = substr($response, 4);
- $read+= strlen($temp);
- if ($local_file === false)
- {
- $content.= $temp;
- }
- else
- {
- fputs($fp, $temp);
- }
- break;
- case NET_SFTP_STATUS:
- $this->_string_shift($response, 4);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- default:
- return false;
- }
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- if (isset($content))
- {
- return $content;
- }
-
- fclose($fp);
- return true;
- }
-
- /**
- * Deletes a file on the SFTP server.
- *
- * @param String $path
- * @return Boolean
- * @access public
- */
- function delete($path)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $remote_file = $this->_realpath($path);
- if ($path === false)
- {
- return false;
- }
-
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
- if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
-
- // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
- return $status == NET_SFTP_STATUS_OK;
- }
-
- /**
- * Renames a file or a directory on the SFTP server
- *
- * @param String $oldname
- * @param String $newname
- * @return Boolean
- * @access public
- */
- function rename($oldname, $newname)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $oldname = $this->_realpath($oldname);
- $newname = $this->_realpath($newname);
- if ($oldname === false || $newname === false)
- {
- return false;
- }
-
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
- $packet = pack('Na*Na*', strlen($oldname), $oldname, strlen($newname), $newname);
- if (!$this->_send_sftp_packet(NET_SFTP_RENAME, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
-
- // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
- return $status == NET_SFTP_STATUS_OK;
- }
-
- /**
- * Parse Attributes
- *
- * See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info.
- *
- * @param String $response
- * @return Array
- * @access private
- */
- function _parse_attributes(&$response)
- {
- $attr = array();
- list(, $flags) = unpack('N', $this->_string_shift($response, 4));
- // SFTPv4+ have a type field (a byte) that follows the above flag field
- foreach ($this->attributes as $key => $value)
- {
- switch ($flags & $key)
- {
- case NET_SFTP_ATTR_SIZE: // 0x00000001
- // size is represented by a 64-bit integer, so we perhaps ought to be doing the following:
- //$attr['size'] = new Math_BigInteger($this->_string_shift($response, 8), 256);
- // of course, you shouldn't be using sftp to transfer files that are in excess of 4GB
- // (0xFFFFFFFF bytes), anyway. as such, we'll just represent all file sizes that are bigger than
- // 4GB as being 4GB.
- list(, $upper) = unpack('N', $this->_string_shift($response, 4));
- list(, $attr['size']) = unpack('N', $this->_string_shift($response, 4));
- if ($upper)
- {
- $attr['size'] = 0xFFFFFFFF;
- }
- break;
- case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
- list(, $attr['uid']) = unpack('N', $this->_string_shift($response, 4));
- list(, $attr['gid']) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004
- list(, $attr['permissions']) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008
- list(, $attr['atime']) = unpack('N', $this->_string_shift($response, 4));
- list(, $attr['mtime']) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SFTP_ATTR_EXTENDED: // 0x80000000
- list(, $count) = unpack('N', $this->_string_shift($response, 4));
- for ($i = 0; $i < $count; $i++)
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $key = $this->_string_shift($response, $length);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $attr[$key] = $this->_string_shift($response, $length);
- }
- }
- }
- return $attr;
- }
-
- /**
- * Sends SFTP Packets
- *
- * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
- *
- * @param Integer $type
- * @param String $data
- * @see ssh2_sftp::_get_sftp_packet()
- * @see ssh2_sftp::_send_channel_packet()
- * @return Boolean
- * @access private
- */
- function _send_sftp_packet($type, $data)
- {
- $data = $this->request_id !== false ?
- pack('NCNa*', strlen($data) + 5, $type, $this->request_id, $data) :
- pack('NCa*', strlen($data) + 1, $type, $data);
-
- if (defined('NET_SFTP_LOGGING'))
- {
- $this->packet_type_log[] = '-> ' . $this->packet_types[$type];
- $this->packet_log[] = $data;
- }
-
- return $this->_send_channel_packet($data);
- }
-
- /**
- * Sends Channel Packets
- *
- * If this function were in Net_SSH2, there'd have to be an additional server channel parameter since the Net_SSH2 object
- * doesn't currently have one. Plus, it wouldn't actually make a lot of sense for Net_SSH2 even to have one - if it did
- * and if Net_SSH2::exec() used it then ssh2_sftp::exec() would also use it (through inheritance) and you'd have the
- * single server channel being overwritten and... all in all, I think this is easier.
- *
- * @param Integer $type
- * @param String $data
- * @see ssh2_sftp::_send_sftp_packet()
- * @return Boolean
- * @access private
- */
- function _send_channel_packet($data)
- {
- return $this->_send_binary_packet(pack('CN2a*', NET_SSH2_MSG_CHANNEL_DATA, $this->server_channel, strlen($data), $data));
- }
-
- /**
- * Receives SFTP Packets
- *
- * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
- *
- * @see ssh2_sftp::_send_sftp_packet()
- * @return String
- * @access private
- */
- function _get_sftp_packet()
- {
- $packet = $this->_get_channel_packet();
- if (is_bool($packet))
- {
- $this->packet_type = false;
- return false;
- }
- /*
- normally, strlen($packet) == $length, however, for really large packets, strlen($packet) < $length. what this means,
- when it happens, is that the string is being spanned out across multiple SSH_MSG_CHANNEL_DATA messages and we'll
- need to read them multiple times until we reach $length bytes.
-
- presumably, strlen($packet) > $length would never happen unless you were trying to employ steganography or
- something
- */
- list(, $length) = unpack('N', $this->_string_shift($packet, 4));
- $this->packet_type = ord($this->_string_shift($packet));
- if ($this->request_id !== false)
- {
- $this->_string_shift($packet, 4); // remove the request id
- $length-= 5; // account for the request id and the packet type
- }
- else
- {
- $length-= 1; // account for the packet type
- }
- $packet = substr($packet, 0, $length); // just in case strlen($packet) > $length
- $length-= strlen($packet);
- while ($length > 0)
- {
- $temp = $this->_get_channel_packet();
- if (is_bool($temp))
- {
- $this->packet_type = false;
- return false;
- }
- $packet.= $temp;
- $length-= strlen($temp);
- }
-
- if (defined('NET_SFTP_LOGGING'))
- {
- $this->packet_type_log[] = '<- ' . $this->packet_types[$this->packet_type];
- $this->packet_log[] = $packet;
- }
-
- return $packet;
- }
-
- /**
- * Returns a log of the packets that have been sent and received.
- *
- * $type can be either NET_SFTP_LOG_SIMPLE or NET_SFTP_LOG_COMPLEX. Enable by defining NET_SSH2_LOGGING.
- *
- * @param Integer $type
- * @access public
- * @return String or Array
- */
- function get_sftp_log($type = NET_SFTP_LOG_COMPLEX)
- {
- $message_number_log = $this->message_number_log;
- $message_log = $this->message_log;
-
- $this->message_number_log = $this->packet_type_log;
- $this->message_log = $this->packet_log;
-
- $return = $this->getLog($type);
-
- $this->message_number_log = $message_number_log;
- $this->message_log = $message_log;
-
- return $return;
- }
-
- /**
- * Get supported SFTP versions
- *
- * @return Array
- * @access public
- */
- function get_supported_versions()
- {
- $temp = array('version' => $this->version);
- if (isset($this->extensions['versions']))
- {
- $temp['extensions'] = $this->extensions['versions'];
- }
- return $temp;
- }
-
- /**
- * Disconnect
- *
- * @param Integer $reason
- * @return Boolean
- * @access private
- */
- function _disconnect($reason)
- {
- $this->pwd = false;
- parent::_disconnect($reason);
- }
-}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/zend/Exception.php b/phpBB/includes/libraries/zend/Exception.php deleted file mode 100644 index 599d8a033e..0000000000 --- a/phpBB/includes/libraries/zend/Exception.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend - * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - - -/** - * @category Zend - * @package Zend - * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Exception extends Exception -{} - diff --git a/phpBB/includes/libraries/zend/loader.php b/phpBB/includes/libraries/zend/loader.php deleted file mode 100644 index 99a5543901..0000000000 --- a/phpBB/includes/libraries/zend/loader.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** -* -* @package zend -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -if (version_compare(PHP_VERSION, '5.2.4', '<') || !function_exists('spl_autoload_register')) -{ - trigger_error('PHP >= 5.2.4 and spl_autoload_register() required', E_USER_ERROR); -} - -/** -* Autoload function for Zend framework classes -*/ -function phpbb_zend_autoload($class_name) -{ - global $phpbb_root_path; - - if (strpos($class_name, '_') !== false) - { - $path = str_replace('_', '/', $class_name) . '.php'; - require("{$phpbb_root_path}includes/" . $path); - return true; - } -} - -/** -* @ignore -*/ -// make sure Zend is in the include path -ini_set( 'include_path', ini_get( 'include_path' ) . PATH_SEPARATOR . $phpbb_root_path . 'includes' ); - -// check whether a regular autoload function already exists, so we can load it into the spl stack afterwards -$register_autoload = false; -if (function_exists('__autoload')) -{ - $register_autoload = true; -} - -spl_autoload_register('phpbb_zend_autoload'); - -// load the old autoload function into the spl stack if necessary -if ($register_autoload) -{ - spl_autoload_register('__autoload'); -}
\ No newline at end of file |