This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * vCard class for parsing a vCard and/or creating one |
||
4 | * |
||
5 | * @link https://github.com/nuovo/vCard-parser |
||
6 | * @author Martins Pilsetnieks, Roberts Bruveris |
||
7 | * @see RFC 2426, RFC 2425 |
||
8 | * @version 0.4.8 |
||
9 | */ |
||
10 | class vCard implements Countable, Iterator |
||
11 | { |
||
12 | const MODE_ERROR = 'error'; |
||
13 | const MODE_SINGLE = 'single'; |
||
14 | const MODE_MULTIPLE = 'multiple'; |
||
15 | |||
16 | const endl = "\n"; |
||
17 | |||
18 | /** |
||
19 | * @var string Current object mode - error, single or multiple (for a single vCard within a file and multiple combined vCards) |
||
20 | */ |
||
21 | private $Mode; //single, multiple, error |
||
22 | |||
23 | private $Path = ''; |
||
24 | private $RawData = ''; |
||
25 | |||
26 | /** |
||
27 | * @var array Internal options container. Options: |
||
28 | * bool Collapse: If true, elements that can have multiple values but have only a single value are returned as that value instead of an array |
||
29 | * If false, an array is returned even if it has only one value. |
||
30 | */ |
||
31 | private $Options = array( |
||
32 | 'Collapse' => false |
||
33 | ); |
||
34 | |||
35 | /** |
||
36 | * @var array Internal data container. Contains vCard objects for multiple vCards and just the data for single vCards. |
||
37 | */ |
||
38 | private $Data = array(); |
||
39 | |||
40 | /** |
||
41 | * @static Parts of structured elements according to the spec. |
||
42 | */ |
||
43 | private static $Spec_StructuredElements = array( |
||
44 | 'n' => array('lastname', 'firstname', 'additionalnames', 'prefixes', 'suffixes'), |
||
45 | 'adr' => array('pobox', 'extendedaddress', 'streetaddress', 'locality', 'region', 'postalcode', 'country'), |
||
46 | 'geo' => array('latitude', 'longitude'), |
||
47 | 'org' => array('name', 'unit1', 'unit2') |
||
48 | ); |
||
49 | private static $Spec_MultipleValueElements = array('nickname', 'categories'); |
||
50 | |||
51 | private static $Spec_ElementTypes = array( |
||
52 | 'email' => array('internet', 'x400', 'pref', 'home', 'work'), |
||
53 | 'adr' => array('dom', 'intl', 'postal', 'parcel', 'home', 'work', 'pref'), |
||
54 | 'label' => array('dom', 'intl', 'postal', 'parcel', 'home', 'work', 'pref'), |
||
55 | 'tel' => array('home', 'msg', 'work', 'pref', 'voice', 'fax', 'cell', 'video', 'pager', 'bbs', 'modem', 'car', 'isdn', 'pcs'), |
||
56 | 'impp' => array('personal', 'business', 'home', 'work', 'mobile', 'pref') |
||
57 | ); |
||
58 | |||
59 | private static $Spec_FileElements = array('photo', 'logo', 'sound'); |
||
60 | |||
61 | /** |
||
62 | * vCard constructor |
||
63 | * |
||
64 | * @param string Path to file, optional. |
||
65 | * @param string Raw data, optional. |
||
66 | * @param array Additional options, optional. Currently supported options: |
||
67 | * bool Collapse: If true, elements that can have multiple values but have only a single value are returned as that value instead of an array |
||
68 | * If false, an array is returned even if it has only one value. |
||
69 | * |
||
70 | * One of these parameters must be provided, otherwise an exception is thrown. |
||
71 | */ |
||
72 | public function __construct($Path = false, $RawData = false, array $Options = null) |
||
73 | { |
||
74 | // Checking preconditions for the parser. |
||
75 | // If path is given, the file should be accessible. |
||
76 | // If raw data is given, it is taken as it is. |
||
77 | // In both cases the real content is put in $this -> RawData |
||
78 | if ($Path) |
||
79 | { |
||
80 | if (!is_readable($Path)) |
||
81 | { |
||
82 | throw new Exception('vCard: Path not accessible ('.$Path.')'); |
||
83 | } |
||
84 | |||
85 | $this -> Path = $Path; |
||
0 ignored issues
–
show
|
|||
86 | $this -> RawData = file_get_contents($this -> Path); |
||
87 | } |
||
88 | elseif ($RawData) |
||
89 | { |
||
90 | $this -> RawData = $RawData; |
||
0 ignored issues
–
show
The property
$RawData was declared of type string , but $RawData is of type boolean . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||
91 | } |
||
92 | else |
||
0 ignored issues
–
show
This
else statement is empty and can be removed.
This check looks for the These if (rand(1, 6) > 3) {
print "Check failed";
} else {
//print "Check succeeded";
}
could be turned into if (rand(1, 6) > 3) {
print "Check failed";
}
This is much more concise to read. ![]() |
|||
93 | { |
||
94 | //throw new Exception('vCard: No content provided'); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
67% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
95 | // Not necessary anymore as possibility to create vCards is added |
||
96 | } |
||
97 | |||
98 | if (!$this -> Path && !$this -> RawData) |
||
99 | { |
||
100 | return true; |
||
0 ignored issues
–
show
|
|||
101 | } |
||
102 | |||
103 | if ($Options) |
||
104 | { |
||
105 | $this -> Options = array_merge($this -> Options, $Options); |
||
106 | } |
||
107 | |||
108 | // Counting the begin/end separators. If there aren't any or the count doesn't match, there is a problem with the file. |
||
109 | // If there is only one, this is a single vCard, if more, multiple vCards are combined. |
||
110 | $Matches = array(); |
||
111 | $vCardBeginCount = preg_match_all('{^BEGIN\:VCARD}miS', $this -> RawData, $Matches); |
||
112 | $vCardEndCount = preg_match_all('{^END\:VCARD}miS', $this -> RawData, $Matches); |
||
113 | |||
114 | if (($vCardBeginCount != $vCardEndCount) || !$vCardBeginCount) |
||
115 | { |
||
116 | $this -> Mode = vCard::MODE_ERROR; |
||
117 | throw new Exception('vCard: invalid vCard'); |
||
118 | } |
||
119 | |||
120 | $this -> Mode = $vCardBeginCount == 1 ? vCard::MODE_SINGLE : vCard::MODE_MULTIPLE; |
||
121 | |||
122 | // Removing/changing inappropriate newlines, i.e., all CRs or multiple newlines are changed to a single newline |
||
123 | $this -> RawData = str_replace("\r", "\n", $this -> RawData); |
||
124 | $this -> RawData = preg_replace('{(\n+)}', "\n", $this -> RawData); |
||
125 | |||
126 | // In multiple card mode the raw text is split at card beginning markers and each |
||
127 | // fragment is parsed in a separate vCard object. |
||
128 | if ($this -> Mode == self::MODE_MULTIPLE) |
||
129 | { |
||
130 | $this -> RawData = explode('BEGIN:VCARD', $this -> RawData); |
||
0 ignored issues
–
show
It seems like
explode('BEGIN:VCARD', $this->RawData) of type array is incompatible with the declared type string of property $RawData .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
131 | $this -> RawData = array_filter($this -> RawData); |
||
0 ignored issues
–
show
It seems like
array_filter($this->RawData) of type array is incompatible with the declared type string of property $RawData .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
132 | |||
133 | foreach ($this -> RawData as $SinglevCardRawData) |
||
134 | { |
||
135 | // Prepending "BEGIN:VCARD" to the raw string because we exploded on that one. |
||
136 | // If there won't be the BEGIN marker in the new object, it will fail. |
||
137 | $SinglevCardRawData = 'BEGIN:VCARD'."\n".$SinglevCardRawData; |
||
138 | |||
139 | $ClassName = get_class($this); |
||
140 | $this -> Data[] = new $ClassName(false, $SinglevCardRawData); |
||
141 | } |
||
142 | } |
||
143 | else |
||
144 | { |
||
145 | // Protect the BASE64 final = sign (detected by the line beginning with whitespace), otherwise the next replace will get rid of it |
||
146 | $this -> RawData = preg_replace('{(\n\s.+)=(\n)}', '$1-base64=-$2', $this -> RawData); |
||
147 | |||
148 | // Joining multiple lines that are split with a hard wrap and indicated by an equals sign at the end of line |
||
149 | // (quoted-printable-encoded values in v2.1 vCards) |
||
150 | $this -> RawData = str_replace("=\n", '', $this -> RawData); |
||
151 | |||
152 | // Joining multiple lines that are split with a soft wrap (space or tab on the beginning of the next line |
||
153 | $this -> RawData = str_replace(array("\n ", "\n\t"), '-wrap-', $this -> RawData); |
||
154 | |||
155 | // Restoring the BASE64 final equals sign (see a few lines above) |
||
156 | $this -> RawData = str_replace("-base64=-\n", "=\n", $this -> RawData); |
||
157 | |||
158 | $Lines = explode("\n", $this -> RawData); |
||
159 | |||
160 | foreach ($Lines as $Line) |
||
161 | { |
||
162 | // Lines without colons are skipped because, most likely, they contain no data. |
||
163 | if (strpos($Line, ':') === false) |
||
164 | { |
||
165 | continue; |
||
166 | } |
||
167 | |||
168 | // Each line is split into two parts. The key contains the element name and additional parameters, if present, |
||
169 | // value is just the value |
||
170 | list($Key, $Value) = explode(':', $Line, 2); |
||
171 | |||
172 | // Key is transformed to lowercase because, even though the element and parameter names are written in uppercase, |
||
173 | // it is quite possible that they will be in lower- or mixed case. |
||
174 | // The key is trimmed to allow for non-significant WSP characters as allowed by v2.1 |
||
175 | $Key = strtolower(trim(self::Unescape($Key))); |
||
176 | |||
177 | // These two lines can be skipped as they aren't necessary at all. |
||
178 | if ($Key == 'begin' || $Key == 'end') |
||
179 | { |
||
180 | continue; |
||
181 | } |
||
182 | |||
183 | if ((strpos($Key, 'agent') === 0) && (stripos($Value, 'begin:vcard') !== false)) |
||
184 | { |
||
185 | $ClassName = get_class($this); |
||
186 | $Value = new $ClassName(false, str_replace('-wrap-', "\n", $Value)); |
||
187 | if (!isset($this -> Data[$Key])) |
||
188 | { |
||
189 | $this -> Data[$Key] = array(); |
||
190 | } |
||
191 | $this -> Data[$Key][] = $Value; |
||
192 | continue; |
||
193 | } |
||
194 | else |
||
195 | { |
||
196 | $Value = str_replace('-wrap-', '', $Value); |
||
197 | } |
||
198 | |||
199 | $Value = trim(self::Unescape($Value)); |
||
200 | $Type = array(); |
||
201 | |||
202 | // Here additional parameters are parsed |
||
203 | $KeyParts = explode(';', $Key); |
||
204 | $Key = $KeyParts[0]; |
||
205 | $Encoding = false; |
||
206 | |||
207 | if (strpos($Key, 'item') === 0) |
||
208 | { |
||
209 | $TmpKey = explode('.', $Key, 2); |
||
210 | $Key = $TmpKey[1]; |
||
211 | $ItemIndex = (int)str_ireplace('item', '', $TmpKey[0]); |
||
0 ignored issues
–
show
$ItemIndex is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
212 | } |
||
213 | |||
214 | if (count($KeyParts) > 1) |
||
215 | { |
||
216 | $Parameters = self::ParseParameters($Key, array_slice($KeyParts, 1)); |
||
217 | |||
218 | foreach ($Parameters as $ParamKey => $ParamValue) |
||
219 | { |
||
220 | switch ($ParamKey) |
||
221 | { |
||
222 | case 'encoding': |
||
223 | $Encoding = $ParamValue; |
||
224 | if (in_array($ParamValue, array('b', 'base64'))) |
||
0 ignored issues
–
show
This
if statement is empty and can be removed.
This check looks for the bodies of These if (rand(1, 6) > 3) {
//print "Check failed";
} else {
print "Check succeeded";
}
could be turned into if (rand(1, 6) <= 3) {
print "Check succeeded";
}
This is much more concise to read. ![]() |
|||
225 | { |
||
226 | //$Value = base64_decode($Value); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
56% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
227 | } |
||
228 | elseif ($ParamValue == 'quoted-printable') // v2.1 |
||
229 | { |
||
230 | $Value = quoted_printable_decode($Value); |
||
231 | } |
||
232 | break; |
||
233 | case 'charset': // v2.1 |
||
234 | if ($ParamValue != 'utf-8' && $ParamValue != 'utf8') |
||
235 | { |
||
236 | $Value = mb_convert_encoding($Value, 'UTF-8', $ParamValue); |
||
237 | } |
||
238 | break; |
||
239 | case 'type': |
||
240 | $Type = $ParamValue; |
||
241 | break; |
||
242 | } |
||
243 | } |
||
244 | } |
||
245 | |||
246 | // Checking files for colon-separated additional parameters (Apple's Address Book does this), for example, "X-ABCROP-RECTANGLE" for photos |
||
247 | if (in_array($Key, self::$Spec_FileElements) && isset($Parameters['encoding']) && in_array($Parameters['encoding'], array('b', 'base64'))) |
||
248 | { |
||
249 | // If colon is present in the value, it must contain Address Book parameters |
||
250 | // (colon is an invalid character for base64 so it shouldn't appear in valid files) |
||
251 | if (strpos($Value, ':') !== false) |
||
252 | { |
||
253 | $Value = explode(':', $Value); |
||
254 | $Value = array_pop($Value); |
||
255 | } |
||
256 | } |
||
257 | |||
258 | // Values are parsed according to their type |
||
259 | if (isset(self::$Spec_StructuredElements[$Key])) |
||
260 | { |
||
261 | $Value = self::ParseStructuredValue($Value, $Key); |
||
262 | if ($Type) |
||
263 | { |
||
264 | $Value['type'] = $Type; |
||
265 | } |
||
266 | } |
||
267 | else |
||
268 | { |
||
269 | if (in_array($Key, self::$Spec_MultipleValueElements)) |
||
270 | { |
||
271 | $Value = self::ParseMultipleTextValue($Value, $Key); |
||
0 ignored issues
–
show
The call to
vCard::ParseMultipleTextValue() has too many arguments starting with $Key .
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the ![]() |
|||
272 | } |
||
273 | |||
274 | if ($Type) |
||
275 | { |
||
276 | $Value = array( |
||
277 | 'value' => $Value, |
||
278 | 'type' => $Type |
||
279 | ); |
||
280 | } |
||
281 | } |
||
282 | |||
283 | if (is_array($Value) && $Encoding) |
||
284 | { |
||
285 | $Value['encoding'] = $Encoding; |
||
286 | } |
||
287 | |||
288 | if (!isset($this -> Data[$Key])) |
||
289 | { |
||
290 | $this -> Data[$Key] = array(); |
||
291 | } |
||
292 | |||
293 | $this -> Data[$Key][] = $Value; |
||
294 | } |
||
295 | } |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * Magic method to get the various vCard values as object members, e.g. |
||
300 | * a call to $vCard -> N gets the "N" value |
||
301 | * |
||
302 | * @param string Key |
||
303 | * |
||
304 | * @return mixed Value |
||
305 | */ |
||
306 | public function __get($Key) |
||
307 | { |
||
308 | $Key = strtolower($Key); |
||
309 | if (isset($this -> Data[$Key])) |
||
310 | { |
||
311 | if ($Key == 'agent') |
||
312 | { |
||
313 | return $this -> Data[$Key]; |
||
314 | } |
||
315 | elseif (in_array($Key, self::$Spec_FileElements)) |
||
316 | { |
||
317 | $Value = $this -> Data[$Key]; |
||
318 | foreach ($Value as $K => $V) |
||
319 | { |
||
320 | if (stripos($V['value'], 'uri:') === 0) |
||
321 | { |
||
322 | $Value[$K]['value'] = substr($V, 4); |
||
323 | $Value[$K]['encoding'] = 'uri'; |
||
324 | } |
||
325 | } |
||
326 | return $Value; |
||
327 | } |
||
328 | |||
329 | if ($this -> Options['Collapse'] && is_array($this -> Data[$Key]) && (count($this -> Data[$Key]) == 1)) |
||
330 | { |
||
331 | return $this -> Data[$Key][0]; |
||
332 | } |
||
333 | return $this -> Data[$Key]; |
||
334 | } |
||
335 | elseif ($Key == 'Mode') |
||
336 | { |
||
337 | return $this -> Mode; |
||
338 | } |
||
339 | return array(); |
||
340 | } |
||
341 | |||
342 | /** |
||
343 | * Saves an embedded file |
||
344 | * |
||
345 | * @param string Key |
||
346 | * @param int Index of the file, defaults to 0 |
||
347 | * @param string Target path where the file should be saved, including the filename |
||
348 | * |
||
349 | * @return bool Operation status |
||
350 | */ |
||
351 | public function SaveFile($Key, $Index = 0, $TargetPath = '') |
||
352 | { |
||
353 | if (!isset($this -> Data[$Key])) |
||
354 | { |
||
355 | return false; |
||
356 | } |
||
357 | if (!isset($this -> Data[$Key][$Index])) |
||
358 | { |
||
359 | return false; |
||
360 | } |
||
361 | |||
362 | // Returing false if it is an image URL |
||
363 | if (stripos($this -> Data[$Key][$Index]['value'], 'uri:') === 0) |
||
364 | { |
||
365 | return false; |
||
366 | } |
||
367 | |||
368 | if (is_writable($TargetPath) || (!file_exists($TargetPath) && is_writable(dirname($TargetPath)))) |
||
369 | { |
||
370 | $RawContent = $this -> Data[$Key][$Index]['value']; |
||
371 | if (isset($this -> Data[$Key][$Index]['encoding']) && $this -> Data[$Key][$Index]['encoding'] == 'b') |
||
372 | { |
||
373 | $RawContent = base64_decode($RawContent); |
||
374 | } |
||
375 | $Status = file_put_contents($TargetPath, $RawContent); |
||
376 | return (bool)$Status; |
||
377 | } |
||
378 | else |
||
379 | { |
||
380 | throw new Exception('vCard: Cannot save file ('.$Key.'), target path not writable ('.$TargetPath.')'); |
||
381 | } |
||
382 | return false; |
||
0 ignored issues
–
show
return false; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
383 | } |
||
384 | |||
385 | /** |
||
386 | * Magic method for adding data to the vCard |
||
387 | * |
||
388 | * @param string Key |
||
389 | * @param string Method call arguments. First element is value. |
||
390 | * |
||
391 | * @return vCard Current object for method chaining |
||
392 | */ |
||
393 | public function __call($Key, $Arguments) |
||
394 | { |
||
395 | $Key = strtolower($Key); |
||
396 | |||
397 | if (!isset($this -> Data[$Key])) |
||
398 | { |
||
399 | $this -> Data[$Key] = array(); |
||
400 | } |
||
401 | |||
402 | $Value = isset($Arguments[0]) ? $Arguments[0] : false; |
||
403 | |||
404 | if (count($Arguments) > 1) |
||
405 | { |
||
406 | $Types = array_map('strtolower', array_values(array_slice($Arguments, 1))); |
||
407 | |||
408 | if (isset(self::$Spec_StructuredElements[$Key]) && |
||
409 | in_array(strtolower($Arguments[1]), self::$Spec_StructuredElements[$Key]) |
||
410 | ) |
||
411 | { |
||
412 | $LastElementIndex = 0; |
||
413 | |||
414 | if (count($this -> Data[$Key])) |
||
415 | { |
||
416 | $LastElementIndex = count($this -> Data[$Key]) - 1; |
||
417 | } |
||
418 | |||
419 | if (isset($this -> Data[$Key][$LastElementIndex])) |
||
420 | { |
||
421 | if (empty($this -> Data[$Key][$LastElementIndex][$Types[0]])) |
||
422 | { |
||
423 | $this -> Data[$Key][$LastElementIndex][$Types[0]] = $Value; |
||
424 | } |
||
425 | else |
||
426 | { |
||
427 | $LastElementIndex++; |
||
428 | } |
||
429 | } |
||
430 | |||
431 | if (!isset($this -> Data[$Key][$LastElementIndex])) |
||
432 | { |
||
433 | $this -> Data[$Key][$LastElementIndex] = array( |
||
434 | $Types[0] => $Value |
||
435 | ); |
||
436 | } |
||
437 | } |
||
438 | elseif (isset(self::$Spec_ElementTypes[$Key])) |
||
439 | { |
||
440 | $this -> Data[$Key][] = array( |
||
441 | 'value' => $Value, |
||
442 | 'type' => $Types |
||
443 | ); |
||
444 | } |
||
445 | } |
||
446 | elseif ($Value) |
||
447 | { |
||
448 | $this -> Data[$Key][] = $Value; |
||
449 | } |
||
450 | |||
451 | return $this; |
||
452 | } |
||
453 | |||
454 | /** |
||
455 | * Magic method for getting vCard content out |
||
456 | * |
||
457 | * @return string Raw vCard content |
||
458 | */ |
||
459 | public function __toString() |
||
460 | { |
||
461 | $Text = 'BEGIN:VCARD'.self::endl; |
||
462 | $Text .= 'VERSION:3.0'.self::endl; |
||
463 | |||
464 | foreach ($this -> Data as $Key => $Values) |
||
465 | { |
||
466 | $KeyUC = strtoupper($Key); |
||
467 | $Key = strtolower($Key); |
||
468 | |||
469 | if (in_array($KeyUC, array('PHOTO', 'VERSION'))) |
||
470 | { |
||
471 | continue; |
||
472 | } |
||
473 | |||
474 | foreach ($Values as $Index => $Value) |
||
475 | { |
||
476 | $Text .= $KeyUC; |
||
477 | if (is_array($Value) && isset($Value['type'])) |
||
478 | { |
||
479 | $Text .= ';TYPE='.self::PrepareTypeStrForOutput($Value['type']); |
||
480 | } |
||
481 | $Text .= ':'; |
||
482 | |||
483 | if (isset(self::$Spec_StructuredElements[$Key])) |
||
484 | { |
||
485 | $PartArray = array(); |
||
486 | foreach (self::$Spec_StructuredElements[$Key] as $Part) |
||
487 | { |
||
488 | $PartArray[] = isset($Value[$Part]) ? $Value[$Part] : ''; |
||
489 | } |
||
490 | $Text .= implode(';', $PartArray); |
||
491 | } |
||
492 | elseif (is_array($Value) && isset(self::$Spec_ElementTypes[$Key])) |
||
493 | { |
||
494 | $Text .= $Value['value']; |
||
495 | } |
||
496 | else |
||
497 | { |
||
498 | $Text .= $Value; |
||
499 | } |
||
500 | |||
501 | $Text .= self::endl; |
||
502 | } |
||
503 | } |
||
504 | |||
505 | $Text .= 'END:VCARD'.self::endl; |
||
506 | return $Text; |
||
507 | } |
||
508 | |||
509 | // !Helper methods |
||
510 | |||
511 | private static function PrepareTypeStrForOutput($Type) |
||
512 | { |
||
513 | return implode(',', array_map('strtoupper', $Type)); |
||
514 | } |
||
515 | |||
516 | /** |
||
517 | * Removes the escaping slashes from the text. |
||
518 | * |
||
519 | * @access private |
||
520 | * |
||
521 | * @param string Text to prepare. |
||
522 | * |
||
523 | * @return string Resulting text. |
||
524 | */ |
||
525 | private static function Unescape($Text) |
||
526 | { |
||
527 | return str_replace(array('\:', '\;', '\,', "\n"), array(':', ';', ',', ''), $Text); |
||
528 | } |
||
529 | |||
530 | /** |
||
531 | * Separates the various parts of a structured value according to the spec. |
||
532 | * |
||
533 | * @access private |
||
534 | * |
||
535 | * @param string Raw text string |
||
536 | * @param string Key (e.g., N, ADR, ORG, etc.) |
||
537 | * |
||
538 | * @return array Parts in an associative array. |
||
539 | */ |
||
540 | private static function ParseStructuredValue($Text, $Key) |
||
541 | { |
||
542 | $Text = array_map('trim', explode(';', $Text)); |
||
543 | |||
544 | $Result = array(); |
||
545 | $Ctr = 0; |
||
0 ignored issues
–
show
$Ctr is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
546 | |||
547 | foreach (self::$Spec_StructuredElements[$Key] as $Index => $StructurePart) |
||
548 | { |
||
549 | $Result[$StructurePart] = isset($Text[$Index]) ? $Text[$Index] : null; |
||
550 | } |
||
551 | return $Result; |
||
552 | } |
||
553 | |||
554 | /** |
||
555 | * @access private |
||
556 | */ |
||
557 | private static function ParseMultipleTextValue($Text) |
||
558 | { |
||
559 | return explode(',', $Text); |
||
560 | } |
||
561 | |||
562 | /** |
||
563 | * @access private |
||
564 | */ |
||
565 | private static function ParseParameters($Key, array $RawParams = null) |
||
566 | { |
||
567 | if (!$RawParams) |
||
568 | { |
||
569 | return array(); |
||
570 | } |
||
571 | |||
572 | // Parameters are split into (key, value) pairs |
||
573 | $Parameters = array(); |
||
574 | foreach ($RawParams as $Item) |
||
575 | { |
||
576 | $Parameters[] = explode('=', strtolower($Item)); |
||
577 | } |
||
578 | |||
579 | $Type = array(); |
||
580 | $Result = array(); |
||
581 | |||
582 | // And each parameter is checked whether anything can/should be done because of it |
||
583 | foreach ($Parameters as $Index => $Parameter) |
||
584 | { |
||
585 | // Skipping empty elements |
||
586 | if (!$Parameter) |
||
587 | { |
||
588 | continue; |
||
589 | } |
||
590 | |||
591 | // Handling type parameters without the explicit TYPE parameter name (2.1 valid) |
||
592 | if (count($Parameter) == 1) |
||
593 | { |
||
594 | // Checks if the type value is allowed for the specific element |
||
595 | // The second part of the "if" statement means that email elements can have non-standard types (see the spec) |
||
596 | if ( |
||
597 | (isset(self::$Spec_ElementTypes[$Key]) && in_array($Parameter[0], self::$Spec_ElementTypes[$Key])) || |
||
598 | ($Key == 'email' && is_scalar($Parameter[0])) |
||
599 | ) |
||
600 | { |
||
601 | $Type[] = $Parameter[0]; |
||
602 | } |
||
603 | } |
||
604 | elseif (count($Parameter) > 2) |
||
605 | { |
||
606 | if(count(explode(',', $RawParams[$Index], -1)) > 0) |
||
607 | { |
||
608 | $TempTypeParams = self::ParseParameters($Key, explode(',', $RawParams[$Index])); |
||
609 | if ($TempTypeParams['type']) |
||
610 | { |
||
611 | $Type = array_merge($Type, $TempTypeParams['type']); |
||
612 | } |
||
613 | } |
||
614 | } |
||
615 | else |
||
616 | { |
||
617 | switch ($Parameter[0]) |
||
618 | { |
||
619 | case 'encoding': |
||
620 | if (in_array($Parameter[1], array('quoted-printable', 'b', 'base64'))) |
||
621 | { |
||
622 | $Result['encoding'] = $Parameter[1] == 'base64' ? 'b' : $Parameter[1]; |
||
623 | } |
||
624 | break; |
||
625 | case 'charset': |
||
626 | $Result['charset'] = $Parameter[1]; |
||
627 | break; |
||
628 | case 'type': |
||
629 | $Type = array_merge($Type, explode(',', $Parameter[1])); |
||
630 | break; |
||
631 | case 'value': |
||
632 | if (strtolower($Parameter[1]) == 'url') |
||
633 | { |
||
634 | $Result['encoding'] = 'uri'; |
||
635 | } |
||
636 | break; |
||
637 | } |
||
638 | } |
||
639 | } |
||
640 | |||
641 | $Result['type'] = $Type; |
||
642 | |||
643 | return $Result; |
||
644 | } |
||
645 | |||
646 | // !Interface methods |
||
647 | |||
648 | // Countable interface |
||
649 | public function count() |
||
650 | { |
||
651 | switch ($this -> Mode) |
||
652 | { |
||
653 | case self::MODE_ERROR: |
||
654 | return 0; |
||
655 | 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. ![]() |
|||
656 | case self::MODE_SINGLE: |
||
657 | return 1; |
||
658 | 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. ![]() |
|||
659 | case self::MODE_MULTIPLE: |
||
660 | return count($this -> Data); |
||
661 | 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. ![]() |
|||
662 | } |
||
663 | return 0; |
||
664 | } |
||
665 | |||
666 | // Iterator interface |
||
667 | public function rewind() |
||
668 | { |
||
669 | reset($this -> Data); |
||
670 | } |
||
671 | |||
672 | public function current() |
||
673 | { |
||
674 | return current($this -> Data); |
||
675 | } |
||
676 | |||
677 | public function next() |
||
678 | { |
||
679 | return next($this -> Data); |
||
680 | } |
||
681 | |||
682 | public function valid() |
||
683 | { |
||
684 | return ($this -> current() !== false); |
||
685 | } |
||
686 | |||
687 | public function key() |
||
688 | { |
||
689 | return key($this -> Data); |
||
690 | } |
||
691 | } |
||
692 | ?> |
||
0 ignored issues
–
show
It is not recommended to use PHP's closing tag
?> in files other than templates.
Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore. A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever. ![]() |
|||
693 |
This check looks for assignments to scalar types that may be of the wrong type.
To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.