Issues (165)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Includes/SSH.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
This file is part of Peachy MediaWiki Bot API
4
5
Peachy is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
/**
20
 * @file
21
 * SSH object
22
 * Establishes and maintains a remote SSH connection
23
 */
24
25
/**
26
 * SSH Class, Establishes and maintains a remote SSH connection
27
 */
28
class SSH {
29
30
	/**
31
	 * Host of server
32
	 *
33
	 * @var string
34
	 * @access private
35
	 */
36
	private $host;
37
38
	/**
39
	 * Username of authenticated session
40
	 *
41
	 * @var string
42
	 * @access private
43
	 */
44
	private $username;
45
46
	/**
47
	 * File path to the private key file
48
	 *
49
	 * @var string
50
	 * @access private
51
	 */
52
    private $privateKey;
53
54
	/**
55
	 * SSH protocol being used
56
	 *
57
	 * @var int
58
	 * @access private
59
	 */
60
	private $protocol;
61
62
	/**
63
	 * Whether or not the connection was successful.
64
	 *
65
	 * @var bool
66
	 * @access private
67
	 */
68
	public $connected = false;
69
70
	/**
71
	 * The SSH connection object.
72
	 *
73
	 * @var Object
74
	 * @access private
75
	 */
76
    private $SSHObject;
77
78
	/**
79
	 * The SFTP connection object.
80
	 *
81
	 * @var Object
82
	 * @access private
83
	 */
84
    private $SFTPObject;
85
86
	/**
87
	 * Stores the commits of the PHPSecLib class
88
	 *
89
	 * @var array
90
	 * @access private
91
	 */
92
	protected $commits;
93
94
	/**
95
	 * HTTP class
96
	 *
97
	 * @var Object
98
	 * @access private
99
	 */
100
	protected $http;
101
102
103
	/**
104
	 * Construction method for the SSH class
105
	 *
106
	 * @FIXME: Codebase no longer includes SSH-related classes
107
	 *
108
     * @access      public
109
     * @param       string $pgHost Address of remote host.Default
110
     * @param       int $pgPort Default: 22
111
     * @param       string|null $pgUsername
112
     * @param       string|null $pgPassphrase
113
     * @param       string|null $pgPrivateKey
114
     * @param       int $pgProtocol
115
     * @param       int $pgTimeout
116
     * @param       HTTP $http This must be a HTTP class object from HTTP::getDefaultInstance()
117
     *
118
     * @see         HTTP::getDefaultInstance()
119
     * @see         WIKI::__construct()
120
	 */
121
    public function __construct(
122
        $pgHost,
123
        $pgPort = 22,
124
        $pgUsername = null,
125
        $pgPassphrase = null,
126
        $pgPrivateKey = null,
127
        $pgProtocol = 2,
128
        $pgTimeout = 10,
129
        HTTP $http
130
    ) {
131
		pecho( "Initializing SSH class...\n\n", PECHO_NORMAL );
132
		global $pgIP;
133
		$this->http = $http;
134
        // FIXME    The code base no longer includes a 'Includes/SSHCore' directory
135
        if (!file_exists($pgIP . 'Includes/SSHCore')) {
136
			pecho( "Setting up the SSH Class for first time use...\n\n", PECHO_NOTICE );
137
			$data = json_decode( $this->http->get( 'https://api.github.com/repos/phpseclib/phpseclib/branches/master', null, array(), false ), true );
138
			$this->commits = $data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $data of type * is incompatible with the declared type array of property $commits.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
139
			$this->installPHPseclib();
140
		}
141
142
		//Check for updates
143
		if( !$this->CheckForUpdate() ) $this->installPHPseclib();
144
145
		set_include_path( get_include_path() . PATH_SEPARATOR . $pgIP . 'Includes/SSHCore' );
146
        require_once('Net/SCP.php');      // FIXME    Directory doesn't exist
147
        require_once('Crypt/RSA.php');    // FIXME    Directory doesn't exist
148
        require_once('Net/SFTP.php');     // FIXME    Directory doesn't exist
149
		switch( $pgProtocol ){
150
			case 1:
151
                require_once('Net/SSH1.php'); // FIXME    Directory doesn't exist
152
				break;
153
			case 2:
154
                require_once('Net/SSH2.php'); // FIXME    Directory doesn't exist
155
				break;
156
			default:
157
                require_once('Net/SSH2.php'); // FIXME    Directory doesn't exist
158
				break;
159
		}
160
161
		//Determine which SSH class to use. We could just use $pgProtocol as a variable to define the class, but this method error handles better.
162
		$this->protocol = $pgProtocol;
163
		$this->host = $pgHost;
164
		$this->username = $pgUsername;
165
        $this->privateKey = $pgPrivateKey;
166
		if( !$this->connect( $pgHost, $pgPort, $pgProtocol, $pgTimeout ) ) {
167
			pecho( "Cannot connect, aborting SSH initialization...\n\n", PECHO_FATAL );
168
			$this->__destruct();
169
			return;
170
		}
171
		pecho( "Successfully connected to $pgHost.\n\n", PECHO_NORMAL );
172
173
		//Now authenticate
174
        if (!($this->authenticate($pgUsername, $pgPassphrase, $pgPrivateKey))) {
175
			$this->__destruct();
176
			return;
177
		}
178
179
		$this->connected = true;
180
		if( $this->connected ) {
181
			echo "Connection socket open.\n\n";
182
		} else {
183
            echo "A connection error occurred. Closing...\n\n";
184
			$this->__destruct();
185
			return;
186
		}
187
	}
188
189
    /**
190
     * Establishes a connection to the remote server.
191
     *
192
     * @FIXME: Codebase no longer includes SSH-related classes
193
     *
194
     * @access  protected
195
     * @param   string $pgHost Host of server to connect to.
196
     * @param   int $pgPort Port of server.
197
     * @param   int $pgProtocol Which SSH protocol to use.
198
     * @param   int $pgTimeout How long before the connection times out. (Milliseconds)
199
     * @return  bool
200
     */
201
	protected function connect( $pgHost, $pgPort = 22, $pgProtocol, $pgTimeout = 10 ) {
202
		pecho( "Connecting to $pgHost:$pgPort...\n\n", PECHO_NORMAL );
203
		switch( $pgProtocol ){
204
			case 1:
205
                $this->SSHObject = new Net_SSH1($pgHost, $pgPort, $pgTimeout); // FIXME    Directory doesn't exist
206
				break;
207
			case 2:
208
                $this->SSHObject = new Net_SSH2($pgHost, $pgPort, $pgTimeout); // FIXME    Directory doesn't exist
209
				break;
210
			default:
211
                $this->SSHObject = new Net_SSH2($pgHost, $pgPort, $pgTimeout); // FIXME    Directory doesn't exist
212
				break;
213
		}
214
215
        return $this->SFTPObject = new Net_SFTP($pgHost, $pgPort, $pgTimeout); // FIXME    Directory doesn't exist
216
	}
217
218
	/**
219
	 * Authenticates to the remote server.
220
	 *
221
     * @access  protected
222
     * @param   string $pgUsername Username
223
     * @param   string $pgPassphrase Password or passphrase of key file
224
     * @param   string $pgPrivateKey File path of key file.
225
     * @return  bool
226
	 */
227
    protected function authenticate($pgUsername, $pgPassphrase, $pgPrivateKey)
228
    {
229
		//Determine the type of authentication to use.
230
		if( is_null( $pgUsername ) ) {
231
			pecho( "A username must at least be specified to authenticate to the server,\neven if there is authentication is none.\n\n", PECHO_FATAL );
232
			return false;
233
		}
234
		$fails = 0;
235
        if (!is_null($pgUsername) && !is_null($pgPrivateKey) && $this->protocol == 2) {
236
			pecho( "Authenticating with Private Key Authentication...\n\n", PECHO_NORMAL );
237
            $key = new Crypt_RSA(); // FIXME    Class doesn't exist
238
            if (!is_null($pgPassphrase)) {
239
                $key->setPassword($pgPassphrase);
240
            } // FIXME    Method doesn't exist
241
            $key->loadKey(file_get_contents($pgPrivateKey)); // FIXME    Method doesn't exist
242
            if ($this->SSHObject->login($pgUsername, $key) && $this->SFTPObject->login($pgUsername, $key)) {
243
				pecho( "Successfully authenticated using Private Key Authentication.\n\n", PECHO_NORMAL );
244
				return true;
245
			}
246
			$fails++;
247
		} else $fails += 5;
248
		if( !is_null( $pgUsername ) && !is_null( $pgPassphrase ) ) {
249
			pecho( "Authenticating with Password Authentication...\n\n", PECHO_NORMAL );
250
            if ($this->SSHObject->login($pgUsername, $pgPassphrase) && $this->SFTPObject->login($pgUsername,
251
                    $pgPassphrase)
252
            ) {
253
				pecho( "Successfully authenticated using Password Authentication\n\n", PECHO_NORMAL );
254
				return true;
255
			}
256
			$fails++;
257
		} else $fails += 5;
258
		if( !is_null( $pgUsername ) ) {
259
			pecho( "Authenticating with No Authentication...\n\n", PECHO_NORMAL );
260
            if ($this->SSHObject->login($pgUsername) && $this->SFTPObject->login($pgUsername)) {
261
				pecho( "Successfully authenticated with No Authentication\n\n", PECHO_NORMAL );
262
				return true;
263
			}
264
			$fails++;
265
		} else $fails += 5;
266
267
		if( $fails == 15 ) {
268
			pecho( "An incorrect combination of parameters was used and therefore, no proper authentication can be established.\n\n", PECHO_FATAL );
269
			return false;
270
		} else {
271
			pecho( "Peachy was unable to authenticate with any method of authentication.\nPlease check your connection settings and try again.\n\n", PECHO_FATAL );
272
			return false;
273
		}
274
	}
275
276
	/**
277
	 * Opens a shell, sends a command and returns output and closes the shell.
278
	 * NOTICE: Using a command that opens a new shell will cause hangups.
279
	 *
280
	 * @access public
281
	 * @param string $command Command to execute
282
	 * @param string $callback Function to call upon executing task.
283
	 * @param bool $displayError Should stderr be outputted as well. Only available with SSH2.
284
	 * @param bool $exitstatus Returns the exit status along with output.  Output becomes array. Only available with SSH2.
285
	 * @returns bool|string|array
286
	 */
287
	public function exec( $command, $callback = null, $displayError = false, $exitstatus = false ) {
288
		if( $this->protocol === 2 ) {
289
			if( $displayError ) {
290
                $this->SSHObject->enableQuietMode();
291
            } else $this->SSHObject->disableQuietMode();
292
		}
293
		if( $this->protocol === 2 && $exitstatus ) {
294
			return array(
295
                'result' => $this->SSHObject->exec($command, $callback),
296
                'exit_status' => $this->SSHObject->getExitStatus()
297
			);
298
        } else return $this->SSHObject->exec($command, $callback);
299
	}
300
301
	/**
302
	 * Opens an interactive shell if not done already and transmits commands and returns output.
303
	 *
304
	 * @access public
305
	 * @param string $command Command to execute
306
	 * @param string $expect String of output to expect and remove from output.
307
     * @param bool $expectRegex Switches string expectation to regular expressions.
308
	 * @returns bool|string
309
     *
310
     * FIXME    Contains undefined constants
311
	 */
312
    public function iExec($command, $expect = "", $expectRegex = false) {
313
		trim( $command, "\n" );
314
        if ($this->SSHObject->write($command . "\n")) {
315
            return $this->SSHObject->read($expect,
316
                ($expectRegex ? NET_SSH . $this->protocol . _READ_REGEX : NET_SSH . $this->protocol . _READ_SIMPLE));
317
		} else return false;
318
	}
319
320
	/**
321
	 * Sets a timeout for exec and iexec
322
	 *
323
	 * @access public
324
	 * @param int $time
325
	 * @return void
326
	 */
327
	public function setTimeout( $time )
328
    {
329
        $this->SSHObject->setTimeout($time);
330
	}
331
332
	/**
333
	 * Returns whether or not exec or iexec timed out.  Only available for SSH2.
334
	 *
335
	 * @access public
336
	 * @returns bool|null
337
	 */
338
	public function didTimout() {
339
		if( $this->protocol === 2 ) {
340
            return $this->SSHObject->isTimout();
341
		} else return null;
342
	}
343
344
	/**
345
	 * Write a file to a remote server
346
	 *
347
	 * @access public
348
	 * @param string $to location of file to be placed
349
	 * @param string $data data to write or file location of file to upload
350
	 * @param bool $resume resume an interrupted transfer
351
	 * @return bool
352
     *
353
     * FIXME    Contains undefined constants
354
	 */
355
	public function file_put_contents( $to, $data, $resume = false ) {
356
		if( $resume ) {
357
            return $this->SFTPObject->put($to, $data,
358
                (is_file($data) && file_exists($data) ? NET_SFTP_LOCAL_FILE : NET_SFTP_STRING) | NET_SFTP_RESUME);
359
        } else return $this->SFTPObject->put($to, $data,
360
            (is_file($data) && file_exists($data) ? NET_SFTP_LOCAL_FILE : NET_SFTP_STRING));
361
362
	}
363
364
	/**
365
	 * Retrieve a file from a remote server
366
	 *
367
	 * @access public
368
	 * @param string $from Location on remote server to retrieve from.
369
     * @param string|bool $to Location to write to.  If left blank, file contents is returned.
370
	 * @param int $offset Where to start retrieving files from.
371
	 * @param int $length How much of the file to retrieve.
372
	 * @returns bool|string
373
	 */
374
	public function file_get_contents( $from, $to = false, $offset = 0, $length = -1 )
375
    {
376
        return $this->SFTPObject->get($from, $to, $offset, $length);
377
	}
378
379
	/**
380
	 * Makes directory
381
	 *
382
	 * @param string $pathname The directory path.
383
	 * @param int $mode The mode is 0777 by default, which means the widest possible access.
384
	 * @param bool $recursive Allows the creation of nested directories specified in the pathname.
385
	 * @return bool
386
	 * @access public
387
	 */
388
	public function mkdir( $pathname, $mode = 0777, $recursive = false )
389
    {
390
        return $this->SFTPObject->mkdir($pathname, $mode, $recursive);
391
	}
392
393
	/**
394
	 * Changes SFTP's current directory to directory.
395
	 *
396
	 * @param string $directory The new current directory
397
	 * @return bool
398
	 * @access public
399
	 */
400
	public function chdir( $directory )
401
    {
402
        return $this->SFTPObject->chdir($directory);
403
	}
404
405
	/**
406
	 * Displays the current directory
407
	 *
408
	 * @access public
409
	 * @return string
410
	 */
411
	public function pwd()
412
    {
413
        return $this->SFTPObject->pwd();
414
	}
415
416
	/**
417
	 * Deletes a directory and all of its contents
418
	 *
419
	 * @access public
420
	 * @param string $dirname Path to the directory.
421
	 * @return bool
422
	 */
423
	public function rmdir( $dirname )
424
    {
425
        return $this->SFTPObject->delete($dirname, true);
426
	}
427
428
	/**
429
	 * Retrieves the contents of the directory
430
	 *
431
	 * @param string $dir Directory to retrieve
432
	 * @param bool $detailed Return details of contents
433
	 * @access public
434
	 * @return bool|array
435
	 */
436
	public function directory_get_contents( $dir, $detailed = false )
437
    {
438
        return $this->SFTPObject->_list($dir, $detailed);
439
	}
440
441
	/**
442
	 * Changes file mode
443
	 *
444
	 * @access public
445
	 * @param string $path Path to the directory or file
446
	 * @param int $mode Mode to change to
447
	 * @param bool $recursive Apply it to files within directory and children directories.
448
	 * @return bool|int
449
	 */
450
	public function chmod( $path, $mode, $recursive = false )
451
    {
452
        return $this->SFTPObject->chmod($mode, $path, $recursive);
453
	}
454
455
	/**
456
	 * Sets access and modification time of file
457
	 *
458
	 * @access public
459
	 * @param string $filename The name of the file being touched.
460
	 * @param int $time The touch time. If time is not supplied, the current system time is used.
461
	 * @param int $atime If present, the access time of the given filename is set to the value of atime. Otherwise, it is set to the value passed to the time parameter. If neither are present, the current system time is used.
462
	 * @return bool
463
	 */
464
	public function touch( $filename, $time = null, $atime = null )
465
    {
466
        return $this->SFTPObject->touch($filename, $time, $atime);
467
	}
468
469
	/**
470
	 * Changes file or directory owner
471
	 *
472
	 * @param string $filename Path to the file or directory.
473
	 * @param int $user A user number.
474
	 * @param bool $recursive Apply to all files and directories within dirctory.
475
	 * @access public
476
	 * @return bool
477
	 */
478
	public function chown( $filename, $user, $recursive = false )
479
    {
480
        return $this->SFTPObject->chown($filename, $user, $recursive);
481
	}
482
483
	/**
484
	 * Changes file or directory group
485
	 *
486
	 * @param string $filename Path to the file or directory.
487
	 * @param int $group A group number.
488
	 * @param bool $recursive Apply to all files and directories within dirctory.
489
	 * @access public
490
	 * @return bool
491
	 */
492
	public function chgrp( $filename, $group, $recursive = false )
493
    {
494
        return $this->SFTPObject->chgrp($filename, $group, $recursive);
495
	}
496
497
	/**
498
	 * Truncates a file to a specified size
499
	 *
500
	 * @param string $filename Path to the file.
501
	 * @param int $size Size to truncate to.
502
	 * @access public
503
	 * @return bool
504
	 */
505
	public function truncate( $filename, $size )
506
    {
507
        return $this->SFTPObject->truncate($filename, $size);
508
	}
509
510
	/**
511
	 * Gives information about a file
512
	 *
513
	 * @param string $filename Path to the file.
514
	 * @access public
515
	 * @return array|bool
516
	 */
517
	public function stat( $filename )
518
    {
519
        return $this->SFTPObject->stat($filename);
520
	}
521
522
	/**
523
	 * Gives information about a file or symbolic link
524
	 *
525
	 * @param string $filename Path to a file or a symbolic link.
526
	 * @access public
527
	 * @return array|bool
528
	 */
529
	public function lstat( $filename )
530
    {
531
        return $this->SFTPObject->lstat($filename);
532
	}
533
534
	/**
535
	 * Gets file size.  Files >4GB return as 4GB.
536
	 *
537
	 * @access public
538
	 * @param string $filename Path to the file.
539
	 * @return bool|int
540
	 */
541
	public function filesize( $filename )
542
    {
543
        return $this->SFTPObject->size($filename);
544
	}
545
546
	/**
547
	 * Deletes a file
548
	 *
549
	 * @access public
550
	 * @param string $filename Path to the file.
551
	 * @return bool
552
	 */
553
	public function unlink( $filename )
554
    {
555
        return $this->SFTPObject->delete($filename, false);
556
	}
557
558
	/**
559
	 * Renames a file or directory
560
	 *
561
	 * @access public
562
	 * @param string $oldname The old name.
563
	 * @param string $newname The new name.
564
	 * @return bool
565
	 */
566
	public function rename( $oldname, $newname )
567
    {
568
        return $this->SFTPObject->rename($oldname, $newname);
569
	}
570
571
    /**
572
     * Check for Update Function
573
     *
574
     * Checks the phpseclib/phpseclib library for updates.
575
     *
576
     * @return  bool    Returns true if no updates
577
     *                  Returns false if updates needed
578
     *
579
     * FIXME    The .json file may no longer contain ['commit']['sha'], but possibly ['tree']['sha']
580
     */
581
    protected function CheckForUpdate() {
582
		global $pgIP;
583
		$data = json_decode( $this->http->get( 'https://api.github.com/repos/phpseclib/phpseclib/branches/master', null, array(), false ), true );
584
		$this->commits = $data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $data of type * is incompatible with the declared type array of property $commits.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
585
		if( !file_exists( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . 'phpseclibupdate' ) ) return false;
586
		$log = unserialize( file_get_contents( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . 'phpseclibupdate' ) );
587
		if( isset( $data['commit']['sha'] ) && $log['commit']['sha'] != $data['commit']['sha'] ) {
588
			pecho( "Updating SSH class!\n\n", PECHO_NOTICE );
589
			return false;
590
		}
591
		return true;
592
	}
593
594
	protected function installPHPseclib() {
595
		global $pgIP;
596
		$gitZip = $pgIP . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'phpseclibupdate.zip';
597
		if( file_exists( $gitZip ) ) {
598
			unlink( $gitZip );
599
		}
600
		file_put_contents( $gitZip, file_get_contents( 'http://github.com/phpseclib/phpseclib/archive/master.zip' ) );
601
		$zip = new ZipArchive();
602
		$res = $zip->open( $gitZip );
603
		if( $res === true ) {
604
			$gitFolder = $pgIP . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'phpseclibupdate';
605
			if( file_exists( $gitFolder ) ) {
606
				$this->rrmdir( $gitFolder );
607
			}
608
			mkdir( $gitFolder, 02775 );
609
			$zip->extractTo( $gitFolder );
610
			$zip->close();
611
612
			$this->copyOverGitFiles( $gitFolder . DIRECTORY_SEPARATOR . 'phpseclib-master' . DIRECTORY_SEPARATOR . 'phpseclib' . DIRECTORY_SEPARATOR );
613
614
			pecho( "Successfully installed SSH class\n\n", PECHO_NOTICE );
615
616
			file_put_contents( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . 'phpseclibupdate', serialize( $this->commits ) );
617
		} else {
618
			pecho( "Unable to install SSH class\n\n", PECHO_WARN );
619
		}
620
	}
621
622
	/**
623
	 * @param string $gitFolder
624
	 */
625
	private function copyOverGitFiles( $gitFolder ) {
626
		/** @var $fileInfo DirectoryIterator */
627
		global $pgIP;
628
		if( !file_exists( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . 'SSHCore' ) ) mkdir( $pgIP . 'Includes' . DIRECTORY_SEPARATOR . 'SSHCore', 2775 );
629
		foreach( new DirectoryIterator( $gitFolder ) as $fileInfo ){
630
			if( $fileInfo->isDot() ) continue;
631
			$gitPath = $fileInfo->getRealPath();
632
			$lclPatch = $this->getLocalPath( $gitPath );
633
634
			if( $fileInfo->isDir() ) {
635
				if( !file_exists( $lclPatch ) ) {
636
					mkdir( $lclPatch );
637
				}
638
				$this->copyOverGitFiles( $gitPath );
639
			} elseif( $fileInfo->isFile() ) {
640
				file_put_contents( $lclPatch, file_get_contents( $gitPath ) );
641
			}
642
		}
643
	}
644
645
	/**
646
	 * recursively remove a directory
647
	 * @param string $dir
648
	 */
649
	private function rrmdir( $dir ) {
650
		if( is_dir( $dir ) ) {
651
			$objects = scandir( $dir );
652
			foreach( $objects as $object ){
653
				if( $object != "." && $object != ".." ) {
654
					if( filetype( $dir . "/" . $object ) == "dir" ) $this->rrmdir( $dir . "/" . $object ); else unlink( $dir . "/" . $object );
655
				}
656
			}
657
			reset( $objects );
658
			rmdir( $dir );
659
		}
660
	}
661
662
	/**
663
	 * @param string $fullUpdatePath
664
	 * @return string
665
	 */
666
	private function getLocalPath( $fullUpdatePath ) {
667
		global $pgIP;
668
		$xplodesAt = DIRECTORY_SEPARATOR . 'phpseclibupdate' . DIRECTORY_SEPARATOR . 'phpseclib-master' . DIRECTORY_SEPARATOR . 'phpseclib' . DIRECTORY_SEPARATOR;
669
		$parts = explode( $xplodesAt, $fullUpdatePath, 2 );
670
		return $pgIP . 'Includes' . DIRECTORY_SEPARATOR . 'SSHCore' . DIRECTORY_SEPARATOR . $parts[1];
671
	}
672
673
	/**
674
	 * Destruction class. Closes the SSH connection and kills everything.
675
	 *
676
	 * @access private
677
	 * @return void
678
	 */
679
	public function __destruct()
680
    {
681
        $this->privateKey = null;
682
		$this->connected = false;
683
		$this->host = null;
684
		$this->username = null;
685
        $this->SSHObject->_disconnect("Peachy Connection Terminated");
686
        $this->SFTPObject->_disconnect("Peachy Connection Terminated");
687
	}
688
}
689