2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_INI_SETTING_H_
18 #define incl_HPHP_INI_SETTING_H_
20 #include "hphp/runtime/base/type-variant.h"
22 #include <folly/Range.h>
30 ///////////////////////////////////////////////////////////////////////////////
36 bool ini_on_update(const Variant
& value
, bool& p
);
37 bool ini_on_update(const Variant
& value
, double& p
);
38 bool ini_on_update(const Variant
& value
, char& p
);
39 bool ini_on_update(const Variant
& value
, int16_t& p
);
40 bool ini_on_update(const Variant
& value
, int32_t& p
);
41 bool ini_on_update(const Variant
& value
, int64_t& p
);
42 bool ini_on_update(const Variant
& value
, unsigned char& p
);
43 bool ini_on_update(const Variant
& value
, uint16_t& p
);
44 bool ini_on_update(const Variant
& value
, uint32_t& p
);
45 bool ini_on_update(const Variant
& value
, uint64_t& p
);
46 bool ini_on_update(const Variant
& value
, std::string
& p
);
47 bool ini_on_update(const Variant
& value
, String
& p
);
48 bool ini_on_update(const Variant
& value
, Array
& p
);
49 bool ini_on_update(const Variant
& value
, std::set
<std::string
>& p
);
50 bool ini_on_update(const Variant
& value
, std::vector
<std::string
>& p
);
51 bool ini_on_update(const Variant
& value
,
52 std::map
<std::string
, std::string
>& p
);
53 bool ini_on_update(const Variant
& value
,
54 std::map
<std::string
, std::string
, stdltistr
>& p
);
55 bool ini_on_update(const Variant
& value
,
56 std::set
<std::string
, stdltistr
>& p
);
57 bool ini_on_update(const Variant
& value
,
58 boost::container::flat_set
<std::string
>& p
);
59 bool ini_on_update(const Variant
& value
,
60 hphp_string_imap
<std::string
>& p
);
61 Variant
ini_get(bool& p
);
62 Variant
ini_get(double& p
);
63 Variant
ini_get(char& p
);
64 Variant
ini_get(int16_t& p
);
65 Variant
ini_get(int32_t& p
);
66 Variant
ini_get(int64_t& p
);
67 Variant
ini_get(unsigned char& p
);
68 Variant
ini_get(uint16_t& p
);
69 Variant
ini_get(uint32_t& p
);
70 Variant
ini_get(uint64_t& p
);
71 Variant
ini_get(std::string
& p
);
72 Variant
ini_get(String
& p
);
73 Variant
ini_get(Array
& p
);
74 Variant
ini_get(std::set
<std::string
>& p
);
75 Variant
ini_get(std::vector
<std::string
>& p
);
76 Variant
ini_get(std::map
<std::string
, std::string
>& p
);
77 Variant
ini_get(std::map
<std::string
, std::string
, stdltistr
>& p
);
78 Variant
ini_get(std::set
<std::string
, stdltistr
>& p
);
79 Variant
ini_get(boost::container::flat_set
<std::string
>& p
);
80 Variant
ini_get(hphp_string_imap
<std::string
>& p
);
83 * If given an ini setting like "hhvm.abc[def][ghi]=yyy" and we have
84 * an ini Variant with the top key being hhvm.abc pointing to its
85 * values, we will have something like:
86 * {hhvm.abc {def {ghi : yyy}}}
87 * And we pass as the name to get the value of as "def.ghi" for that
88 * Variant, we need to iterate over the pointer for the dot (.) values to
89 * get to the final setting value of yyy
91 const IniSettingMap
ini_iterate(const IniSettingMap
& ini
,
92 const std::string
& name
);
95 * Consult the private implementation details in ini-setting.cpp.
97 * There's one instance of an IniCallbackData for each initialization
98 * setting. Management of system and per-request (per-thread)
99 * mappings from names of ini settings to actual IniCallbackData
100 * is done privately with the statics s_user_callbacks and
101 * s_system_ini_callbacks.
103 * In addition, a unique instance of the struct UserIniData can be
104 * associated with the IniCallbackData. The IniCallbackData instance
105 * is the point of ownership of the instance of UserIniData, and is
106 * responsible for firing the destructor.
108 * The struct UserIniData should be subclassed to hold data specific
109 * to an initialization regime, such as the zend compatibility layer
110 * implementation of zend_ini_entry. That subclass is responsible for
111 * allocating/freeing its own internal data.
113 * There's a mechanism for registering an initter, which is a factory to
114 * produce UserIniData. This registration is done at the same time that
115 * the setter and getter are established; see the class SetAndGet
118 virtual ~UserIniData() {}
121 struct IniSettingMap
{
122 // placeholder to allow the form:
123 // IniSettingMap ini = IniSettingMap::object;
124 // is used throughout the codebase. We can convert later to remove them
125 enum Type
{ object
};
127 /* implicit */ IniSettingMap(Type
);
128 /* implicit */ IniSettingMap(const IniSettingMap
& i
); // copy constructor
129 /* implicit */ IniSettingMap(const Variant
& v
);
130 /* implicit */ IniSettingMap(IniSettingMap
&& i
) noexcept
; // move constructor
131 IniSettingMap
& operator=(const IniSettingMap
& i
);
134 const IniSettingMap
operator[](const String
& key
) const;
135 String
toString() const { return m_map
.toString();}
136 Array
toArray() const { return m_map
.toArray();}
137 Array
& toArrRef() { return m_map
.toArrRef(); }
138 Object
toObject() const { return m_map
.toObject();}
139 bool isNull() const { return m_map
.isNull();}
140 bool isString() const { return m_map
.isString();}
141 bool isArray() const { return m_map
.isArray();}
142 bool isObject() const { return m_map
.isObject();}
143 Variant
& toVariant() { return m_map
; }
144 void set(const String
& key
, const Variant
& v
);
145 TypedValue
detach() noexcept
{
146 return m_map
.detach();
155 struct CallbackData
{
156 Variant active_section
;
161 // can remove later in a diff that explicitly changes all uses of
162 // IniSetting::Map to IniSettingMap
163 typedef IniSettingMap Map
;
164 static const Extension
* CORE
;
170 struct ParserCallback
{
171 virtual ~ParserCallback() {};
172 virtual void onSection(const std::string
&name
, void *arg
);
173 virtual void onLabel(const std::string
&name
, void *arg
);
174 virtual void onEntry(const std::string
&key
, const std::string
&value
,
176 virtual void onPopEntry(const std::string
&key
, const std::string
&value
,
177 const std::string
&offset
, void *arg
);
178 virtual void onConstant(std::string
&result
, const std::string
&name
);
179 virtual void onVar(std::string
&result
, const std::string
&name
);
180 virtual void onOp(std::string
&result
, char type
, const std::string
& op1
,
181 const std::string
& op2
);
183 void makeArray(Variant
&hash
, const std::string
&offset
,
184 const std::string
&value
);
186 // Substitution copy or symlink via @ or : markers in the config line
187 void makeSettingSub(const String
&key
, const std::string
&offset
,
188 const std::string
&value
, Variant
& cur_settings
);
189 void traverseToSet(const String
&key
, const std::string
& offset
,
190 Variant
& value
, Variant
& cur_settings
,
191 const std::string
& stopChar
);
193 struct SectionParserCallback
: ParserCallback
{
194 void onSection(const std::string
& name
, void* arg
) override
;
195 void onLabel(const std::string
& name
, void* arg
) override
;
196 void onEntry(const std::string
& key
, const std::string
& value
, void* arg
)
199 const std::string
& key
,
200 const std::string
& value
,
201 const std::string
& offset
,
205 Variant
* activeArray(CallbackData
* data
);
207 struct SystemParserCallback
: ParserCallback
{
208 void onEntry(const std::string
& key
, const std::string
& value
, void* arg
)
211 const std::string
& key
,
212 const std::string
& value
,
213 const std::string
& offset
,
215 void onConstant(std::string
& result
, const std::string
& name
) override
;
220 // These 3 match zend
221 PHP_INI_USER
= (1u << 0),
222 PHP_INI_PERDIR
= (1u << 1),
223 PHP_INI_SYSTEM
= (1u << 2),
225 PHP_INI_ONLY
= (1u << 3),
226 PHP_INI_ALL
= (1u << 4),
228 PHP_INI_SET_USER
= PHP_INI_USER
| PHP_INI_ALL
,
229 PHP_INI_SET_EVERY
= PHP_INI_ONLY
| PHP_INI_SYSTEM
| PHP_INI_PERDIR
|
234 static Variant
FromString(const String
& ini
, const String
& filename
,
235 bool process_sections
= false,
236 int scanner_mode
= NormalScanner
);
237 static IniSettingMap
FromStringAsMap(const std::string
& ini
,
238 const std::string
& filename
);
240 static bool Get(const std::string
& name
, std::string
&value
);
241 static bool Get(const String
& name
, Variant
& value
);
242 static bool Get(const String
& name
, String
& value
);
243 static std::string
Get(const std::string
& name
);
244 static Array
GetAll(const String
& extension
, bool details
);
245 static std::string
GetAllAsJSON();
248 * Change an INI setting as if it was in the php.ini file
250 static bool SetSystem(const String
& name
, const Variant
& value
);
254 static bool GetSystem(const String
& name
, Variant
& value
);
257 * Change an INI setting as if there was a call to ini_set()
259 static bool SetUser(const String
& name
, const Variant
& value
);
262 * Restore an INI setting to the default value before the first call to
265 static void RestoreUser(const String
& name
);
268 * Fill in constant that may not have been bound when an
269 * ini file was initially parsed
271 static bool FillInConstant(const std::string
& name
,
272 const Variant
& value
);
274 * Get the mode for a setting
276 static bool GetMode(const std::string
& name
, Mode
& mode
);
281 std::function
<bool (const T
&)> setter
,
282 std::function
<T ()> getter
,
283 std::function
<struct UserIniData
*()>initter
= nullptr)
288 explicit SetAndGet() {}
290 std::function
<bool (const T
&)> setter
;
291 std::function
<T ()> getter
;
292 std::function
<struct UserIniData
*()> initter
;
296 * The heavy lifting of creating ini settings. First of all, if you don't
297 * have to use this method, please don't. Instead use the simpler:
299 * IniSetting::Bind(this, PHP_INI_SYSTEM, "my.ini", &some_global_var);
301 * IniSetting::Bind(this, PHP_INI_ALL, "my.ini", &some_thread_local_var);
303 * If you have to do something special before your variable is set or gotten
304 * then you can use this function to add callbacks. Both callbacks are
305 * optional (but if you don't pass any, why are you using this method in the
306 * first place?). If the setter callback returns "false" then the value will
307 * not be saved into p. If the getter is not provided, the contents of p will
311 static void Bind(const Extension
* extension
, const Mode mode
,
312 const std::string
& name
, const char *defaultValue
,
313 SetAndGet
<T
> callbacks
, T
* p
= nullptr) {
314 auto callback_set
= callbacks
.setter
;
315 auto setter
= [callback_set
, p
](const Variant
&value
) {
317 auto ret
= ini_on_update(value
, v
);
322 ret
= callback_set(v
);
332 auto callback_get
= callbacks
.getter
;
333 auto getter
= [callback_get
, p
]() {
342 Bind(extension
, mode
, name
, setter
, getter
, callbacks
.initter
);
343 auto hasSystemDefault
= ResetSystemDefault(name
);
344 if (!hasSystemDefault
&& defaultValue
) {
345 setter(defaultValue
);
350 static void Bind(const Extension
* extension
, const Mode mode
,
351 const std::string
& name
, SetAndGet
<T
> callbacks
,
353 Bind(extension
, mode
, name
, nullptr, callbacks
, p
);
357 * Prefer to use this method whenever possible (the non-default one is ok
358 * too). Use Config::Bind if immediate access to the ini setting is
359 * necessary. For performance reasons, Config::Bind should only be used
360 * when access to the ini setting is needed prior to loading the rest of
364 static void Bind(const Extension
* extension
, const Mode mode
,
365 const std::string
& name
, const char *defaultValue
, T
*p
) {
366 Bind(extension
, mode
, name
, defaultValue
, SetAndGet
<T
>(), p
);
370 static void Bind(const Extension
* extension
, const Mode mode
,
371 const std::string
& name
, T
*p
) {
372 Bind(extension
, mode
, name
, nullptr, p
);
375 static void Unbind(const std::string
& name
);
378 * Set an ini setting back to the value from the config file
379 * (or the hard-coded default)
381 static bool ResetSystemDefault(const std::string
& name
);
384 * After a request, we want to set all user settings back to their original
385 * defaults before the request. This should be called on requestShutdown.
387 static void ResetSavedDefaults();
390 * Used to help us late bind extension constants (e.g. E_ALL) that
391 * were incorrectly bound initially, and needed to be bound again after
394 static bool s_config_is_a_constant
;
395 static std::set
<std::string
> config_names_that_use_constants
;
398 * A flag to ensure we don't try to add a system setting after the
399 * runtime options have been loaded
401 static bool s_system_settings_are_set
;
405 const Extension
* extension
,
407 const std::string
& name
,
408 std::function
<bool(const Variant
&)>updateCallback
,
409 std::function
<Variant()> getCallback
,
410 std::function
<UserIniData
*(void)> userDataCallback
= nullptr);
413 * Take a Variant full of KindOfRefs and unbox it.
415 static Variant
Unbox(const Variant
& boxed
, std::set
<ArrayData
*>& seen
,
416 bool& use_defaults
, const String
& array_key
);
419 int64_t convert_bytes_to_long(folly::StringPiece value
);
420 std::string
convert_long_to_bytes(int64_t value
);
422 void add_default_config_files_globbed(
423 const char *default_config_file
,
424 std::function
<void (const char *filename
)> cb
);
426 ///////////////////////////////////////////////////////////////////////////////
429 #endif // incl_HPHP_INI_SETTING_H_