aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes/functions_sphinx.php
blob: a93a1d950ffb53a899d28a14596d202c44a0dc0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
<?php
/** 
*
* @package search
* @copyright (c) 2005 phpBB Group 
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/

/**
*/
if (!defined('IN_PHPBB'))
{
	exit;
}

/**
* sphinx_config
* An object representing the sphinx configuration
* Can read it from file and write it back out after modification
* @package search
*/
class sphinx_config
{
	var $loaded = false;
	var $sections = array();

	/**
	* Constructor which optionally loads data from a file
	*
	* @param	string	$filename	The path to a file containing the sphinx configuration
	*/
	function sphinx_config($filename = false)
	{
		if ($filename !== false && file_exists($filename))
		{
			$this->read($filename);
		}
	}

	/**
	* Get a section object by its name
	*
	* @param	string 					$name	The name of the section that shall be returned
	* @return	sphinx_config_section			The section object or null if none was found
	*/
	function get_section_by_name($name)
	{
		for ($i = 0, $size = sizeof($this->sections); $i < $size; $i++)
		{
			// make sure this is really a section object and not a comment
			if (($this->sections[$i] instanceof sphinx_config_section) && $this->sections[$i]->get_name() == $name)
			{
				return $this->sections[$i];
			}
		}
	}

	/**
	* Appends a new empty section to the end of the config
	*
	* @param	string					$name	The name for the new section
	* @return	sphinx_config_section			The newly created section object
	*/
	function add_section($name)
	{
		$this->sections[] = new sphinx_config_section($name, '');
		return $this->sections[sizeof($this->sections) - 1];
	}

	/**
	* Parses the config file at the given path, which is stored in $this->loaded for later use
	*
	* @param	string	$filename	The path to the config file
	*/
	function read($filename)
	{
		// split the file into lines, we'll process it line by line
		$config_file = file($filename);

		$this->sections = array();

		$section = null;
		$found_opening_bracket = false;
		$in_value = false;

		foreach ($config_file as $i => $line)
		{
			// if the value of a variable continues to the next line because the line break was escaped
			// then we don't trim leading space but treat it as a part of the value
			if ($in_value)
			{
				$line = rtrim($line);
			}
			else
			{
				$line = trim($line);
			}

			// if we're not inside a section look for one
			if (!$section)
			{
				// add empty lines and comments as comment objects to the section list
				// that way they're not deleted when reassembling the file from the sections
				if (!$line || $line[0] == '#')
				{
					$this->sections[] = new sphinx_config_comment($config_file[$i]);
					continue;
				}
				else
				{
					// otherwise we scan the line reading the section name until we find
					// an opening curly bracket or a comment
					$section_name = '';
					$section_name_comment = '';
					$found_opening_bracket = false;
					for ($j = 0, $length = strlen($line); $j < $length; $j++)
					{
						if ($line[$j] == '#')
						{
							$section_name_comment = substr($line, $j);
							break;
						}

						if ($found_opening_bracket)
						{
							continue;
						}

						if ($line[$j] == '{')
						{
							$found_opening_bracket = true;
							continue;
						}

						$section_name .= $line[$j];
					}

					// and then we create the new section object
					$section_name = trim($section_name);
					$section = new sphinx_config_section($section_name, $section_name_comment);
				}
			}
			else // if we're looking for variables inside a section
			{
				$skip_first = false;

				// if we're not in a value continuing over the line feed
				if (!$in_value)
				{
					// then add empty lines and comments as comment objects to the variable list
					// of this section so they're not deleted on reassembly
					if (!$line || $line[0] == '#')
					{
						$section->add_variable(new sphinx_config_comment($config_file[$i]));
						continue;
					}
	
					// as long as we haven't yet actually found an opening bracket for this section
					// we treat everything as comments so it's not deleted either
					if (!$found_opening_bracket)
					{
						if ($line[0] == '{')
						{
							$skip_first = true;
							$line = substr($line, 1);
							$found_opening_bracket = true;
						}
						else
						{
							$section->add_variable(new sphinx_config_comment($config_file[$i]));
							continue;
						}
					}
				}

				// if we did not find a comment in this line or still add to the previous line's value ...
				if ($line || $in_value)
				{
					if (!$in_value)
					{
						$name = '';
						$value = '';
						$comment = '';
						$found_assignment = false;
					}
					$in_value = false;
					$end_section = false;

					/* ... then we should prase this line char by char:
					 - first there's the variable name
					 - then an equal sign
					 - the variable value
					 - possibly a backslash before the linefeed in this case we need to continue
					   parsing the value in the next line
					 - a # indicating that the rest of the line is a comment
					 - a closing curly bracket indicating the end of this section*/
					for ($j = 0, $length = strlen($line); $j < $length; $j++)
					{
						if ($line[$j] == '#')
						{
							$comment = substr($line, $j);
							break;
						}
						else if ($line[$j] == '}')
						{
							$comment = substr($line, $j + 1);
							$end_section = true;
							break;
						}
						else if (!$found_assignment)
						{
							if ($line[$j] == '=')
							{
								$found_assignment = true;
							}
							else
							{
								$name .= $line[$j];
							}
						}
						else
						{
							if ($line[$j] == '\\' && $j == $length - 1)
							{
								$value .= "\n";
								$in_value = true;
								continue 2; // go to the next line and keep processing the value in there
							}
							$value .= $line[$j];
						}
					}

					// if a name and an equal sign were found then we have append a new variable object to the section
					if ($name && $found_assignment)
					{
						$section->add_variable(new sphinx_config_variable(trim($name), trim($value), ($end_section) ? '' : $comment));
						continue;
					}

					// if we found a closing curly bracket this section has been completed and we can append it to the section list
					// and continue with looking for the next section
					if ($end_section)
					{
						$section->set_end_comment($comment);
						$this->sections[] = $section;
						$section = null;
						continue;
					}
				}

				// if we did not find anything meaningful up to here, then just treat it as a comment
				$comment = ($skip_first) ? "\t" . substr(ltrim($config_file[$i]), 1) : $config_file[$i];
				$section->add_variable(new sphinx_config_comment($comment));
			}
		}

		// keep the filename for later use
		$this->loaded = $filename;
	}

