make #includes consistent
[hiphop-php.git] / hphp / runtime / base / intercept.cpp
blob9c4438e60a832db68f83582b61669aca2123dfc6
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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 ///////////////////////////////////////////////////////////////////////////////
37 namespace HPHP {
39 static const Trace::Module TRACEMOD = Trace::intercept;
41 class InterceptRequestData : public RequestEventHandler {
42 public:
43 InterceptRequestData()
44 : m_use_allowed_functions(false) {
47 void clear() {
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() {
57 clear();
60 virtual void requestShutdown() {
61 clear();
64 public:
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);
75 static Mutex s_mutex;
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--) {
84 *flags[i] = 1;
88 bool register_intercept(CStrRef name, CVarRef callback, CVarRef data) {
89 StringIMap<Variant> &handlers = s_intercept_data->m_intercept_handlers;
90 if (!callback.toBoolean()) {
91 if (name.empty()) {
92 s_intercept_data->m_global_handler.reset();
93 handlers.clear();
94 } else {
95 handlers.erase(name);
97 return true;
100 EventHook::EnableIntercept();
102 Array handler = CREATE_VECTOR2(callback, data);
104 if (name.empty()) {
105 s_intercept_data->m_global_handler = handler;
106 handlers.clear();
107 } else {
108 handlers[name] = handler;
111 Lock lock(s_mutex);
112 if (name.empty()) {
113 for (RegisteredFlagsMap::iterator iter =
114 s_registered_flags.begin();
115 iter != s_registered_flags.end(); ++iter) {
116 flag_maybe_interrupted(iter->second);
118 } else {
119 RegisteredFlagsMap::iterator iter =
120 s_registered_flags.find(name);
121 if (iter != s_registered_flags.end()) {
122 flag_maybe_interrupted(iter->second);
126 return true;
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;
135 } else {
136 handler = &s_intercept_data->m_global_handler;
137 if (handler->isNull()) {
138 return nullptr;
141 return handler;
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);
147 if (*flag == -1) {
148 Lock lock(s_mutex);
149 if (*flag == -1) {
150 StringData *sd = name.get();
151 if (!sd->isStatic()) {
152 sd = StringData::GetStaticString(sd);
154 s_registered_flags[StrNR(sd)].push_back(flag);
155 *flag = 0;
159 Variant *handler = get_enabled_intercept_handler(name);
160 if (handler == nullptr) {
161 return nullptr;
163 *flag = 1;
164 return handler;
167 void unregister_intercept_flag(CStrRef name, char *flag) {
168 Lock lock(s_mutex);
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);
176 break;
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());
199 if (f) {
200 return f->nameRef();
202 return name;
205 ///////////////////////////////////////////////////////////////////////////////