GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (1410)

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.

protected/components/Meta.php (5 issues)

Severity

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
 * @author Alexey Tatarinov <[email protected]>
4
 * @link https://github.com/shogodev/argilla/
5
 * @copyright Copyright &copy; 2003-2014 Shogo
6
 * @license http://argilla.ru/LICENSE
7
 * @package frontend.components
8
 *
9
 * @property string $header
10
 * @property string $title
11
 * @property string $description
12
 * @property string $keywords
13
 * @property string $custom
14
 */
15
class Meta extends CApplicationComponent
16
{
17
  const VARIABLE_PATTERN = "/{([\w:]+)}/";
18
19
  const COMMAND_PATTERN = "/([a-z]+)\(([^()]+)\)/";
20
21
  /**
22
   * @var array
23
   */
24
  public $exceptedModels = array('ProductAssignment', 'ProductParameterAssignment', 'ProductTreeAssignment');
25
26
  /**
27
   * @var array
28
   */
29
  public $replaces = array();
30
31
  /**
32
   * @var int
33
   */
34
  public $maxSearchDepth = 1;
35
36
  /**
37
   * @var FController
38
   */
39
  private $controller;
40
41
  /**
42
   * @var string
43
   */
44
  private $route;
45
46
  /**
47
   * @var string
48
   */
49
  private $requestUri;
50
51
  /**
52
   * @var FActiveRecord[]
53
   */
54
  private $renderedModels = array();
55
56
  /**
57
   * @var array
58
   */
59
  private $renderedClips = array();
60
61
  private $header;
62
63
  private $title;
64
65
  private $description;
66
67
  private $keywords;
68
69
  private $custom;
70
71
  private $noindex;
72
73 2
  public function init()
74
  {
75 2
    parent::init();
76
77 2
    if( $controller = Yii::app()->controller )
78 2
    {
79 2
      $this->setController($controller);
80 2
      $this->controller->attachEventHandler('onBeforeRender', array($this, 'setRenderedModels'));
81 2
      $this->controller->attachEventHandler('onBeforeRenderLayout', array($this, 'registerMeta'));
82 2
    }
83
84 2
    Yii::app()->attachEventHandler('onEndRequest', array($this, 'updateRenderedModels'));
85
86 2
    if( isset(Yii::app()->request) )
87 2
      $this->setRequestUri(Yii::app()->request->requestUri);
88
89 2
    $this->replaces = array(
90 2
      '{project}' => Arr::get(Yii::app()->params, 'project'),
91
    );
92 2
  }
93
94
  /**
95
   * @return string
96
   */
97 18
  public function getTitle()
98
  {
99 18
    return CHtml::encode($this->clear($this->title));
100
  }
101
102
  /**
103
   * @return string
104
   */
105 3
  public function getDescription()
106
  {
107 3
    return $this->clear($this->description);
108
  }
109
110
  /**
111
   * @return string
112
   */
113 3
  public function getKeywords()
114
  {
115 3
    return $this->clear($this->keywords);
116
  }
117
118
  /**
119
   * @return string
120
   */
121 7
  public function getCustom()
122
  {
123 7
    return $this->clear($this->custom);
124
  }
125
126
  /**
127
   * @param $header
128
   *
129
   * @return string
130
   */
131 6
  public function setHeader($header)
132
  {
133 6
    if( !empty($this->header) )
134 6
    {
135
      $header = $this->clear($this->header);
136
    }
137
138 6
    $this->registerClip('h1', $header);
139 6
    return $header;
140
  }
141
142
  /**
143
   * @param FController $controller
144
   */
145 7
  public function setController(FController $controller)
146
  {
147 7
    if( !isset($this->controller) )
148 7
    {
149 7
      $this->controller = $controller;
150 7
      $this->setRoute();
151 7
    }
152 7
  }
153
154
  /**
155
   * @param string $uri
156
   */
157 10
  public function setRequestUri($uri)
158
  {
159 10
    $this->requestUri = preg_replace('/\?.*/', '', $uri);
160 10
  }
161
162 14
  public function setMeta()
163
  {
164
    /**
165
     * @var MetaMask $metaMask
166
     * @var MetaRoute $metaRoute
167
     */
168 14
    $metaMask = MetaMask::model()->findByUri($this->requestUri);
169 14
    $metaRoute = MetaRoute::model()->findByRoute($this->route);
170
171 14
    foreach(array('header', 'title', 'keywords', 'description', 'noindex', 'custom') as $property)
172
    {
173
      if( $metaRoute )
174 14
        $this->$property = Arr::get($metaRoute, $property);
175
176 14
      if( $metaMask && trim($metaMask->$property) !== '' )
177 14
        $this->$property = $metaMask->$property;
178 14
    }
179
180 14
    if( empty($this->title) )
181 14
    {
182
      $this->title = $this->controller->getPageTitle();
183
    }
184 14
  }
185
186
  /**
187
   * Собираем все модели, переданные в render()
188
   *
189
   * @param CEvent $event
190
   */
191 2
  public function setRenderedModels(CEvent $event)
192
  {
193 2
    $this->setRoute();
194 2
    $this->setMeta();
195
196 2
    $this->processModels(Arr::get($event->params, 'data', array()));
197 2
  }
198
199
  /**
200
   * @param FActiveRecord[] $models
201
   */
202 3
  public function addModels(array $models)
203
  {
204 3
    $this->processModels($models);
205 3
  }
206
207 10
  public function registerClip($id, $value)
208
  {
209 10
    $this->replaces['{'.$id.'}'] = $value;
210 10
    $this->renderedClips[$id] = $id;
211
212 10
    return $value;
213
  }
214
215
  /**
216
   * Запись в базу моделей, найденных во время рендеринга
217
   */
218 1
  public function updateRenderedModels()
219
  {
220 1
    if( strpos($this->route, '/') !== false )
221 1
    {
222 1
      if( !$model = MetaRoute::model()->resetScope()->findByRoute($this->route, false) )
223 1
        $model = new MetaRoute();
224
225 1
      $model->route  = $this->route;
226 1
      $model->models = implode(',', array_keys($this->renderedModels));
227 1
      $model->clips  = implode(',', array_keys($this->renderedClips));
228 1
      $model->save();
229 1
    }
230 1
  }
231
232 2
  public function registerMeta()
233
  {
234 2
    if( $clientScript = Yii::app()->clientScript )
235 2
    {
236 2
      $clientScript->registerMetaTag($this->getDescription(), 'description', null, array(), 'description');
237 2
      $clientScript->registerMetaTag($this->getKeywords(), 'keywords', null, array(), 'keywords');
238
239 2
      if( $this->noindex )
240 2
      {
241 1
        $clientScript->registerMetaTag('noindex, nofollow', 'robots', null, array(), 'robots');
242 1
      }
243 2
    }
244 2
  }
245
246 7
  private function setRoute()
247
  {
248 7
    if( isset($this->controller) )
249 7
      $this->route = $this->controller->route;
250 7
  }
251
252
  /**
253
   * Удаление переменных моделей в строке метатегов
254
   *
255
   * @param string $string
256
   *
257
   * @return string
258
   */
259 19
  private function clear($string)
260
  {
261 19
    $string = $this->replaceVariables($string);
262 19
    $string = $this->replaceCommands($string);
263 19
    $string = preg_replace(self::VARIABLE_PATTERN, '', $string);
264 19
    $string = preg_replace('/\s+/', ' ', $string);
265
266 19
    return trim($string);
267
  }
268
269
  /**
270
   * @param FActiveRecord[] $data
271
   */
272 5
  private function processModels(array $data)
273
  {
274 5
    static $depth;
275
276 5
    foreach($data as $model)
277
    {
278 4
      if( $model instanceof FActiveRecord )
279 4
        $modelName = get_class($model);
280 2
      else if( $model instanceof FForm )
281 2
      {
282 1
        $model = $model->model;
283 1
        $modelName = get_class($model);
284 1
      }
285
      else
286
        continue;
287
288 4
      if( in_array($modelName, $this->exceptedModels) )
289 4
        continue;
290
291 4
      $this->renderedModels[$modelName] = $model;
292
293 4
      if( $model instanceof FActiveRecord && $depth <= $this->maxSearchDepth )
294 4
      {
295 2
        $depth++;
296 2
        $this->processRelations($model);
297 2
      }
298 5
    }
299 5
  }
300
301
  /**
302
   * @param FActiveRecord $model
303
   */
304 2
  private function processRelations(FActiveRecord $model)
305
  {
306 2
    foreach($model->relations() as $name => $relation)
307
    {
308
      if( in_array($relation[0], array(FActiveRecord::HAS_ONE, FActiveRecord::BELONGS_TO)) )
309
      {
310
        if( !isset($this->renderedModels[$relation[1]]) )
311
        {
312
          $this->processModels(array($model->{$name}));
313
        }
314
      }
315 2
    }
316 2
  }
317
318
  /**
319
   * Замена встречающиеся переменных на значения свойств $model
320
   *
321
   * @param $string
322
   *
323
   * @return string
324
   */
325 19
  private function replaceVariables($string)
326
  {
327 19
    if( preg_match_all(self::VARIABLE_PATTERN, $string, $matches) )
328 19
    {
329 17
      if( !empty($matches[0]) )
330 17
      {
331 17
        foreach($matches[0] as $key => $value)
332
        {
333 17
          $replace = $matches[0][$key];
334 17
          $value = $matches[1][$key];
335 17
          $this->processValue($value, $replace);
336 17
        }
337 17
      }
338
339 17
      $string = strtr($string, $this->replaces);
340 17
    }
341
342 19
    return $string;
343
  }
344
345 19
  private function replaceCommands($string)
346
  {
347 19
    if( preg_match(self::COMMAND_PATTERN, $string, $matches) )
348 19
    {
349 5
      if( !empty($matches[0]) )
350 5
      {
351 5
        $command = $matches[1];
352 5
        $args = $matches[2];
353 5
        $value = $this->processCommand($command, $args);
354
355 5
        $string = strtr($string, array($matches[0] => $value));
356 5
        $string = $this->replaceCommands($string);
357 5
      }
358 5
    }
359
360 19
    return $string;
361
  }
362
363
  /**
364
   * @param $value
365
   * @param $replace
366
   */
367 17
  private function processValue($value, $replace)
368
  {
369 17
    if( strpos($value, ':') !== false )
370 17
    {
371 2
      list($modelName, $attribute) = explode(':', $value);
372 2
      $model = Arr::get($this->renderedModels, $modelName);
373
374 2
      if( $model && ($property = $this->getPropertyValue($model, $attribute)) )
375 2
      {
376 2
        $this->replaces[$replace] = $property;
377 2
      }
378 2
    }
379 17
  }
380
381
  /**
382
   * @param string $command
383
   * @param string $args
384
   *
385
   * @return string
386
   */
387 5
  private function processCommand($command, $args)
388
  {
389 5
    $args = Arr::trim(explode(',', $args));
390
391
    switch($command)
392
    {
393 5
      case 'ucfirst':
394 1
        return Utils::ucfirst($args[0]);
395
        break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
396
397 5
      case 'upper':
398 1
        return mb_strtoupper($args[0]);
399
        break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
400
401 5
      case 'lower':
402 1
        return mb_strtolower($args[0]);
403
        break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
404
405 4
      case 'wrap':
406 3
        $left = Arr::get($args, 1, '(');
407 3
        $right = Arr::get($args, 2, ')');
408 3
        return $left.$args[0].$right;
409
        break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
410
411 2
      case 'implode':
412 1
        return implode(trim(Arr::cut($args, 0), '\'"'), $args);
413
        break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
414
415 1
      default:
416 1
        return $args[0];
417 1
    }
418
  }
419
420
  /**
421
   * @param FActiveRecord $model
422
   * @param string $property
423
   *
424
   * @return string
425
   */
426 2
  private function getPropertyValue($model, $property)
427
  {
428 2
    return isset($model->$property) && !is_object($model->$property) && !is_array($model->$property) ? $model->$property : null;
429
  }
430
}