Blame view

sources/lib/private/arrayparser.php 5.34 KB
03e52840d   Kload   Init
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
  <?php
  
  /**
   * @author Robin Appelman
   * @copyright 2013 Robin Appelman icewind@owncloud.com
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
   * License as published by the Free Software Foundation; either
   * version 3 of the License, or any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
   *
   * You should have received a copy of the GNU Affero General Public
   * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
   *
   */
  
  namespace OC;
  
  class SyntaxException extends \Exception {
  }
  
  class ArrayParser {
  	const TYPE_NUM = 1;
  	const TYPE_BOOL = 2;
  	const TYPE_STRING = 3;
  	const TYPE_ARRAY = 4;
6d9380f96   Cédric Dupont   Update sources OC...
32
33
34
35
  	/**
  	 * @param string $string
  	 * @return array|bool|int|null|string
  	 */
03e52840d   Kload   Init
36
37
38
39
40
  	function parsePHP($string) {
  		$string = $this->stripPHPTags($string);
  		$string = $this->stripAssignAndReturn($string);
  		return $this->parse($string);
  	}
6d9380f96   Cédric Dupont   Update sources OC...
41
42
43
44
  	/**
  	 * @param string $string
  	 * @return string
  	 */
03e52840d   Kload   Init
45
46
47
48
49
50
51
52
53
54
  	function stripPHPTags($string) {
  		$string = trim($string);
  		if (substr($string, 0, 5) === '<?php') {
  			$string = substr($string, 5);
  		}
  		if (substr($string, -2) === '?>') {
  			$string = substr($string, 0, -2);
  		}
  		return $string;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
55
56
57
58
  	/**
  	 * @param string $string
  	 * @return string
  	 */
03e52840d   Kload   Init
59
60
61
62
63
64
65
66
67
68
  	function stripAssignAndReturn($string) {
  		$string = trim($string);
  		if (substr($string, 0, 6) === 'return') {
  			$string = substr($string, 6);
  		}
  		if (substr($string, 0, 1) === '$') {
  			list(, $string) = explode('=', $string, 2);
  		}
  		return $string;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
69
70
71
72
  	/**
  	 * @param string $string
  	 * @return array|bool|int|null|string
  	 */
03e52840d   Kload   Init
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  	function parse($string) {
  		$string = trim($string);
  		$string = trim($string, ';');
  		switch ($this->getType($string)) {
  			case self::TYPE_NUM:
  				return $this->parseNum($string);
  			case self::TYPE_BOOL:
  				return $this->parseBool($string);
  			case self::TYPE_STRING:
  				return $this->parseString($string);
  			case self::TYPE_ARRAY:
  				return $this->parseArray($string);
  		}
  		return null;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
88
89
90
91
  	/**
  	 * @param string $string
  	 * @return int
  	 */
03e52840d   Kload   Init
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  	function getType($string) {
  		$string = strtolower($string);
  		$first = substr($string, 0, 1);
  		$last = substr($string, -1, 1);
  		$arrayFirst = substr($string, 0, 5);
  		if (($first === '"' or $first === "'") and ($last === '"' or $last === "'")) {
  			return self::TYPE_STRING;
  		} elseif ($string === 'false' or $string === 'true') {
  			return self::TYPE_BOOL;
  		} elseif ($arrayFirst === 'array' and $last === ')') {
  			return self::TYPE_ARRAY;
  		} else {
  			return self::TYPE_NUM;
  		}
  	}
6d9380f96   Cédric Dupont   Update sources OC...
107
108
109
110
  	/**
  	 * @param string $string
  	 * @return string
  	 */
03e52840d   Kload   Init
111
112
113
  	function parseString($string) {
  		return substr($string, 1, -1);
  	}
6d9380f96   Cédric Dupont   Update sources OC...
114
115
116
117
  	/**
  	 * @param string $string
  	 * @return int
  	 */
03e52840d   Kload   Init
118
119
120
  	function parseNum($string) {
  		return intval($string);
  	}
6d9380f96   Cédric Dupont   Update sources OC...
121
122
123
124
  	/**
  	 * @param string $string
  	 * @return bool
  	 */
03e52840d   Kload   Init
125
126
127
128
  	function parseBool($string) {
  		$string = strtolower($string);
  		return $string === 'true';
  	}
6d9380f96   Cédric Dupont   Update sources OC...
129
130
131
132
  	/**
  	 * @param string $string
  	 * @return array
  	 */
03e52840d   Kload   Init
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
  	function parseArray($string) {
  		$body = substr($string, 5);
  		$body = trim($body);
  		$body = substr($body, 1, -1);
  		$items = $this->splitArray($body);
  		$result = array();
  		$lastKey = -1;
  		foreach ($items as $item) {
  			$item = trim($item);
  			if ($item) {
  				if (strpos($item, '=>')) {
  					list($key, $value) = explode('=>', $item, 2);
  					$key = $this->parse($key);
  					$value = $this->parse($value);
  				} else {
  					$key = ++$lastKey;
  					$value = $item;
  				}
  
  				if (is_numeric($key)) {
  					$lastKey = $key;
  				}
  				$result[$key] = $value;
  			}
  		}
  		return $result;
  	}
6d9380f96   Cédric Dupont   Update sources OC...
160
161
162
163
  	/**
  	 * @param string $body
  	 * @return array
  	 */
03e52840d   Kload   Init
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
  	function splitArray($body) {
  		$inSingleQuote = false;//keep track if we are inside quotes
  		$inDoubleQuote = false;
  		$bracketDepth = 0;//keep track if we are inside brackets
  		$parts = array();
  		$start = 0;
  		$escaped = false;//keep track if we are after an escape character
  		$skips = array();//keep track of the escape characters we need to remove from the result
  		if (substr($body, -1, 1) !== ',') {
  			$body .= ',';
  		}
  		for ($i = 0; $i < strlen($body); $i++) {
  			$char = substr($body, $i, 1);
  			if ($char === '\\') {
  				if ($escaped) {
  					array_unshift($skips, $i - 1);
  				}
  				$escaped = !$escaped;
  			} else {
  				if ($char === '"' and !$inSingleQuote) {
  					if ($escaped) {
  						array_unshift($skips, $i - 1);
  					} else {
  						$inDoubleQuote = !$inDoubleQuote;
  					}
  				} elseif ($char === "'" and !$inDoubleQuote) {
  					if ($escaped) {
  						array_unshift($skips, $i - 1);
  					} else {
  						$inSingleQuote = !$inSingleQuote;
  					}
  				} elseif (!$inDoubleQuote and !$inSingleQuote) {
  					if ($char === '(') {
  						$bracketDepth++;
  					} elseif ($char === ')') {
  						if ($bracketDepth <= 0) {
  							throw new SyntaxException;
  						} else {
  							$bracketDepth--;
  						}
  					} elseif ($bracketDepth === 0 and $char === ',') {
  						$part = substr($body, $start, $i - $start);
  						foreach ($skips as $skip) {
  							$part = substr($part, 0, $skip - $start) . substr($part, $skip - $start + 1);
  						}
  						$parts[] = $part;
  						$start = $i + 1;
  						$skips = array();
  					}
  				}
  				$escaped = false;
  			}
  		}
  		return $parts;
  	}
  }