Open Journal Systems  3.3.0
functions.inc.php
Go to the documentation of this file.
1 <?php
2 
22 if (!function_exists('import')) {
23  function import($class) {
24  $filePath = str_replace('.', '/', $class) . '.inc.php';
25  require_once(BASE_SYS_DIR.'/'.$filePath);
26  }
27 }
28 
32 function fatalError($reason) {
33  // Because this method may be called when checking the value of the show_stacktrace
34  // configuration string, we need to ensure that we don't get stuck in an infinite loop.
35  static $isErrorCondition = null;
36  static $showStackTrace = false;
37 
38  if ($isErrorCondition === null) {
39  $isErrorCondition = true;
40  $showStackTrace = Config::getVar('debug', 'show_stacktrace');
41  $isErrorCondition = false;
42  }
43 
44  echo "<h1>" . htmlspecialchars($reason) . "</h1>";
45 
46  if ($showStackTrace) {
47  echo "<h4>Stack Trace:</h4>\n";
48  $trace = debug_backtrace();
49 
50  // Remove the call to fatalError from the call trace.
51  array_shift($trace);
52 
53  // Back-trace pretty-printer adapted from the following URL:
54  // http://ca3.php.net/manual/en/function.debug-backtrace.php
55  // Thanks to diz at ysagoon dot com
56 
57  // FIXME: Is there any way to localize this when the localization
58  // functions may have caused the failure in the first place?
59  foreach ($trace as $bt) {
60  $args = '';
61  if (isset($bt['args'])) foreach ($bt['args'] as $a) {
62  if (!empty($args)) {
63  $args .= ', ';
64  }
65  switch (gettype($a)) {
66  case 'integer':
67  case 'double':
68  $args .= $a;
69  break;
70  case 'string':
71  $a = htmlspecialchars(substr($a, 0, 64)).((strlen($a) > 64) ? '...' : '');
72  $args .= "\"$a\"";
73  break;
74  case 'array':
75  $args .= 'Array('.count($a).')';
76  break;
77  case 'object':
78  $args .= 'Object('.get_class($a).')';
79  break;
80  case 'resource':
81  $args .= 'Resource('.strstr($a, '#').')';
82  break;
83  case 'boolean':
84  $args .= $a ? 'True' : 'False';
85  break;
86  case 'NULL':
87  $args .= 'Null';
88  break;
89  default:
90  $args .= 'Unknown';
91  }
92  }
93  $class = isset($bt['class'])?$bt['class']:'';
94  $type = isset($bt['type'])?$bt['type']:'';
95  $function = isset($bt['function'])?$bt['function']:'';
96  $file = isset($bt['file'])?$bt['file']:'(unknown)';
97  $line = isset($bt['line'])?$bt['line']:'(unknown)';
98 
99  echo "<strong>File:</strong> {$file} line {$line}<br />\n";
100  echo "<strong>Function:</strong> {$class}{$type}{$function}($args)<br />\n";
101  echo "<br/>\n";
102  }
103  }
104 
105  // Determine the application name. Use defensive code so that we
106  // can handle errors during early application initialization.
107  $application = null;
108  if (class_exists('Registry')) {
109  $application = Registry::get('application', true, null);
110  }
111  $applicationName = '';
112  if (!is_null($application)) {
113  $applicationName = $application->getName().': ';
114  }
115 
116  error_log($applicationName.$reason);
117 
118  if (defined('DONT_DIE_ON_ERROR') && DONT_DIE_ON_ERROR == true) {
119  // trigger an error to be catched outside the application
120  trigger_error($reason);
121  return;
122  }
123 
124  die();
125 }
126 
132 function checkPhpVersion($version) {
133  return (version_compare(PHP_VERSION, $version) !== -1);
134 }
135 
165 function &instantiate($fullyQualifiedClassName, $expectedTypes = null, $expectedPackages = null, $expectedMethods = null, $constructorArg = null) {
166  $errorFlag = false;
167 
168  // Validate the class name
169  if (!preg_match('/^[a-zA-Z0-9.]+$/', $fullyQualifiedClassName)) {
170  return $errorFlag;
171  }
172 
173  // Validate the class package
174  if (!is_null($expectedPackages)) {
175  if (is_scalar($expectedPackages)) $expectedPackages = array($expectedPackages);
176  $validPackage = false;
177  foreach ($expectedPackages as $expectedPackage) {
178  // No need to use String class here as class names are always US-ASCII
179  if (substr($fullyQualifiedClassName, 0, strlen($expectedPackage)+1) == $expectedPackage.'.') {
180  $validPackage = true;
181  break;
182  }
183  }
184 
185  // Raise a fatal error if the class does not belong
186  // to any of the expected packages. This is to prevent
187  // certain types of code inclusion attacks.
188  if (!$validPackage) {
189  // Construct meaningful error message.
190  $expectedPackageCount = count($expectedPackages);
191  $separator = '';
192  $expectedPackageString = '';
193  foreach($expectedPackages as $expectedPackageIndex => $expectedPackage) {
194  if ($expectedPackageIndex > 0) {
195  $separator = ($expectedPackageIndex == $expectedPackageCount-1 ? ' or ' : ', ' );
196  }
197  $expectedPackageString .= $separator.'"'.$expectedPackage.'"';
198  }
199  fatalError('Trying to instantiate class "'.$fullyQualifiedClassName.'" which is not in any of the expected packages '.$expectedPackageString.'.');
200  }
201  }
202 
203  // Import the requested class
204  import($fullyQualifiedClassName);
205 
206  // Identify the class name
207  $fullyQualifiedClassNameParts = explode('.', $fullyQualifiedClassName);
208  $className = array_pop($fullyQualifiedClassNameParts);
209 
210  // Type check I: The requested class should be declared by now.
211  if (!class_exists($className)) {
212  fatalError('Cannot instantiate class. Class "'.$className.'" is not declared in "'.$fullyQualifiedClassName.'".');
213  }
214 
215  // Ensure all expected methods are declared.
216  $expectedMethods = (array) $expectedMethods; // Possibly scalar or null; ensure array
217  $declaredMethods = get_class_methods($className);
218  if (count(array_intersect($expectedMethods, $declaredMethods)) != count($expectedMethods)) {
219  return $errorFlag;
220  }
221 
222  // Instantiate the requested class
223  if (is_null($constructorArg)) {
224  $classInstance = new $className();
225  } else {
226  $classInstance = new $className($constructorArg);
227  }
228 
229  // Type check II: The object must conform to the given interface (if any).
230  if (!is_null($expectedTypes)) {
231  if (is_scalar($expectedTypes)) $expectedTypes = array($expectedTypes);
232  $validType = false;
233  foreach($expectedTypes as $expectedType) {
234  if (is_a($classInstance, $expectedType)) {
235  $validType = true;
236  break;
237  }
238  }
239  if (!$validType) return $errorFlag;
240  }
241 
242  return $classInstance;
243 }
244 
250 function arrayClean($array) {
251  if (!is_array($array)) return null;
252  return array_filter($array, function($o) {
253  return !empty($o);
254  });
255 }
256 
257 
263 function stripAssocArray($values) {
264  foreach ($values as $key => $value) {
265  if (is_scalar($value)) {
266  $values[$key] = strip_tags($values[$key]);
267  } else {
268  $values[$key] = stripAssocArray($values[$key]);
269  }
270  }
271  return $values;
272 }
273 
280 function strtolower_codesafe($str) {
281  return strtr($str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz');
282 }
283 
290 function strtoupper_codesafe($str) {
291  return strtr($str, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
292 }
293 
300 function lcfirst_codesafe($str) {
301  return strtolower_codesafe(substr($str, 0, 1)) . substr($str, 1);
302 }
303 
310 function ucfirst_codesafe($str) {
311  return strtoupper_codesafe(substr($str, 0, 1)) . substr($str, 1);
312 }
313 
322 function customAutoload($rootPath, $prefix, $class) {
323  if (substr($class, 0, strlen($prefix)) !== $prefix) {
324  return;
325  }
326 
327  $class = substr($class, strlen($prefix));
328  $parts = explode('\\', $class);
329 
330  // we expect at least one folder in the namespace
331  // there is no class defined directly under classes/ folder
332  if (count($parts) < 2) {
333  return;
334  }
335 
336  $className = Core::cleanFileVar(array_pop($parts));
337  $parts = array_map(function($part) {
338  $part = Core::cleanFileVar($part);
339  if (strlen($part)>1) $part[0] = strtolower_codesafe($part[0]); // pkp/pkp-lib#5731
340  return $part;
341  }, $parts);
342 
343  $subParts = join('/', $parts);
344  $filePath = "{$rootPath}/{$subParts}/{$className}.inc.php";
345 
346  if (is_file($filePath)) {
347  require_once($filePath);
348  }
349 }
350 
instantiate
& instantiate($fullyQualifiedClassName, $expectedTypes=null, $expectedPackages=null, $expectedMethods=null, $constructorArg=null)
Definition: functions.inc.php:165
$application
$application
Definition: index.php:65
BASE_SYS_DIR
const BASE_SYS_DIR(!defined('DIRECTORY_SEPARATOR'))
Definition: lib/pkp/includes/bootstrap.inc.php:32
strtoupper_codesafe
strtoupper_codesafe($str)
Definition: functions.inc.php:290
Registry\get
static & get($key, $createIfEmpty=false, $createWithDefault=null)
Definition: Registry.inc.php:35
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
ucfirst_codesafe
ucfirst_codesafe($str)
Definition: functions.inc.php:310
stripAssocArray
stripAssocArray($values)
Definition: functions.inc.php:263
strtolower_codesafe
strtolower_codesafe($str)
Definition: functions.inc.php:280
customAutoload
customAutoload($rootPath, $prefix, $class)
Definition: functions.inc.php:322
fatalError
if(!function_exists('import')) fatalError($reason)
Definition: functions.inc.php:32
checkPhpVersion
checkPhpVersion($version)
Definition: functions.inc.php:132
Core\cleanFileVar
static cleanFileVar($var)
Definition: Core.inc.php:54
lcfirst_codesafe
lcfirst_codesafe($str)
Definition: functions.inc.php:300
arrayClean
arrayClean($array)
Definition: functions.inc.php:250