1 /*
2  * Copyright (C) 2004-2020 ZNC, see the NOTICE file for details.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ZNC_MAIN_H
18 #define ZNC_MAIN_H
19 
20 #include <znc/zncconfig.h>
21 #include <znc/version.h>
22 
23 extern bool ZNC_NO_NEED_TO_DO_ANYTHING_ON_MODULE_CALL_EXITER;
24 #define NOTHING &ZNC_NO_NEED_TO_DO_ANYTHING_ON_MODULE_CALL_EXITER
25 
26 #define ALLMODULECALL(macFUNC, macEXITER)                                      \
27     do {                                                                       \
28         CModules& GMods = CZNC::Get().GetModules();                            \
29         bool bAllExit = false;                                                 \
30         if (GMods.macFUNC) {                                                   \
31             bAllExit = true;                                                   \
32         } else {                                                               \
33             const map<CString, CUser*>& mUsers = CZNC::Get().GetUserMap();     \
34             map<CString, CUser*>::const_iterator it;                           \
35             for (it = mUsers.begin(); it != mUsers.end(); ++it) {              \
36                 CModules& UMods = it->second->GetModules();                    \
37                 if (UMods.macFUNC) {                                           \
38                     bAllExit = true;                                           \
39                     break;                                                     \
40                 }                                                              \
41                 const vector<CIRCNetwork*>& mNets = it->second->GetNetworks(); \
42                 vector<CIRCNetwork*>::const_iterator it2;                      \
43                 for (it2 = mNets.begin(); it2 != mNets.end(); ++it2) {         \
44                     CModules& NMods = (*it2)->GetModules();                    \
45                     if (NMods.macFUNC) {                                       \
46                         bAllExit = true;                                       \
47                         break;                                                 \
48                     }                                                          \
49                 }                                                              \
50                 if (bAllExit) break;                                           \
51             }                                                                  \
52         }                                                                      \
53         if (bAllExit) *macEXITER = true;                                       \
54     } while (false)
55 
56 #define _GLOBALMODULECALL(macFUNC, macUSER, macNETWORK, macCLIENT, macEXITER) \
57     do {                                                                      \
58         CModules& GMods = CZNC::Get().GetModules();                           \
59         CUser* pOldGUser = GMods.GetUser();                                   \
60         CIRCNetwork* pOldGNetwork = GMods.GetNetwork();                       \
61         CClient* pOldGClient = GMods.GetClient();                             \
62         GMods.SetUser(macUSER);                                               \
63         GMods.SetNetwork(macNETWORK);                                         \
64         GMods.SetClient(macCLIENT);                                           \
65         if (GMods.macFUNC) {                                                  \
66             GMods.SetUser(pOldGUser);                                         \
67             GMods.SetNetwork(pOldGNetwork);                                   \
68             GMods.SetClient(pOldGClient);                                     \
69             *macEXITER = true;                                                \
70         }                                                                     \
71         GMods.SetUser(pOldGUser);                                             \
72         GMods.SetNetwork(pOldGNetwork);                                       \
73         GMods.SetClient(pOldGClient);                                         \
74     } while (false)
75 
76 #define _USERMODULECALL(macFUNC, macUSER, macNETWORK, macCLIENT, macEXITER) \
77     do {                                                                    \
78         bool bGlobalExited = false;                                         \
79         _GLOBALMODULECALL(macFUNC, macUSER, macNETWORK, macCLIENT,          \
80                           &bGlobalExited);                                  \
81         if (bGlobalExited) {                                                \
82             *macEXITER = true;                                              \
83             break;                                                          \
84         }                                                                   \
85         if (macUSER != nullptr) {                                           \
86             CModules& UMods = macUSER->GetModules();                        \
87             CIRCNetwork* pOldUNetwork = UMods.GetNetwork();                 \
88             CClient* pOldUClient = UMods.GetClient();                       \
89             UMods.SetNetwork(macNETWORK);                                   \
90             UMods.SetClient(macCLIENT);                                     \
91             if (UMods.macFUNC) {                                            \
92                 UMods.SetNetwork(pOldUNetwork);                             \
93                 UMods.SetClient(pOldUClient);                               \
94                 *macEXITER = true;                                          \
95             }                                                               \
96             UMods.SetNetwork(pOldUNetwork);                                 \
97             UMods.SetClient(pOldUClient);                                   \
98         }                                                                   \
99     } while (false)
100 
101 #define NETWORKMODULECALL(macFUNC, macUSER, macNETWORK, macCLIENT, macEXITER) \
102     do {                                                                      \
103         bool bUserExited = false;                                             \
104         _USERMODULECALL(macFUNC, macUSER, macNETWORK, macCLIENT,              \
105                         &bUserExited);                                        \
106         if (bUserExited) {                                                    \
107             *macEXITER = true;                                                \
108             break;                                                            \
109         }                                                                     \
110         if (macNETWORK != nullptr) {                                          \
111             CModules& NMods = macNETWORK->GetModules();                       \
112             CClient* pOldNClient = NMods.GetClient();                         \
113             NMods.SetClient(macCLIENT);                                       \
114             if (NMods.macFUNC) {                                              \
115                 NMods.SetClient(pOldNClient);                                 \
116                 *macEXITER = true;                                            \
117             }                                                                 \
118             NMods.SetClient(pOldNClient);                                     \
119         }                                                                     \
120     } while (false)
121 
122 #define GLOBALMODULECALL(macFUNC, macEXITER) \
123     _GLOBALMODULECALL(macFUNC, nullptr, nullptr, nullptr, macEXITER)
124 
125 #define USERMODULECALL(macFUNC, macUSER, macCLIENT, macEXITER) \
126     _USERMODULECALL(macFUNC, macUSER, nullptr, macCLIENT, macEXITER)
127 
128 /** @mainpage
129  *  Welcome to the API documentation for ZNC.
130  *
131  *  To write your own module, you should start with writing a new class which
132  *  inherits from CModule. Use #MODCONSTRUCTOR for the module's constructor and
133  *  call #MODULEDEFS at the end of your source file.
134  *  Congratulations, you just wrote your first module. <br>
135  *  For global modules, the procedure is similar. Instead of #MODULEDEFS call
136  *  #GLOBALMODULEDEFS.
137  *
138  *  If you want your module to actually do something, you should override some
139  *  of the hooks from CModule. These are the functions whose names start with
140  *  "On". They are called when the associated event happens.
141  *
142  *  Feel free to also look at existing modules.
143  */
144 
145 #endif  // !ZNC_MAIN_H
146