Completed
Push — master ( 7665c8...9af7b9 )
by Robbert
61:21 queued 52:46
created

store::list_paths()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
nc 1
dl 0
loc 1
c 0
b 0
f 0
ccs 0
cts 0
cp 0
1
<?php
2
/******************************************************************************
3
  Generic Store 1.0						Ariadne
4
5
  Copyright (C) 1998-2005  Muze
6
7
  This program is free software; you can redistribute it and/or
8
  modify it under the terms of the GNU General Public License
9
  as published by the Free Software Foundation; either version 2
10
  of the License, or (at your option) any later version.
11
12
  This program is distributed in the hope that it will be useful,
13
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
  GNU General Public License for more details.
16
17
  You should have received a copy of the GNU General Public License
18
  along with this program; if not, write to the Free Software
19
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21
  --------------------------------------------------------------------------
22
23
  This Is a Generic implementation of the store, all generic functions are defined here
24
25
  the implemented functions are
26
27
	function get_config($field)
28
	function is_supported($feature)
29
	function newobject($path, $parent, $type, $data, $id=0, $lastchanged=0, $vtype="", $size=0, $priority=0)
30
	function close()
31
	function make_path($curr_dir, $path)
32
	function save_properties($properties, $id)
33
	function get_filestore($name)
34
35
*******************************************************************************/
36
37
38
abstract class store {
39
40
	public $error;
41
	public $root;
42
	public $rootoptions;
43
	public $mod_lock;
44
	public $total;
45
	protected $code;
46
	protected $files;
47
	protected $_filestores;
48
	protected $config;
49
50
51
52
	public function __construct($path, $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
53
		echo "You have not configured the store properly. Please check your configuration files.";
54
		exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method __construct() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
55
	}
56
57
	/*  abstract functions
58
		 need implementation in your implementation of this store
59
	*/
60
61
	public abstract function call($template, $args, $objects);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
62
63
	public abstract function count($objects);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
64
65
	public abstract function info($objects);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
66
67
	public abstract function get($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
68
	/**********************************************************************************
69
	 This function takes as argument a path to an object in the store and will retrieve
70
	 all the necessary data and return this in the objectlist type needed for
71
	 store->call(). If the requested path does not exist, it will retrieve the object
72
	 with the longest matching path.
73
74
	 $path should always start and end with a '/'.
75
	 **********************************************************************************/
76
77
	public abstract function touch($id, $timestamp = -1);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
78
	/**********************************************************************************
79
	 This function takes as argument a path to an object (or id of an object)
80
     in the store and will set the timestamp to $timestamp.
81
82
	 $path should always start and end with a '/'.
83
	 **********************************************************************************/
84
85
	public abstract function ls($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
86
	/**********************************************************************************
87
	 This function takes as argument a path to an object in the store and will retrieve
88
	 all the objects and their data which have this object as their parent. It will
89
	 then return this in the objectlist type needed for store->call(). If the requested
90
	 path does not exist, it will retrieve the object with the longest matching path.
91
92
	 $path should always start and end with a '/'.
93
	 **********************************************************************************/
94
95
	public abstract function parents($path, $top="/");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
96
	/**********************************************************************************
97
	 This function takes as argument a path to an object in the store. It will return
98
	 all objects with a path which is a substring of the given path. The resulsts are
99
	 ordered by path (length), shortest paths first.
100
	 In effect all parents of an object in the tree are called, in order, starting at
101
	 the root.
102
103
	 $path should always start and end with a '/'.
104
	 **********************************************************************************/
105
106
	public abstract function find($path, $criteria, $limit=100, $offset=0);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
107
	/**********************************************************************************
108
	 This function takes as arguments a path to an object in the store and some search
109
	 criteria. It will search for all matching objects under the given path. If the
110
	 given path is not in this store but in a substore it will not automatically search
111
	 that substore.
112
113
	 $criteria is of the form
114
115
	 $criteria ::= ({ $property_name => ({ $valuename => ({ $compare_function, $value }) }) })
116
117
	 e.g.: $criteria["status"]["value"][">"]="published";
118
119
	 $path should always start and end with a '/'.
120
121
	 **********************************************************************************/
122
123
124
	public abstract function save($path, $type, $data, $properties="", $vtype="", $priority=false);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
125
	/***************************************************************
126
		This function takes as argument a path, type, objectdata and
127
		possibly a properties list and vtype (virtual type).
128
		If there exists no object with the given path, a new object is
129
		saved with the given type, data, properties and vtype, and a
130
		new path is saved pointing to it.
131
		If there does exist an object with the given path, it's object
132
		data is overwritten with the given data and if vtype is set the
133
		current vtype is overwritten with the new one.
134
135
		$path must be an absolute path (containing no '..' and starting
136
			with '/')
137
		$type must be a valid type
138
		$data can be any string (usually a serialized object.)
139
		$properties is a multidimensional hash of the following form:
140
			$properties[{property_name}][][{value_name}]={value}
141
			{property_name} must be a valid property name
142
			{value_name} must be a valid value name for this property
143
			{value} can be a number, boolean or string.
144
		example:
145
			$properties["name"][0]["value"]="A name";
146
			$properties["name"][1]["value"]="A second name!";
147
		if $properties["name"]=1 then all properties for property name
148
			will be removed.
149
150
		$vtype must be a valid type.
151
152
		if $properties or $vtype are not set or empty ("",0 or false)
153
		they will be ignored. $vtype defaults to $type.
154
		Only those properties listed in $properties will be updated.
155
		Any other property set will remain as it was.
156
	***************************************************************/
157
158
159
	protected abstract function purge($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
160
	/**********************************************************************
161
		This function will delete the object pointed to by $path and all
162
	other paths pointing to that object. It will then remove any property
163
	for this object from all property tables.
164
		The function returns the number of paths found and removed or 1 if
165
	there was no path found (meaning that the object doesn't exist and
166
	therefor purge succeeded while doing nothing.)
167
168
	 $path should always start and end with a '/'.
169
	**********************************************************************/
170
171
	public abstract function delete($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
172
	/**********************************************************************
173
		This function deletes the path given. If this is the last path pointing
174
	to an object, the object will be purged instead.
175
176
	$path should always start and end with a '/'.
177
	**********************************************************************/
178
179
	abstract function exists($path);
180
	/**********************************************************************
181
		This function checks the given path to see if it exists. If it does
182
	it returns the id of the object to which it points. Otherwise it returns
183
	0.
184
185
	$path should always start and end with a '/'.
186
	**********************************************************************/
187
188
189
	public abstract function link($source, $destination);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
190
	/**********************************************************************
191
		Link adds an extra path to an already existing object. It has two
192
	arguments: $source and $destination. $source is an existing path of
193
	an object, $destination is the new path. $destination must not already
194
	exist.
195
196
	$destination should always start and end with a '/'.
197
	**********************************************************************/
198
199
	public abstract function move($source, $destination);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
200
	/**********************************************************************
201
	$destination should always start and end with a '/'.
202
	**********************************************************************/
203
204
205
	public abstract function list_paths($path);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
206
	/**********************************************************************
207
		This function returns an array of all paths pointing to the same object
208
	as $path does.
209
	**********************************************************************/
210
211
	public abstract function AR_implements($type, $implements);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
212
	/**********************************************************************
213
		This function returns 1 if the $type implements the type or
214
	interface in $implements. Otherwise it returns 0.
215
	**********************************************************************/
216
217
	public abstract function load_properties($object, $values="");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
218
219
	public abstract function load_property($object, $property, $values="");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
220
221
	public abstract function add_property($object, $property, $values);
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
222
223
	public abstract function del_property($object, $property="", $values="");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
224
225
	protected abstract function get_nextid($path, $mask="{5:id}");
0 ignored issues
show
Coding Style introduced by
The abstract declaration must precede the visibility declaration
Loading history...
226
	/**********************************************************************
227
		'private' function of mysql store. This will return the next
228
		'autoid' for $path.
229
	**********************************************************************/
230
231
232
233
	/*
234
		Implemented functions
235
	*/
236
237 92
	public function get_config($field) {
238
		switch ($field) {
239 92
			case 'code':
240 92
			case 'files':
241 92
			case 'root':
242 92
			case 'rootoptions':
243 92
				$result = $this->$field;
244 92
				break;
245
			default:
246
				$result =  null;
247
				debug("store::get_config: undefined field $field requested","store");
248
				break;
249
		}
250 92
		return $result;
251
	}
252
253 60
	public function is_supported($feature) {
254
	/**********************************************************************************
255
		This function takes as argument a feature description and returns
256
		true if this feature is supported and false otherwise
257
	**********************************************************************************/
258 60
		$result = false;
259
		switch($feature) {
260
			// features depending on config values
261 60
			case 'fulltext_boolean':
262 60
			case 'fulltext':
263 48
				if ($this->config[$feature]) {
264 24
					$result = true;
265 24
				} else {
266 24
					$result = false;
267
				}
268 48
			break;
269
			// features depending store implementation, if stores don't implements this, they have to override this function
270 60
			case 'grants':
271 45
			case 'regexp':
272 60
				$result = true;
273 60
			break;
274
		}
275 60
		return $result;
276
	}
277
278
	/**********************************************************************************
279
		This functions creates a new ariadne object
280
	**********************************************************************************/
281 184
	public function newobject($path, $parent, $type, $data, $id=0, $lastchanged=0, $vtype="", $size=0, $priority=0) {
282 184
		global $ARnls;
283 184
		$class = $type;
284 184
		if ($subcpos = strpos($type, '.')) {
285 24
			$class = substr($type, 0, $subcpos);
286 24
			$vtype = $class;
287 18
		}
288 184
		if (!class_exists($class, false)) {
289
			include_once($this->code."objects/".$class.".phtml");
290
		}
291 184
		$object=new $class;
292 184
		$object->type=$type;
293 184
		$object->parent=$parent;
294 184
		$object->id=(int)$id;
295 184
		$object->lastchanged=(int)$lastchanged;
296 184
		$object->vtype=$vtype;
297 184
		$object->size=(int)$size;
298 184
		$object->priority=(int)$priority;
299 184
		$object->ARnls = $ARnls;
300 184
		$object->init($this, $path, $data);
301 184
		return $object;
302
	}
303
304 104
	public function close() {
305
		// This is the destructor function, nothing much to see :)
306 104
		if (is_array($this->_filestores)) {
307
			foreach ($this->_filestores as $filestore) {
308
				$filestore->close();
309
			}
310
		}
311 104
	}
312
313 104
	public function __destruct() {
314 104
		$this->close();
315 104
	}
316
317 112
	public function make_path($curr_dir, $path) {
318 112
		return \arc\path::collapse($path, $curr_dir);
319
	}
320
321 68
	public function save_properties($properties, $id) {
322
	/********************************************************************
323
		'private' function of mysql.phtml. It updates all property tables
324
		defined in $properties and sets the values to the values in
325
		$properties.
326
	********************************************************************/
327
328 68
		if ($properties && (is_array($properties)) && (is_numeric($id))) {
329 48
			foreach ( $properties as $property => $property_set ) {
330 48
				$this->del_property((int)$id, $property);
331 48
				if (is_array($property_set)) {
332 48
					foreach ( $property_set as $values ) {
333 48
						$this->add_property((int)$id, $property, $values);
334 36
					}
335 36
				}
336 36
			}
337 36
		}
338 68
	}
339
340
341 102
	public function get_filestore($name) {
342 102
		global $AR;
343 102
		if (!$this->_filestores[$name]) {
344 102
			if ($AR->SVN->enabled && ($name == "templates")) {
345
				require_once($this->code."modules/mod_filestore_svn.phtml");
346
				$this->_filestores[$name]=new filestore_svn($name, $this->files, $this);
347
			} else {
348 102
				require_once($this->code."modules/mod_filestore.phtml");
349 102
				$this->_filestores[$name]=new filestore($name, $this->files, $this);
350
			}
351 77
		}
352 102
		return $this->_filestores[$name];
353
	}
354
355 28
	public function get_filestore_svn($name) {
356 28
		require_once($this->code."modules/mod_filestore_svn.phtml");
357 28
		if (!$this->_filestores["svn_" . $name]) {
358 28
			$this->_filestores["svn_" . $name] = new filestore_svn($name, $this->files, $this);
359 21
		}
360 28
		return $this->_filestores["svn_" . $name];
361
	}
362
363 94
	protected function compilerFactory(){
364 94
		switch($this->config["dbms"]){
365 94
			case 'axstore':
366
				return false;
367 94
			default:
368 94
				$compiler = $this->config["dbms"].'_compiler';
369 94
				return new $compiler($this,$this->tbl_prefix);
0 ignored issues
show
Bug introduced by
The property tbl_prefix does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
370 94
		}
371
	}
372
373 51
	protected function serialize($value, $path) {
374 51
		if ($value->failedDecrypt && $value->originalData) {
375
			$value = $value->originalData;
376
			return $value;
377
		}
378
379
		// Notice: When upgrading to a new crypto format, prepend the object data with a key of the crypto. This way you can be backwards compatible but new objects will be saved in the new crypto.
380 51
		if ($this->config['crypto'] instanceof \Closure) {
381
			$crypto = $this->config['crypto']();
382
			// use the last crypto configured;
383
			$cryptoConfig = end($crypto);
384
			if (is_array($cryptoConfig['paths'])) {
385
				foreach ($cryptoConfig['paths'] as $cryptoPath) {
386
					if (strpos($path, $cryptoPath) === 0) {
387
						$value->ARcrypted = true;
388
						switch ($cryptoConfig['method']) {
389
							case 'ar_crypt':
390
								$key = base64_decode($cryptoConfig['key']);
391
								$crypto = new ar_crypt($key,$cryptoConfig['crypto'],1);
392
								$cryptedValue = $crypto->crypt(serialize($value));
393
								if($cryptedValue !== false ) {
394
									return $cryptoConfig['token'] . ":" . $cryptedValue;
395
								}
396
							break;
397
							default:
398
							break;
399
						}
400
401
					}
402
				}
403
			}
404
		}
405 51
		unset($value->ARcrypted);
406 51
		return serialize($value);
407
	}
408
409 184
	protected function unserialize($value, $path) {
0 ignored issues
show
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
410 184
		if ($value[0] === "O" && $value[1] === ":") {
411 184
			return unserialize($value);
412
		} else if ($this->config['crypto'] instanceof \Closure) {
413
			$crypto = $this->config['crypto']();
414
			list($token,$datavalue) = explode(':', $value, 2);
415
			foreach ($crypto as $cryptoConfig) {
416
				$cryptoToken = $cryptoConfig['token'];
417
				if ($token === $cryptoToken ) {
418
					$value = $datavalue;
419
					switch ($cryptoConfig['method']) {
420
						case 'ar_crypt':
421
							$key = base64_decode($cryptoConfig['key']);
422
							$crypto = new ar_crypt($key,$cryptoConfig['crypto'],1);
423
							$decryptedValue =  $crypto->decrypt($value);
424
						break;
425
						default:
426
						break;
427
					}
428
				}
429
			}
430
431
			if ($decryptedValue[0] === "O" && $decryptedValue[1] === ":") {
432
				return unserialize($decryptedValue);
0 ignored issues
show
Bug introduced by
The variable $decryptedValue does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
433
			} else {
434
				$dummy = unserialize('O:6:"object":7:{s:5:"value";s:0:"";s:3:"nls";O:6:"object":2:{s:7:"default";s:2:"nl";s:4:"list";a:1:{s:2:"nl";s:10:"Nederlands";}}s:2:"nl";O:6:"object":1:{s:4:"name";s:14:"Crypted object";}s:6:"config";O:6:"object":2:{s:10:"owner_name";s:6:"Nobody";s:5:"owner";s:6:"nobody";}s:5:"mtime";i:0;s:5:"ctime";i:0;s:5:"muser";s:6:"nobody";}');
435
				$dummy->failedDecrypt = true;
436
				$dummy->originalData = $value;
437
				return $dummy;
438
			}
439
		}
440
	}
441
442
} 
443