	/**
	* Writes the config data into a file
	*
	* @param	string	$filename	The optional filename into which the config data shall be written.
	*								If it's not specified it will be written into the file that the config
	*								was originally read from.
	*/
	function write($filename = false)
	{
		if ($filename === false && $this->loaded)
		{
			$filename = $this->loaded;
		}

		$data = "";
		foreach ($this->sections as $section)
		{
			$data .= $section->to_string();
		}

		$fp = fopen($filename, 'wb');
		fwrite($fp, $data);
		fclose($fp);
	}
}

/**
* sphinx_config_section
* Represents a single section inside the sphinx configuration
*/
class sphinx_config_section
{
	var $name;
	var $comment;
	var $end_comment;
	var $variables = array();

	/**
	* Construct a new section
	*
	* @param	string	$name		Name of the section
	* @param	string	$comment	Comment that should be appended after the name in the
	*								textual format.
	*/
	function sphinx_config_section($name, $comment)
	{
		$this->name = $name;
		$this->comment = $comment;
		$this->end_comment = '';
	}

	/**
	* Add a variable object to the list of variables in this section
	*
	* @param	sphinx_config_variable	$variable	The variable object
	*/
	function add_variable($variable)
	{
		$this->variables[] = $variable;
	}

	/**
	* Adds a comment after the closing bracket in the textual representation
	*/
	function set_end_comment($end_comment)
	{
		$this->end_comment = $end_comment;
	}

	/**
	* Getter for the name of this section
	*
	* @return	string	Section's name
	*/
	function get_name()
	{
		return $this->name;
	}

	/**
	* Get a variable object by its name
	*
	* @param	string 					$name	The name of the variable that shall be returned
	* @return	sphinx_config_section			The first variable object from this section with the
	*											given name or null if none was found
	*/
	function get_variable_by_name($name)
	{
		for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++)
		{
			// make sure this is a variable object and not a comment
			if (($this->variables[$i] instanceof sphinx_config_variable) && $this->variables[$i]->get_name() == $name)
			{
				return $this->variables[$i];
			}
		}
	}

	/**
	* Deletes all variables with the given name
	*
	* @param	string	$name	The name of the variable objects that are supposed to be removed
	*/
	function delete_variables_by_name($name)
	{
		for ($i = 0, $size = sizeof($this->variables); $i < $size; $i++)
		{
			// make sure this is a variable object and not a comment
			if (($this->variables[$i] instanceof sphinx_config_variable) && $this->variables[$i]->get_name() == $name)
			{
				array_splice($this->variables, $i, 1);
				$i--;
			}
		}
	}

	/**
	* Create a new variable object and append it to the variable list of this section
	*
	* @param	string					$name	The name for the new variable
	* @param	string					$value	The value for the new variable
	* @return	sphinx_config_variable			Variable object that was created
	*/
	function create_variable($name, $value)
	{
		$this->variables[] = new sphinx_config_variable($name, $value, '');
		return $this->variables[sizeof($this->variables) - 1];
	}

	/**
	* Turns this object into a string which can be written to a config file
	*
	* @return	string	Config data in textual form, parsable for sphinx
	*/
	function to_string()
	{
		$content = $this->name . " " . $this->comment . "\n{\n";

		// make sure we don't get too many newlines after the opening bracket
		while (trim($this->variables[0]->to_string()) == "")
		{
			array_shift($this->variables);
		}

		foreach ($this->variables as $variable)
		{
			$content .= $variable->to_string();
		}
		$content .= '}' . $this->end_comment . "\n";

		return $content;
	}
}

/**
* sphinx_config_variable
* Represents a single variable inside the sphinx configuration
*/
class sphinx_config_variable
{
	var $name;
	var $value;
	var $comment;

	/**
	* Constructs a new variable object
	*
	* @param	string	$name		Name of the variable
	* @param	string	$value		Value of the variable
	* @param	string	$comment	Optional comment after the variable in the
	*								config file
	*/
	function sphinx_config_variable($name, $value, $comment)
	{
		$this->name = $name;
		$this->value = $value;
		$this->comment = $comment;
	}

	/**
	* Getter for the variable's name
	*
	* @return	string	The variable object's name
	*/
	function get_name()
	{
		return $this->name;
	}

	/**
	* Allows changing the variable's value
	*
	* @param	string	$value	New value for this variable
	*/
	function set_value($value)
	{
		$this->value = $value;
	}

	/**
	* Turns this object into a string readable by sphinx
	*
	* @return	string	Config data in textual form
	*/
	function to_string()
	{
		return "\t" . $this->name . ' = ' . str_replace("\n", "\\\n", $this->value) . ' ' . $this->comment . "\n";
	}
}


/**
* sphinx_config_comment
* Represents a comment inside the sphinx configuration
*/
class sphinx_config_comment
{
	var $exact_string;

	/**
	* Create a new comment
	*
	* @param	string	$exact_string	The content of the comment including newlines, leading whitespace, etc.
	*/
	function sphinx_config_comment($exact_string)
	{
		$this->exact_string = $exact_string;
	}

	/**
	* Simply returns the comment as it was created
	*
	* @return	string	The exact string that was specified in the constructor
	*/
	function to_string()
	{
		return $this->exact_string;
	}
}

?>