├── LICENSE ├── README.md ├── admin ├── ajax.html ├── branding.html ├── bulkprotect.html ├── configuration.html ├── index.html ├── login.html ├── support.html └── update.html ├── assets ├── bootstrap.min.css ├── jquery.js ├── module.js └── style.css ├── configuration.conf.new ├── directadminapi.conf.new ├── hooks ├── _reseller_img.html ├── _reseller_txt.html ├── _user_img.html ├── _user_txt.html ├── admin_img.html ├── admin_txt.html ├── reseller_img.html ├── reseller_txt.html ├── scripts │ ├── domain_create_post.php │ ├── domain_destroy_post.php │ ├── domain_pointer_create_post.php │ └── domain_pointer_destroy_post.php ├── user_img.html └── user_txt.html ├── images ├── ajax-loader.gif ├── link.jpg └── logo.jpg ├── lib ├── Ajax.php ├── Branding.php ├── Configuration.php ├── DirectAdmin_API.php ├── DirectAdmin_DNS.php ├── DirectAdmin_Domain.php ├── DirectAdmin_HTTPSocket.php ├── HTTPSocket.php ├── Menu.php ├── SpamExperts_API.php └── plugin.php ├── plugin.conf.new ├── reseller ├── ajax.html ├── index.html └── login.html ├── scripts ├── getconfig ├── hooks │ ├── domain_create_post.sh │ ├── domain_destroy_post.sh │ ├── domain_pointer_create_post.sh │ └── domain_pointer_destroy_post.sh ├── install.sh ├── uninstall.sh └── update.sh └── user ├── ajax.html ├── index.html └── login.html /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Code Climate](https://codeclimate.com/github/SpamExperts/directadmin-addon/badges/gpa.svg)](https://codeclimate.com/github/SpamExperts/directadmin-addon) [![Issue Count](https://codeclimate.com/github/SpamExperts/directadmin-addon/badges/issue_count.svg)](https://codeclimate.com/github/SpamExperts/directadmin-addon) 2 | 3 | # DirectAdmin addon 4 | An add-on for [DirectAdmin control panel](http://directadmin.com) providing integration with SpamExperts services. 5 | 6 | ## Documentation 7 | Documentation can be found [here](https://documentation.n-able.com/spamexperts/userguide/Content/Integration/directadmin-addon.htm "SpamExperts' Knowledge base") 8 | 9 | ### Using DirectAdmin login keys 10 | 11 | To secure the add-on setup it's recommended to use [DirectAdmin Login Keys](https://www.directadmin.com/features.php?id=1298) for all communications with DirectAdmin API. In order to use a Login Key the following steps have to be performed. 12 | 13 | #### Login Keys must be enabled 14 | 15 | Check your `directadmin.conf` and make sure that Login Keys are enabled: 16 | ``` 17 | login_keys=1 18 | ``` 19 | Also make sure that the user that you're going to use for API communications does not have that setting overriden. F.i. in that's the `admin`, the `login_keys` value in `/usr/local/directadmin/data/users/admin/user.conf` should be `1` or `On`. 20 | 21 | If you are making chnages to the configuration file(s) don't forget to reload the `directadmin` service (e.g. `service directadmin restart`). 22 | 23 | #### Login Key creation 24 | 25 | 1. Log in as the user that you're going to use for the DirectAdmin API communication (it's `admin` in our case); 26 | 1. Go to `http://your.directadmin.host:2222/CMD_LOGIN_KEYS` 27 | 1. Create a new Login Key 28 | 1. Pick a meaning Key Name 29 | 1. Use hard-to-guess Key Value 30 | 1. Allow the following commands: 31 | 1. `CMD_API_ALL_USER_USAGE` 32 | 1. `CMD_API_DNS_ADMIN` 33 | 1. `CMD_API_DNS_MX` 34 | 1. `CMD_API_SHOW_USER_USAGE` 35 | 1. `CMD_API_SYSTEM_INFO` 36 | 1. Allow your localhost IP address only 37 | 38 | #### Login Key utilization 39 | 40 | Once the key is ready use it as the `password` configuration directive value in the `directadminapi.conf` file. 41 | 42 | #### Troubleshooting 43 | 44 | If you experience issues when using a Login Key it may be useful to turn DirectAdmin into a debug mode and troubleshoot the issue. More info on this can be found [here](https://help.directadmin.com/item.php?id=293). 45 | -------------------------------------------------------------------------------- /admin/ajax.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | _getSpamExpertsApi(); 11 | $res = $api->getDomainStatus( $this->_params['domain'] ); 12 | $msg = $res ? 'This domain is present in the filter.' : 'This domain is not present in the filter.'; 13 | $msgColor = $res ? 'green' : 'red'; 14 | $this->sendResponse(true, ''.$msg.'', array( 15 | 'domainstatus' => $res ? 1 : 0 16 | )); 17 | 18 | } catch (Exception $e){ 19 | $this->sendResponse(false, $e->getMessage(), array( 20 | 'domainstatus' => 0 21 | )); 22 | 23 | } 24 | } 25 | 26 | public function call_login(){ 27 | try { 28 | $conf = new Configuration(); 29 | $api = $this->_getSpamExpertsApi(); 30 | 31 | if ($conf->get('add_domain_during_login')){ 32 | $api->protectDomains( array($this->_params['domain']), $conf, new DirectAdmin_API() ); 33 | } 34 | 35 | $res = $api->login( $this->_params['domain'] ); 36 | $msg = $res ? 'Logging for '.$domain.' successful' : 'Unable to get login token for ' . $domain; 37 | $this->sendResponse($res ? true : false, $msg, array( 38 | 'token' => $res, 39 | 'url' => $conf->get('spampanel_url') . '/?authticket=' . $res 40 | )); 41 | 42 | } catch (Exception $e){ 43 | $this->sendResponse(false, $e->getMessage()); 44 | } 45 | } 46 | 47 | public function call_toggleDomains(){ 48 | try { 49 | $api = $this->_getSpamExpertsApi(); 50 | $this->sendResponse(true, 'OK', array( 51 | 'results' => $api->toggleDomains( $this->_params['domains'] ) 52 | )); 53 | 54 | } catch (Exception $e){ 55 | $this->sendResponse(false, $e->getMessage()); 56 | 57 | } 58 | } 59 | 60 | public function call_protectDomains(){ 61 | try { 62 | $api = $this->_getSpamExpertsApi(); 63 | $this->sendResponse(true, 'OK', array( 64 | 'results' => $api->protectDomains( $this->_params['domains'], new Configuration(), new DirectAdmin_API() ) 65 | )); 66 | 67 | } catch (Exception $e){ 68 | $this->sendResponse(false, $e->getMessage()); 69 | } 70 | } 71 | 72 | public function call_unprotectDomains(){ 73 | try { 74 | $api = $this->_getSpamExpertsApi(); 75 | $this->sendResponse(true, 'OK', array( 76 | 'results' => $api->unprotectDomains( $this->_params['domains'], new Configuration(), new DirectAdmin_API() ) 77 | )); 78 | 79 | } catch (Exception $e){ 80 | $this->sendResponse(false, $e->getMessage()); 81 | } 82 | } 83 | 84 | public function call_listDaDomains(){ 85 | $conf = new Configuration(); 86 | 87 | $processExtraDomains = $conf->get('process_addon_and_parked_domains'); 88 | 89 | try { 90 | $api = new DirectAdmin_API(); 91 | $this->sendResponse(true, 'OK', array( 92 | 'domains' => $api->getAllDomains(array( 93 | 'page' => 1, 94 | 'limit' => 10000, 95 | 'includePointers' => !empty($processExtraDomains), 96 | )) 97 | )); 98 | 99 | } catch (Exception $e){ 100 | $this->sendResponse(false, $e->getMessage()); 101 | } 102 | } 103 | 104 | public function call_updateBulkprotectDate(){ 105 | try { 106 | $conf = new Configuration(); 107 | $conf->set('bulkprotect_date', date("Y-m-d H:i:s")); 108 | $res = $conf->save(); 109 | 110 | $this->sendResponse($res, $res ? 'OK' : 'Error during saving'); 111 | 112 | } catch (Exception $e){ 113 | $this->sendResponse(false, $e->getMessage()); 114 | } 115 | } 116 | 117 | public function call_runDiagnostic(){ 118 | $pluginPath = dirname(__FILE__) . '/../'; 119 | try { 120 | $conf = new Configuration(); 121 | $DA = new DirectAdmin_API(); 122 | 123 | try { 124 | $info = $DA->getSystemInfo(); 125 | $daVersion = trim(explode('|', $info['directadmin'])[0]); 126 | $daAPI = (bool)$info; 127 | } catch (Exception $e){ 128 | $daAPI = false; 129 | $daVersion = null; 130 | } 131 | try { 132 | $spamExp = $this->_getSpamExpertsApi(); 133 | $spamAPI = is_bool($spamExp->getDomainStatus('testdomain.com')); 134 | } catch (Exception $e){ 135 | $spamAPI = strpos($e->getMessage(), 'testdomain.com') ? true : false; 136 | } 137 | 138 | } catch (Exception $e){ 139 | $this->sendResponse(false, $e->getMessage()); 140 | } 141 | 142 | $phpVersion = phpversion(); 143 | $confPerm = substr(sprintf('%o', fileperms($pluginPath . 'configuration.conf')), -4); 144 | $diradminPerm = substr(sprintf('%o', fileperms($pluginPath . 'directadminapi.conf')), -4); 145 | $hookDomainCrea = file_exists($pluginPath . '../../scripts/custom/domain_create_post.sh'); 146 | $hookDomainRemo = file_exists($pluginPath . '../../scripts/custom/domain_destroy_post.sh'); 147 | 148 | $this->sendResponse(true, 'OK', array( 149 | 'phpversion' => version_compare($phpVersion, "5.3") != -1 ? 1 : 0, 150 | 'phpexec' => function_exists("exec"), 151 | 'confPerm' => $confPerm == "0660" ? 1 : 0, 152 | 'diradminPerm' => $diradminPerm == "0660" ? 1 : 0, 153 | 'hookDomainCrea'=> $hookDomainCrea ? 1 : 0, 154 | 'hookDomainRemo'=> $hookDomainRemo ? 1 : 0, 155 | 'daVersion' => isset($daVersion) ? (version_compare($daVersion, "1.43.3") != -1 ? 1 : 0) : 1, 156 | 'daAPI' => $daAPI ? 1 : 0, 157 | 'spamAPI' => $spamAPI ? 1 : 0, 158 | )); 159 | } 160 | 161 | 162 | private function _getSpamExpertsApi(){ 163 | $conf = new Configuration(); 164 | 165 | return new SpamExperts_API( 166 | $conf->get('api_hostname'), 167 | $conf->get('api_username'), 168 | $conf->get('api_password') 169 | ); 170 | } 171 | 172 | } 173 | 174 | $ajax = new Ajax_SpamExperts(); 175 | $ajax->processRequest( getParams() ); 176 | -------------------------------------------------------------------------------- /admin/branding.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | render('branding'); 8 | 9 | $brandNameFlashMessage = ''; 10 | $brandLogoFlashMessage = ''; 11 | 12 | $brand = new Branding(); 13 | $params = getPOSTValues(); 14 | 15 | if(!empty($params['newName'])){ 16 | $response = $brand->setBrandName($params['newName']); 17 | if($response['status']=='success'){ 18 | $brandNameFlashMessage = '
Success! '.$response['msg'].'
'; 19 | } else { 20 | $brandNameFlashMessage = '
Error occured! '.$response['msg'].'
'; 21 | } 22 | } 23 | if(!empty($params['newLogo'])){ 24 | if(!$brand->validateLogo($params['newLogo'])){ 25 | $brandLogoFlashMessage = '
Ivalid File! Logo must have jpeg or jpg extension and cannot have width more than ' . $brand->getMaxLogoWidth(). 'px and height ' . $brand->getMaxLogoHeight() . 'px.
'; 26 | }elseif($brand->setBrandLogo($params['newLogo'])){ 27 | $brandLogoFlashMessage = '
Success! Logo changed successfully. Please force browser to reload cache to see changes.
'; 28 | } else { 29 | $brandLogoFlashMessage = '
Error occured! Logo changing failure!.
'; 30 | } 31 | } 32 | ?> 33 | 34 |
35 |
36 |
37 | 38 |
39 | On this page you can change how the addon looks for the customers. 40 |
41 | 42 |
43 | <?php echo $brand->getBrandName(); ?> 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 |

Setup new branding:

52 |
53 |
54 | 55 |
56 | 57 |
58 |
59 | 60 |
61 | 62 |
63 |
64 |
65 |
66 | 67 |
68 | -------------------------------------------------------------------------------- /admin/bulkprotect.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | render('bulkprotect'); 8 | 9 | $conf = new Configuration(); 10 | 11 | ?> 12 | 13 |
14 | 15 |
16 | get("bulkprotect_date")) { ?> 17 |
18 | You have not executed a bulk protect yet.
19 | This is recommended to protect all domains on this server. 20 |
21 | 22 | 23 |
24 | On this page you can add all current domains to the spam filter. 25 | Depending on the settings it may (or may not) execute certain actions. 26 | It is generally not required to run this more than once after the installation. 27 | Running bulk protect is usually only necessary after the first installation. 28 |
29 | 30 |
31 | Bulk protect has been executed last at: get("bulkprotect_date") ? $conf->get("bulkprotect_date") : 'never'; ?> 32 |
33 | 34 | Execute Bulk Protect 35 |
36 | 37 | 101 | 102 |
103 | 104 | 105 | 106 | 206 | -------------------------------------------------------------------------------- /admin/configuration.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | render('configuration'); 8 | 9 | $flashMessage = ''; 10 | 11 | try { 12 | $conf = new Configuration(); 13 | 14 | $params = getPOSTValues(); 15 | if (isset($params['spampanel_url'])){ 16 | $conf->set('spampanel_url', $params['spampanel_url']); 17 | $conf->set('api_hostname', $params['api_hostname']); 18 | $conf->set('api_username', $params['api_username']); 19 | $conf->set('api_password', $params['api_password']); 20 | $conf->set('primary_mx', $params['primary_mx']); 21 | $conf->set('primary_mx_priority', $params['primary_mx_priority']); 22 | $conf->set('secondary_mx', $params['secondary_mx']); 23 | $conf->set('secondary_mx_priority', $params['secondary_mx_priority']); 24 | $conf->set('tertiary_mx', $params['tertiary_mx']); 25 | $conf->set('tertiary_mx_priority', $params['tertiary_mx_priority']); 26 | $conf->set('automatically_add_domains', isset($params['automatically_add_domains']) ? 1 : 0); 27 | $conf->set('automatically_delete_domains', isset($params['automatically_delete_domains']) ? 1 : 0); 28 | $conf->set('automatically_change_mx', isset($params['automatically_change_mx']) ? 1 : 0); 29 | $conf->set('process_addon_and_parked_domains', isset($params['process_addon_and_parked_domains']) ? 1 : 0); 30 | $conf->set('use_existing_mx_as_routes', isset($params['use_existing_mx_as_routes']) ? 1 : 0); 31 | $conf->set('do_not_protect_remote_domains', isset($params['do_not_protect_remote_domains']) ? 1 : 0); 32 | $conf->set('add_domain_during_login', isset($params['add_domain_during_login']) ? 1 : 0); 33 | 34 | $conf->save(); 35 | $conf = new Configuration(); 36 | $flashMessage = '
Configuration has been saved.
'; 37 | } 38 | 39 | } catch (Exception $e){ 40 | echo '
'.$e->getMessage().'
'; 41 | die(); 42 | } 43 | 44 | ?> 45 | 46 |
47 |
48 | 49 |
50 | On this page you can configure the admin settings of the addon. 51 | You can hover over the options to see more detailed information about what they do. 52 |
53 | 54 |
55 |
56 | 57 |
58 | 59 |
60 |
61 |
62 | 63 |
64 | 65 |
66 |
67 |
68 | 69 |
70 | 71 |
72 |
73 |
74 | 75 |
76 | 77 |
78 |
79 |
80 | 81 |
82 | 83 |
84 |
85 | 86 |
87 |
88 |
89 | 90 |
91 | 92 |
93 |
94 | 95 |
96 |
97 |
98 | 99 |
100 | 101 |
102 |
103 | 104 |
105 |
106 |
107 |
108 |
109 | 113 |
114 |
115 |
116 |
117 |
118 |
119 | 123 |
124 |
125 |
126 |
127 |
128 |
129 | 133 |
134 |
135 |
136 |
137 |
138 |
139 | 143 |
144 |
145 |
146 |
147 |
148 |
149 | 153 |
154 |
155 |
156 |
157 |
158 |
159 | 163 |
164 |
165 |
166 | 167 |
168 |
169 |
170 | 174 |
175 |
176 |
177 | 178 |
179 |
180 | 181 |
182 |
183 |
184 |
185 | -------------------------------------------------------------------------------- /admin/index.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | render('domain_list'); 7 | 8 | $page = getParam('page', 1); 9 | $limit = getParam('limit', 100); 10 | $searchUsername = getParam('searchUsername', ''); 11 | $searchDomain = getParam('searchDomain', ''); 12 | $conf = new Configuration(); 13 | 14 | $processExtraDomains = $conf->get('process_addon_and_parked_domains'); 15 | 16 | try { 17 | $api = new DirectAdmin_API(); 18 | $domains = $api->getAllDomains(array( 19 | 'page' => $page, 20 | 'limit' => $limit, 21 | 'searchUsername'=> $searchUsername, 22 | 'searchDomain' => $searchDomain, 23 | 'includePointers' => !empty($processExtraDomains), 24 | )); 25 | } catch (Exception $e){ 26 | echo '
'.$e->getMessage().'
'; 27 | die(); 28 | } 29 | 30 | ?> 31 | 32 |
33 |
34 | 35 |
36 |
37 | 38 |
39 |
40 | 41 |
42 | 43 |
44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 |
DomainUsernamePresent in FilterToggle ProtectionLogin
pointsto ? 'P: ' : '') . $domain->domain; ?>username; ?>Check statusToggle ProtectionLogin
No domains found.
74 | 75 | $searchUsername, 78 | 'searchDomain' => $searchDomain, 79 | )); 80 | ?> 81 | 82 | 83 | 84 | 85 |
86 | Progress: 87 |
88 |
89 | 90 |
91 |
92 |
93 |
94 | 95 |
96 | 97 | 230 | -------------------------------------------------------------------------------- /admin/login.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | render(''); 8 | 9 | $domain = getParam('domain'); 10 | 11 | if (!$domain) { 12 | echo '
No domain provided
'; 13 | die(); 14 | } 15 | 16 | try { 17 | $conf = new Configuration(); 18 | $api = new SpamExperts_API($conf->get('api_hostname'), $conf->get('api_username'), $conf->get('api_password')); 19 | 20 | if ($conf->get('add_domain_during_login')) { 21 | $api->protectDomains(array($domain), $conf, new DirectAdmin_API()); 22 | } 23 | 24 | $res = $api->login($domain); 25 | $msg = $res ? 'Logging for ' . $domain . ' successful. Please wait...' : 'Unable to get login token for ' . $domain; 26 | 27 | } catch (Exception $e) { 28 | echo '
' . $e->getMessage() . '
'; 29 | die(); 30 | } 31 | 32 | ?> 33 | 34 |
Please Wait...
35 | 36 | -------------------------------------------------------------------------------- /admin/support.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | render('support'); 8 | 9 | try { 10 | $mainconf = new Configuration('plugin.conf'); 11 | $pluginVersion = $mainconf->get("version"); 12 | } catch (Exception $e){ 13 | $pluginVersion = $e->getMessage(); 14 | } 15 | try { 16 | $DA = new DirectAdmin_API(); 17 | $info = $DA->getSystemInfo(); 18 | 19 | } catch (Exception $e){ 20 | $info['directadmin'] = ''; 21 | } 22 | $processUser = trim(`whoami`); 23 | $logsPath['user'] = dirname(dirname(__FILE__)) . "/logs/prospamfilter_{$processUser}.log"; 24 | $logsPath['hooks'] = dirname(dirname(__FILE__)) . "/logs/prospamfilter_root.log"; 25 | ?> 26 | 27 |
28 |

Information

29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 49 | 50 |
ControlpanelDirectAdmin
PHP version
Addon version
Debug logs, if enabled
(run by SSH as root)
46 |
47 | 48 |
51 | 52 |

Diagnostics

53 | 54 | In case you have issues with the addon, you can run a diagnostics on your installation prior to contacting support. 55 | 56 |
57 | Run diagnostics 58 |
59 | 60 | 92 |
93 | 94 | 120 | -------------------------------------------------------------------------------- /admin/update.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | render('update'); 8 | 9 | $mainconf = new Configuration('plugin.conf'); 10 | ?> 11 | 12 |
13 |

14 | On this page you can manually update the addon to the latest version. 15 |

16 | 17 | You are using version: get("version"); ?> 18 |
19 |
20 |
21 | Click to update 22 |
23 | -------------------------------------------------------------------------------- /assets/module.js: -------------------------------------------------------------------------------- 1 | function parseAjaxResponse(res){ 2 | var st = res.indexOf("[AJAX_RESPONSE]") + 15; 3 | var en = res.indexOf("[/AJAX_RESPONSE]"); 4 | var j = res.substring(st, en); 5 | return jQuery.parseJSON( j ); 6 | } 7 | 8 | /** 9 | * type string success|info|warning|danger 10 | */ 11 | function addFlashMsg(type, msg, clear){ 12 | if (clear) 13 | $('#flash_messages').html('
'+msg+'
'); 14 | else 15 | $('#flash_messages').append('
'+msg+'
'); 16 | } 17 | 18 | function clearFlashMsgs(type, msg){ 19 | $('#flash_messages').html(''); 20 | } 21 | 22 | function updateProgressBar($barContainer, percent){ 23 | if (percent > 100) 24 | percent = 100; 25 | $barContainer.show().find('.progress-bar').css('width', percent+'%'); 26 | $barContainer.find('span').html(percent + '%'); 27 | } 28 | 29 | function ucfirst(str){ 30 | str += ''; 31 | var f = str.charAt(0).toUpperCase(); 32 | return f + str.substr(1); 33 | } 34 | 35 | $(document).ready(function(){ 36 | $('.checkAll').change(function(){ 37 | var checked = $(this).is(':checked'); 38 | $(this).closest('table').find('input[type=checkbox]').prop('checked', checked); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /assets/style.css: -------------------------------------------------------------------------------- 1 | /* BASE STYLES */ 2 | 3 | .moduleContent {max-width: 780px;padding:5px;} 4 | 5 | .paginationContainer {margin:10px 5px;} 6 | .paginationLeft {float:left;width:200px;} 7 | .paginationRight {float:right;overflow:hidden;text-align:right;} 8 | .paginationItem {border: 1px solid silver;background: #ededed;padding: 2px 5px;margin-right: 2px;display: inline-block;} 9 | .paginationItem.current {font-weight:bold;border-color: gray;} 10 | 11 | .alert {padding:7px;margin-bottom: 20px;border: 1px solid transparent;border-radius: 4px;} 12 | .alert-success {color: #3c763d;background-color: #dff0d8;border-color: #d6e9c6;} 13 | .alert-info {color: #31708f;background-color: #d9edf7;border-color: #bce8f1;} 14 | .alert-warning {color: #8a6d3b;background-color: #fcf8e3;border-color: #faebcc;} 15 | .alert-danger {color: #a94442;background-color: #f2dede;border-color: #ebccd1;} 16 | 17 | .simple-success {color: green;font-weight: bold;} 18 | .simple-error {color: red;font-weight: bold;} 19 | 20 | .modnav {margin-bottom:15px; margin-left:5px;} 21 | 22 | .modulename {margin:15px 0;} 23 | .modulename a {font-size: 25px;} 24 | .modulename a:link {color:#08c; text-decoration:none;} 25 | 26 | .progressContainer {margin:20px 0;display:none;} 27 | .progress-bar .sr-only {position:static !important;line-height: 20px;} 28 | 29 | 30 | /* MODULE STYLES */ 31 | 32 | #domainsstats td, #domainsstats th {text-align:center;} 33 | #domainsstats td {font-weight:bold;} 34 | 35 | label.branding{ 36 | margin-top:13px; 37 | } 38 | 39 | p.branding{ 40 | font-size: 15px; 41 | margin-top: 15px; 42 | margin-left: 10px; 43 | } 44 | 45 | div.branding{ 46 | margin: 5px 0 15px 0; 47 | } 48 | 49 | p.headTitle{ 50 | font-size: 30px; 51 | margin-left:3%; 52 | margin-bottom:4%; 53 | margin-top:4%; 54 | font-family: 'Oswald', sans-serif; 55 | font-weight: bold; 56 | } 57 | 58 | div.brandLogo{ 59 | padding: 0 15px 15px 15px; 60 | margin-bottom: 15px; 61 | border-bottom: 1px solid #ccc; 62 | } 63 | -------------------------------------------------------------------------------- /configuration.conf.new: -------------------------------------------------------------------------------- 1 | ; URL to Spampanel a web UI for the control panel 2 | ;spampanel_url="" 3 | 4 | ; Spampanel API hostname, the URL where to send API requests for the spamfilter options/domains management 5 | ;api_hostname="" 6 | 7 | ; Username to communicate with the Spampanel API 8 | ;api_username="" 9 | 10 | ; Password to communicate with the Spampanel API 11 | ;api_password="" 12 | 13 | ; Primary hostname or an IP address of the spamfiltering cluster 14 | ;primary_mx="" 15 | 16 | ; Primary MX priority 17 | ;primary_mx_priority="" 18 | 19 | ; Secondary hostname or an IP address of the spamfiltering cluster 20 | ;secondary_mx="" 21 | 22 | ; Secondary MX priority 23 | ;secondary_mx_priority="" 24 | 25 | ; Tertiary hostname or an IP address of the spamfiltering cluster 26 | ;tertiary_mx="" 27 | 28 | ; Tertiary MX priority 29 | ;tertiary_mx_priority="" 30 | 31 | ; Automatically add domains to the SpamFilter (active by default) determines 32 | ; should the plugin add new domains into the spamfilter automatically or not. 33 | ; 1 or 0 34 | ;automatically_add_domains=1 35 | 36 | ; Automatically delete domains from the SpamFilter (checkbox, active by default) determines 37 | ; should the plugin remove obsolete domains from the spamfilter automatically or not. 38 | ; 1 or 0 39 | ;automatically_delete_domains=1 40 | 41 | ; Automatically change the MX records for domains (active by default) determines 42 | ; should the plugin change domains’ MX records on add/remove events. In 43 | ; case of this option is active, the plugin will set up values of the “Primary MX”, 44 | ; “Secondary MX” and “Secondary MX” as a domain’s new MX records after the domain is successfully added into the spamfilter 45 | ; 1 or 0 46 | ;automatically_change_mx=1 47 | 48 | ; Process addon and parked domains (inactive by default) determines 49 | ; should the plugin also process secondary domains or not 50 | ; 1 or 0 51 | ;process_addon_and_parked_domains=0 52 | 53 | ; Use existing MX records as routes in the spamfilter (active by default) each 54 | ; domain in the spamfilter has at least one destination route a hostname where all the 55 | ; clean email should be delivered and it is reasonable to use actual MX records on a 56 | ; domain’s MX records switching as a destination for the clean email. This checkbox 57 | ; enables or disables such behavior 58 | ; 1 or 0 59 | ;use_existing_mx_as_routes=1 60 | 61 | ; Do not protect remote domains (active by default) if this checkbox is enabled 62 | ; all the “remote” domains (domains which don’t DNShost at this server) should be skipped 63 | ; 1 or 0 64 | ;do_not_protect_remote_domains=1 65 | 66 | ; Add the domain to the spamfilter during login if it does not exist (active by default) if this option is active, 67 | ; the plugin should check a domain’s presence in the spamfilter upon login attempt and try to add it in case of it’s still missing there. 68 | ; 1 or 0 69 | ;add_domain_during_login=1 70 | -------------------------------------------------------------------------------- /directadminapi.conf.new: -------------------------------------------------------------------------------- 1 | ; Setup values needed to DirectAdmin API 2 | host=127.0.0.1 3 | port=2222 4 | ; 1 or 0 5 | secure=0 6 | username=admin 7 | password=123 -------------------------------------------------------------------------------- /hooks/_reseller_img.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /hooks/_reseller_txt.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /hooks/_user_img.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /hooks/_user_txt.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /hooks/admin_img.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter 2 | -------------------------------------------------------------------------------- /hooks/admin_txt.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /hooks/reseller_img.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /hooks/reseller_txt.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /hooks/scripts/domain_create_post.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | $domain = $argv[1]; 30 | if (!$domain) 31 | die('Error: empty domain'); 32 | 33 | include_once __DIR__ . '/../../lib/plugin.php'; 34 | 35 | $conf = new Configuration(); 36 | if ($conf->get('automatically_add_domains')){ 37 | 38 | // auto-adding to spamexperts 39 | echo 'Adding domain '.$domain.' to SpamExperts
'; 40 | 41 | $hostname = $conf->get('api_hostname'); 42 | $username = $conf->get('api_username'); 43 | $password = $conf->get('api_password'); 44 | 45 | // no credentials in configuration 46 | if (!$hostname || !$username || !$password) 47 | die('Unable to add domain to SpamExperts - check credentials on plugin\'s configuration'); 48 | 49 | $api = new SpamExperts_API($hostname, $username, $password); 50 | $res = $api->protectDomains(array($domain), $conf, new DirectAdmin_API()); 51 | 52 | if (isset($res[$domain]['result'])){ 53 | 54 | die( $res[$domain]['result'] ? 'Domain has been added to the SpamExperts' : 'Error during adding domain to the SpamExperts' ); 55 | 56 | } else { 57 | die('Error during adding domain to the SpamExperts'); 58 | } 59 | 60 | } else { 61 | // auto-adding to spamexperts disabled -> no action 62 | } 63 | -------------------------------------------------------------------------------- /hooks/scripts/domain_destroy_post.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | $domain = $argv[1]; 30 | if (!$domain) 31 | die('Error: empty domain'); 32 | 33 | include_once __DIR__ . '/../../lib/plugin.php'; 34 | 35 | $conf = new Configuration(); 36 | if ($conf->get('automatically_delete_domains')){ 37 | 38 | // auto-adding to spamexperts 39 | echo 'Deleting domain '.$domain.' from the SpamExperts
'; 40 | 41 | $hostname = $conf->get('api_hostname'); 42 | $username = $conf->get('api_username'); 43 | $password = $conf->get('api_password'); 44 | 45 | // no credentials in configuration 46 | if (!$hostname || !$username || !$password) 47 | die('Unable to delete domain from the SpamExperts - check credentials on plugin\'s configuration'); 48 | 49 | $api = new SpamExperts_API($hostname, $username, $password); 50 | 51 | // we should remove domain pointers when a domain is removed from DA 52 | $daApi = new DirectAdmin_API; 53 | 54 | $allDomains = $daApi->getAllDomains(array( 55 | 'searchDomain' => $domain, 56 | 'includePointers' => true, 57 | )); 58 | 59 | $domains = array(); 60 | foreach ($allDomains as $addon => $props) { 61 | if ($props->pointsto == $domain) { 62 | $domains[] = $addon; 63 | } 64 | } 65 | 66 | $domains[] = $domain; 67 | 68 | $res = $api->unprotectDomains($domains, $conf, $daApi); 69 | 70 | if (isset($res[$domain]['result'])){ 71 | 72 | die( $res[$domain]['result'] ? 'Domain has been deleted from the SpamExperts' : 'Error during deleting domain from the SpamExperts' ); 73 | 74 | } else { 75 | die('Error during adding domain to the SpamExperts'); 76 | } 77 | 78 | } else { 79 | // auto-adding to spamexperts disabled -> no action 80 | } 81 | -------------------------------------------------------------------------------- /hooks/scripts/domain_pointer_create_post.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | /** 30 | * TODO For now the pointer domain should be treated as normal domain in spampanel 31 | * until we add the option to process the pointer, subdomain as aliases in spampanel 32 | */ 33 | $domain = $argv[1]; 34 | if (!$domain) 35 | die('Error: empty domain'); 36 | 37 | include_once __DIR__ . '/../../lib/plugin.php'; 38 | 39 | $conf = new Configuration(); 40 | if ($conf->get('automatically_add_domains') && 41 | $conf->get('process_addon_and_parked_domains') 42 | ) { 43 | 44 | // auto-adding to spamexperts 45 | echo 'Adding pointer domain '.$domain.' to SpamExperts
'; 46 | 47 | $hostname = $conf->get('api_hostname'); 48 | $username = $conf->get('api_username'); 49 | $password = $conf->get('api_password'); 50 | 51 | // no credentials in configuration 52 | if (!$hostname || !$username || !$password) 53 | die('Unable to add pointer domain to SpamExperts - check credentials on plugin\'s configuration'); 54 | 55 | $api = new SpamExperts_API($hostname, $username, $password); 56 | $res = $api->protectDomains(array($domain), $conf, new DirectAdmin_API()); 57 | 58 | if (isset($res[$domain]['result'])){ 59 | 60 | die( $res[$domain]['result'] ? 'Pointer domain has been added to the SpamExperts' : 'Error during adding pointer domain to the SpamExperts' ); 61 | 62 | } else { 63 | die('Error during adding pointer domain to the SpamExperts'); 64 | } 65 | 66 | } else { 67 | // auto-adding to spamexperts disabled -> no action 68 | } 69 | -------------------------------------------------------------------------------- /hooks/scripts/domain_pointer_destroy_post.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | /** 30 | * TODO For now the pointer domain should be treated as normal domain in spampanel 31 | * until we add the option to process the pointer, subdomain as aliases in spampanel 32 | */ 33 | 34 | $domain = $argv[1]; 35 | if (!$domain) 36 | die('Error: empty domain'); 37 | 38 | include_once __DIR__ . '/../../lib/plugin.php'; 39 | 40 | $conf = new Configuration(); 41 | if ($conf->get('automatically_delete_domains') && 42 | $conf->get('process_addon_and_parked_domains') 43 | ) { 44 | 45 | // auto-adding to spamexperts 46 | echo 'Deleting domain '.$domain.' from the SpamExperts
'; 47 | 48 | $hostname = $conf->get('api_hostname'); 49 | $username = $conf->get('api_username'); 50 | $password = $conf->get('api_password'); 51 | 52 | // no credentials in configuration 53 | if (!$hostname || !$username || !$password) 54 | die('Unable to delete pointer domain from the SpamExperts - check credentials on plugin\'s configuration'); 55 | 56 | $api = new SpamExperts_API($hostname, $username, $password); 57 | $res = $api->unprotectDomains(array($domain), $conf, new DirectAdmin_API()); 58 | 59 | if (isset($res[$domain]['result'])){ 60 | 61 | die( $res[$domain]['result'] ? 'Pointer domain has been deleted from the SpamExperts' : 'Error during deleting pointer domain from the SpamExperts' ); 62 | 63 | } else { 64 | die('Error during pointer domain removal in SpamExperts ControlPanel'); 65 | } 66 | 67 | } else { 68 | // auto-adding to spamexperts disabled -> no action 69 | } 70 | -------------------------------------------------------------------------------- /hooks/user_img.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /hooks/user_txt.html: -------------------------------------------------------------------------------- 1 | Professional Spam Filter -------------------------------------------------------------------------------- /images/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpamExperts/directadmin-addon/84c6b59228ac35e5b36e8704d1f5065ef558d831/images/ajax-loader.gif -------------------------------------------------------------------------------- /images/link.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpamExperts/directadmin-addon/84c6b59228ac35e5b36e8704d1f5065ef558d831/images/link.jpg -------------------------------------------------------------------------------- /images/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpamExperts/directadmin-addon/84c6b59228ac35e5b36e8704d1f5065ef558d831/images/logo.jpg -------------------------------------------------------------------------------- /lib/Ajax.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | class Ajax { 30 | 31 | protected $_params; 32 | 33 | public function processRequest($params){ 34 | $this->_params = $params; 35 | $method = 'call_' . $params['action']; 36 | call_user_func_array(array($this, $method), array()); 37 | $this->sendResponse(false, 'Action does not respond the standard way.'); 38 | } 39 | 40 | public function __call($name, $arguments) { 41 | $this->sendResponse(false, 'Action "'.$name.'" is not supported'); 42 | } 43 | 44 | protected function sendResponse($success, $msg, array $params = array()) { 45 | $res = array( 46 | 'success' => $success ? 1 : 0, 47 | 'msg' => $msg 48 | ); 49 | $json = json_encode(array_merge($res, $params)); 50 | echo '[AJAX_RESPONSE]' . $json . '[/AJAX_RESPONSE]'; 51 | die(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /lib/Branding.php: -------------------------------------------------------------------------------- 1 | pluginConf = SE_BASE_DIR . DS . 'plugin.conf'; 13 | $this->files = array( 14 | SE_BASE_DIR . DS . 'hooks' . DS . 'user_txt.html', 15 | SE_BASE_DIR . DS . 'hooks' . DS . 'admin_txt.html', 16 | SE_BASE_DIR . DS . 'hooks' . DS . 'reseller_txt.html' 17 | ); 18 | $this->maxLogoHeight = 150; 19 | $this->maxLogoWidth = 600; 20 | $this->setBrandNameFromFile(); 21 | } 22 | 23 | public function getBrandName() { 24 | return $this->brandName; 25 | } 26 | 27 | public function setBrandNameFromFile() { 28 | $branding = parse_ini_string($this->getBrandFileContent($this->pluginConf), true); 29 | $this->brandName = $branding['name']; 30 | } 31 | 32 | public function setBrandName($brandName) { 33 | $length = strlen(utf8_decode(html_entity_decode($brandName, ENT_COMPAT, 'utf-8'))); 34 | if ($length < 4) { 35 | return array('status' => 'failed', 36 | 'msg' => 'Brandame must consist of at least 4 characters.'); 37 | } 38 | if ($length > 32) { 39 | return array('status' => 'failed', 40 | 'msg' => 'Maximum length of brandname allowed is 32 characters.'); 41 | } 42 | if (preg_match('/[\x00-\x1F\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]/', $brandName)) { 43 | return array('status' => 'failed', 44 | 'msg' => 'Brandame must be alphanumeric. Additionally white space can be used'); 45 | } 46 | $failedTo = array(); 47 | $output = array(); 48 | $result = $this->changeBrandingInConf($brandName); 49 | if (!empty($result)) { 50 | $failedTo[] = array('file' => $this->pluginConf, 51 | 'reason' => $result); 52 | } 53 | foreach ($this->files as $file) { 54 | $data = $this->getBrandFileContent($file); 55 | $replaced = str_replace($this->brandName, $brandName, $data); 56 | exec(SE_BASE_DIR . DS . 'scripts' . DS . 'getconfig --brandsave ' . $file . ' "' . $replaced . '" 2>&1', $output); 57 | unset($data); 58 | unset($replaced); 59 | if (!empty($output)) { 60 | $failedTo[] = array('file' => $file, 61 | 'reason' => $output); 62 | } 63 | unset($output); 64 | } 65 | if (!empty($failedTo)) { 66 | return array('status' => 'failed', 67 | 'msg' => 'Branding changing failure!'); 68 | } 69 | return array('status' => 'success', 70 | 'msg' => 'Branding changed successfully!'); 71 | } 72 | 73 | private function getBrandFileContent($fileName) { 74 | exec(SE_BASE_DIR . DS . 'scripts' . DS . 'getconfig --brandget ' . $fileName, $content, $return); 75 | if (sizeof($content) > 1) { 76 | $data = implode("\n", $content); 77 | } else { 78 | $data = $content[0]; 79 | } 80 | return $data; 81 | } 82 | 83 | private function changeBrandingInConf($brandName) { 84 | $output = array(); 85 | $data = $this->getBrandFileContent($this->pluginConf); 86 | 87 | $replaced = str_replace('"' . $this->brandName . '"', '\"' . $brandName . '\"', $data); 88 | // If data isn't replaced for value in quotest then, Branding must be saved without quoutes (made for backward compatibility) 89 | if ($replaced == $data) { 90 | $replaced = str_replace($this->brandName, '\"' . $brandName . '\"', $data); 91 | } 92 | exec(SE_BASE_DIR . DS . 'scripts' . DS . 'getconfig --brandsave ' . $this->pluginConf . ' "' . $replaced . '" 2>&1', $output); 93 | return $output; 94 | } 95 | 96 | public function setBrandLogo($filePath) { 97 | $command = SE_BASE_DIR . DS . 'scripts' . DS . 'getconfig --mvLogo ' . $filePath . ' ' . SE_BASE_DIR . DS . 'images' . DS . 'logo.jpg'; 98 | exec($command, $output, $retval); 99 | return 0 === $retval; 100 | } 101 | 102 | public function validateLogo($filePath) { 103 | exec(SE_BASE_DIR . DS . 'scripts' . DS . 'getconfig --chmodFile ' . $filePath, $output); // get permission to do that 104 | $imageInfo = getimagesize($filePath); 105 | return $imageInfo['mime'] === "image/jpeg" 106 | && $imageInfo[0] <= $this->maxLogoWidth 107 | && $imageInfo[1] <= $this->maxLogoHeight; 108 | } 109 | 110 | public function getMaxLogoWidth() { 111 | return $this->maxLogoWidth; 112 | } 113 | 114 | public function getMaxLogoHeight() { 115 | return $this->maxLogoHeight; 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /lib/Configuration.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | if (!defined('PLUGIN_NAME')) { 30 | define('PLUGIN_NAME', basename(dirname(__DIR__))); 31 | } 32 | 33 | class Configuration 34 | { 35 | protected $_filename; 36 | protected $_values; 37 | 38 | public function __construct($filename = null) 39 | { 40 | $this->_filename = PLUGIN_NAME . DS . 'configuration.conf'; 41 | if ($filename) { 42 | $this->_filename = PLUGIN_NAME . DS . $filename; 43 | } 44 | 45 | $this->_load(); 46 | } 47 | 48 | protected function _load() 49 | { 50 | $path = __DIR__ . DS . '..' . DS . '..' . DS . $this->_filename; 51 | if (!file_exists($path)) { 52 | throw new Exception('Configuration file ' . $this->_filename . ' does not exists', 404); 53 | } 54 | 55 | $file = str_replace('.conf', '', $this->_filename); 56 | exec($this->_getConfigScriptPath() . ' --config '.$file, $output, $return); 57 | 58 | $this->_values = parse_ini_string(implode("\r\n", $output)); 59 | } 60 | 61 | public function get($key, $default = null) 62 | { 63 | return isset($this->_values[$key]) ? stripslashes($this->_values[$key]) : $default; 64 | } 65 | 66 | public function set($key, $value) 67 | { 68 | $this->_values[$key] = $value; 69 | } 70 | 71 | public function save() 72 | { 73 | $str = ''; 74 | foreach ($this->_values as $k => $v) { 75 | $str .= addslashes($k.'="'.addslashes($v).'"') . "\n"; 76 | } 77 | 78 | $file = str_replace('.conf', '', $this->_filename); 79 | exec($this->_getConfigScriptPath() . ' --save '.$file.' "'.$str.'" 2>&1', $output, $return); 80 | } 81 | 82 | private function _getConfigScriptPath() 83 | { 84 | return dirname(__DIR__) . '/scripts/getconfig'; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /lib/DirectAdmin_API.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | class DirectAdmin_API { 30 | 31 | public static $total = 0; 32 | 33 | protected $_host; 34 | protected $_login; 35 | protected $_pass; 36 | protected $_secure; 37 | protected $_port; 38 | 39 | public function __construct($host = null, $login = null, $pass = null, $secure = true, $port = 2222){ 40 | $this->_host = $host; 41 | $this->_login = $login; 42 | $this->_pass = $pass; 43 | $this->_secure = $secure; 44 | $this->_port = $port; 45 | 46 | if (empty($host)) 47 | $this->_setupLocalConnection(); 48 | } 49 | 50 | public function getDomainsMxRecords($domain, $username = null){ 51 | $sock = $this->_getSocket(); 52 | $sock->query('/CMD_API_DNS_ADMIN?domain='.$domain.'&urlencoded=yes'); 53 | $result = $sock->fetch_body(); 54 | 55 | if (!$result){ 56 | throw new Exception('Unable to get DNS zone of domain ' . $domain); 57 | } 58 | 59 | $isRemote = FALSE; 60 | if (strlen($username) != 0) { 61 | $sock->query('/CMD_API_DNS_MX?domain='.$domain.'&as_user='.$username.'&urlencoded=yes'); 62 | $mx = $sock->fetch_body(); 63 | 64 | $lines = explode("\n", $mx); 65 | foreach ($lines as $line) { 66 | $setting = strtok($line, '='); 67 | if ($setting != 'internal') 68 | continue; 69 | 70 | $value = strtok(substr($line, strlen($setting)+1), "&"); 71 | if ($value == 'no') { 72 | $isRemote = TRUE; 73 | } 74 | } 75 | } 76 | 77 | $records = array(); 78 | $lines = explode("\n", $result); 79 | foreach ($lines as $line){ 80 | $recordType = strtok($line, '='); 81 | if ($recordType != 'MX') 82 | continue; 83 | 84 | $recordValue = substr($line, strlen($recordType) + 1); 85 | if (empty($recordValue)) 86 | continue; 87 | 88 | $entries = array_map(function ($entry) { 89 | $parts = explode(' ', rawurldecode($entry)); 90 | return end($parts); 91 | }, explode('&', $recordValue)); 92 | foreach ($entries as $entry) { 93 | 94 | // If the checkbox at CMD_API_DNS_MX isn't checked make sure we run an additional test 95 | if ($isRemote === FALSE) { 96 | if (substr($entry, -1) === '.' && strpos($entry, $domain) === false) { 97 | $isRemote = TRUE; 98 | } 99 | } 100 | 101 | $records[] = array( 102 | 'original' => $entry, 103 | 'full' => substr($entry, -1) === '.' 104 | ? substr($entry, 0, -1) 105 | : $entry . '.' . $domain, 106 | 'isRemote' => $isRemote, 107 | ); 108 | } 109 | } 110 | return $records; 111 | } 112 | 113 | public function getAllDomains(array $filters = array()){ 114 | $sock = $this->_getSocket(); 115 | $sock->query('/CMD_API_ALL_USER_USAGE'); 116 | $result = $sock->fetch_body(); 117 | 118 | if (!$result){ 119 | return array(); 120 | } 121 | 122 | $startIndex = 0; 123 | $endIndex = 10000; 124 | $searchReseller = null; 125 | $searchUsername = null; 126 | $searchDomain = null; 127 | $includePointers = true; 128 | 129 | if (isset($filters['page']) && isset($filters['limit']) && $filters['page'] && $filters['limit']){ 130 | $startIndex = ($filters['page']-1) * $filters['limit']; 131 | $endIndex = $startIndex + $filters['limit']; 132 | } 133 | if (isset($filters['searchUsername']) && $filters['searchUsername']) 134 | $searchUsername = $filters['searchUsername']; 135 | if (isset($filters['searchReseller']) && $filters['searchReseller']) 136 | $searchReseller = $filters['searchReseller']; 137 | if (isset($filters['searchDomain']) && $filters['searchDomain']) 138 | $searchDomain = $filters['searchDomain']; 139 | if (isset($filters['includePointers'])) 140 | $includePointers = !!$filters['includePointers']; 141 | 142 | self::$total = 0; 143 | $domains = array(); 144 | $lines = explode("\n", $result); 145 | foreach ($lines as $line){ 146 | $username = strtok($line, '='); 147 | parse_str($line, $details); 148 | if (isset($details['list']) && $details['list']){ 149 | $ds = explode('
', trim($details['list'])); 150 | foreach ($ds as $dom){ 151 | if (!$dom) 152 | continue; 153 | if ($searchDomain && strpos($dom, $searchDomain) === false) 154 | continue; 155 | if ($searchUsername && $username != $searchUsername) 156 | continue; 157 | if ($searchReseller && $details['creator'] != $searchReseller) 158 | continue; 159 | 160 | self::$total++; 161 | 162 | $domains[$dom] = array( 163 | 'username' => $username, 164 | ); 165 | } 166 | } 167 | 168 | // we should not process the pointer domains if that is the case 169 | if ($includePointers) { 170 | foreach ($details as $detailkey => $detail){ 171 | if (substr($detailkey, 0, 8) == 'pointer_'){ 172 | $pointers = explode('|', $detail); 173 | foreach ($pointers as $pointer){ 174 | if ($pointer){ 175 | if ($searchDomain && strpos($pointer, $searchDomain) === false) 176 | continue; 177 | if ($searchUsername && strpos($username, $searchUsername) === false) 178 | continue; 179 | if ($searchReseller && strpos($details['creator'], $searchReseller) === false) 180 | continue; 181 | 182 | self::$total++; 183 | $domains[$pointer] = array( 184 | 'username' => $username, 185 | 'pointsto' => str_replace('_', '.', substr($detailkey, 8)) 186 | ); 187 | } 188 | } 189 | } 190 | } 191 | } 192 | 193 | } 194 | 195 | ksort($domains); 196 | 197 | $di = 0; 198 | $return = array(); 199 | foreach ($domains as $domain => $details){ 200 | if ($di >= $startIndex && $di <= $endIndex){ 201 | $return[$domain] = new DirectAdmin_Domain( 202 | $domain, 203 | $details['username'], 204 | isset($details['pointsto']) ? $details['pointsto'] : null 205 | ); 206 | } 207 | $di++; 208 | } 209 | 210 | return $return; 211 | } 212 | 213 | public function getSystemInfo(){ 214 | $sock = $this->_getSocket(); 215 | $sock->query('/CMD_API_SYSTEM_INFO'); 216 | $result = $sock->fetch_body(); 217 | 218 | if (!$result || strpos($result, 'setConfig(array( 229 | 'username' => $this->_login, 230 | 'password' => $this->_pass, 231 | 'hostname' => $this->_host, 232 | 'port' => $this->_port, 233 | 'ssl' => $this->_secure ? '1' : '0', 234 | 'end_dot' => 1, 235 | )); 236 | return $dns; 237 | } 238 | 239 | public function isUsersDomain($domain, $reseller = false){ 240 | $domains = $this->getAllDomains(array( 241 | 'page' => 1, 242 | 'limit' => 999999, 243 | 'searchUsername'=> $reseller ? null : getenv('USERNAME'), 244 | 'searchReseller'=> $reseller ? getenv('USERNAME') : null, 245 | 'searchDomain' => $domain, 246 | )); 247 | foreach ($domains as $d){ 248 | if ($d->domain == $domain) 249 | return true; 250 | } 251 | return false; 252 | } 253 | 254 | protected function _setupLocalConnection(){ 255 | // THAT COMMENTED OUT WILL NOT WORK IN HOOKS -> all connection details are in directadminapi.conf 256 | 257 | // if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) 258 | // $this->_secure = true; 259 | // else 260 | // $this->_secure = false; 261 | // 262 | // $this->_host = $_SERVER['SERVER_NAME']; 263 | // $this->_port = $_SERVER['SERVER_PORT']; 264 | 265 | $conf = new Configuration('directadminapi.conf'); 266 | 267 | $this->_login = $conf->get('username'); 268 | $this->_pass = $conf->get('password'); 269 | $this->_secure = (bool)$conf->get('secure'); 270 | $this->_host = $conf->get('host'); 271 | $this->_port = $conf->get('port'); 272 | } 273 | 274 | protected function _getSocket(){ 275 | $sock = new DirectAdmin_HTTPSocket; 276 | $sock->connect( ($this->_secure ? "ssl://" : '') . $this->_host, $this->_port); 277 | $sock->set_login($this->_login, $this->_pass); 278 | 279 | return $sock; 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /lib/DirectAdmin_DNS.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 8 | * CONTACT -> contact@modulesgarden.com 9 | * 10 | * 11 | * 12 | * 13 | * This software is furnished under a license and may be used and copied 14 | * only in accordance with the terms of such license and with the 15 | * inclusion of the above copyright notice. This software or any other 16 | * copies thereof may not be provided or otherwise made available to any 17 | * other person. No title to and ownership of the software is hereby 18 | * transferred. 19 | * 20 | * You may not reverse engineer, decompile, defeat license encryption 21 | * mechanisms, or disassemble this software product or software product 22 | * license. ModulesGarden may terminate this license if you don't 23 | * comply with any of the terms and conditions. 24 | * 25 | * In such event, licensee agrees to return 26 | * licensor or destroy all copies of software upon termination of the 27 | * license. 28 | * 29 | * 30 | * 31 | ********************************************************************/ 32 | set_time_limit (30); 33 | error_reporting(E_ALL ^ E_NOTICE); 34 | 35 | class DirectAdmin_DNS 36 | { 37 | private $domain; 38 | private $ip; 39 | private $hasTTL = false; 40 | private $supportRDNS = false; 41 | private $requireIP = true; 42 | 43 | public $error; 44 | public $results = array(); 45 | private $oconfig = array 46 | ( 47 | 'username' => '', 48 | 'password' => '', 49 | 'hostname' => '', 50 | 'port' => '', 51 | 'ssl' => '', 52 | 'defaultIP' => '', 53 | 'ns1' => '', 54 | 'ns2' => '' 55 | ); 56 | 57 | public $config = array 58 | ( 59 | 'option1' =>array 60 | ( 61 | 'name'=> 'username', 62 | 'type'=> 'text', 63 | ), 64 | 'option2' =>array 65 | ( 66 | 'name'=> 'password', 67 | 'type'=> 'password', 68 | ), 69 | 'option3' =>array 70 | ( 71 | 'name'=> 'hostname', 72 | 'type'=> 'text', 73 | ), 74 | 'option4' =>array 75 | ( 76 | 'name'=> 'ssl', 77 | 'type'=> 'yesno', 78 | ), 79 | 'option5' =>array 80 | ( 81 | 'name'=> 'defaultIP', 82 | 'type'=> 'text', 83 | ), 84 | 'option6' =>array 85 | ( 86 | 'friendlyName' => 'Return error when not dot at the end name', 87 | 'name'=> 'end_dot', 88 | 'type'=> 'yesno', 89 | ), 90 | 'option7' =>array 91 | ( 92 | 'friendlyName' => 'NS1', 93 | 'name'=> 'ns1', 94 | 'type'=> 'text', 95 | ), 96 | 'option8' =>array 97 | ( 98 | 'friendlyName' => 'NS2', 99 | 'name'=> 'ns2', 100 | 'type'=> 'text', 101 | ), 102 | ); 103 | 104 | /** available records types **/ 105 | private $availableTypes = array('A', 'NS', 'MX', 'CNAME', 'TXT', 'AAAA', 'SRV'); 106 | /** 107 | * Zwraca false jezeli cos sie zepsulu. Jeżeli operacja się powiodła zwraca "cos" do sparsowania 108 | */ 109 | 110 | private function get($function, $params=array()) 111 | { 112 | $username = urlencode($this->oconfig['username']); 113 | $password = urlencode($this->oconfig['password']); 114 | $port = $this->oconfig['port']; 115 | $url = ($this->oconfig['ssl'] == '1' ? 116 | 'https://'.$username.':'.$password.'@'.$this->oconfig['hostname'].':'.$port : 117 | 'http://'.$username.':'.$password.'@'.$this->oconfig['hostname'].':'.$port).'/'.$function; 118 | 119 | 120 | if(is_array($params)) 121 | { 122 | $url .= '?'; 123 | foreach($params as $key=>$value) 124 | { 125 | $value = urlencode($value); 126 | $key = urlencode($key); 127 | $url .= "{$key}={$value}&"; 128 | } 129 | } 130 | 131 | $ch = curl_init(); 132 | $chOptions = array ( 133 | CURLOPT_URL => trim($url, '&'), 134 | CURLOPT_RETURNTRANSFER => true, 135 | CURLOPT_SSL_VERIFYPEER => false, 136 | CURLOPT_SSL_VERIFYHOST => false, 137 | CURLOPT_FOLLOWLOCATION => true, 138 | CURLOPT_TIMEOUT => 30 139 | ); 140 | curl_setopt_array($ch, $chOptions); 141 | $out = curl_exec($ch); 142 | 143 | if($out === false) 144 | { 145 | $this->error = ucwords(curl_error($ch)); 146 | return false; 147 | } 148 | 149 | //parsujemy 150 | $out = urldecode($out); 151 | parse_str($out, $parsed); 152 | 153 | if(isset($parsed['error'])) 154 | { 155 | if($parsed['error'] > 0) 156 | { 157 | $this->results[] = array('success' => 0, 'info' => 'Error occured:'.$parsed['text'].' '.$parsed['details']); 158 | return false; 159 | } 160 | else 161 | { 162 | $this->results[] = array('success' => 1, 'info' => 'Info:'.$parsed['text']); 163 | return true; 164 | } 165 | } 166 | 167 | return $out; 168 | } 169 | 170 | public function testConnection() 171 | { 172 | $out = $this->get('CMD_API_SHOW_USER_USAGE', array('user' => $this->oconfig['username'])); 173 | if($out === false) 174 | return array( 175 | 'status' => false, 176 | 'error' => $this->error 177 | ); 178 | elseif(strpos($out, '') !== false) 179 | return array( 180 | 'status' => false, 181 | 'error' => 'Incorrect username or password' 182 | ); 183 | else 184 | return array( 185 | 'status' => true, 186 | 'error' => '' 187 | ); 188 | } 189 | 190 | public function requireIP(){ 191 | return $this->requireIP; 192 | } 193 | 194 | public function isTTL(){ 195 | return $this->hasTTL; 196 | } 197 | 198 | public function supportRDNS(){ 199 | return $this->supportRDNS; 200 | } 201 | 202 | public function setIP($ip) 203 | { 204 | $this->ip = $ip; 205 | } 206 | 207 | public function getDefaultIP(){ 208 | return $this->oconfig['defaultIP']; 209 | } 210 | 211 | public function __construct($domain) 212 | { 213 | $this->domain = $domain; 214 | } 215 | 216 | public function setConfig($config) 217 | { 218 | if(isset($config['username'])) $this->oconfig['username'] = $config['username']; 219 | if(isset($config['password'])) $this->oconfig['password'] = $config['password']; 220 | if(isset($config['hostname'])) $this->oconfig['hostname'] = $config['hostname']; 221 | if(isset($config['port'])) $this->oconfig['port'] = $config['port']; 222 | if(isset($config['ssl'])) $this->oconfig['ssl'] = $config['ssl']; 223 | if(isset($config['defaultIP'])) $this->oconfig['defaultIP'] = $config['defaultIP']; 224 | if(isset($config['end_dot'])) $this->oconfig['end_dot'] = $config['end_dot']; 225 | //nameservers 226 | if(isset($config['ns1'])) $this->oconfig['ns1'] = $config['ns1']; 227 | if(isset($config['ns2'])) $this->oconfig['ns2'] = $config['ns2']; 228 | } 229 | 230 | public function zoneExists() 231 | { 232 | $out = $this->get('CMD_API_DNS_ADMIN', array( 233 | 'domain' => $this->domain 234 | )); 235 | 236 | if($out == false || strpos($out, '') !== false){ 237 | $this->results[] = strpos($out, 'You cannot execute that command') ? 'You cannot execute that command' : 'Unexpected error'; 238 | return false; 239 | } else { 240 | return true; 241 | } 242 | } 243 | 244 | public function getRecords($recordType=false) 245 | { 246 | $out = $this->get('CMD_API_DNS_ADMIN', array( 247 | 'domain' => $this->domain, 248 | 'urlencoded' => 'yes' 249 | )); 250 | 251 | if($out == false) 252 | { 253 | return false; 254 | } 255 | 256 | /** TRZEBA TO ZMIENIC!!! **/ 257 | $exploded = explode("\n", $out); 258 | $arr = array(); 259 | foreach($exploded as $ex) 260 | { 261 | $line = explode('=', $ex, 2); 262 | $data = explode('&', $line[1] ?? ''); 263 | foreach($data as $d) 264 | { 265 | $x = explode('=', $d, 2); 266 | if(isset($x[0]) && isset($x[1])) 267 | { 268 | $arr[$line[0]][][$x[0]] = $x[1]; 269 | } 270 | } 271 | } 272 | 273 | $out = array(); 274 | $i = 0; 275 | foreach($arr as $type => $r) 276 | foreach($r as $records) 277 | { 278 | if($recordType && $type != $recordType) 279 | { 280 | continue; 281 | } 282 | 283 | foreach($records as $name => $value) 284 | { 285 | if(empty($name)) 286 | { 287 | continue; 288 | } 289 | 290 | switch($type) 291 | { 292 | case 'SRV': 293 | $srv = explode(" ", $value); 294 | $out[] = array( 295 | 'line' => $i, 296 | 'name' => $name, 297 | 'value' => $srv[3], 298 | 'type' => $type, 299 | 'ttl' => '', 300 | 'priority' => $srv[0], 301 | 'weight' => $srv[1], 302 | 'port' => $srv[2] 303 | ); 304 | break; 305 | case 'NS': 306 | $out[] = array( 307 | 'line' => $i, 308 | 'name' => $name, 309 | 'value' => $value, 310 | 'type' => $type, 311 | 'ttl' => '', 312 | 'priority' => '' 313 | ); 314 | break; 315 | case 'MX': 316 | $out[] = array( 317 | 'line' => $i, 318 | 'name' => $name, 319 | 'value' => '', 320 | 'type' => $type, 321 | 'ttl' => '', 322 | 'priority' => $value 323 | ); 324 | break; 325 | case 'TXT': 326 | $out[] = array( 327 | 'line' => $i, 328 | 'name' => $name, 329 | 'value' => trim($value,"\""), 330 | 'type' => $type, 331 | 'ttl' => '', 332 | 'priority' => '' 333 | ); 334 | break; 335 | default: 336 | $out[] = array( 337 | 'line' => $i, 338 | 'name' => $name, 339 | 'value' => $value, 340 | 'type' => $type, 341 | 'ttl' => '', 342 | 'priority' => '' 343 | ); 344 | } 345 | $i++; 346 | } 347 | } 348 | 349 | return $out; 350 | } 351 | 352 | public function add($data) 353 | { 354 | global $_LANG; 355 | 356 | if(empty($data)) 357 | { 358 | return false; 359 | } 360 | 361 | foreach($data as $record) 362 | { 363 | $out['action'] = 'add'; 364 | $out['domain'] = $this->domain; 365 | $out['type'] = strtoupper($record['type']); 366 | if(filter_var($record['name'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4|FILTER_FLAG_IPV6) === false && $this->oconfig['end_dot'] == 1 && (count(explode('.', $record['name'])) > 1 && substr($record['name'], -1) != '.')){ 367 | $this->results[] = array('success' => 0, 'info' => ''.(isset($_LANG['directadmin_error1']) ? $_LANG['directadmin_error1'] : 'Error occured: Cannot Add Record. Invalid \'name\' field. At the end of the domain name must be a .dot')); 368 | return false; 369 | } 370 | if($out['type'] != 'TXT' && filter_var($record['value'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4|FILTER_FLAG_IPV6) === false && $this->oconfig['end_dot'] == 1 && (count(explode('.', $record['value'])) > 1 && substr($record['value'], -1) != '.')){ 371 | $this->results[] = array('success' => 0, 'info' => ''.(isset($_LANG['directadmin_error2']) ? $_LANG['directadmin_error2'] : 'Error occured: Cannot Add Record. Invalid \'value\' field. At the end of the domain name must be a .dot')); 372 | return false; 373 | } 374 | $out['name'] = $record['name']; 375 | 376 | switch($out['type']) 377 | { 378 | case 'SRV': 379 | $out['value'] = $record['priority'].' '.$record['weight'].' '.$record['port'].' '.$record['value']; 380 | break; 381 | case 'TXT': 382 | $out['value'] = '"'.trim($record['value'], '"').'"'; 383 | break; 384 | case 'MX': 385 | $out['value'] = $record['priority']; 386 | break; 387 | default: 388 | $out['value'] = $record['value']; 389 | } 390 | 391 | $this->get('CMD_API_DNS_ADMIN', $out); 392 | } 393 | } 394 | 395 | /* DA nie posiada update */ 396 | public function modify($data) 397 | { 398 | global $_LANG; 399 | 400 | if(empty($data)) 401 | { 402 | return false; 403 | } 404 | //single page or subpages? 405 | $type = strtoupper($data[0]['type']); 406 | $single = false; 407 | foreach($data as $d) 408 | { 409 | if(strtoupper($d['type']) != $type) 410 | { 411 | $single = true; 412 | break; 413 | } 414 | } 415 | 416 | $records = array(); 417 | if($single) 418 | { 419 | $records = $this->getRecords(); 420 | } 421 | else 422 | { 423 | $records = $this->getRecords($type); 424 | } 425 | 426 | $delete = array(); 427 | $add = array(); 428 | foreach($data as $key => $record) 429 | { 430 | $record['type'] = strtoupper($record['type']); 431 | $diff = false; 432 | if (!array_key_exists('line', $record)) { 433 | $diff = true; 434 | } else { 435 | switch ($record['type']) { 436 | case 'MX' : 437 | if ($records[$record['line']]['name'] != $record['name'] || $records[$record['line']]['value'] != $record['value'] || $records[$record['line']]['priority'] != $record['priority']) $diff = true; 438 | break; 439 | case 'SRV': 440 | if ($records[$record['line']]['name'] != $record['name'] || $records[$record['line']]['value'] != $record['value'] || $records[$record['line']]['priority'] != $record['priority'] || $records[$record['line']]['weight'] != $record['weight'] || $records[$record['line']]['port'] != $record['port']) $diff = true; 441 | break; 442 | default : 443 | if ($records[$record['line']]['name'] != $record['name'] || $records[$record['line']]['value'] != $record['value']) $diff = true; 444 | break; 445 | } 446 | } 447 | if($diff === true) 448 | { 449 | if(filter_var($record['name'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4|FILTER_FLAG_IPV6) === false && $this->oconfig['end_dot'] == 1 && (count(explode('.', $record['name'])) > 1 && substr($record['name'], -1) != '.')){ 450 | $this->results[] = array('success' => 0, 'info' => ''.(isset($_LANG['directadmin_error1']) ? $_LANG['directadmin_error1'] : 'Error occured: Cannot Add Record. Invalid \'name\' field. At the end of the domain name must be a .dot')); 451 | return false; 452 | } 453 | if($record['type'] != 'TXT' && filter_var($record['value'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4|FILTER_FLAG_IPV6) === false && $this->oconfig['end_dot'] == 1 && (count(explode('.', $record['value'])) > 1 && substr($record['value'], -1) != '.')){ 454 | $this->results[] = array('success' => 0, 'info' => ''.(isset($_LANG['directadmin_error2']) ? $_LANG['directadmin_error2'] : 'Error occured: Cannot Add Record. Invalid \'value\' field. At the end of the domain name must be a .dot')); 455 | return false; 456 | } 457 | 458 | if (array_key_exists('line', $record)) { 459 | $delete[] = $records[$record['line']]; 460 | } 461 | $add[] = $record; 462 | } 463 | 464 | } 465 | $this->delete($delete); 466 | $this->add($add); 467 | } 468 | 469 | public function delete($data) 470 | { 471 | if(empty($data)) 472 | { 473 | return false; 474 | } 475 | 476 | foreach($data as $record) 477 | { 478 | if (empty($record)) { 479 | continue; 480 | } 481 | $record['type'] = strtoupper($record['type']); 482 | $out['domain'] = $this->domain; 483 | $out['action'] = 'select'; 484 | switch($record['type']) 485 | { 486 | case 'SRV': 487 | $records = $this->getRecords('SRV'); 488 | foreach($records as $r) 489 | { 490 | if($record['name'] == $r['name'] && $record['value'] == $r['value']) 491 | { 492 | $out[strtolower($record['type']).'recs0'] = 'name='.$record['name'].'&value='.$r['priority'].' '.$r['weight'].' '.$r['port'].' '.$r['value']; 493 | break; 494 | } 495 | } 496 | break; 497 | case 'MX': 498 | $records = $this->getRecords('MX'); 499 | foreach($records as $r) 500 | { 501 | if($record['name'] == $r['name'] && $record['value'] == $r['value']) 502 | { 503 | $out[strtolower($record['type']).'recs0'] = 'name='.$r['name'].'&value='.$r['priority']; 504 | break; 505 | } 506 | } 507 | break; 508 | case 'NS': 509 | $out[strtolower($record['type']).'recs0'] = 'name='.$record['value'].'&value='.$record['name']; 510 | break; 511 | case 'TXT': 512 | $out[strtolower($record['type']).'recs0'] = 'name='.$record['name'].'&value="'.$record['value'].'"'; 513 | break; 514 | default: 515 | $out[strtolower($record['type']).'recs0'] = 'name='.$record['name'].'&value='.$record['value']; 516 | } 517 | 518 | $this->get('CMD_API_DNS_ADMIN', $out); 519 | } 520 | 521 | } 522 | 523 | 524 | public function activateZone() 525 | { 526 | if($this->ip != '') { 527 | if(!filter_var($this->ip, FILTER_VALIDATE_IP)) { 528 | $this->error = 'IP is not valid!'; 529 | return false; 530 | } 531 | } else { 532 | $this->ip = $this->oconfig['defaultIP']; 533 | } 534 | $out = $this->get('CMD_API_DNS_ADMIN', array( 535 | 'action' => 'create', 536 | 'domain' => $this->domain, 537 | 'ip' => $this->ip, 538 | 'ns1' => $this->oconfig['ns1'], 539 | 'ns2' => $this->oconfig['ns2'] 540 | )); 541 | 542 | if($out !== true){ 543 | $this->getErrorFromOutput($out); 544 | return false; 545 | } else { 546 | return true; 547 | } 548 | } 549 | 550 | public function terminateZone() 551 | { 552 | $out = $this->get('CMD_API_DNS_ADMIN', array( 553 | 'action' => 'delete', 554 | 'select0' => $this->domain 555 | )); 556 | if($out !== true){ 557 | $this->getErrorFromOutput($out); 558 | return false; 559 | } else { 560 | return true; 561 | } 562 | } 563 | 564 | public function getAvailableTypes() 565 | { 566 | return $this->availableTypes; 567 | } 568 | 569 | private function getErrorFromOutput($out){ 570 | if(strpos($out, 'You cannot execute that command') !== false) 571 | $this->error = 'You cannot execute that command'; 572 | elseif(strpos($out, 'Please enter your Username and Password') !== false) 573 | $this->error = 'Incorrect username or password'; 574 | elseif(strpos($out, 'Your IP is blacklisted') !== false) 575 | $this->error = 'Your IP is blacklisted'; 576 | else 577 | $this->error = empty($this->error) ? 'Unexpected error' : $this->error; 578 | } 579 | } 580 | -------------------------------------------------------------------------------- /lib/DirectAdmin_Domain.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | class DirectAdmin_Domain { 30 | 31 | public $domain; 32 | public $username; 33 | public $pointsto; 34 | 35 | public function __construct($domain, $username, $pointsto = null){ 36 | $this->domain = $domain; 37 | $this->username = $username; 38 | $this->pointsto = $pointsto; 39 | } 40 | 41 | /** 42 | * Checks first MX record 43 | * @return bool 44 | */ 45 | public function isRemote(){ 46 | $api = new DirectAdmin_API(); 47 | $records = $api->getDomainsMxRecords($this->domain, $this->username); 48 | return isset($records[0]['isRemote']) && $records[0]['isRemote']; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /lib/DirectAdmin_HTTPSocket.php: -------------------------------------------------------------------------------- 1 | _debugMode && !$this->_loggedResponse) { 25 | $requestUrl = strpos($request, '://') === false ? $this->remote_host.$request : $request; 26 | $this->logResponse($requestUrl, 'HTTP '.$this->result_status_code."\n".$this->result_body); 27 | $this->_loggedResponse = true; 28 | } 29 | } 30 | 31 | public function setLogPath($path){ 32 | $this->_logPath = $path; 33 | } 34 | 35 | public function setDebugMode($turnOn){ 36 | $this->_debugMode = (bool)$turnOn; 37 | } 38 | 39 | public function logResponse($request, $response){ 40 | if (!$this->_logPath || !$this->_debugMode) { 41 | return false; 42 | } 43 | 44 | $h = fopen($this->_logPath, 'a'); 45 | // make sure the file permissions are ok 46 | chmod($this->_logPath, 0600); 47 | fwrite($h, date('Y-m-d H:i:s') . "\n"); 48 | fwrite($h, "Request ".$request."\n"); 49 | fwrite($h, $response."\n\n"); 50 | fclose($h); 51 | return true; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /lib/HTTPSocket.php: -------------------------------------------------------------------------------- 1 | get('http://user:pass@somesite.com/somedir/some.file?query=string&this=that'); 11 | * 12 | * @author Phi1 'l0rdphi1' Stier 13 | * @package HTTPSocket 14 | * @version 3.0.4 15 | 16 | * 3.0.4 17 | * store first proxy headers for return, in event of redirect 18 | 19 | * 3.0.3 20 | * curl Cookie for SESSION_ID+SESSION_KEY changed to setopt with 21 | 22 | * 3.0.2 23 | * added longer curl timeouts 24 | 25 | * 3.0.1 26 | * support for tcp:// conversion to http:// 27 | 28 | * 3.0.0 29 | * swapped to use curl to address ssl certificate issues with php 5.6 30 | 31 | * 2.7.2 32 | * added x-use-https header check 33 | * added max number of location redirects 34 | * added custom settable message if x-use-https is found, so users can be told where to set their scripts 35 | * if a redirect host is https, add ssl:// to remote_host 36 | 37 | * 2.7.1 38 | * added isset to headers['location'], line 306 39 | 40 | */ 41 | class HTTPSocket { 42 | 43 | var $version = '3.0.4'; 44 | 45 | /* all vars are private except $error, $query_cache, and $doFollowLocationHeader */ 46 | 47 | var $method = 'GET'; 48 | 49 | var $remote_host; 50 | var $remote_port; 51 | var $remote_uname; 52 | var $remote_passwd; 53 | 54 | var $result; 55 | var $result_header; 56 | var $result_body; 57 | var $result_status_code; 58 | 59 | var $lastTransferSpeed; 60 | 61 | var $bind_host; 62 | 63 | var $error = array(); 64 | var $warn = array(); 65 | var $query_cache = array(); 66 | 67 | var $doFollowLocationHeader = TRUE; 68 | var $redirectURL; 69 | var $max_redirects = 5; 70 | var $ssl_setting_message = 'DirectAdmin appears to be using SSL. Change your script to connect to ssl://'; 71 | 72 | var $extra_headers = array(); 73 | 74 | var $proxy = false; 75 | var $proxy_headers = array(); 76 | 77 | /** 78 | * Create server "connection". 79 | * 80 | */ 81 | function connect($host, $port = '' ) 82 | { 83 | if (!is_numeric($port)) 84 | { 85 | $port = 80; 86 | } 87 | 88 | $this->remote_host = $host; 89 | $this->remote_port = $port; 90 | } 91 | 92 | function bind( $ip = '' ) 93 | { 94 | if ( $ip == '' ) 95 | { 96 | $ip = $_SERVER['SERVER_ADDR']; 97 | } 98 | 99 | $this->bind_host = $ip; 100 | } 101 | 102 | /** 103 | * Change the method being used to communicate. 104 | * 105 | * @param string|null request method. supports GET, POST, and HEAD. default is GET 106 | */ 107 | function set_method( $method = 'GET' ) 108 | { 109 | $this->method = strtoupper($method); 110 | } 111 | 112 | /** 113 | * Specify a username and password. 114 | * 115 | * @param string|null username. defualt is null 116 | * @param string|null password. defualt is null 117 | */ 118 | function set_login( $uname = '', $passwd = '' ) 119 | { 120 | if ( strlen($uname) > 0 ) 121 | { 122 | $this->remote_uname = $uname; 123 | } 124 | 125 | if ( strlen($passwd) > 0 ) 126 | { 127 | $this->remote_passwd = $passwd; 128 | } 129 | 130 | } 131 | /** 132 | * For pass through, this function writes the data in chunks. 133 | */ 134 | private function stream_chunk($ch, $data) 135 | { 136 | echo($data); 137 | return strlen($data); 138 | } 139 | private function stream_header($ch, $data) 140 | { 141 | if (!preg_match('/^HTTP/i', $data)) 142 | { 143 | header($data); 144 | } 145 | return strlen($data); 146 | } 147 | 148 | 149 | /** 150 | * Query the server 151 | * 152 | * @param string containing properly formatted server API. See DA API docs and examples. Http:// URLs O.K. too. 153 | * @param string|array query to pass to url 154 | * @param int if connection KB/s drops below value here, will drop connection 155 | */ 156 | function query( $request, $content = '', $doSpeedCheck = 0 ) 157 | { 158 | $this->error = $this->warn = array(); 159 | $this->result_status_code = NULL; 160 | 161 | $is_ssl = FALSE; 162 | 163 | // is our request a http:// ... ? 164 | if (preg_match('!^http://!i',$request) || preg_match('!^https://!i',$request)) 165 | { 166 | $location = parse_url($request); 167 | if (preg_match('!^https://!i',$request)) 168 | { 169 | // use https default port if no custom port is specified in the redirect URL 170 | $this->connect('https://'.$location['host'],$location['port'] ?? 443); 171 | } 172 | else 173 | $this->connect('http://'.$location['host'],$location['port']); 174 | 175 | // forward basic auth data if nothing else is specified in the redirect URL 176 | $this->set_login($location['user'] ?? $this->remote_uname,$location['pass'] ?? $this->remote_passwd); 177 | 178 | $request = $location['path']; 179 | // default to an empty string if not available 180 | $content = $location['query'] ?? ''; 181 | 182 | if ( strlen($request) < 1 ) 183 | { 184 | $request = '/'; 185 | } 186 | 187 | } 188 | 189 | if (preg_match('!^ssl://!i', $this->remote_host)) 190 | $this->remote_host = 'https://'.substr($this->remote_host, 6); 191 | 192 | if (preg_match('!^tcp://!i', $this->remote_host)) 193 | $this->remote_host = 'http://'.substr($this->remote_host, 6); 194 | 195 | if (preg_match('!^https://!i', $this->remote_host)) 196 | $is_ssl = TRUE; 197 | 198 | $array_headers = array( 199 | 'Host' => ( $this->remote_port == 80 ? $this->remote_host : "$this->remote_host:$this->remote_port" ), 200 | 'Accept' => '*/*', 201 | 'Connection' => 'Close' ); 202 | 203 | foreach ( $this->extra_headers as $key => $value ) 204 | { 205 | $array_headers[$key] = $value; 206 | } 207 | 208 | $this->result = $this->result_header = $this->result_body = ''; 209 | 210 | // was content sent as an array? if so, turn it into a string 211 | if (is_array($content)) 212 | { 213 | $pairs = array(); 214 | 215 | foreach ( $content as $key => $value ) 216 | { 217 | $pairs[] = "$key=".urlencode($value); 218 | } 219 | 220 | $content = join('&',$pairs); 221 | unset($pairs); 222 | } 223 | 224 | $OK = TRUE; 225 | 226 | if ($this->method == 'GET' && isset($content) && $content != '') 227 | $request .= '?'.$content; 228 | 229 | $ch = curl_init($this->remote_host.':'.$this->remote_port.$request); 230 | 231 | if ($is_ssl) 232 | { 233 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //1 234 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //2 235 | //curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); 236 | } 237 | 238 | curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 239 | curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 240 | curl_setopt($ch, CURLOPT_USERAGENT, "HTTPSocket/$this->version"); 241 | curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); 242 | curl_setopt($ch, CURLOPT_TIMEOUT, 100); 243 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); 244 | curl_setopt($ch, CURLOPT_HEADER, 1); 245 | 246 | if ($this->proxy) 247 | { 248 | curl_setopt($ch, CURLOPT_RETURNTRANSFER,false); 249 | curl_setopt($ch, CURLOPT_HEADER, false); 250 | curl_setopt($ch, CURLINFO_HEADER_OUT, false); 251 | curl_setopt($ch, CURLOPT_BUFFERSIZE, 8192); // 8192 252 | curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, "stream_chunk")); 253 | curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, "stream_header")); 254 | } 255 | 256 | curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 512); 257 | curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 120); 258 | 259 | // instance connection 260 | if ($this->bind_host) 261 | { 262 | curl_setopt($ch, CURLOPT_INTERFACE, $this->bind_host); 263 | } 264 | 265 | // if we have a username and password, add the header 266 | if ( isset($this->remote_uname) && isset($this->remote_passwd) ) 267 | { 268 | curl_setopt($ch, CURLOPT_USERPWD, $this->remote_uname.':'.$this->remote_passwd); 269 | } 270 | 271 | // for DA skins: if $this->remote_passwd is NULL, try to use the login key system 272 | if ( isset($this->remote_uname) && $this->remote_passwd == NULL ) 273 | { 274 | curl_setopt($ch, CURLOPT_COOKIE, "session={$_SERVER['SESSION_ID']}; key={$_SERVER['SESSION_KEY']}"); 275 | } 276 | 277 | // if method is POST, add content length & type headers 278 | if ( $this->method == 'POST' ) 279 | { 280 | curl_setopt($ch, CURLOPT_POST, 1); 281 | curl_setopt($ch, CURLOPT_POSTFIELDS, $content); 282 | 283 | //$array_headers['Content-type'] = 'application/x-www-form-urlencoded'; 284 | $array_headers['Content-length'] = strlen($content); 285 | } 286 | 287 | curl_setopt($ch, CURLOPT_HTTPHEADER, $array_headers); 288 | 289 | 290 | if( !($this->result = curl_exec($ch)) ) 291 | { 292 | $this->error[] .= curl_error($ch); 293 | $OK = FALSE; 294 | } 295 | 296 | $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 297 | $this->result_header = substr($this->result, 0, $header_size); 298 | $this->result_body = substr($this->result, $header_size); 299 | $this->result_status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 300 | 301 | $this->lastTransferSpeed = curl_getinfo($ch, CURLINFO_SPEED_DOWNLOAD) / 1024; 302 | 303 | curl_close($ch); 304 | 305 | $this->query_cache[] = $this->remote_host.':'.$this->remote_port.$request; 306 | 307 | $headers = $this->fetch_header(); 308 | 309 | // did we get the full file? 310 | if ( !empty($headers['content-length']) && $headers['content-length'] != strlen($this->result_body) ) 311 | { 312 | $this->result_status_code = 206; 313 | } 314 | 315 | // now, if we're being passed a location header, should we follow it? 316 | if ($this->doFollowLocationHeader) 317 | { 318 | //dont bother if we didn't even setup the script correctly 319 | if (isset($headers['x-use-https']) && $headers['x-use-https']=='yes') 320 | die($this->ssl_setting_message); 321 | 322 | if (isset($headers['location'])) 323 | { 324 | if ($this->max_redirects <= 0) 325 | die("Too many redirects on: ".$headers['location']); 326 | 327 | $this->max_redirects--; 328 | $this->redirectURL = $headers['location']; 329 | $this->query($headers['location']); 330 | } 331 | } 332 | 333 | } 334 | 335 | function getTransferSpeed() 336 | { 337 | return $this->lastTransferSpeed; 338 | } 339 | 340 | /** 341 | * The quick way to get a URL's content :) 342 | * 343 | * @param string URL 344 | * @param boolean return as array? (like PHP's file() command) 345 | * @return string result body 346 | */ 347 | function get($location, $asArray = FALSE ) 348 | { 349 | $this->query($location); 350 | 351 | if ( $this->get_status_code() == 200 ) 352 | { 353 | if ($asArray) 354 | { 355 | return preg_split("/\n/",$this->fetch_body()); 356 | } 357 | 358 | return $this->fetch_body(); 359 | } 360 | 361 | return FALSE; 362 | } 363 | 364 | /** 365 | * Returns the last status code. 366 | * 200 = OK; 367 | * 403 = FORBIDDEN; 368 | * etc. 369 | * 370 | * @return int status code 371 | */ 372 | function get_status_code() 373 | { 374 | return $this->result_status_code; 375 | } 376 | 377 | /** 378 | * Adds a header, sent with the next query. 379 | * 380 | * @param string header name 381 | * @param string header value 382 | */ 383 | function add_header($key,$value) 384 | { 385 | $this->extra_headers[$key] = $value; 386 | } 387 | 388 | /** 389 | * Clears any extra headers. 390 | * 391 | */ 392 | function clear_headers() 393 | { 394 | $this->extra_headers = array(); 395 | } 396 | 397 | /** 398 | * Return the result of a query. 399 | * 400 | * @return string result 401 | */ 402 | function fetch_result() 403 | { 404 | return $this->result; 405 | } 406 | 407 | /** 408 | * Return the header of result (stuff before body). 409 | * 410 | * @param string (optional) header to return 411 | * @return array result header 412 | */ 413 | function fetch_header( $header = '' ) 414 | { 415 | if ($this->proxy) 416 | return $this->proxy_headers; 417 | 418 | $array_headers = preg_split("/\r\n/",$this->result_header); 419 | 420 | $array_return = array( 0 => $array_headers[0] ); 421 | unset($array_headers[0]); 422 | 423 | foreach ( $array_headers as $pair ) 424 | { 425 | if ($pair == '' || $pair == "\r\n") continue; 426 | list($key,$value) = preg_split("/: /",$pair,2); 427 | $array_return[strtolower($key)] = $value; 428 | } 429 | 430 | if ( $header != '' ) 431 | { 432 | return $array_return[strtolower($header)]; 433 | } 434 | 435 | return $array_return; 436 | } 437 | 438 | /** 439 | * Return the body of result (stuff after header). 440 | * 441 | * @return string result body 442 | */ 443 | function fetch_body() 444 | { 445 | return $this->result_body; 446 | } 447 | 448 | /** 449 | * Return parsed body in array format. 450 | * 451 | * @return array result parsed 452 | */ 453 | function fetch_parsed_body() 454 | { 455 | parse_str($this->result_body,$x); 456 | return $x; 457 | } 458 | 459 | 460 | /** 461 | * Set a specifc message on how to change the SSL setting, in the event that it's not set correctly. 462 | */ 463 | function set_ssl_setting_message($str) 464 | { 465 | $this->ssl_setting_message = $str; 466 | } 467 | 468 | 469 | } 470 | 471 | ?> 472 | -------------------------------------------------------------------------------- /lib/Menu.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | class Menu { 30 | 31 | protected $_scope; 32 | protected $_logo = array( 33 | 'url' => '/CMD_PLUGINS/', 34 | 'img' => '/CMD_PLUGINS//images/logo.jpg' 35 | ); 36 | protected $_admin = array( 37 | 'configuration' => array('title' => 'Configuration','url' => '/CMD_PLUGINS_ADMIN//configuration.html'), 38 | 'branding' => array('title' => 'Branding', 'url' => '/CMD_PLUGINS_ADMIN//branding.html'), 39 | 'domain_list' => array('title' => 'Domain List', 'url' => '/CMD_PLUGINS_ADMIN/'), 40 | 'bulkprotect' => array('title' => 'Bulk Protect', 'url' => '/CMD_PLUGINS_ADMIN//bulkprotect.html'), 41 | 'update' => array('title' => 'Update', 'url' => '/CMD_PLUGINS_ADMIN//update.html'), 42 | 'support' => array('title' => 'Support', 'url' => '/CMD_PLUGINS_ADMIN//support.html'), 43 | ); 44 | 45 | 46 | public function __construct($scope){ 47 | if (!in_array($scope, array('admin','user','reseller'))) 48 | throw new Exception('No such scope'); 49 | 50 | $this->_scope = $scope; 51 | } 52 | 53 | public function render($active){ 54 | 55 | $str = $this->addLogo(); 56 | $str .= '
57 | 65 |
66 |
67 | '; 68 | } 69 | 70 | public function addLogo(){ 71 | return ''; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /lib/SpamExperts_API.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | class SpamExperts_API { 30 | 31 | protected $_host; 32 | protected $_port; 33 | protected $_login; 34 | protected $_pass; 35 | 36 | /** 37 | * {"messages":{"error":["Domain already exists.","Failed to add domain 'gmail.com'"]},"result":null} 38 | * @param string $hostname 39 | * @param string $username 40 | * @param string $password 41 | */ 42 | public function __construct($hostname, $username, $password){ 43 | $this->_host = $hostname; 44 | $this->_port = 80; 45 | 46 | if ( 47 | preg_match('!^ssl://!i', $hostname) 48 | || preg_match('!^https://!i', $hostname) 49 | ) { 50 | $this->_port = 443; 51 | } 52 | 53 | $this->_login = $username; 54 | $this->_pass = $password; 55 | } 56 | 57 | /** 58 | * {"messages":[],"result":{"present":0}} 59 | * @param string $domain 60 | * @throws Exception 61 | */ 62 | public function getDomainStatus($domain){ 63 | $sock = $this->_getSocket(); 64 | 65 | $sock->query('/api/domain/exists/domain/'.$domain.'/format/json'); 66 | $result = $sock->fetch_body(); 67 | $json = json_decode($result, true); 68 | 69 | if (!$result || !$json) 70 | throw new Exception('Unable to get domain status.', 500); 71 | 72 | // the “present” field value can be 1 or 0 indicating the domain presents or is missing in the spamfilter. 73 | if (isset($json['result']['present'])){ 74 | return (bool)$json['result']['present']; 75 | } 76 | 77 | // This is somewhat of an edge case apparently. If it happens the domain isn't there. 78 | if (preg_match('/does not belong to the admin/i', implode('. ', $json['messages']['error']))) { 79 | return FALSE; 80 | } 81 | 82 | throw new Exception( isset($json['messages']['error']) ? implode('. ', $json['messages']['error']) : 'Unknown error.' ); 83 | } 84 | 85 | /** 86 | * 87 | * @param array $domains 88 | * @return array 89 | */ 90 | public function toggleDomains(array $domains){ 91 | $conf = new Configuration(); 92 | $daApi = new DirectAdmin_API(); 93 | 94 | $toProtect = array(); 95 | $toUnprotect = array(); 96 | foreach ($domains as $domain){ 97 | try { 98 | $status = $this->getDomainStatus($domain); 99 | } catch (Exception $e){ 100 | $status = false; 101 | } 102 | 103 | if (!$status){ // protect 104 | $toProtect[] = $domain; 105 | } else { // unprotect 106 | $toUnprotect[] = $domain; 107 | } 108 | } 109 | 110 | $results = $this->protectDomains($toProtect, $conf, $daApi); 111 | $results = array_merge($results, $this->unprotectDomains($toUnprotect, $conf, $daApi) ); 112 | 113 | return $results; 114 | } 115 | 116 | /** 117 | * 118 | * @param string $domain 119 | * @return bool 120 | * @throws Exception 121 | */ 122 | public function login($domain){ 123 | $sock = $this->_getSocket(); 124 | 125 | $sock->query('/api/authticket/create/username/'.$domain.'/format/json/'); 126 | $result = $sock->fetch_body(); 127 | $json = json_decode($result, true); 128 | 129 | if (!$result || !$json) 130 | throw new Exception('Unable to get domain login token.', 500); 131 | 132 | // If the “result” field is not empty further redirect user to: {Spampanel URL}/?authticket=96902e3989150ebedffcb6a9f7c01a1070aa4d8b 133 | // (in a new browser window/tab preferrably). 134 | // {"messages":[],"result":"96902e3989150ebedffcb6a9f7c01a1070aa4d8b"} 135 | if (isset($json['result']) && $json['result']) 136 | return $json['result']; 137 | return null; 138 | } 139 | 140 | /** 141 | * 142 | * @param array $domains 143 | * @param Configuration $conf main configuration object 144 | * @param DirectAdmin_API $daApi 145 | * @return array Results for each domain 146 | */ 147 | public function protectDomains(array $domains, Configuration $conf, DirectAdmin_API $daApi){ 148 | $results = array(); 149 | 150 | // load domains if checking is required 151 | if (!$conf->get('process_addon_and_parked_domains') || $conf->get('do_not_protect_remote_domains')){ 152 | $allDomains = $daApi->getAllDomains(); 153 | } 154 | 155 | foreach ($domains as $domain){ 156 | if (!$conf->get('process_addon_and_parked_domains')){ 157 | if (isset($allDomains[$domain]) && $allDomains[$domain]->pointsto){ 158 | $results[$domain] = array('action' => 'protect', 'result' => false, 'msg' => 'Pointers domains are disabled for adding to the Spam Filter'); 159 | continue; 160 | } 161 | } 162 | if ($conf->get('do_not_protect_remote_domains')){ 163 | if (isset($allDomains[$domain]) && $allDomains[$domain]->isRemote()){ 164 | $results[$domain] = array('action' => 'protect', 'result' => false, 'msg' => 'Remote domains are disabled for adding to the Spam Filter'); 165 | continue; 166 | } 167 | } 168 | 169 | // use the domain itself as the default destination route 170 | $mxes = "$domain"; 171 | 172 | // each domain in the spamfilter has at least one destination route a hostname where all the 173 | // clean email should be delivered and it is reasonable to use actual MX records on a 174 | // domain’s MX records switching as a destination for the clean email. 175 | if ($conf->get('use_existing_mx_as_routes')){ 176 | try { 177 | $mxrecords = $daApi->getDomainsMxRecords($domain); 178 | if (count($mxrecords)) { 179 | $mxes = implode('","', array_map(function ($mxrecord) { 180 | return $mxrecord['full']; 181 | }, $mxrecords)); 182 | } 183 | } catch (Exception $e){} 184 | } 185 | $sock = $this->_getSocket(); 186 | $sock->query('/api/domain/add/domain/'.$domain.'/destinations/["'.$mxes.'"]/format/json/'); 187 | $result = $sock->fetch_body(); 188 | $json = json_decode($result, true); 189 | 190 | if (!$result || !$json){ 191 | $results[$domain] = array('action' => 'protect', 'result' => false); 192 | continue; 193 | } 194 | 195 | // in case the result doesn’t contain errors it is safe to assume that the domain has been added (protected) successfully. 196 | if (!isset($json['messages']['error']) || empty($json['messages']['error'])){ 197 | $results[$domain] = array('action' => 'protect', 'result' => true); 198 | 199 | // After a domain is successfully protected and the “Automatically change the MX records for domains” option is active 200 | // it is required to update it’s MX records with the “Primary MX”, “Secondary MX” and “Tertiary MX” fields’ values 201 | if ($conf->get('automatically_change_mx')){ 202 | $newMX = array(); 203 | $defaultMX = array('primary_mx' => '10', 'secondary_mx' => '20', 'tertiary_mx' => '30'); 204 | foreach (array('primary_mx','secondary_mx','tertiary_mx') as $mx_key){ 205 | if ($conf->get($mx_key)) { 206 | 207 | $MXPriority = $conf->get($mx_key . '_priority'); 208 | $value = empty($MXPriority) ? $defaultMX[$mx_key] : $MXPriority; 209 | 210 | $newMX[] = array( 211 | 'type' => 'MX', 212 | 'name' => $conf->get($mx_key) . '.', 213 | 'value' => $value, 214 | 'priority' => $value, 215 | ); 216 | } 217 | } 218 | 219 | if (!empty($newMX)){ 220 | $dns = $daApi->getDns($domain); 221 | $currentMX = $dns->getRecords('MX'); 222 | if ($currentMX) 223 | $dns->delete($currentMX); 224 | $dns->modify($newMX); 225 | } 226 | } 227 | 228 | } else { 229 | $results[$domain] = array('action' => 'protect', 'result' => false, 'msg' => implode('
', $json['messages']['error'])); 230 | } 231 | } 232 | return $results; 233 | } 234 | 235 | public function unprotectDomains(array $domains, Configuration $conf, DirectAdmin_API $daApi){ 236 | $results = array(); 237 | 238 | foreach ($domains as $domain){ 239 | $routes = array(); 240 | $sock = $this->_getSocket(); 241 | 242 | if ($conf->get('automatically_change_mx')) { 243 | $sock->query('/api/domain/getroute/domain/' . $domain . '/format/json/'); 244 | $result = $sock->fetch_body(); 245 | $json = json_decode($result, true); 246 | $routes = $json['result']; 247 | } 248 | 249 | $sock->query('/api/domain/remove/domain/'.$domain.'/format/json/'); 250 | $result = $sock->fetch_body(); 251 | $json = json_decode($result, true); 252 | 253 | if (!$result || !$json){ 254 | $results[$domain] = array('action' => 'unprotect', 'result' => false); 255 | continue; 256 | } 257 | 258 | // in case the result doesn't contain errors it is safe to assume that the domain has been removed (unprotected) successfully. 259 | if (!isset($json['messages']['error']) || empty($json['messages']['error'])) { 260 | $dns = $daApi->getDns($domain); 261 | if ($conf->get('automatically_change_mx')) { 262 | $newMX = array(); 263 | foreach ($routes as $key => $route) { 264 | $route = $this->removePort($route); 265 | $route = $this->reverseDNS($route); 266 | 267 | if ($route) { 268 | $newMX[] = array( 269 | 'type' => 'MX', 270 | 'name' => $route . ".", 271 | 'value' => '', 272 | 'priority' => (1 + $key) * 10, 273 | ); 274 | } 275 | } 276 | 277 | $currentMX = $dns->getRecords('MX'); 278 | 279 | if ($currentMX) { 280 | $dns->delete($currentMX); 281 | } 282 | $dns->modify($newMX); 283 | } 284 | 285 | // last chance: check if we have some mx, if not use hostname 286 | if (!$dns->getRecords('MX')) { 287 | $newMX[] = array( 288 | 'type' => 'MX', 289 | 'name' => gethostname().".", 290 | 'value' => '', 291 | 'priority' => 10, 292 | ); 293 | 294 | $dns->modify($newMX); 295 | } 296 | 297 | $results[$domain] = array('action' => 'unprotect', 'result' => true); 298 | } else { 299 | $results[$domain] = array('action' => 'unprotect', 'result' => false); 300 | } 301 | } 302 | return $results; 303 | } 304 | 305 | protected function _getSocket(){ 306 | $sock = new DirectAdmin_HTTPSocket(); 307 | $sock->connect($this->_host, $this->_port); 308 | $sock->set_login($this->_login, $this->_pass); 309 | 310 | $pluginDir = dirname(dirname(__FILE__)); 311 | $enableDebugMode = file_exists($pluginDir . '/debug'); 312 | $sock->setDebugMode($enableDebugMode); 313 | 314 | $processUser = trim(`whoami`); 315 | $logPath = $pluginDir . "/logs/prospamfilter_{$processUser}.log"; 316 | $sock->setLogPath($logPath); 317 | 318 | return $sock; 319 | } 320 | 321 | /** 322 | * Try to get hostname from ip 323 | * 324 | * @param $record 325 | * @return mixed 326 | */ 327 | 328 | private static function reverseDNS($record) { 329 | if(filter_var($record, FILTER_VALIDATE_IP) == $record){ 330 | $hostname = gethostbyaddr($record); 331 | if ($hostname && $hostname != $record) { 332 | return $hostname; 333 | } 334 | 335 | return false; 336 | } 337 | 338 | return $record; 339 | } 340 | 341 | /** 342 | * Removes port from gathered route 343 | * 344 | * @param type $route 345 | * @return sanitized route 346 | */ 347 | 348 | private static function removePort($route){ 349 | $x = explode('::', $route); 350 | if (count($x)>1) { 351 | array_pop($x); 352 | } 353 | 354 | return implode("::", $x); 355 | } 356 | 357 | } 358 | -------------------------------------------------------------------------------- /lib/plugin.php: -------------------------------------------------------------------------------- 1 | http://modulesgarden.com 10 | * CONTACT -> contact@modulesgarden.com 11 | * 12 | * 13 | * 14 | * 15 | * This software is furnished under a license and may be used and copied 16 | * only in accordance with the terms of such license and with the 17 | * inclusion of the above copyright notice. This software or any other 18 | * copies thereof may not be provided or otherwise made available to any 19 | * other person. No title to and ownership of the software is hereby 20 | * transferred. 21 | * 22 | * 23 | * ******************************************************************** */ 24 | 25 | /** 26 | * @author Grzegorz Draganik 27 | */ 28 | 29 | if (!defined('SE_BASE_DIR')){ 30 | define('SE_BASE_DIR', dirname(__DIR__)); 31 | } 32 | 33 | if (!defined('DS')) 34 | define('DS', DIRECTORY_SEPARATOR); 35 | 36 | spl_autoload_register(function ($class_name) { 37 | $path = __DIR__ . DS . $class_name . '.php'; 38 | if (!file_exists($path)) 39 | throw new Exception('File '.$path.' does not exists!'); 40 | include_once $path; 41 | }); 42 | 43 | function pasteAssets(){ 44 | return ' 45 | 46 | 47 | 48 | 49 | 50 | '; 51 | } 52 | 53 | function getParam($key, $default = null){ 54 | $params = getParams(); 55 | return isset($params[$key]) ? $params[$key] : $default; 56 | } 57 | 58 | function getParams(){ 59 | parse_str($_SERVER['QUERY_STRING'], $output); 60 | return $output; 61 | } 62 | 63 | function getPOSTValues(){ 64 | parse_str($_SERVER['POST'], $values); 65 | return $values; 66 | } 67 | 68 | function pastePaginationHtml($total, $page, $limit, array $additionalParams = array()){ 69 | $pagesStr = ''; 70 | $urlStr = '?'; 71 | foreach ($additionalParams as $k => $v) 72 | $urlStr .= $k . '=' . $v . '&'; 73 | $pagesCount = ceil($total / $limit); 74 | for ($p = 1; $p <= $pagesCount; $p++){ 75 | $pagesStr .= ''.$p.' '; 76 | } 77 | return ' 78 |
79 |
80 | Page '.$page.' of '.($pagesCount == 0 ? 1 : $pagesCount).'; Total '.$total.' 81 |
82 |
83 | '.($pagesStr ? 'Page: '.$pagesStr : '').' 84 |
85 |
86 |
87 | '; 88 | } 89 | -------------------------------------------------------------------------------- /plugin.conf.new: -------------------------------------------------------------------------------- 1 | active=yes 2 | author=SpamExperts 3 | id= 4 | installed=yes 5 | name="Professional Spam Filter" 6 | update_url=http://download.cdn.seinternal.com/releases/addons/directadmin/latest.tar.gz 7 | version=4.0.1726059124 8 | version_url=http://download.cdn.seinternal.com/releases/addons/directadmin/latest_version.html 9 | -------------------------------------------------------------------------------- /reseller/ajax.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | _isUsersDomain($this->_params['domain'])) 11 | $this->sendResponse(false, 'Domain does not belong to you'); 12 | 13 | $api = $this->_getSpamExpertsApi(); 14 | $res = $api->getDomainStatus( $this->_params['domain'] ); 15 | $msg = $res ? 'This domain is present in the filter.' : 'This domain is not present in the filter.'; 16 | $msgColor = $res ? 'green' : 'red'; 17 | $this->sendResponse(true, ''.$msg.'', array( 18 | 'domainstatus' => $res ? 1 : 0 19 | )); 20 | 21 | } catch (Exception $e){ 22 | $this->sendResponse(false, $e->getMessage(), array( 23 | 'domainstatus' => 0 24 | )); 25 | 26 | } 27 | } 28 | 29 | public function call_login(){ 30 | try { 31 | if (!$this->_isUsersDomain($this->_params['domain'])) 32 | $this->sendResponse(false, 'Domain does not belong to you'); 33 | 34 | $conf = new Configuration(); 35 | $api = $this->_getSpamExpertsApi(); 36 | 37 | if ($conf->get('add_domain_during_login')){ 38 | $api->protectDomains( array($this->_params['domain']), $conf, new DirectAdmin_API() ); 39 | } 40 | 41 | $res = $api->login( $this->_params['domain'] ); 42 | $msg = $res ? 'Logging for '.$domain.' successful' : 'Unable to get login token for ' . $domain; 43 | $this->sendResponse($res ? true : false, $msg, array( 44 | 'token' => $res, 45 | 'url' => $conf->get('spampanel_url') . '/?authticket=' . $res 46 | )); 47 | 48 | } catch (Exception $e){ 49 | $this->sendResponse(false, $e->getMessage()); 50 | } 51 | } 52 | 53 | public function call_toggleDomains(){ 54 | try { 55 | foreach ($this->_params['domains'] as $d){ 56 | if (!$this->_isUsersDomain($d)) 57 | $this->sendResponse(false, 'Domain does not belong to you'); 58 | } 59 | 60 | $api = $this->_getSpamExpertsApi(); 61 | $this->sendResponse(true, 'OK', array( 62 | 'results' => $api->toggleDomains( $this->_params['domains'] ) 63 | )); 64 | 65 | } catch (Exception $e){ 66 | $this->sendResponse(false, $e->getMessage()); 67 | 68 | } 69 | } 70 | 71 | public function call_protectDomains(){ 72 | try { 73 | foreach ($this->_params['domains'] as $d){ 74 | if (!$this->_isUsersDomain($d)) 75 | $this->sendResponse(false, 'Domain does not belong to you'); 76 | } 77 | 78 | $api = $this->_getSpamExpertsApi(); 79 | $this->sendResponse(true, 'OK', array( 80 | 'results' => $api->protectDomains( $this->_params['domains'], new Configuration(), new DirectAdmin_API() ) 81 | )); 82 | 83 | } catch (Exception $e){ 84 | $this->sendResponse(false, $e->getMessage()); 85 | } 86 | } 87 | 88 | public function call_unprotectDomains(){ 89 | try { 90 | foreach ($this->_params['domains'] as $d){ 91 | if (!$this->_isUsersDomain($d)) 92 | $this->sendResponse(false, 'Domain does not belong to you'); 93 | } 94 | 95 | $api = $this->_getSpamExpertsApi(); 96 | $this->sendResponse(true, 'OK', array( 97 | 'results' => $api->unprotectDomains( $this->_params['domains'], new Configuration(), new DirectAdmin_API() ) 98 | )); 99 | 100 | } catch (Exception $e){ 101 | $this->sendResponse(false, $e->getMessage()); 102 | } 103 | } 104 | 105 | 106 | protected function _isUsersDomain($domain){ 107 | $api = new DirectAdmin_API(); 108 | return $api->isUsersDomain($domain, true); 109 | } 110 | 111 | private function _getSpamExpertsApi(){ 112 | $conf = new Configuration(); 113 | 114 | return new SpamExperts_API( 115 | $conf->get('api_hostname'), 116 | $conf->get('api_username'), 117 | $conf->get('api_password') 118 | ); 119 | } 120 | 121 | } 122 | 123 | $ajax = new Ajax_SpamExperts(); 124 | $ajax->processRequest( getParams() ); 125 | -------------------------------------------------------------------------------- /reseller/index.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | getAllDomains(array( 14 | 'page' => $page, 15 | 'limit' => $limit, 16 | 'searchUsername'=> $searchUsername, 17 | 'searchDomain' => $searchDomain, 18 | 'searchReseller'=> getenv('USERNAME'), 19 | )); 20 | } catch (Exception $e){ 21 | echo '
'.$e->getMessage().'
'; 22 | die(); 23 | } 24 | 25 | $menu = new Menu('reseller'); 26 | echo $menu->addLogo(); 27 | ?> 28 | 29 |
30 |
31 | 32 |
33 |
34 | 35 |
36 |
37 | 38 |
39 | 40 |
41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
DomainUsernamePresent in FilterToggle ProtectionLogin
pointsto ? 'P: ' : '') . $domain->domain; ?>username; ?>Check statusToggle ProtectionLogin
No domains found.
71 | 72 | $searchUsername, 75 | 'searchDomain' => $searchDomain, 76 | 'searchReseller'=> getenv('USERNAME'), 77 | )); 78 | ?> 79 | 80 | 81 | 82 | 83 |
84 | Progress: 85 |
86 |
87 | 88 |
89 |
90 |
91 |
92 | 93 |
94 | 95 | 228 | -------------------------------------------------------------------------------- /reseller/login.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | No domain provided
'; 11 | die(); 12 | } 13 | 14 | try { 15 | $conf = new Configuration(); 16 | $api = new SpamExperts_API($conf->get('api_hostname'), $conf->get('api_username'), $conf->get('api_password')); 17 | $DAapi = new DirectAdmin_API(); 18 | 19 | if (!$DAapi->isUsersDomain($domain, true)) { 20 | throw new Exception("This domain does not belong to you"); 21 | } 22 | 23 | if ($conf->get('add_domain_during_login')) { 24 | $api->protectDomains(array($domain), $conf, new DirectAdmin_API()); 25 | } 26 | 27 | $res = $api->login($domain); 28 | $msg = $res ? 'Logging for ' . $domain . ' successful. Please wait...' : 'Unable to get login token for ' . $domain; 29 | 30 | } catch (Exception $e) { 31 | echo '
' . $e->getMessage() . '
'; 32 | die(); 33 | } 34 | 35 | ?> 36 | 37 |
Please Wait...
38 | 39 | -------------------------------------------------------------------------------- /scripts/getconfig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpamExperts/directadmin-addon/84c6b59228ac35e5b36e8704d1f5065ef558d831/scripts/getconfig -------------------------------------------------------------------------------- /scripts/hooks/domain_create_post.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo `php /usr/local/directadmin/plugins//hooks/scripts/domain_create_post.php $domain` 4 | 5 | exit 0; -------------------------------------------------------------------------------- /scripts/hooks/domain_destroy_post.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo `php /usr/local/directadmin/plugins//hooks/scripts/domain_destroy_post.php $domain` 4 | 5 | exit 0; -------------------------------------------------------------------------------- /scripts/hooks/domain_pointer_create_post.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo `php /usr/local/directadmin/plugins//hooks/scripts/domain_pointer_create_post.php $from` 4 | 5 | exit 0; -------------------------------------------------------------------------------- /scripts/hooks/domain_pointer_destroy_post.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo `php /usr/local/directadmin/plugins//hooks/scripts/domain_pointer_destroy_post.php $from` 4 | 5 | exit 0; -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pluginpath=$DOCUMENT_ROOT../; 4 | DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ); 5 | PDIR="$(dirname "$DIR")"; 6 | PLUGIN=${PDIR##*/}; 7 | 8 | HOOKFILES="$PDIR/hooks/*" 9 | HOOKSCRIPTS="$PDIR/scripts/hooks/*" 10 | ADMINFILES="$PDIR/admin/*" 11 | RESELLERFILES="$PDIR/reseller/*" 12 | USERFILES="$PDIR/user/*" 13 | CONFFILE="$PDIR/plugin.conf" 14 | LIBFILES="$PDIR/lib/*" 15 | 16 | mv "$pluginpath/configuration.conf.new" "$pluginpath/configuration.conf"; 17 | mv "$pluginpath/directadminapi.conf.new" "$pluginpath/directadminapi.conf"; 18 | mv "$pluginpath/plugin.conf.new" "$pluginpath/plugin.conf"; 19 | 20 | ALLFILES="$HOOKFILES $HOOKSCRIPTS $ADMINFILES $RESELLERFILES $USERFILES $LIBFILES $CONFFILE" 21 | 22 | for file in $ALLFILES; do 23 | sed -i -e "s//$PLUGIN/g" $file 24 | done; 25 | 26 | echo "Adding hooks to DirectAdmin
" 27 | 28 | for hook in domain_create_post domain_destroy_post domain_pointer_create_post domain_pointer_destroy_post; do 29 | if [ -e "$pluginpath../../scripts/custom/$hook.sh" ] ; then 30 | echo "WARNING! - hook file '$hook.sh' already exist
"; 31 | else 32 | cp "$pluginpath/scripts/hooks/$hook.sh" "$pluginpath../../scripts/custom/" 33 | chmod 770 "$pluginpath../../scripts/custom/$hook.sh" 34 | chown diradmin:diradmin "$pluginpath../../scripts/custom/$hook.sh" 35 | fi 36 | done; 37 | 38 | echo "Creating configuration files
" 39 | 40 | chmod -R 755 $pluginpath/* 41 | chown -R diradmin:diradmin $pluginpath/* 42 | 43 | # creating configuration files 44 | for conf in configuration.conf directadminapi.conf plugin.conf; do 45 | if [ ! -e "$pluginpath$conf" ] ; then 46 | touch "$pluginpath$conf" 47 | fi 48 | chmod 660 "$pluginpath$conf" 49 | chown diradmin:diradmin "$pluginpath$conf" 50 | done; 51 | 52 | chown root:root "$pluginpath/scripts/getconfig" 2>&1 53 | chmod 4755 "$pluginpath/scripts/getconfig" 2>&1 54 | 55 | if [ ! -e "$pluginpath/logs" ]; then 56 | mkdir "$pluginpath/logs" 57 | fi 58 | chmod 777 "$pluginpath/logs" 59 | chown diradmin:diradmin "$pluginpath/logs" 60 | 61 | echo "Plugin Installed!
"; 62 | exit 0; 63 | -------------------------------------------------------------------------------- /scripts/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pluginpath=$DOCUMENT_ROOT../ 4 | 5 | echo "Removing hooks from DirectAdmin
" 6 | 7 | for hook in domain_create_post domain_destroy_post domain_pointer_create_post domain_pointer_destroy_post; do 8 | installedhook="$pluginpath../../scripts/custom/$hook.sh" 9 | if [ ! -f $installedhook ]; then 10 | continue 11 | fi 12 | cmp --silent $installedhook "${DOCUMENT_ROOT}hooks/$hook.sh" 13 | if [ $? -ne 0 ]; then 14 | echo "WARNING! - hook file '$hook.sh' differs from the plugin's one. Skipping it.
" 15 | else 16 | rm "$pluginpath../../scripts/custom/$hook.sh" 17 | fi 18 | done 19 | 20 | echo "Plugin Un-Installed!" 21 | 22 | exit 0 23 | -------------------------------------------------------------------------------- /scripts/update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pluginpath=$DOCUMENT_ROOT../ 4 | DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 5 | PDIR="$(dirname "$DIR")" 6 | PLUGIN=${PDIR##*/} 7 | 8 | HOOKFILES="$PDIR/hooks/*" 9 | HOOKSCRIPTS="$PDIR/scripts/hooks/*" 10 | ADMINFILES="$PDIR/admin/*" 11 | RESELLERFILES="$PDIR/reseller/*" 12 | USERFILES="$PDIR/user/*" 13 | CONFFILE="$PDIR/plugin.conf" 14 | LIBFILES="$PDIR/lib/*" 15 | 16 | ALLFILES="$HOOKFILES $HOOKSCRIPTS $ADMINFILES $RESELLERFILES $USERFILES $LIBFILES $CONFFILE" 17 | 18 | for file in $ALLFILES; do 19 | sed -i -e "s//$PLUGIN/g" $file 20 | done 21 | 22 | chmod -R 755 $pluginpath/* 23 | chown -R diradmin:diradmin $pluginpath/* 24 | 25 | # creating configuration files 26 | for conf in configuration.conf directadminapi.conf plugin.conf; do 27 | if [ ! -e "$pluginpath$conf" ] ; then 28 | touch "$pluginpath$conf" 29 | fi 30 | chmod 660 "$pluginpath$conf" 31 | chown diradmin:diradmin "$pluginpath$conf" 32 | done 33 | 34 | chown root:root "$pluginpath/scripts/getconfig" 2>&1 35 | chmod 4755 "$pluginpath/scripts/getconfig" 2>&1 36 | 37 | if [ ! -e "$pluginpath/logs" ]; then 38 | mkdir "$pluginpath/logs" 39 | fi 40 | chmod 777 "$pluginpath/logs" 41 | chown diradmin:diradmin "$pluginpath/logs" 42 | 43 | rm "$pluginpath/configuration.conf.new"; 44 | rm "$pluginpath/directadminapi.conf.new"; 45 | 46 | # update plugin.conf with new version number and urls 47 | newupdateurl=$(grep "^update_url=.*$" "$pluginpath/plugin.conf.new") 48 | sed -i -e "s|^update_url=.*$|$newupdateurl|" "$pluginpath/plugin.conf" 49 | newversion=$(grep "^version=.*$" "$pluginpath/plugin.conf.new") 50 | sed -i -e "s|^version=.*$|$newversion|" "$pluginpath/plugin.conf" 51 | newversionurl=$(grep "^version_url=.*$" "$pluginpath/plugin.conf.new") 52 | sed -i -e "s|^version_url=.*$|$newversionurl|" "$pluginpath/plugin.conf" 53 | 54 | rm "$pluginpath/plugin.conf.new" 55 | 56 | echo "Plugin has been updated!" 57 | 58 | exit 0 59 | -------------------------------------------------------------------------------- /user/ajax.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | _isUsersDomain($this->_params['domain'])) 11 | $this->sendResponse(false, 'Domain does not belong to you'); 12 | 13 | $api = $this->_getSpamExpertsApi(); 14 | $res = $api->getDomainStatus( $this->_params['domain'] ); 15 | $msg = $res ? 'This domain is present in the filter.' : 'This domain is not present in the filter.'; 16 | $msgColor = $res ? 'green' : 'red'; 17 | $this->sendResponse(true, ''.$msg.'', array( 18 | 'domainstatus' => $res ? 1 : 0 19 | )); 20 | 21 | } catch (Exception $e){ 22 | $this->sendResponse(false, $e->getMessage(), array( 23 | 'domainstatus' => 0 24 | )); 25 | 26 | } 27 | } 28 | 29 | public function call_login(){ 30 | try { 31 | if (!$this->_isUsersDomain($this->_params['domain'])) 32 | $this->sendResponse(false, 'Domain does not belong to you'); 33 | 34 | $conf = new Configuration(); 35 | $api = $this->_getSpamExpertsApi(); 36 | 37 | if ($conf->get('add_domain_during_login')){ 38 | $api->protectDomains( array($this->_params['domain']), $conf, new DirectAdmin_API() ); 39 | } 40 | 41 | $res = $api->login( $this->_params['domain'] ); 42 | $msg = $res ? 'Logging for '.$domain.' successful' : 'Unable to get login token for ' . $domain; 43 | $this->sendResponse($res ? true : false, $msg, array( 44 | 'token' => $res, 45 | 'url' => $conf->get('spampanel_url') . '/?authticket=' . $res 46 | )); 47 | 48 | } catch (Exception $e){ 49 | $this->sendResponse(false, $e->getMessage()); 50 | } 51 | } 52 | 53 | protected function _isUsersDomain($domain){ 54 | $api = new DirectAdmin_API(); 55 | return $api->isUsersDomain($domain); 56 | } 57 | 58 | 59 | 60 | private function _getSpamExpertsApi(){ 61 | $conf = new Configuration(); 62 | 63 | return new SpamExperts_API( 64 | $conf->get('api_hostname'), 65 | $conf->get('api_username'), 66 | $conf->get('api_password') 67 | ); 68 | } 69 | 70 | } 71 | 72 | $ajax = new Ajax_SpamExperts(); 73 | $ajax->processRequest( getParams() ); 74 | -------------------------------------------------------------------------------- /user/index.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | getAllDomains(array( 13 | 'page' => $page, 14 | 'limit' => $limit, 15 | 'searchUsername'=> getenv('USERNAME'), 16 | 'searchDomain' => $searchDomain, 17 | )); 18 | } catch (Exception $e){ 19 | echo '
'.$e->getMessage().'
'; 20 | die(); 21 | } 22 | $menu = new Menu('user'); 23 | echo $menu->addLogo(); 24 | ?> 25 | 26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
DomainPresent in FilterLogin
pointsto ? 'P: ' : '') . $domain->domain; ?>Check statusLogin
No domains found.
59 | 60 | getenv('USERNAME'), 63 | 'searchDomain' => $searchDomain, 64 | )); 65 | ?> 66 | 67 |
68 | 69 | 124 | -------------------------------------------------------------------------------- /user/login.html: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/php -d disable_functions="" 2 | No domain provided'; 11 | die(); 12 | } 13 | 14 | try { 15 | $conf = new Configuration(); 16 | $api = new SpamExperts_API($conf->get('api_hostname'), $conf->get('api_username'), $conf->get('api_password')); 17 | $DAapi = new DirectAdmin_API(); 18 | 19 | if (!$DAapi->isUsersDomain($domain)) { 20 | throw new Exception("This domain does not belong to you"); 21 | } 22 | 23 | if ($conf->get('add_domain_during_login')) { 24 | $api->protectDomains(array($domain), $conf, new DirectAdmin_API()); 25 | } 26 | 27 | $res = $api->login($domain); 28 | $msg = $res ? 'Logging for ' . $domain . ' successful. Please wait...' : 'Unable to get login token for ' . $domain; 29 | 30 | } catch (Exception $e) { 31 | echo '
' . $e->getMessage() . '
'; 32 | die(); 33 | } 34 | 35 | ?> 36 | 37 |
Please Wait...
38 | 39 | --------------------------------------------------------------------------------