flickerstreak@1
|
1 --[[
|
flickerstreak@1
|
2 Name: AceHook-2.1
|
flickerstreak@1
|
3 Revision: $Rev: 19980 $
|
flickerstreak@1
|
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
flickerstreak@1
|
5 Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
flickerstreak@1
|
6 Website: http://www.wowace.com/
|
flickerstreak@1
|
7 Documentation: http://www.wowace.com/index.php/AceHook-2.1
|
flickerstreak@1
|
8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.1
|
flickerstreak@1
|
9 Description: Mixin to allow for safe hooking of functions, methods, and scripts.
|
flickerstreak@1
|
10 Dependencies: AceLibrary, AceOO-2.0
|
flickerstreak@1
|
11 ]]
|
flickerstreak@1
|
12
|
flickerstreak@1
|
13 local MAJOR_VERSION = "AceHook-2.1"
|
flickerstreak@1
|
14 local MINOR_VERSION = "$Revision: 19980 $"
|
flickerstreak@1
|
15
|
flickerstreak@1
|
16 -- This ensures the code is only executed if the libary doesn't already exist, or is a newer version
|
flickerstreak@1
|
17 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
|
flickerstreak@1
|
18 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
flickerstreak@1
|
19
|
flickerstreak@1
|
20 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
flickerstreak@1
|
21
|
flickerstreak@1
|
22 --[[---------------------------------------------------------------------------------
|
flickerstreak@1
|
23 Create the library object
|
flickerstreak@1
|
24 ----------------------------------------------------------------------------------]]
|
flickerstreak@1
|
25
|
flickerstreak@1
|
26 local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
flickerstreak@1
|
27 local AceHook = AceOO.Mixin {
|
flickerstreak@1
|
28 "Hook",
|
flickerstreak@1
|
29 "HookScript",
|
flickerstreak@1
|
30 "SecureHook",
|
flickerstreak@1
|
31 "Unhook",
|
flickerstreak@1
|
32 "UnhookAll",
|
flickerstreak@1
|
33 "HookReport",
|
flickerstreak@1
|
34 "IsHooked",
|
flickerstreak@1
|
35 }
|
flickerstreak@1
|
36
|
flickerstreak@1
|
37 --[[---------------------------------------------------------------------------------
|
flickerstreak@1
|
38 Library Definitions
|
flickerstreak@1
|
39 ----------------------------------------------------------------------------------]]
|
flickerstreak@1
|
40
|
flickerstreak@1
|
41 local protectedScripts = {
|
flickerstreak@1
|
42 OnClick = true,
|
flickerstreak@1
|
43 }
|
flickerstreak@1
|
44
|
flickerstreak@1
|
45 local _G = getfenv(0)
|
flickerstreak@1
|
46
|
flickerstreak@1
|
47 local handlers, scripts, actives, registry, onceSecure
|
flickerstreak@1
|
48
|
flickerstreak@1
|
49 --[[---------------------------------------------------------------------------------
|
flickerstreak@1
|
50 Private definitions (Not exposed)
|
flickerstreak@1
|
51 ----------------------------------------------------------------------------------]]
|
flickerstreak@1
|
52
|
flickerstreak@1
|
53 local new, del
|
flickerstreak@1
|
54 do
|
flickerstreak@1
|
55 local list = setmetatable({}, {__mode = "k"})
|
flickerstreak@1
|
56 function new()
|
flickerstreak@1
|
57 local t = next(list)
|
flickerstreak@1
|
58 if not t then
|
flickerstreak@1
|
59 return {}
|
flickerstreak@1
|
60 end
|
flickerstreak@1
|
61 list[t] = nil
|
flickerstreak@1
|
62 return t
|
flickerstreak@1
|
63 end
|
flickerstreak@1
|
64
|
flickerstreak@1
|
65 function del(t)
|
flickerstreak@1
|
66 setmetatable(t, nil)
|
flickerstreak@1
|
67 for k in pairs(t) do
|
flickerstreak@1
|
68 t[k] = nil
|
flickerstreak@1
|
69 end
|
flickerstreak@1
|
70 list[t] = true
|
flickerstreak@1
|
71 end
|
flickerstreak@1
|
72 end
|
flickerstreak@1
|
73
|
flickerstreak@1
|
74 local function createFunctionHook(self, func, handler, orig, secure)
|
flickerstreak@1
|
75 if not secure then
|
flickerstreak@1
|
76 if type(handler) == "string" then
|
flickerstreak@1
|
77 -- The handler is a method, need to self it
|
flickerstreak@1
|
78 local uid
|
flickerstreak@1
|
79 uid = function(...)
|
flickerstreak@1
|
80 if actives[uid] then
|
flickerstreak@1
|
81 return self[handler](self, ...)
|
flickerstreak@1
|
82 else
|
flickerstreak@1
|
83 return orig(...)
|
flickerstreak@1
|
84 end
|
flickerstreak@1
|
85 end
|
flickerstreak@1
|
86 return uid
|
flickerstreak@1
|
87 else
|
flickerstreak@1
|
88 -- The handler is a function, just call it
|
flickerstreak@1
|
89 local uid
|
flickerstreak@1
|
90 uid = function(...)
|
flickerstreak@1
|
91 if actives[uid] then
|
flickerstreak@1
|
92 return handler(...)
|
flickerstreak@1
|
93 else
|
flickerstreak@1
|
94 return orig(...)
|
flickerstreak@1
|
95 end
|
flickerstreak@1
|
96 end
|
flickerstreak@1
|
97 return uid
|
flickerstreak@1
|
98 end
|
flickerstreak@1
|
99 else
|
flickerstreak@1
|
100 -- secure hooks don't call the original method
|
flickerstreak@1
|
101 if type(handler) == "string" then
|
flickerstreak@1
|
102 -- The handler is a method, need to self it
|
flickerstreak@1
|
103 local uid
|
flickerstreak@1
|
104 uid = function(...)
|
flickerstreak@1
|
105 if actives[uid] then
|
flickerstreak@1
|
106 return self[handler](self, ...)
|
flickerstreak@1
|
107 end
|
flickerstreak@1
|
108 end
|
flickerstreak@1
|
109 return uid
|
flickerstreak@1
|
110 else
|
flickerstreak@1
|
111 -- The handler is a function, just call it
|
flickerstreak@1
|
112 local uid
|
flickerstreak@1
|
113 uid = function(...)
|
flickerstreak@1
|
114 if actives[uid] then
|
flickerstreak@1
|
115 return handler(...)
|
flickerstreak@1
|
116 end
|
flickerstreak@1
|
117 end
|
flickerstreak@1
|
118 return uid
|
flickerstreak@1
|
119 end
|
flickerstreak@1
|
120 end
|
flickerstreak@1
|
121 end
|
flickerstreak@1
|
122
|
flickerstreak@1
|
123 local function createMethodHook(self, object, method, handler, orig, secure)
|
flickerstreak@1
|
124 if not secure then
|
flickerstreak@1
|
125 if type(handler) == "string" then
|
flickerstreak@1
|
126 local uid
|
flickerstreak@1
|
127 uid = function(...)
|
flickerstreak@1
|
128 if actives[uid] then
|
flickerstreak@1
|
129 return self[handler](self, ...)
|
flickerstreak@1
|
130 else
|
flickerstreak@1
|
131 return orig(...)
|
flickerstreak@1
|
132 end
|
flickerstreak@1
|
133 end
|
flickerstreak@1
|
134 return uid
|
flickerstreak@1
|
135 else
|
flickerstreak@1
|
136 -- The handler is a function, just call it
|
flickerstreak@1
|
137 local uid
|
flickerstreak@1
|
138 uid = function(...)
|
flickerstreak@1
|
139 if actives[uid] then
|
flickerstreak@1
|
140 return handler(...)
|
flickerstreak@1
|
141 else
|
flickerstreak@1
|
142 return orig(...)
|
flickerstreak@1
|
143 end
|
flickerstreak@1
|
144 end
|
flickerstreak@1
|
145 return uid
|
flickerstreak@1
|
146 end
|
flickerstreak@1
|
147 else
|
flickerstreak@1
|
148 -- secure hooks don't call the original method
|
flickerstreak@1
|
149 if type(handler) == "string" then
|
flickerstreak@1
|
150 local uid
|
flickerstreak@1
|
151 uid = function(...)
|
flickerstreak@1
|
152 if actives[uid] then
|
flickerstreak@1
|
153 return self[handler](self, ...)
|
flickerstreak@1
|
154 end
|
flickerstreak@1
|
155 end
|
flickerstreak@1
|
156 return uid
|
flickerstreak@1
|
157 else
|
flickerstreak@1
|
158 -- The handler is a function, just call it
|
flickerstreak@1
|
159 local uid
|
flickerstreak@1
|
160 uid = function(...)
|
flickerstreak@1
|
161 if actives[uid] then
|
flickerstreak@1
|
162 return handler(...)
|
flickerstreak@1
|
163 end
|
flickerstreak@1
|
164 end
|
flickerstreak@1
|
165 return uid
|
flickerstreak@1
|
166 end
|
flickerstreak@1
|
167 end
|
flickerstreak@1
|
168 end
|
flickerstreak@1
|
169
|
flickerstreak@1
|
170 local function hookFunction(self, func, handler, secure)
|
flickerstreak@1
|
171 local orig = _G[func]
|
flickerstreak@1
|
172
|
flickerstreak@1
|
173 if not orig or type(orig) ~= "function" then
|
flickerstreak@1
|
174 AceHook:error("Attempt to hook a non-existant function %q", func)
|
flickerstreak@1
|
175 end
|
flickerstreak@1
|
176
|
flickerstreak@1
|
177 if not handler then
|
flickerstreak@1
|
178 handler = func
|
flickerstreak@1
|
179 end
|
flickerstreak@1
|
180
|
flickerstreak@1
|
181 local uid = registry[self][func]
|
flickerstreak@1
|
182 if uid then
|
flickerstreak@1
|
183 if actives[uid] then
|
flickerstreak@1
|
184 -- We have an active hook from this source. Don't multi-hook
|
flickerstreak@1
|
185 AceHook:error("%q already has an active hook from this source.", func)
|
flickerstreak@1
|
186 end
|
flickerstreak@1
|
187
|
flickerstreak@1
|
188 if handlers[uid] == handler then
|
flickerstreak@1
|
189 -- The hook is inactive, so reactivate it
|
flickerstreak@1
|
190 actives[uid] = true
|
flickerstreak@1
|
191 return
|
flickerstreak@1
|
192 else
|
flickerstreak@1
|
193 self.hooks[func] = nil
|
flickerstreak@1
|
194 registry[self][func] = nil
|
flickerstreak@1
|
195 handlers[uid] = nil
|
flickerstreak@1
|
196 uid = nil
|
flickerstreak@1
|
197 end
|
flickerstreak@1
|
198 end
|
flickerstreak@1
|
199
|
flickerstreak@1
|
200 if type(handler) == "string" then
|
flickerstreak@1
|
201 if type(self[handler]) ~= "function" then
|
flickerstreak@1
|
202 AceHook:error("Could not find the the handler %q when hooking function %q", handler, func)
|
flickerstreak@1
|
203 end
|
flickerstreak@1
|
204 elseif type(handler) ~= "function" then
|
flickerstreak@1
|
205 AceHook:error("Could not find the handler you supplied when hooking %q", func)
|
flickerstreak@1
|
206 end
|
flickerstreak@1
|
207
|
flickerstreak@1
|
208 uid = createFunctionHook(self, func, handler, orig, secure)
|
flickerstreak@1
|
209 registry[self][func] = uid
|
flickerstreak@1
|
210 actives[uid] = true
|
flickerstreak@1
|
211 handlers[uid] = handler
|
flickerstreak@1
|
212
|
flickerstreak@1
|
213 if not secure then
|
flickerstreak@1
|
214 _G[func] = uid
|
flickerstreak@1
|
215 self.hooks[func] = orig
|
flickerstreak@1
|
216 else
|
flickerstreak@1
|
217 hooksecurefunc(func, uid)
|
flickerstreak@1
|
218 end
|
flickerstreak@1
|
219 end
|
flickerstreak@1
|
220
|
flickerstreak@1
|
221 local function unhookFunction(self, func)
|
flickerstreak@1
|
222 if not registry[self][func] then
|
flickerstreak@1
|
223 AceHook:error("Tried to unhook %q which is not currently hooked.", func)
|
flickerstreak@1
|
224 end
|
flickerstreak@1
|
225
|
flickerstreak@1
|
226 local uid = registry[self][func]
|
flickerstreak@1
|
227
|
flickerstreak@1
|
228 if actives[uid] then
|
flickerstreak@1
|
229 -- See if we own the global function
|
flickerstreak@1
|
230 if self.hooks[func] and _G[func] == uid then
|
flickerstreak@1
|
231 _G[func] = self.hooks[func]
|
flickerstreak@1
|
232 self.hooks[func] = nil
|
flickerstreak@1
|
233 registry[self][func] = nil
|
flickerstreak@1
|
234 handlers[uid] = nil
|
flickerstreak@1
|
235 actives[uid] = nil
|
flickerstreak@1
|
236 -- Magically all-done
|
flickerstreak@1
|
237 else
|
flickerstreak@1
|
238 actives[uid] = nil
|
flickerstreak@1
|
239 end
|
flickerstreak@1
|
240 end
|
flickerstreak@1
|
241 end
|
flickerstreak@1
|
242
|
flickerstreak@1
|
243 local function hookMethod(self, obj, method, handler, script, secure)
|
flickerstreak@1
|
244 if not handler then
|
flickerstreak@1
|
245 handler = method
|
flickerstreak@1
|
246 end
|
flickerstreak@1
|
247
|
flickerstreak@1
|
248 if not obj or type(obj) ~= "table" then
|
flickerstreak@1
|
249 AceHook:error("The object you supplied could not be found, or isn't a table.")
|
flickerstreak@1
|
250 end
|
flickerstreak@1
|
251
|
flickerstreak@1
|
252 local uid = registry[self][obj] and registry[self][obj][method]
|
flickerstreak@1
|
253 if uid then
|
flickerstreak@1
|
254 if actives[uid] then
|
flickerstreak@1
|
255 -- We have an active hook from this source. Don't multi-hook
|
flickerstreak@1
|
256 AceHook:error("%q already has an active hook from this source.", method)
|
flickerstreak@1
|
257 end
|
flickerstreak@1
|
258
|
flickerstreak@1
|
259 if handlers[uid] == handler then
|
flickerstreak@1
|
260 -- The hook is inactive, reactivate it.
|
flickerstreak@1
|
261 actives[uid] = true
|
flickerstreak@1
|
262 return
|
flickerstreak@1
|
263 else
|
flickerstreak@1
|
264 if self.hooks[obj] then
|
flickerstreak@1
|
265 self.hooks[obj][method] = nil
|
flickerstreak@1
|
266 end
|
flickerstreak@1
|
267 registry[self][obj][method] = nil
|
flickerstreak@1
|
268 handlers[uid] = nil
|
flickerstreak@1
|
269 actives[uid] = nil
|
flickerstreak@1
|
270 scripts[uid] = nil
|
flickerstreak@1
|
271 uid = nil
|
flickerstreak@1
|
272 end
|
flickerstreak@1
|
273 end
|
flickerstreak@1
|
274
|
flickerstreak@1
|
275 if type(handler) == "string" then
|
flickerstreak@1
|
276 if type(self[handler]) ~= "function" then
|
flickerstreak@1
|
277 AceHook:error("Could not find the handler %q you supplied when hooking method %q", handler, method)
|
flickerstreak@1
|
278 end
|
flickerstreak@1
|
279 elseif type(handler) ~= "function" then
|
flickerstreak@1
|
280 AceHook:error("Could not find the handler you supplied when hooking method %q", method)
|
flickerstreak@1
|
281 end
|
flickerstreak@1
|
282
|
flickerstreak@1
|
283 local orig
|
flickerstreak@1
|
284 if script then
|
flickerstreak@1
|
285 if not obj.GetScript then
|
flickerstreak@1
|
286 AceHook:error("The object you supplied does not have a GetScript method.")
|
flickerstreak@1
|
287 end
|
flickerstreak@1
|
288 if not obj:HasScript(method) then
|
flickerstreak@1
|
289 AceHook:error("The object you supplied doesn't allow the %q method.", method)
|
flickerstreak@1
|
290 end
|
flickerstreak@1
|
291
|
flickerstreak@1
|
292 orig = obj:GetScript(method)
|
flickerstreak@1
|
293 if type(orig) ~= "function" then
|
flickerstreak@1
|
294 -- Sometimes there is not a original function for a script.
|
flickerstreak@1
|
295 orig = function() end
|
flickerstreak@1
|
296 end
|
flickerstreak@1
|
297 else
|
flickerstreak@1
|
298 orig = obj[method]
|
flickerstreak@1
|
299 end
|
flickerstreak@1
|
300 if not orig then
|
flickerstreak@1
|
301 AceHook:error("Could not find the method or script %q you are trying to hook.", method)
|
flickerstreak@1
|
302 end
|
flickerstreak@1
|
303
|
flickerstreak@1
|
304 if not self.hooks[obj] then
|
flickerstreak@1
|
305 self.hooks[obj] = new()
|
flickerstreak@1
|
306 end
|
flickerstreak@1
|
307 if not registry[self][obj] then
|
flickerstreak@1
|
308 registry[self][obj] = new()
|
flickerstreak@1
|
309 end
|
flickerstreak@1
|
310
|
flickerstreak@1
|
311 local uid = createMethodHook(self, obj, method, handler, orig, secure)
|
flickerstreak@1
|
312 registry[self][obj][method] = uid
|
flickerstreak@1
|
313 actives[uid] = true
|
flickerstreak@1
|
314 handlers[uid] = handler
|
flickerstreak@1
|
315 scripts[uid] = script and true or nil
|
flickerstreak@1
|
316
|
flickerstreak@1
|
317 if script then
|
flickerstreak@1
|
318 obj:SetScript(method, uid)
|
flickerstreak@1
|
319 self.hooks[obj][method] = orig
|
flickerstreak@1
|
320 elseif not secure then
|
flickerstreak@1
|
321 obj[method] = uid
|
flickerstreak@1
|
322 self.hooks[obj][method] = orig
|
flickerstreak@1
|
323 else
|
flickerstreak@1
|
324 hooksecurefunc(obj, method, uid)
|
flickerstreak@1
|
325 end
|
flickerstreak@1
|
326 end
|
flickerstreak@1
|
327
|
flickerstreak@1
|
328 local function unhookMethod(self, obj, method)
|
flickerstreak@1
|
329 if not registry[self][obj] or not registry[self][obj][method] then
|
flickerstreak@1
|
330 AceHook:error("Attempt to unhook a method %q that is not currently hooked.", method)
|
flickerstreak@1
|
331 return
|
flickerstreak@1
|
332 end
|
flickerstreak@1
|
333
|
flickerstreak@1
|
334 local uid = registry[self][obj][method]
|
flickerstreak@1
|
335
|
flickerstreak@1
|
336 if actives[uid] then
|
flickerstreak@1
|
337 if scripts[uid] then -- If this is a script
|
flickerstreak@1
|
338 if obj:GetScript(method) == uid then
|
flickerstreak@1
|
339 -- We own the script. Revert to normal.
|
flickerstreak@1
|
340 obj:SetScript(method, self.hooks[obj][method])
|
flickerstreak@1
|
341 self.hooks[obj][method] = nil
|
flickerstreak@1
|
342 registry[self][obj][method] = nil
|
flickerstreak@1
|
343 handlers[uid] = nil
|
flickerstreak@1
|
344 scripts[uid] = nil
|
flickerstreak@1
|
345 actives[uid] = nil
|
flickerstreak@1
|
346 else
|
flickerstreak@1
|
347 actives[uid] = nil
|
flickerstreak@1
|
348 end
|
flickerstreak@1
|
349 else
|
flickerstreak@1
|
350 if self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then
|
flickerstreak@1
|
351 -- We own the method. Revert to normal.
|
flickerstreak@1
|
352 obj[method] = self.hooks[obj][method]
|
flickerstreak@1
|
353 self.hooks[obj][method] = nil
|
flickerstreak@1
|
354 registry[self][obj][method] = nil
|
flickerstreak@1
|
355 handlers[uid] = nil
|
flickerstreak@1
|
356 actives[uid] = nil
|
flickerstreak@1
|
357 else
|
flickerstreak@1
|
358 actives[uid] = nil
|
flickerstreak@1
|
359 end
|
flickerstreak@1
|
360 end
|
flickerstreak@1
|
361 end
|
flickerstreak@1
|
362 if self.hooks[obj] and not next(self.hooks[obj]) then
|
flickerstreak@1
|
363 self.hooks[obj] = del(self.hooks[obj])
|
flickerstreak@1
|
364 end
|
flickerstreak@1
|
365 if not next(registry[self][obj]) then
|
flickerstreak@1
|
366 registry[self][obj] = del(registry[self][obj])
|
flickerstreak@1
|
367 end
|
flickerstreak@1
|
368 end
|
flickerstreak@1
|
369
|
flickerstreak@1
|
370 -- ("function" [, handler] [, hookSecure]) or (object, "method" [, handler] [, hookSecure])
|
flickerstreak@1
|
371 function AceHook:Hook(object, method, handler, hookSecure)
|
flickerstreak@1
|
372 if type(object) == "string" then
|
flickerstreak@1
|
373 method, handler, hookSecure = object, method, handler
|
flickerstreak@1
|
374 if handler == true then
|
flickerstreak@1
|
375 handler, hookSecure = nil, true
|
flickerstreak@1
|
376 end
|
flickerstreak@1
|
377 AceHook:argCheck(handler, 3, "function", "string", "nil")
|
flickerstreak@1
|
378 AceHook:argCheck(hookSecure, 4, "boolean", "nil")
|
flickerstreak@1
|
379 if issecurevariable(method) or onceSecure[method] then
|
flickerstreak@1
|
380 if hookSecure then
|
flickerstreak@1
|
381 onceSecure[method] = true
|
flickerstreak@1
|
382 else
|
flickerstreak@1
|
383 AceHook:error("Attempt to hook secure function %q. Use `SecureHook' or add `true' to the argument list to override.", method)
|
flickerstreak@1
|
384 end
|
flickerstreak@1
|
385 end
|
flickerstreak@1
|
386 hookFunction(self, method, handler, false)
|
flickerstreak@1
|
387 else
|
flickerstreak@1
|
388 if handler == true then
|
flickerstreak@1
|
389 handler, hookSecure = nil, true
|
flickerstreak@1
|
390 end
|
flickerstreak@1
|
391 AceHook:argCheck(object, 2, "table")
|
flickerstreak@1
|
392 AceHook:argCheck(method, 3, "string")
|
flickerstreak@1
|
393 AceHook:argCheck(handler, 4, "function", "string", "nil")
|
flickerstreak@1
|
394 AceHook:argCheck(hookSecure, 5, "boolean", "nil")
|
flickerstreak@1
|
395 if not hookSecure and issecurevariable(object, method) then
|
flickerstreak@1
|
396 AceHook:error("Attempt to hook secure method %q. Use `SecureHook' or add `true' to the argument list to override.", method)
|
flickerstreak@1
|
397 end
|
flickerstreak@1
|
398 hookMethod(self, object, method, handler, false, false)
|
flickerstreak@1
|
399 end
|
flickerstreak@1
|
400 end
|
flickerstreak@1
|
401
|
flickerstreak@1
|
402 -- ("function", handler) or (object, "method", handler)
|
flickerstreak@1
|
403 function AceHook:SecureHook(object, method, handler)
|
flickerstreak@1
|
404 if type(object) == "string" then
|
flickerstreak@1
|
405 method, handler = object, method
|
flickerstreak@1
|
406 AceHook:argCheck(handler, 3, "function", "string", "nil")
|
flickerstreak@1
|
407 hookFunction(self, method, handler, true)
|
flickerstreak@1
|
408 else
|
flickerstreak@1
|
409 AceHook:argCheck(object, 2, "table")
|
flickerstreak@1
|
410 AceHook:argCheck(method, 3, "string")
|
flickerstreak@1
|
411 AceHook:argCheck(handler, 4, "function", "string", "nil")
|
flickerstreak@1
|
412 hookMethod(self, object, method, handler, false, true)
|
flickerstreak@1
|
413 end
|
flickerstreak@1
|
414 end
|
flickerstreak@1
|
415
|
flickerstreak@1
|
416 function AceHook:HookScript(frame, script, handler)
|
flickerstreak@1
|
417 AceHook:argCheck(frame, 2, "table")
|
flickerstreak@1
|
418 if not frame[0] or type(frame.IsProtected) ~= "function" then
|
flickerstreak@1
|
419 AceHook:error("Bad argument #2 to `HookScript'. Expected frame.")
|
flickerstreak@1
|
420 end
|
flickerstreak@1
|
421 AceHook:argCheck(script, 3, "string")
|
flickerstreak@1
|
422 AceHook:argCheck(handler, 4, "function", "string", "nil")
|
flickerstreak@1
|
423 if frame:IsProtected() and protectedScripts[script] then
|
flickerstreak@1
|
424 AceHook:error("Cannot hook secure script %q.", script)
|
flickerstreak@1
|
425 end
|
flickerstreak@1
|
426 hookMethod(self, frame, script, handler, true, false)
|
flickerstreak@1
|
427 end
|
flickerstreak@1
|
428
|
flickerstreak@1
|
429 -- ("function") or (object, "method")
|
flickerstreak@1
|
430 function AceHook:IsHooked(obj, method)
|
flickerstreak@1
|
431 if type(obj) == "string" then
|
flickerstreak@1
|
432 if registry[self][obj] and actives[registry[self][obj]] then
|
flickerstreak@1
|
433 return true, handlers[registry[self][obj]]
|
flickerstreak@1
|
434 end
|
flickerstreak@1
|
435 else
|
flickerstreak@1
|
436 AceHook:argCheck(obj, 2, "string", "table")
|
flickerstreak@1
|
437 AceHook:argCheck(method, 3, "string")
|
flickerstreak@1
|
438 if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then
|
flickerstreak@1
|
439 return true, handlers[registry[self][obj][method]]
|
flickerstreak@1
|
440 end
|
flickerstreak@1
|
441 end
|
flickerstreak@1
|
442
|
flickerstreak@1
|
443 return false, nil
|
flickerstreak@1
|
444 end
|
flickerstreak@1
|
445
|
flickerstreak@1
|
446 -- ("function") or (object, "method")
|
flickerstreak@1
|
447 function AceHook:Unhook(obj, method)
|
flickerstreak@1
|
448 if type(obj) == "string" then
|
flickerstreak@1
|
449 unhookFunction(self, obj)
|
flickerstreak@1
|
450 else
|
flickerstreak@1
|
451 AceHook:argCheck(obj, 2, "string", "table")
|
flickerstreak@1
|
452 AceHook:argCheck(method, 3, "string")
|
flickerstreak@1
|
453 unhookMethod(self, obj, method)
|
flickerstreak@1
|
454 end
|
flickerstreak@1
|
455 end
|
flickerstreak@1
|
456
|
flickerstreak@1
|
457 function AceHook:UnhookAll()
|
flickerstreak@1
|
458 for key, value in pairs(registry[self]) do
|
flickerstreak@1
|
459 if type(key) == "table" then
|
flickerstreak@1
|
460 for method in pairs(value) do
|
flickerstreak@1
|
461 self:Unhook(key, method)
|
flickerstreak@1
|
462 end
|
flickerstreak@1
|
463 else
|
flickerstreak@1
|
464 self:Unhook(key)
|
flickerstreak@1
|
465 end
|
flickerstreak@1
|
466 end
|
flickerstreak@1
|
467 end
|
flickerstreak@1
|
468
|
flickerstreak@1
|
469 function AceHook:HookReport()
|
flickerstreak@1
|
470 DEFAULT_CHAT_FRAME:AddMessage("This is a list of all active hooks for this object:")
|
flickerstreak@1
|
471 if not next(registry[self]) then
|
flickerstreak@1
|
472 DEFAULT_CHAT_FRAME:AddMessage("No hooks")
|
flickerstreak@1
|
473 end
|
flickerstreak@1
|
474
|
flickerstreak@1
|
475 for key, value in pairs(registry[self]) do
|
flickerstreak@1
|
476 if type(value) == "table" then
|
flickerstreak@1
|
477 for method, uid in pairs(value) do
|
flickerstreak@1
|
478 DEFAULT_CHAT_FRAME:AddMessage(string.format("object: %s method: %q |cff%s|r%s", tostring(key), method, actives[uid] and "00ff00Active" or "ffff00Inactive", not self.hooks[key][method] and " |cff7f7fff-Secure-|r" or ""))
|
flickerstreak@1
|
479 end
|
flickerstreak@1
|
480 else
|
flickerstreak@1
|
481 DEFAULT_CHAT_FRAME:AddMessage(string.format("function: %q |cff%s|r%s", tostring(key), actives[value] and "00ff00Active" or "ffff00Inactive", not self.hooks[key] and " |cff7f7fff-Secure-|r" or ""))
|
flickerstreak@1
|
482 end
|
flickerstreak@1
|
483 end
|
flickerstreak@1
|
484 end
|
flickerstreak@1
|
485
|
flickerstreak@1
|
486 function AceHook:OnInstanceInit(object)
|
flickerstreak@1
|
487 if not object.hooks then
|
flickerstreak@1
|
488 object.hooks = new()
|
flickerstreak@1
|
489 end
|
flickerstreak@1
|
490 if not registry[object] then
|
flickerstreak@1
|
491 registry[object] = new()
|
flickerstreak@1
|
492 end
|
flickerstreak@1
|
493 end
|
flickerstreak@1
|
494
|
flickerstreak@1
|
495 AceHook.OnManualEmbed = AceHook.OnInstanceInit
|
flickerstreak@1
|
496
|
flickerstreak@1
|
497 function AceHook:OnEmbedDisable(target)
|
flickerstreak@1
|
498 self.UnhookAll(target)
|
flickerstreak@1
|
499 end
|
flickerstreak@1
|
500
|
flickerstreak@1
|
501 local function activate(self, oldLib, oldDeactivate)
|
flickerstreak@1
|
502 AceHook = self
|
flickerstreak@1
|
503
|
flickerstreak@1
|
504 self.handlers = oldLib and oldLib.handlers or {}
|
flickerstreak@1
|
505 self.registry = oldLib and oldLib.registry or {}
|
flickerstreak@1
|
506 self.scripts = oldLib and oldLib.scripts or {}
|
flickerstreak@1
|
507 self.actives = oldLib and oldLib.actives or {}
|
flickerstreak@1
|
508 self.onceSecure = oldLib and oldLib.onceSecure or {}
|
flickerstreak@1
|
509
|
flickerstreak@1
|
510 handlers = self.handlers
|
flickerstreak@1
|
511 registry = self.registry
|
flickerstreak@1
|
512 scripts = self.scripts
|
flickerstreak@1
|
513 actives = self.actives
|
flickerstreak@1
|
514 onceSecure = self.onceSecure
|
flickerstreak@1
|
515
|
flickerstreak@1
|
516 self:activate(oldLib, oldDeactivate)
|
flickerstreak@1
|
517
|
flickerstreak@1
|
518 if oldDeactivate then
|
flickerstreak@1
|
519 oldDeactivate(oldLib)
|
flickerstreak@1
|
520 end
|
flickerstreak@1
|
521 end
|
flickerstreak@1
|
522
|
flickerstreak@1
|
523 AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate)
|