2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- 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 +----------------------------------------------------------------------+
16 #include "hphp/runtime/base/intercept.h"
17 #include "hphp/runtime/base/util/request_local.h"
18 #include "hphp/runtime/base/array/array_init.h"
19 #include "hphp/runtime/base/array/array_iterator.h"
20 #include "hphp/runtime/base/type_conversions.h"
21 #include "hphp/runtime/base/builtin_functions.h"
22 #include "hphp/runtime/vm/translator/targetcache.h"
23 #include "hphp/runtime/vm/unit.h"
24 #include "hphp/runtime/vm/event_hook.h"
26 #include "hphp/util/parser/parser.h"
27 #include "hphp/util/lock.h"
29 #include "hphp/runtime/eval/runtime/file_repository.h"
30 #include "hphp/runtime/vm/translator/translator-x64.h"
31 #include "hphp/util/trace.h"
33 using namespace HPHP::Trace
;
35 ///////////////////////////////////////////////////////////////////////////////
39 static const Trace::Module TRACEMOD
= Trace::intercept
;
41 class InterceptRequestData
: public RequestEventHandler
{
43 InterceptRequestData()
44 : m_use_allowed_functions(false) {
48 *s_hasRenamedFunction
= false;
49 m_use_allowed_functions
= false;
50 m_allowed_functions
.clear();
51 m_renamed_functions
.clear();
52 m_global_handler
.reset();
53 m_intercept_handlers
.clear();
56 virtual void requestInit() {
60 virtual void requestShutdown() {
65 bool m_use_allowed_functions
;
66 StringISet m_allowed_functions
;
67 StringIMap
<String
> m_renamed_functions
;
69 Variant m_global_handler
;
70 StringIMap
<Variant
> m_intercept_handlers
;
72 IMPLEMENT_STATIC_REQUEST_LOCAL(InterceptRequestData
, s_intercept_data
);
73 IMPLEMENT_THREAD_LOCAL_NO_CHECK(bool, s_hasRenamedFunction
);
76 typedef StringIMap
<vector
<char*> > RegisteredFlagsMap
;
78 static RegisteredFlagsMap s_registered_flags
;
80 ///////////////////////////////////////////////////////////////////////////////
82 static void flag_maybe_interrupted(vector
<char*> &flags
) {
83 for (int i
= flags
.size() - 1; i
>= 0; i
--) {
88 bool register_intercept(CStrRef name
, CVarRef callback
, CVarRef data
) {
89 StringIMap
<Variant
> &handlers
= s_intercept_data
->m_intercept_handlers
;
90 if (!callback
.toBoolean()) {
92 s_intercept_data
->m_global_handler
.reset();
100 EventHook::EnableIntercept();
102 Array handler
= CREATE_VECTOR2(callback
, data
);
105 s_intercept_data
->m_global_handler
= handler
;
108 handlers
[name
] = handler
;
113 for (RegisteredFlagsMap::iterator iter
=
114 s_registered_flags
.begin();
115 iter
!= s_registered_flags
.end(); ++iter
) {
116 flag_maybe_interrupted(iter
->second
);
119 RegisteredFlagsMap::iterator iter
=
120 s_registered_flags
.find(name
);
121 if (iter
!= s_registered_flags
.end()) {
122 flag_maybe_interrupted(iter
->second
);
129 Variant
*get_enabled_intercept_handler(CStrRef name
) {
130 Variant
*handler
= nullptr;
131 StringIMap
<Variant
> &handlers
= s_intercept_data
->m_intercept_handlers
;
132 StringIMap
<Variant
>::iterator iter
= handlers
.find(name
);
133 if (iter
!= handlers
.end()) {
134 handler
= &iter
->second
;
136 handler
= &s_intercept_data
->m_global_handler
;
137 if (handler
->isNull()) {
144 Variant
*get_intercept_handler(CStrRef name
, char* flag
) {
145 TRACE(1, "get_intercept_handler %s flag is %d\n",
146 name
.get()->data(), (int)*flag
);
150 StringData
*sd
= name
.get();
151 if (!sd
->isStatic()) {
152 sd
= StringData::GetStaticString(sd
);
154 s_registered_flags
[StrNR(sd
)].push_back(flag
);
159 Variant
*handler
= get_enabled_intercept_handler(name
);
160 if (handler
== nullptr) {
167 void unregister_intercept_flag(CStrRef name
, char *flag
) {
169 RegisteredFlagsMap::iterator iter
=
170 s_registered_flags
.find(name
);
171 if (iter
!= s_registered_flags
.end()) {
172 vector
<char*> &flags
= iter
->second
;
173 for (int i
= flags
.size(); i
--; ) {
174 if (flag
== flags
[i
]) {
175 flags
.erase(flags
.begin() + i
);
182 ///////////////////////////////////////////////////////////////////////////////
183 // fb_rename_function()
185 void check_renamed_functions(CArrRef names
) {
186 g_vmContext
->addRenameableFunctions(names
.get());
189 bool check_renamed_function(CStrRef name
) {
190 return g_vmContext
->isFunctionRenameable(name
.get());
193 void rename_function(CStrRef old_name
, CStrRef new_name
) {
194 g_vmContext
->renameFunction(old_name
.get(), new_name
.get());
197 String
get_renamed_function(CStrRef name
) {
198 HPHP::Func
* f
= HPHP::Unit::lookupFunc(name
.get());
205 ///////////////////////////////////////////////////////////////////////////////