Completed
Push — master ( c60cf3...36f595 )
by Sebastien
07:49
created

HackedFileGroup::isBinary()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
rs 8.2222
cc 7
eloc 13
nc 7
nop 1
1
<?php
2
3
namespace Cerbere\Model\Hacked;
4
5
/**
6
 * Represents a group of files on the local filesystem.
7
 */
8
class HackedFileGroup {
9
  /**
10
   * @var string
11
   */
12
  protected $base_path = '';
13
14
  /**
15
   * @var array
16
   */
17
  protected $files = array();
18
19
  /**
20
   * @var array
21
   */
22
  protected $files_hashes = array();
23
24
  /**
25
   * @var array
26
   */
27
  protected $file_mtimes = array();
28
29
  /**
30
   * @var HackedFileHasher
31
   */
32
  protected $hasher;
33
34
  /**
35
   * Constructor.
36
   *
37
   * @param string $base_path
38
   * @param HackedFileHasher $hasher
39
   */
40
  public function __construct($base_path, HackedFileHasher $hasher = null) {
41
    if (null === $hasher) {
42
      $hasher = new HackedFileIgnoreEndingsHasher();
43
    }
44
45
    $this->base_path = $base_path;
46
    $this->hasher = $hasher;
47
  }
48
49
  /**
50
   * @return array
51
   */
52
  public function getFiles()
53
  {
54
    return $this->files;
55
  }
56
57
  /**
58
   * @param string $file
59
   *
60
   * @return string|bool
61
   */
62
  public function getFileHash($file)
63
  {
64
    if (isset($this->files_hashes[$file])) {
65
      return $this->files_hashes[$file];
66
    }
67
68
    return false;
69
  }
70
71
  /**
72
   * Return a new hackedFileGroup listing all files inside the given $path.
73
   *
74
   * @param string $path
75
   *
76
   * @return HackedFileGroup
77
   */
78
  public static function fromDirectory($path) {
79
    $filegroup = new self($path);
80
    // Find all the files in the path, and add them to the file group.
81
    $filegroup->scanBasePath();
82
83
    return $filegroup;
84
  }
85
86
  /**
87
   * Return a new hackedFileGroup listing all files specified.
88
   *
89
   * @param string $path
90
   * @param array  $files
91
   *
92
   * @return HackedFileGroup
93
   */
94
  public static function fromList($path, array $files) {
95
    $filegroup = new self($path);
96
    // Find all the files in the path, and add them to the file group.
97
    $filegroup->files = $files;
98
99
    return $filegroup;
100
  }
101
102
  /**
103
   * Locate all sensible files at the base path of the file group.
104
   */
105
  public function scanBasePath() {
106
    $files = self::scanDirectory($this->base_path, '/.*/', array(
107
      '.',
108
      '..',
109
      'CVS',
110
      '.svn',
111
      '.git'
112
    ));
113
114
    foreach ($files as $file) {
115
      $filename = str_replace($this->base_path . DIRECTORY_SEPARATOR, '', $file->filename);
116
      $this->files[] = $filename;
117
    }
118
  }
119
120
  /**
121
   * Hash all files listed in the file group.
122
   */
123
  public function computeHashes() {
124
    foreach ($this->files as $filename) {
125
      $this->files_hashes[$filename] = $this->hasher->hash($this->base_path . DIRECTORY_SEPARATOR . $filename);
126
    }
127
  }
128
129
  /**
130
   * Determine if the given file is readable.
131
   * @param string $file
132
   * @return bool
133
   */
134
  public function isReadable($file) {
135
    return is_readable($this->base_path . DIRECTORY_SEPARATOR . $file);
136
  }
137
138
  /**
139
   * Determine if a file exists.
140
   * @param string $file
141
   * @return bool
142
   */
143
  public function fileExists($file) {
144
    return file_exists($this->base_path . DIRECTORY_SEPARATOR . $file);
145
  }
146
147
  /**
148
   * Determine if the given file is binary.
149
   * @param string $file
150
   * @return bool
151
   */
152
  public function isNotBinary($file) {
153
    return is_readable($this->base_path . DIRECTORY_SEPARATOR . $file)
154
      && !self::isBinary($this->base_path . DIRECTORY_SEPARATOR . $file);
155
  }
156
157
  /**
158
   * @param string $file
159
   * @return string
160
   */
161
  public function getFileLocation($file) {
162
    return $this->base_path . DIRECTORY_SEPARATOR . $file;
163
  }
164
165
  /**
166
   * Determine if a file is a binary file.
167
   *
168
   * Taken from: http://www.ultrashock.com/forums/server-side/checking-if-a-file-is-binary-98391.html
169
   * and then tweaked in: http://drupal.org/node/760362.
170
   *
171
   * @param string $file
172
   *
173
   * @return bool
174
   */
175
  public static function isBinary($file) {
176
    if (file_exists($file)) {
177
      if (!is_file($file)) return 0;
178
      if (!is_readable($file)) return 1;
179
180
      $fh  = fopen($file, "r");
181
      $blk = fread($fh, 512);
182
      fclose($fh);
183
      clearstatcache();
184
185
      return (
186
        0 or substr_count($blk, "^\r\n") / 512 > 0.3
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
187
        or substr_count($blk, "^ -~") / 512 > 0.3
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
188
        or substr_count($blk, "\x00") > 0
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
189
      );
190
    }
191
    return 0;
192
  }
193
194
  /**
195
   * @param string    $dir
196
   * @param int       $mask
197
   * @param array     $nomask
198
   * @param callable  $callback
199
   * @param bool|true $recurse
200
   * @param string    $key
201
   * @param int       $min_depth
202
   * @param int       $depth
203
   *
204
   * @return array
205
   */
206
  public static function scanDirectory($dir, $mask, $nomask = array('.', '..', 'CVS'), $callback = null, $recurse = TRUE, $key = 'filename', $min_depth = 0, $depth = 0) {
207
    $key = (in_array($key, array('filename', 'basename', 'name')) ? $key : 'filename');
208
    $files = array();
209
210
    if (is_dir($dir) && $handle = opendir($dir)) {
211
      while (FALSE !== ($file = readdir($handle))) {
212
        if (!in_array($file, $nomask)) {
213
          if (is_dir($dir . DIRECTORY_SEPARATOR . $file) && $recurse) {
214
            // Give priority to files in this folder by merging them in after any subdirectory files.
215
            $files = array_merge(self::scanDirectory($dir . DIRECTORY_SEPARATOR . $file, $mask, $nomask, $callback, $recurse, $key, $min_depth, $depth + 1), $files);
216
          }
217
          elseif ($depth >= $min_depth && preg_match($mask, $file)) {
218
            // Always use this match over anything already set in $files with the same $$key.
219
            $filename = $dir . DIRECTORY_SEPARATOR . $file;
220
            $basename = basename($file);
221
            $name = substr($basename, 0, strrpos($basename, '.'));
222
            $files[$$key] = new \stdClass();
223
            $files[$$key]->filename = $filename;
224
            $files[$$key]->basename = $basename;
225
            $files[$$key]->name = $name;
226
            if (is_callable($callback)) {
227
              $callback($filename);
228
            }
229
          }
230
        }
231
      }
232
233
      closedir($handle);
234
    }
235
236
    return $files;
237
  }
238
}
239