PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.30
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.30
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.30, at classes/helpers/FrmSerializedStringParserHelper.php

197 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 *
42 * @return mixed
43 */
44 public function parse( $string ) {
45 $unserialized_data = $this->do_parse( new FrmStringReaderHelper( $string ) );
46
47 if ( is_array( $unserialized_data ) && $this->serialized_string_is_invalid( $string ) ) {
48 return array_filter( $unserialized_data, array( $this, 'serialized_value_is_valid' ) );
49 }
50
51 return $unserialized_data;
52 }
53
54 /**
55 * Check if an unserialized value is valid.
56 *
57 * @since 6.20
58 *
59 * @param mixed $value
60 *
61 * @return bool
62 */
63 private function serialized_value_is_valid( $value ) {
64 return ! is_string( $value ) || ! str_contains( $value, ';s:' );
65 }
66
67 /**
68 * @since 6.20
69 *
70 * @param string $string
71 *
72 * @return bool
73 */
74 private function serialized_string_is_invalid( $string ) {
75 $invalid_substrings = array(
76 ';s:10:\"a"',
77 ';s:";',
78 );
79
80 foreach ( $invalid_substrings as $invalid ) {
81 if ( str_contains( $string, $invalid ) ) {
82 return true;
83 }
84 }
85
86 return false;
87 }
88
89 /**
90 * This is the recursive parser.
91 *
92 * @param FrmStringReaderHelper $string
93 *
94 * @return array|bool|float|int|string|null
95 */
96 private function do_parse( $string ) {
97 // May be : or ; as a terminator, depending on what the data type is.
98 $type = $string->read( 1 );
99 $string->skip_next_character();
100
101 switch ( $type ) {
102 case 'a':
103 return $this->parse_array( $string );
104
105 case 's':
106 return $this->parse_string( $string );
107
108 case 'i':
109 return $this->parse_int( $string );
110
111 case 'd':
112 return $this->parse_float( $string );
113
114 case 'b':
115 return $this->parse_bool( $string );
116 }
117
118 // Includes case 'N' and case 'O'.
119 // Treat a serialized object or anything unexpected as Null.
120 return null;
121 }
122
123 /**
124 * @param FrmStringReaderHelper $string
125 *
126 * @return array
127 */
128 private function parse_array( $string ) {
129 // Associative array: a:length:{[index][value]...}
130 $count = (int) $string->read_until( ':' );
131
132 // Eat the opening "{" of the array.
133 $string->skip_next_character();
134
135 $val = array();
136
137 for ( $i = 0; $i < $count; $i++ ) {
138 $array_key = $this->do_parse( $string );
139 $array_value = $this->do_parse( $string );
140
141 if ( ! is_array( $array_key ) ) {
142 $val[ $array_key ] = $array_value;
143 }
144 }
145
146 // Eat "}" terminating the array.
147 $string->skip_next_character();
148
149 return $val;
150 }
151
152 /**
153 * @param FrmStringReaderHelper $string
154 *
155 * @return string
156 */
157 private function parse_string( $string ) {
158 $len = (int) $string->read_until( ':' );
159 $val = $string->read( $len + 2 );
160
161 // Eat the separator.
162 $string->skip_next_character();
163
164 return $val;
165 }
166
167 /**
168 * @param FrmStringReaderHelper $string
169 *
170 * @return int
171 */
172 private function parse_int( $string ) {
173 return (int) $string->read_until( ';' );
174 }
175
176 /**
177 * @param FrmStringReaderHelper $string
178 *
179 * @return float
180 */
181 private function parse_float( $string ) {
182 return (float) $string->read_until( ';' );
183 }
184
185 /**
186 * @param FrmStringReaderHelper $string
187 *
188 * @return bool
189 */
190 private function parse_bool( $string ) {
191 // Boolean is 0 or 1.
192 $val = $string->read( 1 ) === '1';
193 $string->skip_next_character();
194 return $val;
195 }
196 }
197