Issues (1751)

Security Analysis    not enabled

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.

lib/ar/connect/ftp.php (3 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
	ar_pinp::allow( 'ar_connect_ftp');
4
	ar_pinp::allow( 'ar_connect_ftpClient' );
5
6
	class ar_connect_ftp extends arBase {
7
8
		public static $timeout      = 90;
9
		public static $pasv         = false;
10
		public static $transferMode = FTP_BINARY;
11
12 View Code Duplication
		public static function get( $url, $options = array() ) {
13
			$path = parse_url($url, PHP_URL_PATH );
14
			if ($path !== false ) {
15
				$fileName = basename($path);
16
				$client = new ar_connect_ftpClient( $url, $options );
17
				if ( !ar_error::isError( $client) ) {
18
					return $client->get( $fileName );
19
				} else {
20
					return $client;
21
				}
22
			} else {
23
				return ar::error( "Could not parse url ".(string)$url, 11);
24
			}
25
		}
26
27 View Code Duplication
		public static function put( $url, $contents, $options = array() ) {
28
			$path = parse_url( $url, PHP_URL_PATH );
29
			if ($path !== false ) {
30
				$fileName = basename($path);
31
				$client = new ar_connect_ftpClient($url, $options );
32
				if ( !ar_error::isError( $client ) ) {
33
					return $client->put( $contents, $fileName );
34
				} else {
35
					return $client;
36
				}
37
			} else {
38
				return ar::error( "Could not parse url ".(string)$url, 11);
39
			}
40
		}
41
42
		public static function client( $url = null, $options = array() ) {
43
			return new ar_connect_ftpClient( $url, $options );
44
		}
45
46
		public static function configure( $option, $value ) {
47
			switch ( $option ) {
48
				case 'timeout' :
49
					self::$timeout = $value;
50
				break;
51
				case 'pasv' :
52
					self::$pasv = $value;
53
				break;
54
				case 'transferMode' :
55
					self::$transferMode = $value;
56
				break;
57
			}
58
		}
59
60
		public function __set( $name, $value ) {
61
			ar_connect_ftp::configure( $name, $value );
62
		}
63
64
		public function __get( $name ) {
65
			if ( isset( ar_connect_ftp::${$name} ) ) {
66
				return ar_connect_ftp::${$name};
67
			}
68
		}
69
70
	}
71
72
	interface ar_connect_ftpClientInterface {
73
74
		public function get( $file, $options = array() );
75
76
		public function put( $contents, $file, $options = array() );
77
78
		public function login( $username, $password = null);
79
80
		public function connect( $host, $port = 21);
81
82
		public function disconnect();
83
84
		public function delete( $file, $options = array() );
85
86
		public function cd( $dir );
87
88
		public function ls();
89
90
		public function mkdir( $dirname );
91
92
		public function rename( $name, $newname );
93
94
		public function chmod( $mode, $filename );
95
96
		public function size( $filename );
97
98
		public function mdtm( $filename );
99
100
		public function pwd();
101
102
		public function mode( $mode );
103
104
		public function pasv( $pasv );
105
106
	}
107
108
	class ar_connect_ftpClient extends arBase implements ar_connect_ftpClientInterface {
109
		//FIXME: change error codes to the ar_exception constants
110
		public $options = array();
111
		public $host = null;
112
		public $port = null;
113
		public $user = null;
114
		protected $pass = null;
115
		public $path = null;
116
		protected $connection = null;
117
118
		public function __construct( $url = null, $options = array() ) {
119
			$this->options = $options + array(
120
				'mode' => ar_connect_ftp::$transferMode,
121
				'pasv' => ar_connect_ftp::$pasv
122
			);
123
			$parsed = parse_url( $url );
124
			if ($parsed) {
125
				$this->host = $parsed['host'];
126
				$this->port = $parsed['port'] ? $parsed['port'] : 21;
127
				$this->user = $parsed['user'] ? $parsed['user'] : 'anonymous';
128
				$this->pass = $parsed['pass'] ? $parsed['pass'] : 'guest';
129
				$this->path = $parsed['path'];
130
				if ($this->path[strlen($this->path)-1] != '/' ) {
131
					$this->path = substr(dirname($this->path), 1); // relative path for cd
132
				}
133
				if ($this->host) {
134
					$this->connect( $this->host, $this->port );
135
					$this->login( $this->user, $this->pass );
136
					if ($this->path) {
137
						$this->cd( $this->path );
138
					}
139
				}
140
			}
141
		}
142
143
		public function get( $file, $options = array() ) {
144
			$this->options = array_merge( $this->options, (array) $options );
145
			$fp = fopen("php://temp/maxmemory:10485760", "w");
146
			$result = @ftp_fget( $this->connection, $fp, $file, $this->options['mode'] );
147
			if( $result ) {
148
				fseek( $fp, 0 );
149
				$result = stream_get_contents( $fp );
150
			} else {
151
				$result = ar::error( "Failed to get file $file", 12);
152
			}
153
			fclose( $fp );
154
			return $result;
155
		}
156
157
		public function put( $contents, $file, $options = array() ) {
158
			$this->options = array_merge( $this->options, (array) $options );
159
			if ($contents instanceof pfile ) {
0 ignored issues
show
The class pfile does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
160
				global $store;
161
				$files = $store->get_filestore('files');
162
				$path = $files->make_path($contents->id, 'file');
163
				$fp = fopen($path, 'r');
164
			} else {
165
				$fp = fopen("php://temp/maxmemory:10485760", "w+");
166
				fwrite( $fp, (string) $contents );
167
				fseek( $fp, 0);
168
			}
169
			$result = ftp_fput( $this->connection, $file, $fp, $this->options['mode'] );
170
			fclose($fp);
171
			if ( !$result ) {
172
				return ar::error( "Could not save file $file.", 10 );
173
			}
174
			return $this;
175
		}
176
177
		public function login( $username, $password = null) {
178
			if (!@ftp_login($this->connection, $username, $password)) {
179
				return ar::error( "Could not connect as $username", 1);
180
			}
181
			return $this;
182
		}
183
184
		public function connect( $host, $port = 21) {
185
			if ( ! $this->connection = ftp_connect( $host, $port ) ) { // FIXME: add timeout?
186
				return ar::error( "Could not connect to $host on port $port", 2);
187
			} else if (ar_connect_ftp::$timeout) {
188
				ftp_set_option( $this->connection, FTP_TIMEOUT_SEC, ar_connect_ftp::$timeout );
189
			}
190
			return $this;
191
		}
192
193
		public function cd( $dir ) {
194
			$result = ftp_chdir( $this->connection, $dir );
195
			if ( !$result ) {
196
				return ar::error( "Could not change to directory $dir.", 9);
197
			}
198
			return $this;
199
		}
200
201
		public function disconnect() {
202
			ftp_close( $this->connection );
203
			return $this;
204
		}
205
206
		public function delete( $file, $options = array() ) {
207
			$result = ftp_delete( $this->connection, $file );
208
			if ( !$result ) {
209
				return ar::error( "Could not delete file $file.", 7 );
210
			}
211
			return $this;
212
		}
213
214
		public function ls($path='.', $verbose=false) {
215
			if (!$verbose) {
216
				$result = ftp_nlist($this->connection, $path);
217
				if ( !$result ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $result of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
218
					return ar::error( "Could not list the current directory.", 8);
219
				}
220
			} else {
221
				if (!$this->connection) {
222
					return ar::error("Connection is not active", 42);
223
				}
224
				$list = ftp_rawlist($this->connection, $path);
225
				if ( !$list ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $list of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
226
					return ar::error( "Could not rawlist the current directory.", 9);
227
				}
228
				$result = array();
229
				foreach($list as $info) {
230
					$info = preg_split("/[\s]+/", $info, 9);
231
					$entry = array(
232
						"permissions" => $info[0],
233
						"linkcount" => $info[1],
234
						"userid" => $info[2],
235
						"groupid" => $info[3],
236
						"size" => (int)$info[4],
237
						"mtime" => strtotime($info[5] . " " . $info[6] . " " . $info[7]),
238
						"name"=> $info[8]
239
					);
240
241
					if (substr($info[0], 0, 1) == "d") {
242
						$entry['type'] = "dir";
243
					} elseif (substr($info[0], 0, 1) == "l") {
244
						$entry['type'] = "shortcut";
245
						$nameinfo = explode(" -> ", $info[8]);
246
						$entry['name'] = $nameinfo[0];
247
						$entry['target'] = $nameinfo[1];
248
					} else {
249
						$entry['type'] = "file";
250
					}
251
					$result[$entry['name']] = $entry;
252
				}
253
			}
254
			return $result;
255
		}
256
257
		public function mkdir( $dirname ) {
258
			$result = ftp_mkdir( $this->connection, $dirname );
259
			if (!$result) {
260
				return ar::error( "Could not make directory $dirname.", 3);
261
			}
262
			return $this;
263
		}
264
265
		public function rename( $name, $newname ) {
266
			if (!ftp_rename( $this->connection, $name, $newname ) ) {
267
				return ar::error( "Could not rename $name to $newname.", 4);
268
			}
269
			return $this;
270
		}
271
272
		public function chmod( $mode, $filename ) {
273
			if (!ftp_chmod( $this->connection, $mode, $filename) ) {
274
				return ar::error( "Could not chmod $filename.", 5);
275
			}
276
			return $this;
277
		}
278
279
		public function size( $filename ) {
280
			$result = ftp_size($this->connection, $filename);
281
			if ( $result == -1 ) {
282
				return null;
283
			} else {
284
				return $result;
285
			}
286
		}
287
288
		public function mdtm( $filename ) {
289
			$result = ftp_mdtm( $this->connection, $filename );
290
			if ($result == -1 ) {
291
				return null;
292
			} else {
293
				return $result;
294
			}
295
		}
296
297
		public function pwd() {
298
			return ftp_pwd( $this->connection );
299
		}
300
301
		public function mode( $mode ) {
302
			$this->options['mode'] = $mode;
303
			return $this;
304
		}
305
306
		public function pasv( $pasv = true ) {
307
			$this->options['pasv'] = $pasv;
308
			if ( !ftp_pasv( $this->connection, $pasv) ) {
309
				return ar::error( "Could not switch passive mode.", 6);
310
			}
311
			return $this;
312
		}
313
314
	}
315