PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.25
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.25
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / helpers / FrmSerializedStringParserHelper.php

FrmSerializedStringParserHelper.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.25, at classes/helpers/FrmSerializedStringParserHelper.php

187 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 die( 'You are not allowed to call this page directly.' );
5 }
6
7 /**
8 * Parses serialized strings without using the unsafe unserialize function.
9 *
10 * @since 6.2
11 */
12 class FrmSerializedStringParserHelper {
13
14 /**
15 * @var FrmSerializedStringParserHelper|null
16 */
17 private static $instance;
18
19 /**
20 * Get a singleton instance of the parser.
21 *
22 * @return FrmSerializedStringParserHelper
23 */
24 public static function get() {
25 if ( ! isset( self::$instance ) ) {
26 self::$instance = new self();
27 }
28 return self::$instance;
29 }
30
31 /**
32 * Private constructor to enforce the use of FrmSerializedStringParserHelper::get.
33 */
34 private function __construct() {}
35
36 /**
37 * Parse a string containing a serialized data structure.
38 * This is the initial entry point into the recursive parser.
39 *
40 * @param string $string
41 * @return mixed
42 */
43 public function parse( $string ) {
44 $unserialized_data = $this->do_parse( new FrmStringReaderHelper( $string ) );
45
46 if ( is_array( $unserialized_data ) && $this->serialized_string_is_invalid( $string ) ) {
47 return array_filter( $unserialized_data, array( $this, 'serialized_value_is_valid' ) );
48 }
49
50 return $unserialized_data;
51 }
52
53 /**
54 * Check if an unserialized value is valid.
55 *
56 * @since 6.20
57 *
58 * @param mixed $value
59 * @return bool
60 */
61 private function serialized_value_is_valid( $value ) {
62 return ! is_string( $value ) || strpos( $value, ';s:' ) === false;
63 }
64
65 /**
66 * @since 6.20
67 *
68 * @param string $string
69 * @return bool
70 */
71 private function serialized_string_is_invalid( $string ) {
72 $invalid_substrings = array(
73 ';s:10:\"a"',
74 ';s:";',
75 );
76
77 foreach ( $invalid_substrings as $invalid ) {
78 if ( strpos( $string, $invalid ) !== false ) {
79 return true;
80 }
81 }
82
83 return false;
84 }
85
86 /**
87 * This is the recursive parser.
88 *
89 * @param FrmStringReaderHelper $string
90 * @return array|bool|float|int|string|null
91 */
92 private function do_parse( $string ) {
93 // May be : or ; as a terminator, depending on what the data type is.
94 $type = $string->read( 1 );
95 $string->skip_next_character();
96
97 switch ( $type ) {
98 case 'a':
99 return $this->parse_array( $string );
100
101 case 's':
102 return $this->parse_string( $string );
103
104 case 'i':
105 return $this->parse_int( $string );
106
107 case 'd':
108 return $this->parse_float( $string );
109
110 case 'b':
111 return $this->parse_bool( $string );
112 }
113
114 // Includes case 'N' and case 'O'.
115 // Treat a serialized object or anything unexpected as Null.
116 return null;
117 }
118
119 /**
120 * @param FrmStringReaderHelper $string
121 * @return array
122 */
123 private function parse_array( $string ) {
124 // Associative array: a:length:{[index][value]...}
125 $count = (int) $string->read_until( ':' );
126
127 // Eat the opening "{" of the array.
128 $string->skip_next_character();
129
130 $val = array();
131 for ( $i = 0; $i < $count; $i++ ) {
132 $array_key = $this->do_parse( $string );
133 $array_value = $this->do_parse( $string );
134
135 if ( ! is_array( $array_key ) ) {
136 $val[ $array_key ] = $array_value;
137 }
138 }
139
140 // Eat "}" terminating the array.
141 $string->skip_next_character();
142
143 return $val;
144 }
145
146 /**
147 * @param FrmStringReaderHelper $string
148 * @return string
149 */
150 private function parse_string( $string ) {
151 $len = (int) $string->read_until( ':' );
152 $val = $string->read( $len + 2 );
153
154 // Eat the separator.
155 $string->skip_next_character();
156
157 return $val;
158 }
159
160 /**
161 * @param FrmStringReaderHelper $string
162 * @return int
163 */
164 private function parse_int( $string ) {
165 return (int) $string->read_until( ';' );
166 }
167
168 /**
169 * @param FrmStringReaderHelper $string
170 * @return float
171 */
172 private function parse_float( $string ) {
173 return (float) $string->read_until( ';' );
174 }
175
176 /**
177 * @param FrmStringReaderHelper $string
178 * @return bool
179 */
180 private function parse_bool( $string ) {
181 // Boolean is 0 or 1.
182 $val = $string->read( 1 ) === '1';
183 $string->skip_next_character();
184 return $val;
185 }
186 }
187