├── .gitignore ├── .gitmodules ├── .jshintrc ├── .travis.yml ├── CONTRIBUTING.md ├── Gemfile ├── HACKING.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── Rakefile ├── Vagrantfile ├── bin ├── ami-provision.sh ├── ami.json ├── send-diagnostics-to-vip.php ├── vip-init ├── wp └── wp-filter.awk ├── puppet ├── files │ └── nginx │ │ ├── nginx.conf.erb │ │ └── vip.dev.erb └── manifests │ ├── helpers │ ├── env.pp │ └── line.pp │ ├── init.pp │ └── sections │ ├── cache.pp │ ├── clamav.pp │ ├── database.pp │ ├── env.pp │ ├── gitplugin.pp │ ├── mail.pp │ ├── php.pp │ ├── security.pp │ ├── subversion.pp │ ├── tools.pp │ ├── webserver.pp │ └── wp.pp └── www ├── .gitignore ├── config ├── batcache-config.php ├── is-mobile.php ├── roles.php └── vip-config.php ├── index.php ├── wp-config.php ├── wp-content ├── advanced-cache.php ├── index.php ├── mu-plugins │ ├── .gitignore │ ├── alloptions-limit.php │ ├── batcache.php │ ├── http-concat │ │ ├── cssconcat.php │ │ ├── cssmin.php │ │ ├── jsconcat.php │ │ └── ngx-http-concat.php │ ├── infinite-scroll.php │ ├── mobile-theme-bootstrap.php │ ├── quickstart.php │ ├── rewrite-rules-inspector-helper.php │ ├── vip.php │ └── wpcom.php ├── object-cache.php ├── sunrise.php └── themes │ └── vip │ └── .gitignore └── wp-tests └── wp-tests-config.php /.gitignore: -------------------------------------------------------------------------------- 1 | # Because WordPress is SVN and this is git 2 | .svn 3 | 4 | # Because this really is a working directory, ignore vagrant's files 5 | /.vagrant 6 | 7 | # Enables local modifications 8 | wp-cli.local.yml 9 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "puppet/modules/stdlib"] 2 | path = puppet/modules/stdlib 3 | url = https://github.com/puppetlabs/puppetlabs-stdlib.git 4 | [submodule "puppet/modules/puppi"] 5 | path = puppet/modules/puppi 6 | url = https://github.com/example42/puppi.git 7 | [submodule "puppet/modules/php"] 8 | path = puppet/modules/php 9 | url = https://github.com/jippi/puppet-php.git 10 | [submodule "puppet/modules/mysql"] 11 | path = puppet/modules/mysql 12 | url = https://github.com/example42/puppet-mysql.git 13 | [submodule "puppet/modules/nginx"] 14 | path = puppet/modules/nginx 15 | url = https://github.com/netmanagers/puppet-nginx.git 16 | [submodule "puppet/modules/wp"] 17 | path = puppet/modules/wp 18 | url = https://github.com/joshbetz/puppet-wp.git 19 | [submodule "puppet/modules/ufw"] 20 | path = puppet/modules/ufw 21 | url = https://github.com/anl/puppet-ufw.git 22 | [submodule "puppet/modules/vcsrepo"] 23 | path = puppet/modules/vcsrepo 24 | url = https://github.com/puppetlabs/puppetlabs-vcsrepo.git 25 | [submodule "puppet/modules/apt"] 26 | path = puppet/modules/apt 27 | url = https://github.com/puppetlabs/puppetlabs-apt.git 28 | [submodule "puppet/modules/ssh"] 29 | path = puppet/modules/ssh 30 | url = https://github.com/attachmentgenie/attachmentgenie-ssh.git 31 | [submodule "puppet/modules/inifile"] 32 | path = puppet/modules/inifile 33 | url = https://github.com/puppetlabs/puppetlabs-inifile.git 34 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "boss": true, 3 | "curly": true, 4 | "eqeqeq": true, 5 | "eqnull": true, 6 | "es3": true, 7 | "expr": true, 8 | "immed": true, 9 | "noarg": true, 10 | "onevar": true, 11 | "quotmark": "single", 12 | "trailing": true, 13 | "undef": true, 14 | "unused": true, 15 | 16 | "browser": true, 17 | 18 | "globals": { 19 | "_": false, 20 | "Backbone": false, 21 | "jQuery": false, 22 | "wp": false 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | rvm: 1.9.3 2 | notifications: 3 | email: 4 | - joshb@a8c.com 5 | env: 6 | - PUPPET_VERSION=2.6.14 7 | - PUPPET_VERSION=2.7.11 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribute 2 | 3 | There are a few different components in VIP Quickstart, so the process for contributing can vary, but the general process is always the same: 4 | 5 | 1. Search for [open issues](https://github.com/automattic/vip-quickstart/issues) that are releated. If you can't find anything, open a new issue to get some initial feedback. 6 | 2. [Fork](https://github.com/automattic/vip-quickstart/fork) the repository and make your changes. 7 | 3. Open a [pull request](https://github.com/automattic/vip-quickstart/pulls) 8 | 9 | If you're looking at this project for the first time, check out the [HACKING](HACKING.md) file to get an idea of how the project is set up. 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | if ENV.key?('PUPPET_VERSION') 4 | puppetversion = "= #{ENV['PUPPET_VERSION']}" 5 | else 6 | puppetversion = ['>= 2.7'] 7 | end 8 | 9 | gem 'rake' 10 | gem 'puppet-lint', '=1.0.1' 11 | gem 'rspec-puppet' 12 | gem 'puppet', puppetversion 13 | -------------------------------------------------------------------------------- /HACKING.md: -------------------------------------------------------------------------------- 1 | # Hacking 2 | 3 | Here's an introduction to developing VIP Quickstart. If you have any additional questions, feel free to open an issue so we can write the proper documentation. 4 | 5 | ## AMI 6 | 7 | We distribute an AMI on AWS. To build the AMI, we have a Packer configuration. 8 | 9 | * Install Packer. https://www.packer.io/docs/installation.html 10 | * Set up AWS keys. 11 | * In `bin`, run `packer build ami.json`. 12 | 13 | ## Testing 14 | 15 | At this point we only only test that the syntax is correct with puppet-lint. 16 | 17 | ## Structure 18 | 19 | * bin - Scripts 20 | * puppet - All Puppet manifests, modules, and template 21 | * wbin - Short for Windows bin. Windows ports of the scripts necessary for VIP Quickstart. 22 | * www - The web root, this is where all WordPress files live. 23 | * config - Configuration files 24 | * wp - SVN checkout of http://core.svn.wordpress.org/trunk/ 25 | * wp-cli - The latest stable version of WP-CLI 26 | * wp-content - Just like the normal wp-content directory, this is where all themes and plugins live 27 | * themes/vip - The VIP themes directory 28 | * themes/vip/plugins - The VIP shared plugins directory 29 | * local-config.php - A local WordPress configuration file that's not under version control 30 | * wp-cli.yml - The WP-CLI config 31 | * wp-tests - SVN checkout of WordPress-Tests from http://develop.svn.wordpress.org/trunk/ 32 | 33 | ## Bin scripts 34 | 35 | Any changes to the vip-init script needs to be mirrored to the wbin versions. Generally, we're trying to keep the init script as minimal as possible. If everything could be done in Puppet, that would be ideal. 36 | 37 | ## Puppet 38 | 39 | Manifests that live in `puppet/manifests/sections` get loaded automatically. If you're working on something that doesn't fit into any of the current sections, create a new one there. 40 | 41 | When adding a module, add it as a git submodule in `puppet/modules`. Actively developed repositories are prefered to stale ones. 42 | 43 | ## WordPress 44 | 45 | Plugins can be added in Puppet by adding it to the list in `puppet/manifests/sections/wp.pp` 46 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | VIP Quickstart is deprecated as of March 13, 2017. Support for Quickstart will continue through April 21, 2017. For new environments, we recommend using Chassis or VVV as detailed in the [Local Environment documentation](https://vip.wordpress.com/documentation/vip/dev-environment/). 2 | -------------------------------------------------------------------------------- /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 | ![VIP Quickstart](http://vip.wordpress.com/wp-content/themes/a8c/wpcomvip3/img/illustrations/developmenttools-03.svg) 2 | 3 | ## Deprecated 4 | 5 | **Note:** VIP Quickstart is deprecated as of March 13, 2017. **Support for Quickstart ends April 21, 2017**. For new environments, we recommend using Chassis or VVV as detailed in the [Local Environment documentation](https://vip.wordpress.com/documentation/vip/dev-environment/). 6 | 7 | For full Quickstart documentation, see [http://vip.wordpress.com/documentation/quickstart/](http://vip.wordpress.com/documentation/quickstart/). 8 | 9 | ## Overview 10 | 11 | VIP Quickstart is a local development environment for WordPress.com VIP developers. It provides developers with an environment that closely mirrors WordPress.com along with all the tools we recommend developers use. VIP Quickstart should not be used to run a production site. 12 | 13 | ## What You Get 14 | 15 | * Ubuntu 12.04 16 | * WordPress trunk 17 | * WordPress.com VIP Shared Plugins repository 18 | * WordPress multisite 19 | * WordPress unit tests 20 | * Custom WordPress.com modifications 21 | * WP-CLI 22 | * MySQL 23 | * PHP 24 | * Nginx 25 | * PHPUnit 26 | 27 | ## Acknowledgements 28 | 29 | Thanks to the following projects that VIP Quickstart is built on: 30 | 31 | * [Vagrant](http://vagrantup.com/) 32 | * [Puppet](http://puppetlabs.com/) 33 | * [Varying Vagrant Vagrants](https://github.com/10up/varying-vagrant-vagrants) 34 | * [WP-CLI](http://wp-cli.org) 35 | * [puppet-mysql](https://github.com/example42/puppet-mysql) 36 | * [puppet-nginx](https://github.com/example42/puppet-nginx) 37 | * [puppet-php](https://github.com/jippi/puppet-php) 38 | * [puppi](https://github.com/example42/puppi) 39 | * [puppet-wp](https://github.com/rmccue/puppet-wp) 40 | 41 | If you're not developing for WordPress.com VIP, you might want to check out these other Vagrant/WordPress projects 42 | 43 | * [VVV](https://github.com/Varying-Vagrant-Vagrants/VVV) 44 | * [Salty WordPress](https://github.com/humanmade/Salty-WordPress) 45 | * [Vagrant Genesis](https://github.com/genesis/wordpress/) 46 | * [VagrantPress](https://github.com/chad-thompson/vagrantpress) 47 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'puppet-lint/tasks/puppet-lint' 2 | 3 | # Ignore modules, they should test themselves 4 | PuppetLint.configuration.ignore_paths = ["puppet/modules/**/*.pp"] 5 | 6 | # Disable 80 chars check 7 | PuppetLint.configuration.send("disable_80chars") 8 | PuppetLint.configuration.send("disable_autoloader_layout") 9 | 10 | # Disable documentation check 11 | PuppetLint.configuration.send('disable_documentation') 12 | 13 | task :default => [:lint] 14 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! 5 | VAGRANTFILE_API_VERSION = "2" 6 | 7 | #Vagrant.require_version ">= 1.5.0" 8 | if `vagrant --version` < 'Vagrant 1.5.0' 9 | abort('Your Vagrant is too old. Please install at least 1.5.0') 10 | end 11 | 12 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 13 | 14 | config.vm.box = "precise32" 15 | config.vm.box_url = "http://files.vagrantup.com/precise32.box" 16 | config.vm.hostname = 'vip.local' 17 | config.vm.network :private_network, ip: "10.86.73.80" 18 | config.ssh.insert_key = false #see https://github.com/Automattic/vip-quickstart/issues/502 19 | config.ssh.username = "vagrant" 20 | config.ssh.password = "vagrant" 21 | 22 | 23 | # Virtualbox overrides 24 | config.vm.provider "virtualbox" do |v| 25 | # Use 1GB of memory 26 | v.memory = 1024 27 | 28 | # Use 2 CPUs 29 | v.cpus = 2 30 | 31 | v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 32 | v.customize ["modifyvm", :id, "--natdnsproxy1", "on"] 33 | v.customize ["modifyvm", :id, "--ioapic", "on"] 34 | v.customize ["modifyvm", :id, "--nictype1", "Am79C973"] 35 | end 36 | 37 | # VMWare Fusion overrides 38 | config.vm.provider "vmware_fusion" do |v| 39 | # Use 1GB of memory in vmware_fusion 40 | v.memory = 1024 41 | 42 | v.vm.box = "precise64-vmware" 43 | v.vm.box_url = "http://files.vagrantup.com/precise64_vmware.box" 44 | end 45 | 46 | config.vm.synced_folder ".", "/srv", owner: 'www-data', group: 'www-data', mount_options: ["dmode=775", "fmode=664"] 47 | 48 | # Address a bug in an older version of Puppet 49 | # See http://stackoverflow.com/questions/10894661/augeas-support-on-my-vagrant-machine 50 | config.vm.provision :shell, :inline => "if ! dpkg -s puppet > /dev/null; then sudo apt-get update --quiet --yes && sudo apt-get install puppet --quiet --yes; fi" 51 | 52 | # Provision everything we need with Puppet 53 | config.vm.provision :puppet do |puppet| 54 | puppet.module_path = "puppet/modules" 55 | puppet.manifests_path = "puppet/manifests" 56 | puppet.manifest_file = "init.pp" 57 | puppet.options = ['--templatedir', '/srv/puppet/files'] 58 | puppet.facter = { 59 | "quickstart_domain" => 'vip.local', 60 | } 61 | end 62 | 63 | end 64 | -------------------------------------------------------------------------------- /bin/ami-provision.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Update apt 4 | sudo apt-get update --yes --quiet 5 | 6 | # Install requirements 7 | sudo apt-get install git --yes --quiet 8 | sudo apt-get install puppet --yes --quiet 9 | 10 | # Download Quickstart 11 | sudo git clone https://github.com/Automattic/vip-quickstart.git /srv 12 | 13 | # Install Quickstart 14 | sudo /srv/bin/vip-init --server --domain=vip.dev 15 | 16 | # Delete all authorized_key files 17 | sudo find / -name "authorized_keys" -print -exec rm {} \; 18 | -------------------------------------------------------------------------------- /bin/ami.json: -------------------------------------------------------------------------------- 1 | { 2 | "builders": [ 3 | { 4 | "type": "amazon-ebs", 5 | "region": "us-east-1", 6 | "source_ami": "ami-2acc7a42", 7 | "instance_type": "t1.micro", 8 | "ssh_username": "ubuntu", 9 | "ami_name": "VIP Quickstart {{timestamp}}" 10 | } 11 | ], 12 | 13 | "provisioners": [ 14 | { 15 | "type": "shell", 16 | "inline": [ "sleep 10" ] 17 | }, 18 | { 19 | "type": "shell", 20 | "script": "ami-provision.sh" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /bin/send-diagnostics-to-vip.php: -------------------------------------------------------------------------------- 1 | 0 ) ) { 147 | 148 | $vip_zendesk_email = 'support+id' . $ticket_id . '@wordpressvip.zendesk.com'; 149 | $subject = 'VIP Quickstart diagnostic report from ' . $from_address . ' for #' . $ticket_id . ''; 150 | 151 | } else { 152 | 153 | $vip_zendesk_email = $default_support_email; 154 | $subject = 'VIP Quickstart diagnostic report from ' . $from_address; 155 | 156 | } 157 | 158 | $headers = "From: $from_address\r\n"; 159 | 160 | // should we try to test network access before sending? 161 | 162 | mail( $vip_zendesk_email, $subject, $report_output, $headers ); 163 | 164 | echo "Sent report by email.\n"; 165 | 166 | } else { 167 | 168 | print $report_output; 169 | 170 | } 171 | 172 | exit; 173 | 174 | function read_cli_option( $prompt = "" ) { 175 | echo $prompt; 176 | $out = ""; 177 | $char = ""; 178 | while ( "\r" != $char && "\n" != $char ) { 179 | $out.= $char; 180 | $char = fread( STDIN, 1 ); 181 | } 182 | return $out; 183 | } 184 | 185 | ?> 186 | -------------------------------------------------------------------------------- /bin/vip-init: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Note: VIP Quickstart is deprecated as of March 13, 2017. Please see https://vip.wordpress.com/documentation/vip/dev-environment/" 4 | exit 1 5 | 6 | # ===================================== 7 | # Set cwd to vip-quickstart 8 | # ===================================== 9 | DIR="$( dirname $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) )" 10 | ORIG=`pwd` 11 | cd $DIR 12 | 13 | # ===================================== 14 | # Setup command line flags 15 | # ===================================== 16 | SERVER=false 17 | 18 | for i in "$@" 19 | do 20 | case $i in 21 | --server) 22 | SERVER=true 23 | ;; 24 | --domain=*) 25 | QUICKSTART_DOMAIN=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` 26 | ;; 27 | *) 28 | # unknown option 29 | ;; 30 | esac 31 | done 32 | 33 | # Only use this script to configure servers 34 | if [ false == $SERVER ]; then 35 | git pull 36 | git submodule update --init --recursive 37 | vagrant reload --no-provision || vagrant up --no-provision 38 | vagrant provision 39 | exit 40 | fi 41 | 42 | # ===================================== 43 | # Setup other options 44 | # ===================================== 45 | IS_INSTALLED=`which wp && wp core is-installed` 46 | 47 | 48 | # ===================================== 49 | # VIP Quickstart 50 | # ===================================== 51 | echo ' 52 | _ __(_)___ ____ ___ __(_)____/ /_______/ /_____ ______/ /_ 53 | | | / / / __ \ / __ `/ / / / / ___/ //_/ ___/ __/ __ `/ ___/ __/ 54 | | |/ / / /_/ / / /_/ / /_/ / / /__/ ,< (__ ) /_/ /_/ / / / /_ 55 | |___/_/ .___/ \__, /\__,_/_/\___/_/|_/____/\__/\__,_/_/ \__/ 56 | /_/ /_/ 57 | 58 | ' 59 | 60 | # ===================================== 61 | # Check for requirements 62 | # ===================================== 63 | if [[ ! `which git` || ! `which puppet` ]]; then 64 | echo "Please install the requirements" 65 | echo "* Git" 66 | echo "* Puppet" 67 | exit 1 68 | fi 69 | 70 | # ===================================== 71 | # Give ourselves root access for the rest of the script 72 | # ===================================== 73 | sudo -k 74 | sudo -p "Enter your password to continue:" whoami 1>/dev/null || exit 75 | echo "" 76 | 77 | 78 | # ===================================== 79 | # Ask for domain 80 | # ===================================== 81 | if [[ -z "$QUICKSTART_DOMAIN" && ! $IS_INSTALLED ]]; then 82 | echo "==================================" 83 | echo "= Domain Setup" 84 | echo "==================================" 85 | 86 | read -e -p "What domain would you like to use? [vip.dev]:" QUICKSTART_DOMAIN 87 | QUICKSTART_DOMAIN="${QUICKSTART_DOMAIN:-vip.dev}" 88 | echo "" 89 | fi 90 | 91 | 92 | # ===================================== 93 | # Automatically update the repo 94 | # ===================================== 95 | echo "==================================" 96 | echo "= Updating VIP Quickstart" 97 | echo "==================================" 98 | 99 | git pull 100 | git submodule sync 101 | git submodule update --init --recursive 102 | echo "" 103 | 104 | 105 | # ===================================== 106 | # Start the VM (always provision, even if it's already running) 107 | # ===================================== 108 | echo "==================================" 109 | echo "= Provisioning" 110 | echo "==================================" 111 | [[ -n "$QUICKSTART_DOMAIN" ]] && export FACTER_quickstart_domain="$QUICKSTART_DOMAIN" 112 | puppet apply --modulepath=/srv/puppet/modules --templatedir=/srv/puppet/files /srv/puppet/manifests/init.pp 113 | echo "" 114 | 115 | 116 | # ===================================== 117 | # Outro/next steps 118 | # ===================================== 119 | if [[ ! $IS_INSTALLED ]]; then 120 | echo "==================================" 121 | echo "= Next Steps" 122 | echo "==================================" 123 | 124 | echo "* Go to http://$QUICKSTART_DOMAIN in your browser" 125 | echo "" 126 | fi 127 | 128 | 129 | # ===================================== 130 | # Kill sudo timestamp 131 | # ===================================== 132 | sudo -k 133 | 134 | # ===================================== 135 | # Reset cwd 136 | # ===================================== 137 | cd $ORIG 138 | -------------------------------------------------------------------------------- /bin/wp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | QUOTED_ARGS='' 5 | 6 | if [ "$1" == "test-wp-filter" ]; then 7 | echo "" 8 | fi 9 | 10 | for SINGLE_ARG in "$@"; do 11 | 12 | # $@ argument expansion removes quotes. 13 | # Re-quote if they need it, giving special treatment to --flag=value syntax. 14 | 15 | FIXED=$( echo "$SINGLE_ARG" | awk -f "$DIR/wp-filter.awk" ) 16 | 17 | # Test script: 18 | # wp test-wp-filter escaped\ space --long_flag-name="foo bar" --single-quotes='foo bar' --escaped=foo\ bar --no-equals "foo bar" no quotes here "Escaping \"double quotes\" is fine" 19 | # 20 | # Expected output: 21 | # 'escaped space' 22 | # --long_flag-name='foo bar' 23 | # --single-quotes='foo bar' 24 | # --escaped='foo bar' 25 | # --no-equals 26 | # 'foo bar' 27 | # no 28 | # quotes 29 | # here 30 | # 'Escaping "double quotes" is fine' 31 | 32 | if [ "$1" == "test-wp-filter" ]; then 33 | echo "$FIXED" 34 | else 35 | QUOTED_ARGS="$QUOTED_ARGS $FIXED" 36 | fi 37 | 38 | done; 39 | 40 | if [ "$1" == "test-wp-filter" ]; then 41 | echo "" 42 | else 43 | vagrant ssh -c "cd /srv/www/wp; /usr/bin/wp $QUOTED_ARGS" -- -q 44 | fi 45 | -------------------------------------------------------------------------------- /bin/wp-filter.awk: -------------------------------------------------------------------------------- 1 | # Add single quotes back to arguments with spaces, 2 | # because bash's $@ syntax removes them. 3 | # 4 | # Wraps in single quotes, because Bash allows escaping of double-quotes, but not single. 5 | # For example, bash doesn't allow this: 6 | # 'Escaping \'single quotes\'' 7 | # 8 | # So we're unlikely to get an argument with single quotes in it. 9 | # Edge case: user goes to great lengths, concatenating strings. 10 | # See http://stackoverflow.com/questions/1250079/escaping-single-quotes-within-single-quoted-strings 11 | # 12 | # If a user escapes double quotes, like this: 13 | # "Escaping \"double quotes\"" 14 | # 15 | # The string will come through as: 16 | # Escaping "double quotes" 17 | # 18 | # Which will be converted back to: 19 | # 'Escaping "double quotes"' 20 | # 21 | # Which is fine. 22 | 23 | { 24 | # Check if argument contains spaces. 25 | # Space escapes have already been processed. 26 | if ( $0 ~ / / ) { 27 | 28 | # Is it a flag argument following --flag=value syntax? 29 | if ( $0 ~ /--([a-zA-Z0-9_-]+)=(.*)/ ) { 30 | 31 | # Add single quote after equals sign 32 | gsub( "=", "='", $0 ); 33 | 34 | # Add single quote at end 35 | print( $0 "'" ) 36 | 37 | }else { 38 | # Normal argument. Wrap in single quotes 39 | print( "'" $0 "'" ) 40 | } 41 | 42 | }else { 43 | 44 | # No unescaped spaces. Print as-is 45 | print( $0 ) 46 | 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /puppet/files/nginx/nginx.conf.erb: -------------------------------------------------------------------------------- 1 | # File Managed by Puppet 2 | user <%= scope.lookupvar('nginx::process_user') %>; 3 | worker_processes <%= @processorcount %>; 4 | 5 | error_log <%= scope.lookupvar('nginx::log_dir')%>/error.log; 6 | pid <%= scope.lookupvar('nginx::pid_file')%>; 7 | 8 | events { 9 | worker_connections <%= scope.lookupvar('nginx::worker_connections')%>; 10 | <% if scope.lookupvar('nginx::nx_multi_accept') == 'on' %>multi_accept on;<% end %> 11 | } 12 | 13 | http { 14 | server_tokens off; 15 | include <%= scope.lookupvar('nginx::config_dir')%>/mime.types; 16 | default_type application/octet-stream; 17 | 18 | access_log <%= scope.lookupvar('nginx::log_dir')%>/access.log; 19 | 20 | sendfile off; 21 | tcp_nopush on; 22 | tcp_nodelay on; 23 | 24 | client_max_body_size <%= scope.lookupvar('nginx::client_max_body_size')%>; 25 | keepalive_timeout <%= scope.lookupvar('nginx::keepalive_timeout')%>; 26 | types_hash_max_size <%= scope.lookupvar('nginx::types_hash_max_size') %>; 27 | 28 | gzip <%= scope.lookupvar('nginx::real_gzip')%>; 29 | gzip_comp_level 2; 30 | gzip_http_version 1.0; 31 | gzip_proxied any; 32 | gzip_min_length 1100; 33 | gzip_buffers 16 8k; 34 | gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript; 35 | 36 | # Disable for IE < 6 because there are known problems 37 | gzip_disable "MSIE [1-6]\.(?!.*SV1)"; 38 | 39 | fastcgi_buffers 16 16k; 40 | fastcgi_buffer_size 32k; 41 | 42 | include <%= scope.lookupvar('nginx::vdir')%>/*.conf; 43 | } 44 | -------------------------------------------------------------------------------- /puppet/files/nginx/vip.dev.erb: -------------------------------------------------------------------------------- 1 | # File Managed by Puppet 2 | 3 | server { 4 | listen <%= @port %>; 5 | server_name <%= @name %> <%= @serveraliases %>; 6 | 7 | root <%= @docroot %>; 8 | 9 | access_log <%= scope.lookupvar('nginx::log_dir')%>/<%= @name %>.access.log; 10 | error_log <%= scope.lookupvar('nginx::log_dir')%>/<%= @name %>.error.log; 11 | 12 | index index.html index.php; 13 | 14 | # Block all requests to hidden files 15 | location ~ /\. { 16 | deny all; 17 | } 18 | 19 | # Block all requests to config files 20 | location ~ /((wp|local)-config)\.php$ { 21 | deny all; 22 | } 23 | 24 | # Don't try to rewrite static assets 25 | # Just return 404 if not found 26 | # The reason is pretty simple: each 404'd asset will try to pass that to WP 27 | # Spawning a bunch of unwanted requests and making things SLOOOOOOOW 28 | location ~ \.(png|jpg|css|js)$ { 29 | try_files $uri return 404; 30 | } 31 | 32 | location / { 33 | try_files $uri $uri/ /index.php?$args; 34 | } 35 | 36 | if (!-e $request_filename) { 37 | # Add trailing slash to */wp-admin requests. 38 | rewrite /wp-admin$ $scheme://$host$uri/ permanent; 39 | 40 | # WordPress in a subdirectory rewrite rules 41 | rewrite ^/([_0-9a-zA-Z-]+/)?(wp-.*|xmlrpc.php) /wp/$2 break; 42 | } 43 | 44 | # Pass all .php files onto a php-fpm/php-fcgi server. 45 | location ~ \.php$ { 46 | try_files $uri =404; 47 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 48 | include fastcgi_params; 49 | fastcgi_index index.php; 50 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 51 | fastcgi_pass unix:/run/php/php7.0-fpm.sock; 52 | } 53 | 54 | location /_static/ { 55 | fastcgi_pass unix:/run/php/php7.0-fpm.sock; 56 | include /etc/nginx/fastcgi_params; 57 | fastcgi_param SCRIPT_FILENAME $document_root/wp-content/mu-plugins/http-concat/ngx-http-concat.php; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /puppet/manifests/helpers/env.pp: -------------------------------------------------------------------------------- 1 | # env 2 | define env($value) { 3 | line { $title: 4 | file => '/etc/environment', 5 | line => "${title}='${value}'", 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /puppet/manifests/helpers/line.pp: -------------------------------------------------------------------------------- 1 | # line 2 | define line($file, $line, $ensure = 'present') { 3 | case $ensure { 4 | default : { err ( "unknown ensure value ${ensure}" ) } 5 | present: { 6 | exec { "/bin/echo '${line}' >> '${file}'": 7 | unless => "/bin/grep -qFx '${line}' '${file}'" 8 | } 9 | } 10 | absent: { 11 | exec { "/usr/bin/perl -ni -e 'print unless /^\\Q${line}\\E\$/' '${file}'": 12 | onlyif => "/bin/grep -qFx '${line}' '${file}'" 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /puppet/manifests/init.pp: -------------------------------------------------------------------------------- 1 | Exec { path => '/bin:/usr/bin:/usr/local/bin:/usr/sbin:/sbin' } 2 | 3 | import 'helpers/*' 4 | import 'sections/*' 5 | 6 | # Make sure apt-get is up-to-date before we do anything else 7 | stage { 'updates': before => Stage['main'] } 8 | class { 'updates': stage => updates } 9 | 10 | # updates 11 | class updates { 12 | exec { 'apt-get update': 13 | command => 'apt-get update --quiet --yes', 14 | timeout => 0 15 | } 16 | } 17 | 18 | if 'physical' == $::virtual { 19 | exec { 'apt-get upgrade': 20 | command => 'apt-get upgrade --quiet --yes', 21 | timeout => 0 22 | } 23 | } 24 | 25 | user { ['vagrant', 'ubuntu']: 26 | groups => 'www-data', 27 | } 28 | -------------------------------------------------------------------------------- /puppet/manifests/sections/cache.pp: -------------------------------------------------------------------------------- 1 | package { 'memcached': } 2 | -------------------------------------------------------------------------------- /puppet/manifests/sections/clamav.pp: -------------------------------------------------------------------------------- 1 | # ClamAV 2 | package { 'clamav': ensure => present } 3 | 4 | exec { 'update clamav db': 5 | command => 'sudo freshclam', 6 | require => Package['clamav'] 7 | } 8 | -------------------------------------------------------------------------------- /puppet/manifests/sections/database.pp: -------------------------------------------------------------------------------- 1 | 2 | class database::settings { 3 | $mysql_password = generate('/bin/sh', '-c', "< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c\${1:-64};echo -n;") 4 | } 5 | 6 | include database::settings 7 | 8 | mysql::grant { 'wordpress': 9 | mysql_privileges => 'ALL', 10 | mysql_password => $database::settings::mysql_password, 11 | mysql_db => 'wordpress', 12 | mysql_user => 'wordpress', 13 | mysql_host => 'localhost', 14 | } 15 | 16 | mysql::grant { 'wptests': 17 | mysql_privileges => 'ALL', 18 | mysql_password => 'wptests', 19 | mysql_db => 'wptests', 20 | mysql_user => 'wptests', 21 | mysql_host => 'localhost', 22 | } 23 | 24 | mysql::augeas { 25 | 'mysqld/log_slow_queries': 26 | value => '/var/log/mysql/mysql-slow.log', 27 | require => Package['mysql']; 28 | } 29 | -------------------------------------------------------------------------------- /puppet/manifests/sections/env.pp: -------------------------------------------------------------------------------- 1 | env { 'WP_CLI_CONFIG_PATH': value => '/srv/www/wp-cli.yml' } 2 | env { 'WP_TESTS_DIR': value => '/srv/www/wp-tests/tests/phpunit/' } 3 | 4 | # Set an environment variable for staging environments 5 | if 'physical' == $::virtual { 6 | env { 'QUICKSTART_ENV': value => 'physical' } 7 | } else { 8 | env { 'QUICKSTART_ENV': value => 'virtual' } 9 | } 10 | 11 | # Setup hosts file: 12 | if ( $quickstart_domain ) { 13 | line { 'hosts': 14 | file => '/etc/hosts', 15 | line => "127.0.0.1 ${quickstart_domain}", 16 | notify => Service['networking'], 17 | } 18 | } 19 | 20 | # Set up Zeroconf (Bonjour) 21 | package { 'libnss-mdns': ensure => present } 22 | 23 | # Ensure networking service is running 24 | service { 'networking': ensure => running } 25 | -------------------------------------------------------------------------------- /puppet/manifests/sections/gitplugin.pp: -------------------------------------------------------------------------------- 1 | # GitPlugin clones a git repo into the www/wp-content/plugins directory and activates it in WordPress 2 | define gitplugin ( $git_urls ) { 3 | vcsrepo { "/srv/www/wp-content/plugins/${title}" : 4 | ensure => present, 5 | force => true, 6 | source => $git_urls[$title], 7 | provider => git, 8 | require => [ 9 | Wp::Site['/srv/www/wp'], 10 | File['/srv/www/wp-content/plugins'], 11 | ] 12 | } 13 | 14 | wp::command { "plugin activate ${title}": 15 | command => "plugin activate ${title} --network", 16 | location => '/srv/www/wp', 17 | require => Vcsrepo["/srv/www/wp-content/plugins/${title}"], 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /puppet/manifests/sections/mail.pp: -------------------------------------------------------------------------------- 1 | # Postfix 2 | package { 'postfix': ensure => present } 3 | service { 'postfix': ensure => running } 4 | exec { 'configure postfix hostname': 5 | command => "sed -i 's/precise32/${quickstart_domain}/g' /etc/postfix/main.cf", 6 | onlyif => 'cat /etc/postfix/main.cf | grep "precise32"', 7 | user => root, 8 | notify => Service['postfix'] 9 | } 10 | 11 | # Mailtuils for sending diagnostic reports 12 | package { 'mailutils': ensure => installed } 13 | -------------------------------------------------------------------------------- /puppet/manifests/sections/php.pp: -------------------------------------------------------------------------------- 1 | # PHP 5.6 + extensions 2 | include php 3 | include apt 4 | 5 | apt::ppa { 'ppa:ondrej/php': } 6 | 7 | package { [ 'php7.0-fpm', 'php7.0-cli' ]: 8 | ensure => present, 9 | require => Apt::Ppa['ppa:ondrej/php'] 10 | } 11 | package { [ 12 | 'php-memcache', 13 | 'php-imagick', 14 | 15 | 'php7.0-curl', 16 | 'php7.0-mbstring', 17 | 'php7.0-mcrypt', 18 | 'php7.0-mysql', 19 | 'php7.0-imap', 20 | 'php7.0-json', 21 | 'php7.0-soap', 22 | 'php7.0-ssh2', 23 | 'php7.0-gd', 24 | 'php7.0-xml', 25 | 'php7.0-zip', 26 | ]: 27 | ensure => present, 28 | require => Apt::Ppa['ppa:ondrej/php'] 29 | } 30 | 31 | file_line { 'php error_log': 32 | path => '/etc/php/7.0/fpm/php.ini', 33 | line => 'error_log = /tmp/php-errors', 34 | match => '^error_log', 35 | require => Package['php7.0-fpm'] 36 | } 37 | -------------------------------------------------------------------------------- /puppet/manifests/sections/security.pp: -------------------------------------------------------------------------------- 1 | if 'physical' == $virtual { 2 | # SSH 3 | include ssh::server 4 | 5 | # UFW 6 | include ufw 7 | ufw::limit { 22: } 8 | ufw::allow { 'allow-all-http': 9 | port => 80, 10 | ip => 'any', 11 | } 12 | ufw::allow { 'allow-all-https': 13 | port => 443, 14 | ip => 'any', 15 | } 16 | ufw::allow { 'allow-dns-over-udp': 17 | port => 53, 18 | proto => 'udp', 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /puppet/manifests/sections/subversion.pp: -------------------------------------------------------------------------------- 1 | stage { 'svnupgrade': before => Stage['main'] } 2 | class { 'svnupgrade': stage => svnupgrade } 3 | 4 | # svnupgrade 5 | class svnupgrade { 6 | line { 'deb svn': 7 | file => '/etc/apt/sources.list', 8 | line => 'deb http://ppa.launchpad.net/svn/ppa/ubuntu precise main', 9 | notify => Exec['apt-get update svn'] 10 | } 11 | line { 'deb-src svn': 12 | file => '/etc/apt/sources.list', 13 | line => 'deb-src http://ppa.launchpad.net/svn/ppa/ubuntu precise main', 14 | notify => Exec['apt-get update svn'] 15 | } 16 | 17 | exec { 'apt-get update svn': 18 | command => 'sudo apt-get update', 19 | refreshonly => true, 20 | require => [ 21 | Line['deb svn'], 22 | Line['deb-src svn'] 23 | ] 24 | } 25 | 26 | exec { 'svn': 27 | command => 'sudo apt-get install subversion --yes --force-yes', 28 | unless => 'sudo apt-get install subversion | grep "0 upgraded, 0 newly installed"', 29 | require => [ 30 | Line['deb svn'], 31 | Line['deb-src svn'], 32 | Exec['apt-get update svn'] 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /puppet/manifests/sections/tools.pp: -------------------------------------------------------------------------------- 1 | $tools = [ 2 | 'ack-grep', 3 | 'vim', 4 | 'unzip', 5 | 'zip', 6 | ] 7 | 8 | package { $tools: } 9 | 10 | # Install ack as ack 11 | file { '/usr/local/bin/ack': 12 | ensure => 'link', 13 | target => '/usr/bin/ack-grep', 14 | require => Package['ack-grep'], 15 | } 16 | -------------------------------------------------------------------------------- /puppet/manifests/sections/webserver.pp: -------------------------------------------------------------------------------- 1 | class { 'nginx': 2 | template => 'nginx/nginx.conf.erb', 3 | disable_default_site => true, 4 | client_max_body_size => '1024m', 5 | types_hash_max_size => '2048', 6 | } 7 | 8 | nginx::vhost { '_': 9 | docroot => '/srv/www', 10 | template => 'nginx/vip.dev.erb', 11 | owner => 'www-data', 12 | groupowner => 'www-data', 13 | } 14 | -------------------------------------------------------------------------------- /puppet/manifests/sections/wp.pp: -------------------------------------------------------------------------------- 1 | $plugins = [ 2 | 'log-deprecated-notices', 3 | 'monster-widget', 4 | 'query-monitor', 5 | 'user-switching', 6 | 'wordpress-importer', 7 | 8 | # WordPress.com 9 | 'keyring', 10 | 'mrss', 11 | 'polldaddy', 12 | 'rewrite-rules-inspector', 13 | ] 14 | 15 | $github_plugins = { 16 | 'vip-scanner' => 'https://github.com/Automattic/vip-scanner', 17 | 18 | # WordPress.com 19 | 'jetpack' => 'https://github.com/Automattic/jetpack', 20 | 'media-explorer' => 'https://github.com/Automattic/media-explorer', 21 | 'writing-helper' => 'https://github.com/automattic/writing-helper', 22 | 'amp' => 'https://github.com/automattic/amp-wp', 23 | } 24 | 25 | include database::settings 26 | 27 | # Delete broken plugins 28 | file { '/srv/www/wp-content/plugins/log-viewer': 29 | ensure => 'absent', 30 | force => true, 31 | before => Wp::Site['/srv/www/wp'], 32 | } 33 | 34 | # Install WordPress 35 | wp::site { '/srv/www/wp': 36 | url => $quickstart_domain, 37 | sitename => $quickstart_domain, 38 | admin_user => 'wordpress', 39 | admin_password => 'wordpress', 40 | network => true, 41 | require => [ 42 | Vcsrepo['/srv/www/wp'], 43 | Line['path:/srv/www/wp'], 44 | ] 45 | } 46 | 47 | # Install GitHub Plugins 48 | $github_plugin_keys = keys( $github_plugins ) 49 | gitplugin { $github_plugin_keys: 50 | git_urls => $github_plugins 51 | } 52 | 53 | # Install plugins 54 | wp::plugin { $plugins: 55 | location => '/srv/www/wp', 56 | networkwide => true, 57 | require => [ 58 | Wp::Site['/srv/www/wp'], 59 | File['/srv/www/wp-content/plugins'], 60 | Gitplugin[ $github_plugin_keys ], 61 | ] 62 | } 63 | 64 | # Update all the plugins 65 | wp::command { 'plugin update --all': 66 | command => 'plugin update --all', 67 | location => '/srv/www/wp', 68 | require => Wp::Site['/srv/www/wp'], 69 | } 70 | 71 | # Symlink db.php for Query Monitor 72 | file { '/srv/www/wp-content/db.php': 73 | ensure => 'link', 74 | target => 'plugins/query-monitor/wp-content/db.php', 75 | require => Wp::Plugin['query-monitor'] 76 | } 77 | 78 | # Install WP-CLI 79 | class { 'wp::cli': ensure => installed } 80 | 81 | # Make sure the wp-content directories exists 82 | $wp_content_dirs = [ 83 | '/srv/www/wp-content/themes', 84 | '/srv/www/wp-content/plugins', 85 | '/srv/www/wp-content/upgrade', 86 | '/srv/www/wp-content/uploads', 87 | ] 88 | 89 | file { '/srv/www/wp-content': 90 | ensure => directory, 91 | recurse => false, 92 | mode => 0775, 93 | owner => 'www-data', 94 | group => 'www-data', 95 | } 96 | 97 | 98 | file { $wp_content_dirs: 99 | ensure => directory, 100 | recurse => true, 101 | mode => 0664, 102 | owner => 'www-data', 103 | group => 'www-data', 104 | } 105 | 106 | # VCS Checkout 107 | vcsrepo { '/srv/www/wp': 108 | ensure => latest, 109 | source => 'https://core.svn.wordpress.org/trunk/', 110 | provider => svn, 111 | } 112 | 113 | cron { '/srv/www/wp': 114 | command => '/usr/bin/svn up /srv/www/wp > /dev/null 2>&1', 115 | minute => '0', 116 | hour => '*', 117 | } 118 | 119 | vcsrepo { '/srv/www/wp-content/themes/vip/plugins': 120 | ensure => latest, 121 | source => 'https://vip-svn.wordpress.com/plugins/', 122 | provider => svn, 123 | } 124 | 125 | cron { '/srv/www/wp-content/themes/vip/plugins': 126 | command => '/usr/bin/svn up /srv/www/wp-content/themes/vip/plugins > /dev/null 2>&1', 127 | minute => '0', 128 | hour => '*', 129 | } 130 | 131 | vcsrepo { '/srv/www/wp-content/themes/pub/twentyfifteen': 132 | ensure => latest, 133 | source => 'https://wpcom-themes.svn.automattic.com/twentyfifteen', 134 | provider => svn, 135 | } 136 | 137 | vcsrepo { '/srv/www/wp-tests': 138 | ensure => latest, 139 | source => 'https://develop.svn.wordpress.org/trunk/', 140 | provider => svn, 141 | } 142 | 143 | cron { '/srv/www/wp-tests': 144 | command => '/usr/bin/svn up /srv/www/wp-tests > /dev/null 2>&1', 145 | minute => '0', 146 | hour => '*', 147 | } 148 | 149 | if 'physical' == $::virtual { 150 | # Create a local config 151 | file { 'local-config.php': 152 | ensure => present, 153 | path => '/srv/www/local-config.php', 154 | notify => Exec['SUBDOMAIN_INSTALL'], 155 | } 156 | 157 | exec { 'SUBDOMAIN_INSTALL': 158 | command => 'echo "define(\'SUBDOMAIN_INSTALL\', true);" >> /srv/www/local-config.php', 159 | unless => 'grep "SUBDOMAIN_INSTALL /srv/www/local-config.php', 160 | refreshonly => true, 161 | require => Exec['local config header'], 162 | } 163 | } else { 164 | # Create a local config 165 | file { 'local-config.php': 166 | ensure => present, 167 | path => '/srv/www/local-config.php', 168 | } 169 | } 170 | 171 | $jetpack_dev_debug = $::virtual != 'physical' 172 | file_line { 'JETPACK_DEV_DEBUG': 173 | line => "define('JETPACK_DEV_DEBUG', ${jetpack_dev_debug});", 174 | path => '/srv/www/local-config.php', 175 | match => 'JETPACK_DEV_DEBUG', 176 | require => File['local-config.php'], 177 | } 178 | 179 | # Add default path to local WP-CLI config 180 | line { 'path:/srv/www/wp': 181 | line => 'path:/srv/www/wp', 182 | file => '/srv/www/wp-cli.yml', 183 | } 184 | 185 | # Add default domain to local WP-CLI config 186 | if ( $quickstart_domain ) { 187 | line { "url:${quickstart_domain}": 188 | line => "url:${quickstart_domain}", 189 | file => '/srv/www/wp-cli.yml', 190 | } 191 | } 192 | 193 | exec { 'local config header': 194 | command => 'printf " /srv/www/local-config.php;', 195 | unless => 'grep " File['local-config.php'], 197 | } 198 | 199 | exec { 'generate salts': 200 | command => 'curl https://api.wordpress.org/secret-key/1.1/salt/ >> /srv/www/local-config.php', 201 | unless => 'grep "AUTH_KEY" /srv/www/local-config.php', 202 | require => [ 203 | File['local-config.php'], 204 | Exec['local config header'], 205 | ] 206 | } 207 | 208 | # Add MySQL password created in database.pp to local config 209 | file_line { 'Add DB_PASSWORD to local-config.php': 210 | line => "define(\'DB_PASSWORD\', \'${database::settings::mysql_password}\');", 211 | path => '/srv/www/local-config.php', 212 | match => 'DB_PASSWORD', 213 | require => [ 214 | File['local-config.php'], 215 | Exec['local config header'], 216 | ] 217 | } 218 | -------------------------------------------------------------------------------- /www/.gitignore: -------------------------------------------------------------------------------- 1 | # WordPress directory 2 | /wp 3 | /local-config.php 4 | /wp-cli.yml 5 | 6 | # wp-content directory 7 | /wp-content/plugins 8 | /wp-content/themes/* 9 | !vip 10 | /wp-content/uploads 11 | /wp-content/upgrade 12 | /wp-content/db.php 13 | /wp-content/local-sunrise.php 14 | 15 | # tests 16 | /wp-tests 17 | 18 | # Logs 19 | /wp-content/debug.log 20 | -------------------------------------------------------------------------------- /www/config/batcache-config.php: -------------------------------------------------------------------------------- 1 | $__batcacheignore_default ) { 20 | foreach( $__query_args as $qkey => $__query_arg ) { 21 | if ( $__query_arg == $__batcacheignore_default || 0 === stripos( $__query_arg, "$__batcacheignore_default=" ) ) { 22 | $__batcacheignore_args[] = $__batcacheignore_default; 23 | break; 24 | } 25 | } 26 | } 27 | } 28 | 29 | // These are cookies that would normally prohibit caching, but 30 | // we want to serve cached pages to these folks anyway 31 | $batcache['noskip_cookies'] = array( 32 | 'wordpress_test_cookie', 33 | 'wordpress_eli', 34 | 'wpcom-browser-extension-promos-chrome', 35 | 'wpcom-browser-extension-promos-firefox', 36 | 'wpcom_geo', 37 | ); 38 | 39 | // These variables are for the default configuration. Domain-specific configs follow. 40 | 41 | $batcache['max_age'] = 300; // Expire batcache items aged this many seconds (zero to disable supercache) 42 | $batcache['remote'] = 0; // whether to replicate the cache across datacenters (req/sec not replicated) 43 | 44 | $batcache['times'] = 4; // Only batcache a page after it is accessed this many times... (two or more) 45 | $batcache['seconds'] = 60; // ...in this many whole seconds (zero to ignore this and use batcache immediately) 46 | 47 | $batcache['group'] = 'supercache'; // Name of memcached group 48 | 49 | // Unset all the explicitly ignored GET args to make caching more efficient 50 | if ( $__batcacheignore_args ) { 51 | // batcache requires a normalized query string 52 | $_SERVER['QUERY_STRING'] = preg_replace( '#((' . implode('|', $__batcacheignore_args) . ')=[^&]*&?)#', '', $_SERVER['QUERY_STRING'] ); 53 | // batcache requires an empty get superglobal 54 | foreach ( $__batcacheignore_args as $getarg ) 55 | unset( $_GET[$getarg] ); 56 | } 57 | 58 | if ( !isset( $_SERVER[ 'argv' ] ) ) { 59 | // Special signup page 60 | if ( '/wp-signup.php' == $_SERVER['PHP_SELF'] && isset( $_COOKIE['ref'] ) && '360' == $_COOKIE['ref'] ) { 61 | $batcache['max_age'] = 0; // disable batcache 62 | } 63 | 64 | // Don't cache PHP files except the root index.php 65 | if ( substr($_SERVER['REQUEST_URI'], -4) == '.php' && ( '/index.php' != $_SERVER['REQUEST_URI'] ) ) { 66 | $batcache['max_age'] = 0; // disable batcache 67 | } 68 | if ( substr($_SERVER['REQUEST_URI'], -3) == '.js' ) { 69 | $batcache['max_age'] = 0; // disable batcache 70 | } 71 | if ( substr($_SERVER['REQUEST_URI'], -10) == 'robots.txt' ) { 72 | $batcache['max_age'] = 0; // disable batcache 73 | } 74 | /* Disable batcache for /feed/ requests where there is no query string set 75 | * We cache these responses in nginx and having multiple layers of caching 76 | * with no batcache invalidations results in stale data being served and 77 | * subsequently cached 78 | * */ 79 | if ( $_SERVER['REQUEST_URI'] == '/feed/' && $_SERVER['QUERY_STRING'] == '' ) 80 | $batcache['max_age'] = 0; // disable batcache 81 | 82 | if ( $_SERVER['REQUEST_URI'] == '/sitemap.xml' && $_SERVER['QUERY_STRING'] == '' ) 83 | $batcache['max_age'] = 0; // disable batcache 84 | 85 | 86 | // Mobile batcache 87 | if( jetpack_is_mobile() && isset( $_COOKIE['akm_mobile'] ) ) 88 | $batcache['unique']['mobile-force'] = $_COOKIE['akm_mobile'] == 'true' ? 'true' : 'false'; // the akm_mobile cookie is used to force the desktop version of the site when on a mobile device 89 | 90 | if ( Jetpack_User_Agent_Info::is_blackbeberry() ) { 91 | $batcache['unique']['mobile'] = 'blackberry'; 92 | } elseif ( Jetpack_User_Agent_Info::is_WindowsPhone7() ) { 93 | $batcache['unique']['mobile'] = 'windows-phone7'; 94 | } elseif ( Jetpack_User_Agent_Info::is_S60_OSSBrowser() ) { 95 | $batcache['unique']['mobile'] = 'dumb'; 96 | } elseif ( in_array( jetpack_is_mobile( 'smart', true ), array( 'iphone', 'ipod' ) ) ) { 97 | $batcache['unique']['mobile'] = 'iphone'; 98 | } elseif ( jetpack_is_mobile( 'smart' ) ) { 99 | $batcache['unique']['mobile'] = 'smart'; 100 | } elseif ( jetpack_is_mobile( 'dumb' ) ) { 101 | $batcache['unique']['mobile'] = 'dumb'; 102 | } 103 | 104 | // iPad 105 | if ( Jetpack_User_Agent_Info::is_ipad() ) { 106 | if ( false !== strpos( strtolower( $_SERVER['HTTP_USER_AGENT'] ), 'safari' ) ) 107 | $batcache['unique']['ipad'] = 'ipad-safari'; 108 | else 109 | $batcache['unique']['ipad'] = 'ipad'; 110 | } elseif ( Jetpack_User_Agent_Info::is_tablet() ) { 111 | // Tablets 112 | // Should be treated differently from mobile and iPad 113 | $batcache['unique']['tablet'] = 'tablet'; 114 | } 115 | 116 | // UppSite / MySiteApp 117 | if ( ( isset($_SERVER['HTTP_USER_AGENT']) && false !== strpos( strtolower( $_SERVER['HTTP_USER_AGENT'] ), 'mysiteapp' ) ) || isset( $_COOKIE[ 'uppsite_theme_select' ] ) ) 118 | $batcache['max_age'] = 0; // disable batcache 119 | 120 | // Chrome Frame 121 | if ( isset($_SERVER['HTTP_USER_AGENT']) && false !== strpos( strtolower( $_SERVER['HTTP_USER_AGENT'] ), 'chromeframe' ) ) 122 | $batcache['unique']['chromeframe'] = true; 123 | 124 | // Liveblog 125 | if ( preg_match( '%__liveblog_\d+/\d+/\d+|/liveblog/\d+/\d+/?$%', $_SERVER['REQUEST_URI'] ) ) { 126 | // Liveblog requests include the current time (to the second), so it's important that we don't 127 | // wait and that we cache starting from the first request 128 | $batcache['seconds'] = 0; 129 | $batcache['times'] = 0; 130 | // A cached entry should be requested only for a couple of seconds (+/- clock errors), we don't need the whole 5 minutes 131 | $batcache['max_age'] = 30; 132 | } 133 | } 134 | // GET param caching: start 135 | // Never cache if there is a query string unless the script is whitelisted here 136 | // But, some sites/features have GET params deeply integrated with their sites for various reasons. Add overrides below to cache them 137 | $_batcache_cache_get_requests = false; 138 | 139 | // Finally, should we cache GET requests? 140 | if ( ! empty( $_GET ) && false === $_batcache_cache_get_requests ) { 141 | $batcache['max_age'] = 0; 142 | } 143 | // GET param caching: end 144 | 145 | // Finally, blanket exceptions override all other configs 146 | 147 | // Never batcache when run from CLI 148 | if ( isset( $_SERVER[ 'argv' ] ) ) { 149 | $batcache['max_age'] = 0; 150 | } 151 | 152 | // CampTix restricted content token cookie 153 | if ( isset( $_COOKIE['tix_view_token'] ) ) { 154 | $batcache['max_age'] = 0; 155 | } 156 | 157 | $batcache['headers']['X-nananana'] = 'Batcache'; 158 | 159 | unset( $_batcache_script_name ); 160 | 161 | // VIP Quickstart: Fix module activation 162 | $_GET['module'] = $_module; 163 | 164 | // UNCOMMENT THIS LINE TO DISABLE batcache -- KEEP THIS LAST 165 | // $batcache['max_age'] = 0; 166 | -------------------------------------------------------------------------------- /www/config/roles.php: -------------------------------------------------------------------------------- 1 | 5 | array ( 6 | 'name' => 'Administrator', 7 | 'capabilities' => 8 | array ( 9 | 'switch_themes' => true, 10 | 'edit_themes' => true, 11 | 'edit_theme_options' => true, 12 | 'activate_plugins' => true, 13 | 'edit_plugins' => true, 14 | 'edit_users' => true, 15 | 'edit_files' => true, 16 | 'manage_options' => true, 17 | 'moderate_comments' => true, 18 | 'manage_categories' => true, 19 | 'manage_links' => true, 20 | 'upload_files' => true, 21 | 'import' => true, 22 | 'edit_posts' => true, 23 | 'edit_others_posts' => true, 24 | 'edit_published_posts' => true, 25 | 'publish_posts' => true, 26 | 'edit_pages' => true, 27 | 'read' => true, 28 | 'level_10' => true, 29 | 'level_9' => true, 30 | 'level_8' => true, 31 | 'level_7' => true, 32 | 'level_6' => true, 33 | 'level_5' => true, 34 | 'level_4' => true, 35 | 'level_3' => true, 36 | 'level_2' => true, 37 | 'level_1' => true, 38 | 'level_0' => true, 39 | 'list_users' => true, 40 | 'edit_others_pages' => true, 41 | 'edit_published_pages' => true, 42 | 'publish_pages' => true, 43 | 'delete_pages' => true, 44 | 'delete_others_pages' => true, 45 | 'delete_published_pages' => true, 46 | 'delete_posts' => true, 47 | 'delete_others_posts' => true, 48 | 'delete_published_posts' => true, 49 | 'delete_private_posts' => true, 50 | 'edit_private_posts' => true, 51 | 'read_private_posts' => true, 52 | 'delete_private_pages' => true, 53 | 'edit_private_pages' => true, 54 | 'read_private_pages' => true, 55 | 'delete_users' => true, 56 | 'create_users' => true, 57 | 'remove_users' => true, 58 | 'add_users' => true, 59 | 'promote_users' => true, 60 | 'export' => true, 61 | ), 62 | ), 63 | 'editor' => 64 | array ( 65 | 'name' => 'Editor', 66 | 'capabilities' => 67 | array ( 68 | 'moderate_comments' => true, 69 | 'manage_categories' => true, 70 | 'manage_links' => true, 71 | 'upload_files' => true, 72 | 'edit_posts' => true, 73 | 'edit_others_posts' => true, 74 | 'edit_published_posts' => true, 75 | 'publish_posts' => true, 76 | 'edit_pages' => true, 77 | 'read' => true, 78 | 'level_7' => true, 79 | 'level_6' => true, 80 | 'level_5' => true, 81 | 'level_4' => true, 82 | 'level_3' => true, 83 | 'level_2' => true, 84 | 'level_1' => true, 85 | 'level_0' => true, 86 | 'edit_others_pages' => true, 87 | 'edit_published_pages' => true, 88 | 'publish_pages' => true, 89 | 'delete_pages' => true, 90 | 'delete_others_pages' => true, 91 | 'delete_published_pages' => true, 92 | 'delete_posts' => true, 93 | 'delete_others_posts' => true, 94 | 'delete_published_posts' => true, 95 | 'delete_private_posts' => true, 96 | 'edit_private_posts' => true, 97 | 'read_private_posts' => true, 98 | 'delete_private_pages' => true, 99 | 'edit_private_pages' => true, 100 | 'read_private_pages' => true, 101 | ), 102 | ), 103 | 'author' => 104 | array ( 105 | 'name' => 'Author', 106 | 'capabilities' => 107 | array ( 108 | 'upload_files' => true, 109 | 'edit_posts' => true, 110 | 'edit_published_posts' => true, 111 | 'publish_posts' => true, 112 | 'read' => true, 113 | 'level_2' => true, 114 | 'level_1' => true, 115 | 'level_0' => true, 116 | 'delete_posts' => true, 117 | 'delete_published_posts' => true, 118 | ), 119 | ), 120 | 'contributor' => 121 | array ( 122 | 'name' => 'Contributor', 123 | 'capabilities' => 124 | array ( 125 | 'edit_posts' => true, 126 | 'read' => true, 127 | 'level_1' => true, 128 | 'level_0' => true, 129 | 'delete_posts' => true, 130 | ), 131 | ), 132 | ); 133 | -------------------------------------------------------------------------------- /www/config/vip-config.php: -------------------------------------------------------------------------------- 1 | cancel = true; 19 | } 20 | 21 | // Variants can be set by functions which use early-set globals like $_SERVER to run simple tests. 22 | // Functions defined in WordPress, plugins, and themes are not available and MUST NOT be used. 23 | // Example: vary_cache_on_function('return preg_match("/feedburner/i", $_SERVER["HTTP_USER_AGENT"]);'); 24 | // This will cause batcache to cache a variant for requests from Feedburner. 25 | // Tips for writing $function: 26 | // X_X DO NOT use any functions from your theme or plugins. Those files have not been included. Fatal error. 27 | // X_X DO NOT use any WordPress functions except is_admin() and is_multisite(). Fatal error. 28 | // X_X DO NOT include or require files from anywhere without consulting expensive professionals first. Fatal error. 29 | // X_X DO NOT use $wpdb, $blog_id, $current_user, etc. These have not been initialized. 30 | // ^_^ DO understand how create_function works. This is how your code is used: create_function('', $function); 31 | // ^_^ DO remember to return something. The return value determines the cache variant. 32 | function vary_cache_on_function($function) { 33 | global $batcache; 34 | 35 | if ( preg_match('/include|require|echo|(?add_variant($function); 42 | } 43 | 44 | class batcache { 45 | // This is the base configuration. You can edit these variables or move them into your wp-config.php file. 46 | var $max_age = 300; // Expire batcache items aged this many seconds (zero to disable batcache) 47 | 48 | var $remote = 0; // Zero disables sending buffers to remote datacenters (req/sec is never sent) 49 | 50 | var $times = 2; // Only batcache a page after it is accessed this many times... (two or more) 51 | var $seconds = 120; // ...in this many seconds (zero to ignore this and use batcache immediately) 52 | 53 | var $group = 'batcache'; // Name of memcached group. You can simulate a cache flush by changing this. 54 | 55 | var $unique = array(); // If you conditionally serve different content, put the variable values here. 56 | 57 | var $vary = array(); // Array of functions for create_function. The return value is added to $unique above. 58 | 59 | var $headers = array(); // Add headers here as name=>value or name=>array(values). These will be sent with every response from the cache. 60 | 61 | var $cache_redirects = false; // Set true to enable redirect caching. 62 | var $redirect_status = false; // This is set to the response code during a redirect. 63 | var $redirect_location = false; // This is set to the redirect location. 64 | 65 | var $use_stale = true; // Is it ok to return stale cached response when updating the cache? 66 | var $uncached_headers = array('transfer-encoding'); // These headers will never be cached. Apply strtolower. 67 | 68 | var $debug = true; // Set false to hide the batcache info 69 | 70 | var $cache_control = true; // Set false to disable Last-Modified and Cache-Control headers 71 | 72 | var $cancel = false; // Change this to cancel the output buffer. Use batcache_cancel(); 73 | 74 | var $noskip_cookies = array( 'wordpress_test_cookie' ); // Names of cookies - if they exist and the cache would normally be bypassed, don't bypass it 75 | 76 | var $query = ''; 77 | var $genlock = false; 78 | var $do = false; 79 | 80 | function batcache( $settings ) { 81 | if ( is_array( $settings ) ) foreach ( $settings as $k => $v ) 82 | $this->$k = $v; 83 | } 84 | 85 | function is_ssl() { 86 | if ( isset($_SERVER['HTTPS']) ) { 87 | if ( 'on' == strtolower($_SERVER['HTTPS']) ) 88 | return true; 89 | if ( '1' == $_SERVER['HTTPS'] ) 90 | return true; 91 | } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) { 92 | return true; 93 | } 94 | return false; 95 | } 96 | 97 | function status_header( $status_header, $status_code ) { 98 | $this->status_header = $status_header; 99 | $this->status_code = $status_code; 100 | 101 | return $status_header; 102 | } 103 | 104 | function redirect_status( $status, $location ) { 105 | if ( $this->cache_redirects ) { 106 | $this->redirect_status = $status; 107 | $this->redirect_location = $location; 108 | } 109 | 110 | return $status; 111 | } 112 | 113 | function do_headers( $headers1, $headers2 = array() ) { 114 | // Merge the arrays of headers into one 115 | $headers = array(); 116 | $keys = array_unique( array_merge( array_keys( $headers1 ), array_keys( $headers2 ) ) ); 117 | foreach ( $keys as $k ) { 118 | $headers[$k] = array(); 119 | if ( isset( $headers1[$k] ) && isset( $headers2[$k] ) ) 120 | $headers[$k] = array_merge( (array) $headers2[$k], (array) $headers1[$k] ); 121 | elseif ( isset( $headers2[$k] ) ) 122 | $headers[$k] = (array) $headers2[$k]; 123 | else 124 | $headers[$k] = (array) $headers1[$k]; 125 | $headers[$k] = array_unique( $headers[$k] ); 126 | } 127 | // These headers take precedence over any previously sent with the same names 128 | foreach ( $headers as $k => $values ) { 129 | $clobber = true; 130 | foreach ( $values as $v ) { 131 | header( "$k: $v", $clobber ); 132 | $clobber = false; 133 | } 134 | } 135 | } 136 | 137 | function configure_groups() { 138 | // Configure the memcached client 139 | if ( ! $this->remote ) 140 | if ( function_exists('wp_cache_add_no_remote_groups') ) 141 | wp_cache_add_no_remote_groups(array($this->group)); 142 | if ( function_exists('wp_cache_add_global_groups') ) 143 | wp_cache_add_global_groups(array($this->group)); 144 | } 145 | 146 | // Defined here because timer_stop() calls number_format_i18n() 147 | function timer_stop($display = 0, $precision = 3) { 148 | global $timestart, $timeend; 149 | $mtime = microtime(); 150 | $mtime = explode(' ',$mtime); 151 | $mtime = $mtime[1] + $mtime[0]; 152 | $timeend = $mtime; 153 | $timetotal = $timeend-$timestart; 154 | $r = number_format($timetotal, $precision); 155 | if ( $display ) 156 | echo $r; 157 | return $r; 158 | } 159 | 160 | function ob($output) { 161 | // PHP5 and objects disappearing before output buffers? 162 | wp_cache_init(); 163 | 164 | // Remember, $wp_object_cache was clobbered in wp-settings.php so we have to repeat this. 165 | $this->configure_groups(); 166 | 167 | if ( $this->cancel !== false ) { 168 | wp_cache_delete( "{$this->url_key}_genlock", $this->group ); 169 | return $output; 170 | } 171 | 172 | // Do not batcache blank pages unless they are HTTP redirects 173 | $output = trim($output); 174 | if ( $output === '' && (!$this->redirect_status || !$this->redirect_location) ) { 175 | wp_cache_delete( "{$this->url_key}_genlock", $this->group ); 176 | return; 177 | } 178 | 179 | // Do not cache 5xx responses 180 | if ( isset( $this->status_code ) && intval($this->status_code / 100) == 5 ) { 181 | wp_cache_delete( "{$this->url_key}_genlock", $this->group ); 182 | return $output; 183 | } 184 | 185 | $this->do_variants($this->vary); 186 | $this->generate_keys(); 187 | 188 | // Construct and save the batcache 189 | $this->cache = array( 190 | 'output' => $output, 191 | 'time' => time(), 192 | 'timer' => $this->timer_stop(false, 3), 193 | 'headers' => array(), 194 | 'status_header' => $this->status_header, 195 | 'redirect_status' => $this->redirect_status, 196 | 'redirect_location' => $this->redirect_location, 197 | 'version' => $this->url_version 198 | ); 199 | 200 | foreach ( headers_list() as $header ) { 201 | list($k, $v) = array_map('trim', explode(':', $header, 2)); 202 | $this->cache['headers'][$k][] = $v; 203 | } 204 | 205 | if ( !empty( $this->cache['headers'] ) && !empty( $this->uncached_headers ) ) { 206 | foreach ( $this->uncached_headers as $header ) 207 | unset( $this->cache['headers'][$header] ); 208 | } 209 | 210 | foreach ( $this->cache['headers'] as $header => $values ) { 211 | // Do not cache if cookies were set 212 | if ( strtolower( $header ) === 'set-cookie' ) { 213 | wp_cache_delete( "{$this->url_key}_genlock", $this->group ); 214 | return $output; 215 | } 216 | 217 | foreach ( (array) $values as $value ) 218 | if ( preg_match('/^Cache-Control:.*max-?age=(\d+)/i', "$header: $value", $matches) ) 219 | $this->max_age = intval($matches[1]); 220 | } 221 | 222 | $this->cache['max_age'] = $this->max_age; 223 | 224 | wp_cache_set($this->key, $this->cache, $this->group, $this->max_age + $this->seconds + 30); 225 | 226 | // Unlock regeneration 227 | wp_cache_delete("{$this->url_key}_genlock", $this->group); 228 | 229 | if ( $this->cache_control ) { 230 | // Don't clobber Last-Modified header if already set, e.g. by WP::send_headers() 231 | if ( !isset($this->cache['headers']['Last-Modified']) ) 232 | header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $this->cache['time'] ) . ' GMT', true ); 233 | if ( !isset($this->cache['headers']['Cache-Control']) ) 234 | header("Cache-Control: max-age=$this->max_age, must-revalidate", false); 235 | } 236 | 237 | $this->do_headers( $this->headers ); 238 | 239 | // Add some debug info just before debug ) { 241 | $this->add_debug_just_cached(); 242 | } 243 | 244 | // Pass output to next ob handler 245 | batcache_stats( 'batcache', 'total_page_views' ); 246 | return $this->cache['output']; 247 | } 248 | 249 | function add_variant($function) { 250 | $key = md5($function); 251 | $this->vary[$key] = $function; 252 | } 253 | 254 | function do_variants($dimensions = false) { 255 | // This function is called without arguments early in the page load, then with arguments during the OB handler. 256 | if ( $dimensions === false ) 257 | $dimensions = wp_cache_get("{$this->url_key}_vary", $this->group); 258 | else 259 | wp_cache_set("{$this->url_key}_vary", $dimensions, $this->group, $this->max_age + 10); 260 | 261 | if ( is_array($dimensions) ) { 262 | ksort($dimensions); 263 | foreach ( $dimensions as $key => $function ) { 264 | $fun = create_function('', $function); 265 | $value = $fun(); 266 | $this->keys[$key] = $value; 267 | } 268 | } 269 | } 270 | 271 | function generate_keys() { 272 | // ksort($this->keys); // uncomment this when traffic is slow 273 | $this->key = md5(serialize($this->keys)); 274 | $this->req_key = $this->key . '_reqs'; 275 | } 276 | 277 | function add_debug_just_cached() { 278 | $generation = $this->cache['timer']; 279 | $bytes = strlen( serialize( $this->cache ) ); 280 | $html = <<max_age} seconds 284 | --> 285 | 286 | HTML; 287 | $this->add_debug_html_to_output( $html ); 288 | } 289 | 290 | function add_debug_from_cache() { 291 | $seconds_ago = time() - $this->cache['time']; 292 | $generation = $this->cache['timer']; 293 | $serving = $this->timer_stop( false, 3 ); 294 | $expires = $this->cache['max_age'] - time() + $this->cache['time']; 295 | $html = << 302 | 303 | HTML; 304 | $this->add_debug_html_to_output( $html ); 305 | } 306 | 307 | function add_debug_html_to_output( $debug_html ) { 308 | // Casing on the Content-Type header is inconsistent 309 | foreach ( array( 'Content-Type', 'Content-type' ) as $key ) { 310 | if ( isset( $this->cache['headers'][ $key ][0] ) && 0 !== strpos( $this->cache['headers'][ $key ][0], 'text/html' ) ) 311 | return; 312 | } 313 | 314 | $head_position = strpos( $this->cache['output'], 'cache['output'] .= "\n$debug_html"; 319 | } 320 | } 321 | 322 | global $batcache; 323 | // Pass in the global variable which may be an array of settings to override defaults. 324 | $batcache = new batcache($batcache); 325 | 326 | if ( ! defined( 'WP_CONTENT_DIR' ) ) 327 | return; 328 | 329 | // Never batcache interactive scripts or API endpoints. 330 | if ( in_array( 331 | basename( $_SERVER['SCRIPT_FILENAME'] ), 332 | array( 333 | 'wp-app.php', 334 | 'xmlrpc.php', 335 | 'wp-cron.php', 336 | ) ) ) 337 | return; 338 | 339 | // Never batcache WP javascript generators 340 | if ( strstr( $_SERVER['SCRIPT_FILENAME'], 'wp-includes/js' ) ) 341 | return; 342 | 343 | // Never batcache a POST request. 344 | if ( ! empty( $GLOBALS['HTTP_RAW_POST_DATA'] ) || ! empty( $_POST ) || 345 | ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] ) ) 346 | { 347 | return; 348 | } 349 | 350 | // Never batcache when cookies indicate a cache-exempt visitor. 351 | if ( is_array( $_COOKIE) && ! empty( $_COOKIE ) ) { 352 | foreach ( array_keys( $_COOKIE ) as $batcache->cookie ) { 353 | if ( ! in_array( $batcache->cookie, $batcache->noskip_cookies ) && ( substr( $batcache->cookie, 0, 2 ) == 'wp' || substr( $batcache->cookie, 0, 9 ) == 'wordpress' || substr( $batcache->cookie, 0, 14 ) == 'comment_author' ) ) { 354 | batcache_stats( 'batcache', 'cookie_skip' ); 355 | return; 356 | } 357 | } 358 | } 359 | 360 | if ( ! include_once( WP_CONTENT_DIR . '/object-cache.php' ) ) 361 | return; 362 | 363 | wp_cache_init(); // Note: wp-settings.php calls wp_cache_init() which clobbers the object made here. 364 | 365 | if ( ! is_object( $wp_object_cache ) ) 366 | return; 367 | 368 | // Now that the defaults are set, you might want to use different settings under certain conditions. 369 | 370 | /* Example: if your documents have a mobile variant (a different document served by the same URL) you must tell batcache about the variance. Otherwise you might accidentally cache the mobile version and serve it to desktop users, or vice versa. 371 | $batcache->unique['mobile'] = is_mobile_user_agent(); 372 | */ 373 | 374 | /* Example: never batcache for this host 375 | if ( $_SERVER['HTTP_HOST'] == 'do-not-batcache-me.com' ) 376 | return; 377 | */ 378 | 379 | /* Example: batcache everything on this host regardless of traffic level 380 | if ( $_SERVER['HTTP_HOST'] == 'always-batcache-me.com' ) 381 | return; 382 | */ 383 | 384 | /* Example: If you sometimes serve variants dynamically (e.g. referrer search term highlighting) you probably don't want to batcache those variants. Remember this code is run very early in wp-settings.php so plugins are not yet loaded. You will get a fatal error if you try to call an undefined function. Either include your plugin now or define a test function in this file. 385 | if ( include_once( 'plugins/searchterm-highlighter.php') && referrer_has_search_terms() ) 386 | return; 387 | */ 388 | 389 | // Disabled 390 | if ( $batcache->max_age < 1 ) 391 | return; 392 | 393 | // Make sure we can increment. If not, turn off the traffic sensor. 394 | if ( ! method_exists( $GLOBALS['wp_object_cache'], 'incr' ) ) 395 | $batcache->times = 0; 396 | 397 | // Necessary to prevent clients using cached version after login cookies set. If this is a problem, comment it out and remove all Last-Modified headers. 398 | header('Vary: Cookie', false); 399 | 400 | // Things that define a unique page. 401 | if ( isset( $_SERVER['QUERY_STRING'] ) ) 402 | parse_str($_SERVER['QUERY_STRING'], $batcache->query); 403 | 404 | $batcache->keys = array( 405 | 'host' => $_SERVER['HTTP_HOST'], 406 | 'method' => $_SERVER['REQUEST_METHOD'], 407 | 'path' => ( $batcache->pos = strpos($_SERVER['REQUEST_URI'], '?') ) ? substr($_SERVER['REQUEST_URI'], 0, $batcache->pos) : $_SERVER['REQUEST_URI'], 408 | 'query' => $batcache->query, 409 | 'extra' => $batcache->unique 410 | ); 411 | 412 | if ( $batcache->is_ssl() ) 413 | $batcache->keys['ssl'] = true; 414 | 415 | // Recreate the permalink from the URL 416 | $batcache->permalink = 'http://' . $batcache->keys['host'] . $batcache->keys['path'] . ( isset($batcache->keys['query']['p']) ? "?p=" . $batcache->keys['query']['p'] : '' ); 417 | $batcache->url_key = md5($batcache->permalink); 418 | $batcache->configure_groups(); 419 | $batcache->url_version = (int) wp_cache_get("{$batcache->url_key}_version", $batcache->group); 420 | $batcache->do_variants(); 421 | $batcache->generate_keys(); 422 | 423 | // Get the batcache 424 | $batcache->cache = wp_cache_get($batcache->key, $batcache->group); 425 | 426 | if ( isset( $batcache->cache['version'] ) && $batcache->cache['version'] < $batcache->url_version ) { 427 | // Always refresh the cache if a newer version is available. 428 | $batcache->do = true; 429 | } else if ( $batcache->seconds < 1 || $batcache->times < 2 ) { 430 | // Are we only caching frequently-requested pages? 431 | $batcache->do = true; 432 | } else { 433 | // No batcache item found, or ready to sample traffic again at the end of the batcache life? 434 | if ( !is_array($batcache->cache) || time() >= $batcache->cache['time'] + $batcache->max_age - $batcache->seconds ) { 435 | wp_cache_add($batcache->req_key, 0, $batcache->group); 436 | $batcache->requests = wp_cache_incr($batcache->req_key, 1, $batcache->group); 437 | 438 | if ( $batcache->requests >= $batcache->times && 439 | time() >= $batcache->cache['time'] + $batcache->cache['max_age'] 440 | ) { 441 | wp_cache_delete( $batcache->req_key, $batcache->group ); 442 | $batcache->do = true; 443 | } else { 444 | $batcache->do = false; 445 | } 446 | } 447 | } 448 | 449 | // Obtain cache generation lock 450 | if ( $batcache->do ) 451 | $batcache->genlock = wp_cache_add("{$batcache->url_key}_genlock", 1, $batcache->group, 10); 452 | 453 | if ( isset( $batcache->cache['time'] ) && // We have cache 454 | ! $batcache->genlock && // We have not obtained cache regeneration lock 455 | ( 456 | time() < $batcache->cache['time'] + $batcache->cache['max_age'] || // Batcached page that hasn't expired || 457 | ( $batcache->do && $batcache->use_stale ) // Regenerating it in another request and can use stale cache 458 | ) 459 | ) { 460 | // Issue redirect if cached and enabled 461 | if ( $batcache->cache['redirect_status'] && $batcache->cache['redirect_location'] && $batcache->cache_redirects ) { 462 | $status = $batcache->cache['redirect_status']; 463 | $location = $batcache->cache['redirect_location']; 464 | // From vars.php 465 | $is_IIS = (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false || strpos($_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer') !== false); 466 | 467 | $batcache->do_headers( $batcache->headers ); 468 | if ( $is_IIS ) { 469 | header("Refresh: 0;url=$location"); 470 | } else { 471 | if ( php_sapi_name() != 'cgi-fcgi' ) { 472 | $texts = array( 473 | 300 => 'Multiple Choices', 474 | 301 => 'Moved Permanently', 475 | 302 => 'Found', 476 | 303 => 'See Other', 477 | 304 => 'Not Modified', 478 | 305 => 'Use Proxy', 479 | 306 => 'Reserved', 480 | 307 => 'Temporary Redirect', 481 | ); 482 | $protocol = $_SERVER["SERVER_PROTOCOL"]; 483 | if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol ) 484 | $protocol = 'HTTP/1.0'; 485 | if ( isset($texts[$status]) ) 486 | header("$protocol $status " . $texts[$status]); 487 | else 488 | header("$protocol 302 Found"); 489 | } 490 | header("Location: $location"); 491 | } 492 | exit; 493 | } 494 | 495 | // Respect ETags served with feeds. 496 | $three04 = false; 497 | if ( isset( $SERVER['HTTP_IF_NONE_MATCH'] ) && isset( $batcache->cache['headers']['ETag'][0] ) && $_SERVER['HTTP_IF_NONE_MATCH'] == $batcache->cache['headers']['ETag'][0] ) 498 | $three04 = true; 499 | 500 | // Respect If-Modified-Since. 501 | elseif ( $batcache->cache_control && isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ) { 502 | $client_time = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']); 503 | if ( isset($batcache->cache['headers']['Last-Modified'][0]) ) 504 | $cache_time = strtotime($batcache->cache['headers']['Last-Modified'][0]); 505 | else 506 | $cache_time = $batcache->cache['time']; 507 | 508 | if ( $client_time >= $cache_time ) 509 | $three04 = true; 510 | } 511 | 512 | // Use the batcache save time for Last-Modified so we can issue "304 Not Modified" but don't clobber a cached Last-Modified header. 513 | if ( $batcache->cache_control && !isset($batcache->cache['headers']['Last-Modified'][0]) ) { 514 | header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $batcache->cache['time'] ) . ' GMT', true ); 515 | header('Cache-Control: max-age=' . ($batcache->cache['max_age'] - time() + $batcache->cache['time']) . ', must-revalidate', true); 516 | } 517 | 518 | // Add some debug info just before 519 | if ( $batcache->debug ) { 520 | $batcache->add_debug_from_cache(); 521 | } 522 | 523 | $batcache->do_headers( $batcache->headers, $batcache->cache['headers'] ); 524 | 525 | if ( $three04 ) { 526 | header("HTTP/1.1 304 Not Modified", true, 304); 527 | die; 528 | } 529 | 530 | if ( !empty($batcache->cache['status_header']) ) 531 | header($batcache->cache['status_header'], true); 532 | 533 | // Have you ever heard a death rattle before? 534 | die($batcache->cache['output']); 535 | } 536 | 537 | // Didn't meet the minimum condition? 538 | if ( ! $batcache->do || ! $batcache->genlock ) 539 | return; 540 | 541 | $wp_filter['status_header'][10]['batcache'] = array( 'function' => array(&$batcache, 'status_header'), 'accepted_args' => 2 ); 542 | $wp_filter['wp_redirect_status'][10]['batcache'] = array( 'function' => array(&$batcache, 'redirect_status'), 'accepted_args' => 2 ); 543 | 544 | ob_start(array(&$batcache, 'ob')); 545 | 546 | // It is safer to omit the final PHP closing tag. 547 | 548 | -------------------------------------------------------------------------------- /www/wp-content/index.php: -------------------------------------------------------------------------------- 1 | $alloptions_size_die ) { 17 | sanity_check_alloptions_die( $alloptions_size, $alloptions ); 18 | } 19 | 20 | if ( !$alloptions_size ) { 21 | $alloptions_size = strlen( serialize( $alloptions ) ); 22 | wp_cache_add( 'alloptions_size', $alloptions_size, '', 60 ); 23 | if ( $alloptions_size > $alloptions_size_warn ) { 24 | if ( $alloptions_size > $alloptions_size_die ) 25 | sanity_check_alloptions_die( $alloptions_size, $alloptions ); 26 | 27 | // Warn if we haven't died already 28 | sanity_check_alloptions_notify( $alloptions_size, $alloptions ); 29 | } 30 | } 31 | 32 | return $alloptions; 33 | } 34 | add_filter( 'alloptions', 'sanity_check_alloptions' ); 35 | 36 | function sanity_check_alloptions_die( $size, $alloptions ) { 37 | sanity_check_alloptions_notify( $size, $alloptions, true ); 38 | ?> 39 | 40 | 41 | Something went wrong — Option Error 42 | 57 | 58 | 62 | 63 | 64 |

Uh Oh!

65 | 66 |
67 | 68 |

Something has gone wrong with our servers. It’s probably Matt’s fault.

69 | 70 |

We’ve just been notified of the problem.

71 | 72 |

Hopefully this should be fixed ASAP, so kindly reload in a few minutes and things should be back to normal.

73 | 74 |
75 | 76 | 77 | blogid} options is up to " . number_format( $size ) . ' ' . $msg . ' #vipoptions'; 96 | error_log( $log ); 97 | } 98 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/batcache.php: -------------------------------------------------------------------------------- 1 | configure_groups(); 16 | 17 | // Regen home and permalink on posts and pages 18 | add_action('clean_post_cache', 'batcache_post'); 19 | 20 | // Regen permalink on comments (TODO) 21 | //add_action('comment_post', 'batcache_comment'); 22 | //add_action('wp_set_comment_status', 'batcache_comment'); 23 | //add_action('edit_comment', 'batcache_comment'); 24 | 25 | function batcache_post($post_id) { 26 | global $batcache; 27 | 28 | $post = get_post($post_id); 29 | if ( $post->post_type == 'revision' || ! in_array( get_post_status($post_id), array( 'publish', 'trash' ) ) ) 30 | return; 31 | 32 | $home = trailingslashit( get_option('home') ); 33 | batcache_clear_url( $home ); 34 | batcache_clear_url( $home . 'feed/' ); 35 | batcache_clear_url( get_permalink($post_id) ); 36 | } 37 | 38 | function batcache_clear_url($url) { 39 | global $batcache, $wp_object_cache; 40 | 41 | if ( empty($url) ) 42 | return false; 43 | 44 | if ( 0 === strpos( $url, 'https://' ) ) 45 | $url = str_replace( 'https://', 'http://', $url ); 46 | if ( 0 !== strpos( $url, 'http://' ) ) 47 | $url = 'http://' . $url; 48 | 49 | $url_key = md5( $url ); 50 | wp_cache_add("{$url_key}_version", 0, $batcache->group); 51 | $retval = wp_cache_incr("{$url_key}_version", 1, $batcache->group); 52 | 53 | $batcache_no_remote_group_key = array_search( $batcache->group, (array) $wp_object_cache->no_remote_groups ); 54 | if ( false !== $batcache_no_remote_group_key ) { 55 | // The *_version key needs to be replicated remotely, otherwise invalidation won't work. 56 | // The race condition here should be acceptable. 57 | unset( $wp_object_cache->no_remote_groups[$batcache_group_key] ); 58 | $retval = wp_cache_set( "{$url_key}_version", $retval, $batcache->group ); 59 | $wp_object_cache->no_remote_groups[$batcache_group_key] = $batcache->group; 60 | } 61 | 62 | return $retval; 63 | } 64 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/http-concat/cssconcat.php: -------------------------------------------------------------------------------- 1 | old_styles = $styles; 20 | 21 | // Unset all the object properties except our private copy of the styles object. 22 | // We have to unset everything so that the overload methods talk to $this->old_styles->whatever 23 | // instead of $this->whatever. 24 | foreach ( array_keys( get_object_vars( $this ) ) as $key ) { 25 | if ( 'old_styles' === $key ) { 26 | continue; 27 | } 28 | unset( $this->$key ); 29 | } 30 | 31 | parent::__construct(); 32 | } 33 | 34 | function do_items( $handles = false, $group = false ) { 35 | $handles = false === $handles ? $this->queue : (array) $handles; 36 | $stylesheets = array(); 37 | $siteurl = site_url(); 38 | 39 | $this->all_deps( $handles ); 40 | 41 | $stylesheet_group_index = 0; 42 | foreach( $this->to_do as $key => $handle ) { 43 | $obj = $this->registered[$handle]; 44 | $obj->src = apply_filters( 'style_loader_src', $obj->src, $obj->handle ); 45 | 46 | // Core is kind of broken and returns "true" for src of "colors" handle 47 | // http://core.trac.wordpress.org/attachment/ticket/16827/colors-hacked-fixed.diff 48 | // http://core.trac.wordpress.org/ticket/20729 49 | if ( 'colors' == $obj->handle && true === $obj->src ) { 50 | $css_url = parse_url( wp_style_loader_src( $obj->src, $obj->handle ) ); 51 | } else { 52 | $css_url = parse_url( $obj->src ); 53 | } 54 | $extra = $obj->extra; 55 | 56 | // Don't concat by default 57 | $do_concat = false; 58 | 59 | // Only try to concat static css files 60 | if ( false !== strpos( $css_url['path'], '.css' ) ) 61 | $do_concat = true; 62 | 63 | // Don't try to concat styles which are loaded conditionally (like IE stuff) 64 | if ( isset( $extra['conditional'] ) ) 65 | $do_concat = false; 66 | 67 | // Don't concat rtl stuff for now until concat supports it correctly 68 | if ( 'rtl' === $this->text_direction && ! empty( $extra['rtl'] ) ) 69 | $do_concat = false; 70 | 71 | // Don't try to concat externally hosted scripts 72 | if ( ( isset( $css_url['host'] ) && ( preg_replace( '/https?:\/\//', '', $siteurl ) != $css_url['host'] ) ) ) 73 | $do_concat = false; 74 | 75 | // Concat and canonicalize the paths only for 76 | // existing scripts that aren't outside ABSPATH 77 | $css_realpath = realpath( ABSPATH . $css_url['path'] ); 78 | if ( ! $css_realpath || 0 !== strpos( $css_realpath, ABSPATH ) ) 79 | $do_concat = false; 80 | else 81 | $css_url['path'] = substr( $css_realpath, strlen( ABSPATH ) - 1 ); 82 | 83 | // Allow plugins to disable concatenation of certain stylesheets. 84 | $do_concat = apply_filters( 'css_do_concat', $do_concat, $handle ); 85 | 86 | if ( true === $do_concat ) { 87 | $media = $obj->args; 88 | if ( empty( $media ) ) { 89 | $media = 'all'; 90 | } 91 | if ( empty( $stylesheets[ $stylesheet_group_index ] ) || ! is_array( $stylesheets[ $stylesheet_group_index ] ) ) { 92 | $stylesheets[ $stylesheet_group_index ] = array(); 93 | } 94 | 95 | $stylesheets[ $stylesheet_group_index ][ $media ][ $handle ] = $css_url['path']; 96 | $this->done[] = $handle; 97 | } else { 98 | $stylesheet_group_index++; 99 | $stylesheets[ $stylesheet_group_index ][ 'noconcat' ][] = $handle; 100 | $stylesheet_group_index++; 101 | } 102 | unset( $this->to_do[$key] ); 103 | } 104 | 105 | foreach( $stylesheets as $idx => $stylesheets_group ) { 106 | foreach( $stylesheets_group as $media => $css ) { 107 | if ( 'noconcat' == $media ) { 108 | 109 | foreach( $css as $handle ) { 110 | if ( $this->do_item( $handle, $group ) ) 111 | $this->done[] = $handle; 112 | } 113 | continue; 114 | } elseif ( count( $css ) > 1) { 115 | $paths = array_map( function( $url ) { return ABSPATH . $url; }, $css ); 116 | $mtime = max( array_map( 'filemtime', $paths ) ); 117 | $path_str = implode( $css, ',' ) . "?m=${mtime}j"; 118 | 119 | if ( $this->allow_gzip_compression ) { 120 | $path_64 = base64_encode( gzcompress( $path_str ) ); 121 | if ( strlen( $path_str ) > ( strlen( $path_64 ) + 1 ) ) 122 | $path_str = '-' . $path_64; 123 | } 124 | 125 | $href = $siteurl . "/_static/??" . $path_str; 126 | } else { 127 | $href = $this->cache_bust_mtime( $siteurl . current( $css ) ); 128 | } 129 | 130 | echo apply_filters( 'style_loader_tag', "\n", $handle ); 131 | array_map( array( $this, 'print_inline_style' ), array_keys( $css ) ); 132 | } 133 | } 134 | return $this->done; 135 | } 136 | 137 | function cache_bust_mtime( $url ) { 138 | if ( strpos( $url, '?m=' ) ) 139 | return $url; 140 | 141 | $parts = parse_url( $url ); 142 | if ( ! isset( $parts['path'] ) || empty( $parts['path'] ) ) 143 | return $url; 144 | 145 | $file = ABSPATH . ltrim( $parts['path'], '/' ); 146 | 147 | $mtime = false; 148 | if ( file_exists( $file ) ) 149 | $mtime = filemtime( $file ); 150 | 151 | if ( ! $mtime ) 152 | return $url; 153 | 154 | if ( false === strpos( $url, '?' ) ) { 155 | $q = ''; 156 | } else { 157 | list( $url, $q ) = explode( '?', $url, 2 ); 158 | if ( strlen( $q ) ) 159 | $q = '&' . $q; 160 | } 161 | 162 | return "$url?m={$mtime}g{$q}"; 163 | } 164 | 165 | function __isset( $key ) { 166 | return isset( $this->old_styles->$key ); 167 | } 168 | 169 | function __unset( $key ) { 170 | unset( $this->old_styles->$key ); 171 | } 172 | 173 | function &__get( $key ) { 174 | return $this->old_styles->$key; 175 | } 176 | 177 | function __set( $key, $value ) { 178 | $this->old_styles->$key = $value; 179 | } 180 | } 181 | 182 | function css_concat_init() { 183 | global $wp_styles; 184 | 185 | if ( ! ( $wp_styles instanceof WP_Styles ) ) { 186 | $wp_styles = new WP_Styles(); 187 | } 188 | 189 | $wp_styles = new WPcom_CSS_Concat( $wp_styles ); 190 | $wp_styles->allow_gzip_compression = ALLOW_GZIP_COMPRESSION; 191 | } 192 | 193 | add_action( 'init', 'css_concat_init' ); 194 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/http-concat/cssmin.php: -------------------------------------------------------------------------------- 1 | memory_limit = 128 * 1048576; // 128MB in bytes 47 | $this->max_execution_time = 60; // 1 min 48 | $this->pcre_backtrack_limit = 1000 * 1000; 49 | $this->pcre_recursion_limit = 500 * 1000; 50 | 51 | $this->raise_php_limits = (bool) $raise_php_limits; 52 | } 53 | 54 | /** 55 | * Minify a string of CSS 56 | * @param string $css 57 | * @param int|bool $linebreak_pos 58 | * @return string 59 | */ 60 | public function run($css = '', $linebreak_pos = FALSE) 61 | { 62 | if (empty($css)) { 63 | return ''; 64 | } 65 | 66 | if ($this->raise_php_limits) { 67 | $this->do_raise_php_limits(); 68 | } 69 | 70 | $this->comments = array(); 71 | $this->preserved_tokens = array(); 72 | 73 | $start_index = 0; 74 | $length = strlen($css); 75 | 76 | $css = $this->extract_data_urls($css); 77 | 78 | // collect all comment blocks... 79 | while (($start_index = $this->index_of($css, '/*', $start_index)) >= 0) { 80 | $end_index = $this->index_of($css, '*/', $start_index + 2); 81 | if ($end_index < 0) { 82 | $end_index = $length; 83 | } 84 | $comment_found = $this->str_slice($css, $start_index + 2, $end_index); 85 | $this->comments[] = $comment_found; 86 | $comment_preserve_string = self::COMMENT . (count($this->comments) - 1) . '___'; 87 | $css = $this->str_slice($css, 0, $start_index + 2) . $comment_preserve_string . $this->str_slice($css, $end_index); 88 | // Set correct start_index: Fixes issue #2528130 89 | $start_index = $end_index + 2 + strlen($comment_preserve_string) - strlen($comment_found); 90 | } 91 | 92 | // preserve strings so their content doesn't get accidentally minified 93 | $css = preg_replace_callback('/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S", array($this, 'replace_string'), $css); 94 | 95 | // Let's divide css code in chunks of 5.000 chars aprox. 96 | // Reason: PHP's PCRE functions like preg_replace have a "backtrack limit" 97 | // of 100.000 chars by default (php < 5.3.7) so if we're dealing with really 98 | // long strings and a (sub)pattern matches a number of chars greater than 99 | // the backtrack limit number (i.e. /(.*)/s) PCRE functions may fail silently 100 | // returning NULL and $css would be empty. 101 | $charset = ''; 102 | $charset_regexp = '/(@charset)( [^;]+;)/i'; 103 | $css_chunks = array(); 104 | $css_chunk_length = 5000; // aprox size, not exact 105 | $start_index = 0; 106 | $i = $css_chunk_length; // save initial iterations 107 | $l = strlen($css); 108 | 109 | 110 | // if the number of characters is 5000 or less, do not chunk 111 | if ($l <= $css_chunk_length) { 112 | $css_chunks[] = $css; 113 | } else { 114 | // chunk css code securely 115 | while ($i < $l) { 116 | $i += 50; // save iterations 117 | if ($l - $start_index <= $css_chunk_length || $i >= $l) { 118 | $css_chunks[] = $this->str_slice($css, $start_index); 119 | break; 120 | } 121 | if ($css[$i - 1] === '}' && $i - $start_index > $css_chunk_length) { 122 | // If there are two ending curly braces }} separated or not by spaces, 123 | // join them in the same chunk (i.e. @media blocks) 124 | $next_chunk = substr($css, $i); 125 | if (preg_match('/^\s*\}/', $next_chunk)) { 126 | $i = $i + $this->index_of($next_chunk, '}') + 1; 127 | } 128 | 129 | $css_chunks[] = $this->str_slice($css, $start_index, $i); 130 | $start_index = $i; 131 | } 132 | } 133 | } 134 | 135 | // Minify each chunk 136 | for ($i = 0, $n = count($css_chunks); $i < $n; $i++) { 137 | $css_chunks[$i] = $this->minify($css_chunks[$i], $linebreak_pos); 138 | // Keep the first @charset at-rule found 139 | if (empty($charset) && preg_match($charset_regexp, $css_chunks[$i], $matches)) { 140 | $charset = strtolower($matches[1]) . $matches[2]; 141 | } 142 | // Delete all @charset at-rules 143 | $css_chunks[$i] = preg_replace($charset_regexp, '', $css_chunks[$i]); 144 | } 145 | 146 | // Update the first chunk and push the charset to the top of the file. 147 | $css_chunks[0] = $charset . $css_chunks[0]; 148 | 149 | return implode('', $css_chunks); 150 | } 151 | 152 | /** 153 | * Sets the memory limit for this script 154 | * @param int|string $limit 155 | */ 156 | public function set_memory_limit($limit) 157 | { 158 | $this->memory_limit = $this->normalize_int($limit); 159 | } 160 | 161 | /** 162 | * Sets the maximum execution time for this script 163 | * @param int|string $seconds 164 | */ 165 | public function set_max_execution_time($seconds) 166 | { 167 | $this->max_execution_time = (int) $seconds; 168 | } 169 | 170 | /** 171 | * Sets the PCRE backtrack limit for this script 172 | * @param int $limit 173 | */ 174 | public function set_pcre_backtrack_limit($limit) 175 | { 176 | $this->pcre_backtrack_limit = (int) $limit; 177 | } 178 | 179 | /** 180 | * Sets the PCRE recursion limit for this script 181 | * @param int $limit 182 | */ 183 | public function set_pcre_recursion_limit($limit) 184 | { 185 | $this->pcre_recursion_limit = (int) $limit; 186 | } 187 | 188 | /** 189 | * Try to configure PHP to use at least the suggested minimum settings 190 | */ 191 | private function do_raise_php_limits() 192 | { 193 | $php_limits = array( 194 | 'memory_limit' => $this->memory_limit, 195 | 'max_execution_time' => $this->max_execution_time, 196 | 'pcre.backtrack_limit' => $this->pcre_backtrack_limit, 197 | 'pcre.recursion_limit' => $this->pcre_recursion_limit 198 | ); 199 | 200 | // If current settings are higher respect them. 201 | foreach ($php_limits as $name => $suggested) { 202 | $current = $this->normalize_int(ini_get($name)); 203 | // memory_limit exception: allow -1 for "no memory limit". 204 | if ($current > -1 && ($suggested == -1 || $current < $suggested)) { 205 | ini_set($name, $suggested); 206 | } 207 | } 208 | } 209 | 210 | /** 211 | * Does bulk of the minification 212 | * @param string $css 213 | * @param int|bool $linebreak_pos 214 | * @return string 215 | */ 216 | private function minify($css, $linebreak_pos) 217 | { 218 | // strings are safe, now wrestle the comments 219 | for ($i = 0, $max = count($this->comments); $i < $max; $i++) { 220 | 221 | $token = $this->comments[$i]; 222 | $placeholder = '/' . self::COMMENT . $i . '___/'; 223 | 224 | // ! in the first position of the comment means preserve 225 | // so push to the preserved tokens keeping the ! 226 | if (substr($token, 0, 1) === '!') { 227 | $this->preserved_tokens[] = $token; 228 | $token_tring = self::TOKEN . (count($this->preserved_tokens) - 1) . '___'; 229 | $css = preg_replace($placeholder, $token_tring, $css, 1); 230 | // Preserve new lines for /*! important comments 231 | $css = preg_replace('/\s*[\n\r\f]+\s*(\/\*'. $token_tring .')/S', self::NL.'$1', $css); 232 | $css = preg_replace('/('. $token_tring .'\*\/)\s*[\n\r\f]+\s*/', '$1'.self::NL, $css); 233 | continue; 234 | } 235 | 236 | // \ in the last position looks like hack for Mac/IE5 237 | // shorten that to /*\*/ and the next one to /**/ 238 | if (substr($token, (strlen($token) - 1), 1) === '\\') { 239 | $this->preserved_tokens[] = '\\'; 240 | $css = preg_replace($placeholder, self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1); 241 | $i = $i + 1; // attn: advancing the loop 242 | $this->preserved_tokens[] = ''; 243 | $css = preg_replace('/' . self::COMMENT . $i . '___/', self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1); 244 | continue; 245 | } 246 | 247 | // keep empty comments after child selectors (IE7 hack) 248 | // e.g. html >/**/ body 249 | if (strlen($token) === 0) { 250 | $start_index = $this->index_of($css, $this->str_slice($placeholder, 1, -1)); 251 | if ($start_index > 2) { 252 | if (substr($css, $start_index - 3, 1) === '>') { 253 | $this->preserved_tokens[] = ''; 254 | $css = preg_replace($placeholder, self::TOKEN . (count($this->preserved_tokens) - 1) . '___', $css, 1); 255 | } 256 | } 257 | } 258 | 259 | // in all other cases kill the comment 260 | $css = preg_replace('/\/\*' . $this->str_slice($placeholder, 1, -1) . '\*\//', '', $css, 1); 261 | } 262 | 263 | 264 | // Normalize all whitespace strings to single spaces. Easier to work with that way. 265 | $css = preg_replace('/\s+/', ' ', $css); 266 | 267 | // Fix IE7 issue on matrix filters which browser accept whitespaces between Matrix parameters 268 | $css = preg_replace_callback('/\s*filter\:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^\)]+)\)/', array($this, 'preserve_old_IE_specific_matrix_definition'), $css); 269 | 270 | // Shorten & preserve calculations calc(...) since spaces are important 271 | $css = preg_replace_callback('/calc(\(((?:[^\(\)]+|(?1))*)\))/i', array($this, 'replace_calc'), $css); 272 | 273 | // Replace positive sign from numbers preceded by : or a white-space before the leading space is removed 274 | // +1.2em to 1.2em, +.8px to .8px, +2% to 2% 275 | $css = preg_replace('/((? -9.0 to -9 286 | $css = preg_replace('/((?\+\(\)\]\~\=,])/', '$1', $css); 298 | 299 | // Restore spaces for !important 300 | $css = preg_replace('/\!important/i', ' !important', $css); 301 | 302 | // bring back the colon 303 | $css = preg_replace('/' . self::CLASSCOLON . '/', ':', $css); 304 | 305 | // retain space for special IE6 cases 306 | $css = preg_replace_callback('/\:first\-(line|letter)(\{|,)/i', array($this, 'lowercase_pseudo_first'), $css); 307 | 308 | // no space after the end of a preserved comment 309 | $css = preg_replace('/\*\/ /', '*/', $css); 310 | 311 | // lowercase some popular @directives 312 | $css = preg_replace_callback('/@(font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframe|media|page|namespace)/i', array($this, 'lowercase_directives'), $css); 313 | 314 | // lowercase some more common pseudo-elements 315 | $css = preg_replace_callback('/:(active|after|before|checked|disabled|empty|enabled|first-(?:child|of-type)|focus|hover|last-(?:child|of-type)|link|only-(?:child|of-type)|root|:selection|target|visited)/i', array($this, 'lowercase_pseudo_elements'), $css); 316 | 317 | // lowercase some more common functions 318 | $css = preg_replace_callback('/:(lang|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|(?:-(?:moz|webkit)-)?any)\(/i', array($this, 'lowercase_common_functions'), $css); 319 | 320 | // lower case some common function that can be values 321 | // NOTE: rgb() isn't useful as we replace with #hex later, as well as and() is already done for us 322 | $css = preg_replace_callback('/([:,\( ]\s*)(attr|color-stop|from|rgba|to|url|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|max|min|(?:repeating-)?(?:linear|radial)-gradient)|-webkit-gradient)/iS', array($this, 'lowercase_common_functions_values'), $css); 323 | 324 | // Put the space back in some cases, to support stuff like 325 | // @media screen and (-webkit-min-device-pixel-ratio:0){ 326 | $css = preg_replace('/\band\(/i', 'and (', $css); 327 | 328 | // Remove the spaces after the things that should not have spaces after them. 329 | $css = preg_replace('/([\!\{\}\:;\>\+\(\[\~\=,])\s+/S', '$1', $css); 330 | 331 | // remove unnecessary semicolons 332 | $css = preg_replace('/;+\}/', '}', $css); 333 | 334 | // Fix for issue: #2528146 335 | // Restore semicolon if the last property is prefixed with a `*` (lte IE7 hack) 336 | // to avoid issues on Symbian S60 3.x browsers. 337 | $css = preg_replace('/(\*[a-z0-9\-]+\s*\:[^;\}]+)(\})/', '$1;$2', $css); 338 | 339 | // Replace 0 and 0 values with 0. 340 | // data type: https://developer.mozilla.org/en-US/docs/Web/CSS/length 341 | // data type: https://developer.mozilla.org/en-US/docs/Web/CSS/percentage 342 | $css = preg_replace('/([^\\\\]\:|\s)0(?:em|ex|ch|rem|vw|vh|vm|vmin|cm|mm|in|px|pt|pc|%)/iS', '${1}0', $css); 343 | 344 | // 0% step in a keyframe? restore the % unit 345 | $css = preg_replace_callback('/(@[a-z\-]*?keyframes[^\{]+\{)(.*?)(\}\})/iS', array($this, 'replace_keyframe_zero'), $css); 346 | 347 | // Replace 0 0; or 0 0 0; or 0 0 0 0; with 0. 348 | $css = preg_replace('/\:0(?: 0){1,3}(;|\}| \!)/', ':0$1', $css); 349 | 350 | // Fix for issue: #2528142 351 | // Replace text-shadow:0; with text-shadow:0 0 0; 352 | $css = preg_replace('/(text-shadow\:0)(;|\}| \!)/i', '$1 0 0$2', $css); 353 | 354 | // Replace background-position:0; with background-position:0 0; 355 | // same for transform-origin 356 | // Changing -webkit-mask-position: 0 0 to just a single 0 will result in the second parameter defaulting to 50% (center) 357 | $css = preg_replace('/(background\-position|webkit-mask-position|(?:webkit|moz|o|ms|)\-?transform\-origin)\:0(;|\}| \!)/iS', '$1:0 0$2', $css); 358 | 359 | // Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space) 360 | // Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space) 361 | // This makes it more likely that it'll get further compressed in the next step. 362 | $css = preg_replace_callback('/rgb\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'rgb_to_hex'), $css); 363 | $css = preg_replace_callback('/hsl\s*\(\s*([0-9,\s\-\.\%]+)\s*\)(.{1})/i', array($this, 'hsl_to_hex'), $css); 364 | 365 | // Shorten colors from #AABBCC to #ABC or short color name. 366 | $css = $this->compress_hex_colors($css); 367 | 368 | // border: none to border:0, outline: none to outline:0 369 | $css = preg_replace('/(border\-?(?:top|right|bottom|left|)|outline)\:none(;|\}| \!)/iS', '$1:0$2', $css); 370 | 371 | // shorter opacity IE filter 372 | $css = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $css); 373 | 374 | // Find a fraction that is used for Opera's -o-device-pixel-ratio query 375 | // Add token to add the "\" back in later 376 | $css = preg_replace('/\(([a-z\-]+):([0-9]+)\/([0-9]+)\)/i', '($1:$2'. self::QUERY_FRACTION .'$3)', $css); 377 | 378 | // Remove empty rules. 379 | $css = preg_replace('/[^\};\{\/]+\{\}/S', '', $css); 380 | 381 | // Add "/" back to fix Opera -o-device-pixel-ratio query 382 | $css = preg_replace('/'. self::QUERY_FRACTION .'/', '/', $css); 383 | 384 | // Replace multiple semi-colons in a row by a single one 385 | // See SF bug #1980989 386 | $css = preg_replace('/;;+/', ';', $css); 387 | 388 | // Restore new lines for /*! important comments 389 | $css = preg_replace('/'. self::NL .'/', "\n", $css); 390 | 391 | // Lowercase all uppercase properties 392 | $css = preg_replace_callback('/(\{|\;)([A-Z\-]+)(\:)/', array($this, 'lowercase_properties'), $css); 393 | 394 | // Some source control tools don't like it when files containing lines longer 395 | // than, say 8000 characters, are checked in. The linebreak option is used in 396 | // that case to split long lines after a specific column. 397 | if ($linebreak_pos !== FALSE && (int) $linebreak_pos >= 0) { 398 | $linebreak_pos = (int) $linebreak_pos; 399 | $start_index = $i = 0; 400 | while ($i < strlen($css)) { 401 | $i++; 402 | if ($css[$i - 1] === '}' && $i - $start_index > $linebreak_pos) { 403 | $css = $this->str_slice($css, 0, $i) . "\n" . $this->str_slice($css, $i); 404 | $start_index = $i; 405 | } 406 | } 407 | } 408 | 409 | // restore preserved comments and strings in reverse order 410 | for ($i = count($this->preserved_tokens) - 1; $i >= 0; $i--) { 411 | $css = preg_replace('/' . self::TOKEN . $i . '___/', $this->preserved_tokens[$i], $css, 1); 412 | } 413 | 414 | // Trim the final string (for any leading or trailing white spaces) 415 | return trim($css); 416 | } 417 | 418 | /** 419 | * Utility method to replace all data urls with tokens before we start 420 | * compressing, to avoid performance issues running some of the subsequent 421 | * regexes against large strings chunks. 422 | * 423 | * @param string $css 424 | * @return string 425 | */ 426 | private function extract_data_urls($css) 427 | { 428 | // Leave data urls alone to increase parse performance. 429 | $max_index = strlen($css) - 1; 430 | $append_index = $index = $last_index = $offset = 0; 431 | $sb = array(); 432 | $pattern = '/url\(\s*(["\']?)data\:/i'; 433 | 434 | // Since we need to account for non-base64 data urls, we need to handle 435 | // ' and ) being part of the data string. Hence switching to indexOf, 436 | // to determine whether or not we have matching string terminators and 437 | // handling sb appends directly, instead of using matcher.append* methods. 438 | 439 | while (preg_match($pattern, $css, $m, 0, $offset)) { 440 | $index = $this->index_of($css, $m[0], $offset); 441 | $last_index = $index + strlen($m[0]); 442 | $start_index = $index + 4; // "url(".length() 443 | $end_index = $last_index - 1; 444 | $terminator = $m[1]; // ', " or empty (not quoted) 445 | $found_terminator = FALSE; 446 | 447 | if (strlen($terminator) === 0) { 448 | $terminator = ')'; 449 | } 450 | 451 | while ($found_terminator === FALSE && $end_index+1 <= $max_index) { 452 | $end_index = $this->index_of($css, $terminator, $end_index + 1); 453 | 454 | // endIndex == 0 doesn't really apply here 455 | if ($end_index > 0 && substr($css, $end_index - 1, 1) !== '\\') { 456 | $found_terminator = TRUE; 457 | if (')' != $terminator) { 458 | $end_index = $this->index_of($css, ')', $end_index); 459 | } 460 | } 461 | } 462 | 463 | // Enough searching, start moving stuff over to the buffer 464 | $sb[] = $this->str_slice($css, $append_index, $index); 465 | 466 | if ($found_terminator) { 467 | $token = $this->str_slice($css, $start_index, $end_index); 468 | $token = preg_replace('/\s+/', '', $token); 469 | $this->preserved_tokens[] = $token; 470 | 471 | $preserver = 'url(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___)'; 472 | $sb[] = $preserver; 473 | 474 | $append_index = $end_index + 1; 475 | } else { 476 | // No end terminator found, re-add the whole match. Should we throw/warn here? 477 | $sb[] = $this->str_slice($css, $index, $last_index); 478 | $append_index = $last_index; 479 | } 480 | 481 | $offset = $last_index; 482 | } 483 | 484 | $sb[] = $this->str_slice($css, $append_index); 485 | 486 | return implode('', $sb); 487 | } 488 | 489 | /** 490 | * Utility method to compress hex color values of the form #AABBCC to #ABC or short color name. 491 | * 492 | * DOES NOT compress CSS ID selectors which match the above pattern (which would break things). 493 | * e.g. #AddressForm { ... } 494 | * 495 | * DOES NOT compress IE filters, which have hex color values (which would break things). 496 | * e.g. filter: chroma(color="#FFFFFF"); 497 | * 498 | * DOES NOT compress invalid hex values. 499 | * e.g. background-color: #aabbccdd 500 | * 501 | * @param string $css 502 | * @return string 503 | */ 504 | private function compress_hex_colors($css) 505 | { 506 | // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters) 507 | $pattern = '/(\=\s*?["\']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/iS'; 508 | $_index = $index = $last_index = $offset = 0; 509 | $sb = array(); 510 | // See: http://ajaxmin.codeplex.com/wikipage?title=CSS%20Colors 511 | $short_safe = array( 512 | '#808080' => 'gray', 513 | '#008000' => 'green', 514 | '#800000' => 'maroon', 515 | '#000080' => 'navy', 516 | '#808000' => 'olive', 517 | '#ffa500' => 'orange', 518 | '#800080' => 'purple', 519 | '#c0c0c0' => 'silver', 520 | '#008080' => 'teal', 521 | '#f00' => 'red' 522 | ); 523 | 524 | while (preg_match($pattern, $css, $m, 0, $offset)) { 525 | $index = $this->index_of($css, $m[0], $offset); 526 | $last_index = $index + strlen($m[0]); 527 | $is_filter = $m[1] !== null && $m[1] !== ''; 528 | 529 | $sb[] = $this->str_slice($css, $_index, $index); 530 | 531 | if ($is_filter) { 532 | // Restore, maintain case, otherwise filter will break 533 | $sb[] = $m[1] . '#' . $m[2] . $m[3] . $m[4] . $m[5] . $m[6] . $m[7]; 534 | } else { 535 | if (strtolower($m[2]) == strtolower($m[3]) && 536 | strtolower($m[4]) == strtolower($m[5]) && 537 | strtolower($m[6]) == strtolower($m[7])) { 538 | // Compress. 539 | $hex = '#' . strtolower($m[3] . $m[5] . $m[7]); 540 | } else { 541 | // Non compressible color, restore but lower case. 542 | $hex = '#' . strtolower($m[2] . $m[3] . $m[4] . $m[5] . $m[6] . $m[7]); 543 | } 544 | // replace Hex colors to short safe color names 545 | $sb[] = array_key_exists($hex, $short_safe) ? $short_safe[$hex] : $hex; 546 | } 547 | 548 | $_index = $offset = $last_index - strlen($m[8]); 549 | } 550 | 551 | $sb[] = $this->str_slice($css, $_index); 552 | 553 | return implode('', $sb); 554 | } 555 | 556 | /* CALLBACKS 557 | * --------------------------------------------------------------------------------------------- 558 | */ 559 | 560 | private function replace_string($matches) 561 | { 562 | $match = $matches[0]; 563 | $quote = substr($match, 0, 1); 564 | // Must use addcslashes in PHP to avoid parsing of backslashes 565 | $match = addcslashes($this->str_slice($match, 1, -1), '\\'); 566 | 567 | // maybe the string contains a comment-like substring? 568 | // one, maybe more? put'em back then 569 | if (($pos = $this->index_of($match, self::COMMENT)) >= 0) { 570 | for ($i = 0, $max = count($this->comments); $i < $max; $i++) { 571 | $match = preg_replace('/' . self::COMMENT . $i . '___/', $this->comments[$i], $match, 1); 572 | } 573 | } 574 | 575 | // minify alpha opacity in filter strings 576 | $match = preg_replace('/progid\:DXImageTransform\.Microsoft\.Alpha\(Opacity\=/i', 'alpha(opacity=', $match); 577 | 578 | $this->preserved_tokens[] = $match; 579 | return $quote . self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . $quote; 580 | } 581 | 582 | private function replace_colon($matches) 583 | { 584 | return preg_replace('/\:/', self::CLASSCOLON, $matches[0]); 585 | } 586 | 587 | private function replace_calc($matches) 588 | { 589 | $this->preserved_tokens[] = trim(preg_replace('/\s*([\*\/\(\),])\s*/', '$1', $matches[2])); 590 | return 'calc('. self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')'; 591 | } 592 | 593 | private function preserve_old_IE_specific_matrix_definition($matches) 594 | { 595 | $this->preserved_tokens[] = $matches[1]; 596 | return 'filter:progid:DXImageTransform.Microsoft.Matrix(' . self::TOKEN . (count($this->preserved_tokens) - 1) . '___' . ')'; 597 | } 598 | 599 | private function replace_keyframe_zero($matches) 600 | { 601 | return $matches[1] . preg_replace('/0(\{|,[^\)\{]+\{)/', '0%$1', $matches[2]) . $matches[3]; 602 | } 603 | 604 | private function rgb_to_hex($matches) 605 | { 606 | // Support for percentage values rgb(100%, 0%, 45%); 607 | if ($this->index_of($matches[1], '%') >= 0){ 608 | $rgbcolors = explode(',', str_replace('%', '', $matches[1])); 609 | for ($i = 0; $i < count($rgbcolors); $i++) { 610 | $rgbcolors[$i] = $this->round_number(floatval($rgbcolors[$i]) * 2.55); 611 | } 612 | } else { 613 | $rgbcolors = explode(',', $matches[1]); 614 | } 615 | 616 | // Values outside the sRGB color space should be clipped (0-255) 617 | for ($i = 0; $i < count($rgbcolors); $i++) { 618 | $rgbcolors[$i] = $this->clamp_number(intval($rgbcolors[$i], 10), 0, 255); 619 | $rgbcolors[$i] = sprintf("%02x", $rgbcolors[$i]); 620 | } 621 | 622 | // Fix for issue #2528093 623 | if (!preg_match('/[\s\,\);\}]/', $matches[2])){ 624 | $matches[2] = ' ' . $matches[2]; 625 | } 626 | 627 | return '#' . implode('', $rgbcolors) . $matches[2]; 628 | } 629 | 630 | private function hsl_to_hex($matches) 631 | { 632 | $values = explode(',', str_replace('%', '', $matches[1])); 633 | $h = floatval($values[0]); 634 | $s = floatval($values[1]); 635 | $l = floatval($values[2]); 636 | 637 | // Wrap and clamp, then fraction! 638 | $h = ((($h % 360) + 360) % 360) / 360; 639 | $s = $this->clamp_number($s, 0, 100) / 100; 640 | $l = $this->clamp_number($l, 0, 100) / 100; 641 | 642 | if ($s == 0) { 643 | $r = $g = $b = $this->round_number(255 * $l); 644 | } else { 645 | $v2 = $l < 0.5 ? $l * (1 + $s) : ($l + $s) - ($s * $l); 646 | $v1 = (2 * $l) - $v2; 647 | $r = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h + (1/3))); 648 | $g = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h)); 649 | $b = $this->round_number(255 * $this->hue_to_rgb($v1, $v2, $h - (1/3))); 650 | } 651 | 652 | return $this->rgb_to_hex(array('', $r.','.$g.','.$b, $matches[2])); 653 | } 654 | 655 | private function lowercase_pseudo_first($matches) 656 | { 657 | return ':first-'. strtolower($matches[1]) .' '. $matches[2]; 658 | } 659 | 660 | private function lowercase_directives($matches) 661 | { 662 | return '@'. strtolower($matches[1]); 663 | } 664 | 665 | private function lowercase_pseudo_elements($matches) 666 | { 667 | return ':'. strtolower($matches[1]); 668 | } 669 | 670 | private function lowercase_common_functions($matches) 671 | { 672 | return ':'. strtolower($matches[1]) .'('; 673 | } 674 | 675 | private function lowercase_common_functions_values($matches) 676 | { 677 | return $matches[1] . strtolower($matches[2]); 678 | } 679 | 680 | private function lowercase_properties($matches) 681 | { 682 | return $matches[1].strtolower($matches[2]).$matches[3]; 683 | } 684 | 685 | /* HELPERS 686 | * --------------------------------------------------------------------------------------------- 687 | */ 688 | 689 | private function hue_to_rgb($v1, $v2, $vh) 690 | { 691 | $vh = $vh < 0 ? $vh + 1 : ($vh > 1 ? $vh - 1 : $vh); 692 | if ($vh * 6 < 1) return $v1 + ($v2 - $v1) * 6 * $vh; 693 | if ($vh * 2 < 1) return $v2; 694 | if ($vh * 3 < 2) return $v1 + ($v2 - $v1) * ((2/3) - $vh) * 6; 695 | return $v1; 696 | } 697 | 698 | private function round_number($n) 699 | { 700 | return intval(floor(floatval($n) + 0.5), 10); 701 | } 702 | 703 | private function clamp_number($n, $min, $max) 704 | { 705 | return min(max($n, $min), $max); 706 | } 707 | 708 | /** 709 | * PHP port of Javascript's "indexOf" function for strings only 710 | * Author: Tubal Martin http://blog.margenn.com 711 | * 712 | * @param string $haystack 713 | * @param string $needle 714 | * @param int $offset index (optional) 715 | * @return int 716 | */ 717 | private function index_of($haystack, $needle, $offset = 0) 718 | { 719 | $index = strpos($haystack, $needle, $offset); 720 | 721 | return ($index !== FALSE) ? $index : -1; 722 | } 723 | 724 | /** 725 | * PHP port of Javascript's "slice" function for strings only 726 | * Author: Tubal Martin http://blog.margenn.com 727 | * Tests: http://margenn.com/tubal/str_slice/ 728 | * 729 | * @param string $str 730 | * @param int $start index 731 | * @param int|bool $end index (optional) 732 | * @return string 733 | */ 734 | private function str_slice($str, $start = 0, $end = FALSE) 735 | { 736 | if ($end !== FALSE && ($start < 0 || $end <= 0)) { 737 | $max = strlen($str); 738 | 739 | if ($start < 0) { 740 | if (($start = $max + $start) < 0) { 741 | return ''; 742 | } 743 | } 744 | 745 | if ($end < 0) { 746 | if (($end = $max + $end) < 0) { 747 | return ''; 748 | } 749 | } 750 | 751 | if ($end <= $start) { 752 | return ''; 753 | } 754 | } 755 | 756 | $slice = ($end === FALSE) ? substr($str, $start) : substr($str, $start, $end - $start); 757 | return ($slice === FALSE) ? '' : $slice; 758 | } 759 | 760 | /** 761 | * Convert strings like "64M" or "30" to int values 762 | * @param mixed $size 763 | * @return int 764 | */ 765 | private function normalize_int($size) 766 | { 767 | if (is_string($size)) { 768 | switch (substr($size, -1)) { 769 | case 'M': case 'm': return $size * 1048576; 770 | case 'K': case 'k': return $size * 1024; 771 | case 'G': case 'g': return $size * 1073741824; 772 | } 773 | } 774 | 775 | return (int) $size; 776 | } 777 | } -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/http-concat/jsconcat.php: -------------------------------------------------------------------------------- 1 | old_scripts = $scripts; 20 | 21 | // Unset all the object properties except our private copy of the scripts object. 22 | // We have to unset everything so that the overload methods talk to $this->old_scripts->whatever 23 | // instead of $this->whatever. 24 | foreach ( array_keys( get_object_vars( $this ) ) as $key ) { 25 | if ( 'old_scripts' === $key ) { 26 | continue; 27 | } 28 | unset( $this->$key ); 29 | } 30 | 31 | parent::__construct(); 32 | } 33 | 34 | function do_items( $handles = false, $group = false ) { 35 | $handles = false === $handles ? $this->queue : (array) $handles; 36 | $javascripts= array(); 37 | $siteurl = site_url(); 38 | 39 | $this->all_deps( $handles ); 40 | $level = 0; 41 | 42 | foreach( $this->to_do as $key => $handle ) { 43 | if ( in_array( $handle, $this->done ) || !isset( $this->registered[$handle] ) ) 44 | continue; 45 | 46 | if ( ! $this->registered[$handle]->src ) { // Defines a group. 47 | $this->done[] = $handle; 48 | continue; 49 | } 50 | 51 | if ( 0 === $group && $this->groups[$handle] > 0 ) { 52 | $this->in_footer[] = $handle; 53 | unset( $this->to_do[$key] ); 54 | continue; 55 | } 56 | 57 | if ( false === $group && in_array( $handle, $this->in_footer, true ) ) 58 | $this->in_footer = array_diff( $this->in_footer, (array) $handle ); 59 | 60 | $obj = $this->registered[$handle]; 61 | $js_url = parse_url( $obj->src ); 62 | $extra = $obj->extra; 63 | 64 | // Don't concat by default 65 | $do_concat = false; 66 | 67 | // Only try to concat static js files 68 | if ( false !== strpos( $js_url['path'], '.js' ) ) 69 | $do_concat = true; 70 | 71 | // Don't try to concat externally hosted scripts 72 | if ( ( isset( $js_url['host'] ) && ( preg_replace( '/https?:\/\//', '', $siteurl ) != $js_url['host'] ) ) ) 73 | $do_concat = false; 74 | 75 | // Concat and canonicalize the paths only for 76 | // existing scripts that aren't outside ABSPATH 77 | $js_realpath = realpath( ABSPATH . $js_url['path'] ); 78 | if ( ! $js_realpath || 0 !== strpos( $js_realpath, ABSPATH ) ) 79 | $do_concat = false; 80 | else 81 | $js_url['path'] = substr( $js_realpath, strlen( ABSPATH ) - 1 ); 82 | 83 | if ( true === $do_concat ) { 84 | if ( !isset( $javascripts[$level] ) ) 85 | $javascripts[$level]['type'] = 'concat'; 86 | 87 | $javascripts[$level]['paths'][] = $js_url['path']; 88 | $javascripts[$level]['handles'][] = $handle; 89 | } else { 90 | $level++; 91 | $javascripts[$level]['type'] = 'do_item'; 92 | $javascripts[$level]['handle'] = $handle; 93 | $level++; 94 | } 95 | unset( $this->to_do[$key] ); 96 | } 97 | 98 | if ( empty( $javascripts ) ) 99 | return $this->done; 100 | 101 | foreach ( $javascripts as $js_array ) { 102 | if ( 'do_item' == $js_array['type'] ) { 103 | if ( $this->do_item( $js_array['handle'], $group ) ) 104 | $this->done[] = $js_array['handle']; 105 | } else if ( 'concat' == $js_array['type'] ) { 106 | array_map( array( $this, 'print_extra_script' ), $js_array['handles'] ); 107 | 108 | if ( count( $js_array['paths'] ) > 1) { 109 | $paths = array_map( function( $url ) { return ABSPATH . $url; }, $js_array['paths'] ); 110 | $mtime = max( array_map( 'filemtime', $paths ) ); 111 | $path_str = implode( $js_array['paths'], ',' ) . "?m=${mtime}j"; 112 | 113 | if ( $this->allow_gzip_compression ) { 114 | $path_64 = base64_encode( gzcompress( $path_str ) ); 115 | if ( strlen( $path_str ) > ( strlen( $path_64 ) + 1 ) ) 116 | $path_str = '-' . $path_64; 117 | } 118 | 119 | $href = $siteurl . "/_static/??" . $path_str; 120 | } else { 121 | $href = $this->cache_bust_mtime( $siteurl . $js_array['paths'][0] ); 122 | } 123 | 124 | $this->done = array_merge( $this->done, $js_array['handles'] ); 125 | echo "\n"; 126 | } 127 | } 128 | 129 | return $this->done; 130 | } 131 | 132 | function cache_bust_mtime( $url ) { 133 | if ( strpos( $url, '?m=' ) ) 134 | return $url; 135 | 136 | $parts = parse_url( $url ); 137 | if ( ! isset( $parts['path'] ) || empty( $parts['path'] ) ) 138 | return $url; 139 | 140 | $file = ABSPATH . ltrim( $parts['path'], '/' ); 141 | 142 | $mtime = false; 143 | if ( file_exists( $file ) ) 144 | $mtime = filemtime( $file ); 145 | 146 | if ( ! $mtime ) 147 | return $url; 148 | 149 | if ( false === strpos( $url, '?' ) ) { 150 | $q = ''; 151 | } else { 152 | list( $url, $q ) = explode( '?', $url, 2 ); 153 | if ( strlen( $q ) ) 154 | $q = '&' . $q; 155 | } 156 | 157 | return "$url?m={$mtime}g{$q}"; 158 | } 159 | 160 | function __isset( $key ) { 161 | return isset( $this->old_scripts->$key ); 162 | } 163 | 164 | function __unset( $key ) { 165 | unset( $this->old_scripts->$key ); 166 | } 167 | 168 | function &__get( $key ) { 169 | return $this->old_scripts->$key; 170 | } 171 | 172 | function __set( $key, $value ) { 173 | $this->old_scripts->$key = $value; 174 | } 175 | } 176 | 177 | function js_concat_init() { 178 | global $wp_scripts; 179 | 180 | if ( ! ( $wp_scripts instanceof WP_Scripts ) ) { 181 | $wp_scripts = new WP_Scripts(); 182 | } 183 | 184 | $wp_scripts = new WPcom_JS_Concat( $wp_scripts ); 185 | $wp_scripts->allow_gzip_compression = ALLOW_GZIP_COMPRESSION; 186 | } 187 | 188 | add_action( 'init', 'js_concat_init' ); 189 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/http-concat/ngx-http-concat.php: -------------------------------------------------------------------------------- 1 | 'text/css', 21 | 'js' => 'application/x-javascript' 22 | ); 23 | 24 | /* Constants */ 25 | // By default determine the document root from this scripts path in the plugins dir (you can hardcode this define) 26 | define( 'CONCAT_FILES_ROOT', substr( dirname( __DIR__ ), 0, strpos( dirname( __DIR__ ), '/wp-content' ) ) ); 27 | define( 'CONCAT_WP_DIR', '/wp' ); 28 | 29 | function concat_http_status_exit( $status ) { 30 | switch ( $status ) { 31 | case 200: 32 | $text = 'OK'; 33 | break; 34 | case 400: 35 | $text = 'Bad Request'; 36 | break; 37 | case 403: 38 | $text = 'Forbidden'; 39 | break; 40 | case 404: 41 | $text = 'Not found'; 42 | break; 43 | case 500: 44 | $text = 'Internal Server Error'; 45 | break; 46 | default: 47 | $text = ''; 48 | } 49 | 50 | $protocol = $_SERVER['SERVER_PROTOCOL']; 51 | if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol ) 52 | $protocol = 'HTTP/1.0'; 53 | 54 | @header( "$protocol $status $text", true, $status ); 55 | exit(); 56 | } 57 | 58 | function concat_get_mtype( $file ) { 59 | global $concat_types; 60 | 61 | $lastdot_pos = strrpos( $file, '.' ); 62 | if ( false === $lastdot_pos ) 63 | return false; 64 | 65 | $ext = substr( $file, $lastdot_pos + 1 ); 66 | 67 | return isset( $concat_types[$ext] ) ? $concat_types[$ext] : false; 68 | } 69 | 70 | function concat_get_path( $uri ) { 71 | if ( ! strlen( $uri ) ) 72 | concat_http_status_exit( 400 ); 73 | 74 | if ( false !== strpos( $uri, '..' ) || false !== strpos( $uri, "\0" ) ) 75 | concat_http_status_exit( 400 ); 76 | 77 | return CONCAT_FILES_ROOT . ( '/' != $uri[0] ? '/' : CONCAT_WP_DIR ) . $uri; 78 | } 79 | 80 | /* Main() */ 81 | if ( !in_array( $_SERVER['REQUEST_METHOD'], array( 'GET', 'HEAD' ) ) ) 82 | concat_http_status_exit( 400 ); 83 | 84 | // /_static/??/foo/bar.css,/foo1/bar/baz.css?m=293847g 85 | // or 86 | // /_static/??-eJzTT8vP109KLNJLLi7W0QdyDEE8IK4CiVjn2hpZGluYmKcDABRMDPM= 87 | $args = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY ); 88 | if ( ! $args || false === strpos( $args, '?' ) ) 89 | concat_http_status_exit( 400 ); 90 | 91 | $args = substr( $args, strpos( $args, '?' ) + 1 ); 92 | 93 | // /foo/bar.css,/foo1/bar/baz.css?m=293847g 94 | // or 95 | // -eJzTT8vP109KLNJLLi7W0QdyDEE8IK4CiVjn2hpZGluYmKcDABRMDPM= 96 | if ( '-' == $args[0] ) 97 | $args = gzuncompress( base64_decode( substr( $args, 1 ) ) ); 98 | 99 | // /foo/bar.css,/foo1/bar/baz.css?m=293847g 100 | $version_string_pos = strpos( $args, '?' ); 101 | if ( false !== $version_string_pos ) 102 | $args = substr( $args, 0, $version_string_pos ); 103 | 104 | // /foo/bar.css,/foo1/bar/baz.css 105 | $args = explode( ',', $args ); 106 | if ( ! $args ) 107 | concat_http_status_exit( 400 ); 108 | 109 | // array( '/foo/bar.css', '/foo1/bar/baz.css' ) 110 | if ( 0 == count( $args ) || count( $args ) > $concat_max_files ) 111 | concat_http_status_exit( 400 ); 112 | 113 | $last_modified = 0; 114 | $pre_output = ''; 115 | $output = ''; 116 | 117 | $css_minify = new CSSmin(); 118 | 119 | foreach ( $args as $uri ) { 120 | $fullpath = concat_get_path( $uri ); 121 | 122 | if ( ! file_exists( $fullpath ) ) 123 | concat_http_status_exit( 404 ); 124 | 125 | $mime_type = concat_get_mtype( $fullpath ); 126 | if ( ! in_array( $mime_type, $concat_types ) ) 127 | concat_http_status_exit( 400 ); 128 | 129 | if ( $concat_unique ) { 130 | if ( ! isset( $last_mime_type ) ) 131 | $last_mime_type = $mime_type; 132 | 133 | if ( $last_mime_type != $mime_type ) 134 | concat_http_status_exit( 400 ); 135 | } 136 | 137 | $stat = stat( $fullpath ); 138 | if ( false === $stat ) 139 | concat_http_status_exit( 500 ); 140 | 141 | if ( $stat['mtime'] > $last_modified ) 142 | $last_modified = $stat['mtime']; 143 | 144 | $buf = file_get_contents( $fullpath ); 145 | if ( false === $buf ) 146 | concat_http_status_exit( 500 ); 147 | 148 | if ( 'text/css' == $mime_type ) { 149 | $dirpath = dirname( $uri ); 150 | 151 | // url(relative/path/to/file) -> url(/absolute/and/not/relative/path/to/file) 152 | $buf = preg_replace( 153 | '/(:?\s*url\s*\()\s*(?:\'|")?\s*([^\/\'"\s\)](?:(? AlphaImageLoader(...src='/absolute/path/to/file'...) 159 | $buf = preg_replace( 160 | '/(Microsoft.AlphaImageLoader\s*\([^\)]*src=(?:\'|")?)([^\/\'"\s\)](?:(?@charset\s+[\'"][^\'"]+[\'"];)/i', 169 | function ( $match ) { 170 | global $pre_output; 171 | 172 | if ( 0 === strpos( $pre_output, '@charset' ) ) 173 | return ''; 174 | 175 | $pre_output = $match[0] . "\n" . $pre_output; 176 | 177 | return ''; 178 | }, 179 | $buf 180 | ); 181 | } 182 | 183 | // Move the @import rules on top of the concatenated output. 184 | // Only @charset rule are allowed before them. 185 | if ( false !== strpos( $buf, '@import' ) ) { 186 | $buf = preg_replace_callback( 187 | '/(?P@import\s+(?:url\s*\()?[\'"\s]*)(?P[^\'"\s](?:https?:\/\/.+\/?)?.+?)(?P[\'"\s\)]*;)/i', 188 | function ( $match ) use ( $dirpath ) { 189 | global $pre_output; 190 | 191 | if ( 0 !== strpos( $match['path'], 'http' ) && '/' != $match['path'][0] ) 192 | $pre_output .= $match['pre_path'] . ( $dirpath == '/' ? '/' : $dirpath . '/' ) . 193 | $match['path'] . $match['post_path'] . "\n"; 194 | else 195 | $pre_output .= $match[0] . "\n"; 196 | 197 | return ''; 198 | }, 199 | $buf 200 | ); 201 | } 202 | 203 | $buf = $css_minify->run( $buf ); 204 | } 205 | 206 | if ( 'application/x-javascript' == $mime_type ) 207 | $output .= "$buf;\n"; 208 | else 209 | $output .= "$buf"; 210 | } 211 | 212 | header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $last_modified ) . ' GMT' ); 213 | header( 'Content-Length: ' . ( strlen( $pre_output ) + strlen( $output ) ) ); 214 | header( "Content-Type: $mime_type" ); 215 | 216 | echo $pre_output . $output; 217 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/infinite-scroll.php: -------------------------------------------------------------------------------- 1 | is_android() ) 15 | $settings['footer'] = false; 16 | 17 | return $settings; 18 | } 19 | add_filter( 'infinite_scroll_settings', 'infinite_scroll_filter_settings' ); 20 | 21 | /** 22 | * Only apply IS to homepage on dotcom. 23 | * Plugin supports all archives as part of Jetpack release. 24 | * 25 | * @param bool $supported 26 | * @uses is_home 27 | * @filter infinite_scroll_archive_supported 28 | * @return bool 29 | */ 30 | function infinite_scroll_archive_supported( $supported ) { 31 | return is_home(); 32 | } 33 | add_filter( 'infinite_scroll_archive_supported', 'infinite_scroll_archive_supported' ); 34 | 35 | add_action( 'infinite_scroll_credit', 'wpcom_infinite_scroll_custom_credits' ); 36 | function wpcom_infinite_scroll_custom_credits( $credit ) { 37 | if ( function_exists( 'wpcom_is_vip' ) && wpcom_is_vip() ) 38 | $credit = sprintf( __( 'Powered by WordPress.com VIP' ), 'http://vip.wordpress.com?ref=is-footer' ); 39 | return $credit; 40 | } 41 | 42 | if ( class_exists( 'The_Neverending_Home_Page' ) ) : 43 | /** 44 | * Show Post Flair on Infinite Scroll queries, only if it should show for regular queries as well. 45 | * 46 | * @param bool $show 47 | * @param bool $default 48 | * @uses The_Neverending_Home_Page::got_infinity 49 | * @filter post_flair_should_show 50 | * @return bool 51 | */ 52 | function wpcom_infinite_scroll_show_postflair( $show, $default ) { 53 | if ( $default && The_Neverending_Home_Page::got_infinity() ) 54 | $show = true; 55 | 56 | return $show; 57 | } 58 | 59 | add_filter( 'post_flair_should_show', 'wpcom_infinite_scroll_show_postflair', 10, 2 ); 60 | endif; 61 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/mobile-theme-bootstrap.php: -------------------------------------------------------------------------------- 1 | domain; 53 | return 'wordpress@'.$current_blog->domain; 54 | } ); 55 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/rewrite-rules-inspector-helper.php: -------------------------------------------------------------------------------- 1 | 'wpcom-vip-flush-rewrite-rules', 15 | 'secret' => WPCOM_VIP_FLUSH_REWRITE_RULES_SECRET, 16 | ); 17 | $request_url = add_query_arg( $args, get_home_url( $_blog_id ) ); 18 | wp_remote_get( $request_url, array( 'blocking' => false ) ); 19 | } 20 | 21 | /** 22 | * Always enable custom rewrite rules in VIP Quickstart 23 | */ 24 | function wpcom_theme_has_custom_rewrite_rules( $stylesheet = null ) { 25 | return true; 26 | } 27 | 28 | /** 29 | * When a VIP switches their theme, make a request to flush and reload their rules 30 | * It's less than ideal to do a remote request, but all of the new theme's code 31 | * won't be loaded on this request 32 | */ 33 | add_action( 'switch_theme', 'rri_wpcom_action_switch_theme' ); 34 | function rri_wpcom_action_switch_theme( $new_name ) { 35 | 36 | if ( !wpcom_theme_has_custom_rewrite_rules() ) 37 | return; 38 | 39 | wpcom_initiate_flush_rewrite_rules(); 40 | } 41 | 42 | /** 43 | * Flush rewrite rules for a given VIP 44 | * Most likely called from a post-commit job 45 | * 46 | * Usage: http://site.com/?action=wpcom-vip-flush-rewrite-rules&secret={WPCOM_VIP_FLUSH_REWRITE_RULES_SECRET} 47 | */ 48 | function wpcom_vip_handle_flush_rewrite_rules() { 49 | 50 | if ( ! isset( $_GET['action'] ) || ! $_GET['action'] == 'wpcom-vip-flush-rewrite-rules' ) 51 | return; 52 | 53 | // Pass the secret key check 54 | if ( !isset( $_GET['secret' ] ) || $_GET['secret'] != WPCOM_VIP_FLUSH_REWRITE_RULES_SECRET ) 55 | return; 56 | 57 | global $wp_rewrite; 58 | 59 | /** 60 | * VIPs and other themes can declare the permastruct, tag and category bases in their themes. 61 | * This is done by filtering the option. To ensure we're getting the proper data, refresh. 62 | * 63 | * However, wpcom_vip_refresh_wp_rewrite() noops the values in the database so we only want to run it 64 | * if the permastructs are defined in the theme (e.g. not Enterprise) 65 | */ 66 | if ( ( defined( 'WPCOM_VIP_CUSTOM_PERMALINKS' ) && WPCOM_VIP_CUSTOM_PERMALINKS ) 67 | || ( defined( 'WPCOM_VIP_CUSTOM_CATEGORY_BASE' ) && WPCOM_VIP_CUSTOM_CATEGORY_BASE ) 68 | || ( defined( 'WPCOM_VIP_CUSTOM_TAG_BASE' ) && WPCOM_VIP_CUSTOM_TAG_BASE ) ) 69 | wpcom_vip_refresh_wp_rewrite(); 70 | 71 | /** 72 | * We can't use flush_rewrite_rules( false ) in this context because 73 | * on WPCOM it deletes the transient representation of rewrite_rules, not the option. 74 | * For now, we need to do some code replication. 75 | */ 76 | $wp_rewrite->matches = 'matches'; 77 | $wp_rewrite->rewrite_rules(); 78 | update_option( 'rewrite_rules', $wp_rewrite->rules ); 79 | 80 | wp_die( __( 'Rewrite rules have been flushed for ' . get_site_url() ) ); 81 | exit; 82 | } 83 | add_action( 'init', 'wpcom_vip_handle_flush_rewrite_rules', 99999 ); 84 | 85 | /** 86 | * VIPs and other themes can declare the permastruct, tag and category bases in their themes. 87 | * This is done by filtering the option. 88 | * 89 | * To ensure we're using the freshest values, and that the option value is available earlier 90 | * than when the theme is loaded, we need to get each option, save it again, and then 91 | * reinitialize wp_rewrite. 92 | * 93 | * This is most commonly used in our code to flush rewrites 94 | */ 95 | function wpcom_vip_refresh_wp_rewrite() { 96 | global $wp_rewrite; 97 | 98 | // Permastructs available in the options table and their core defaults 99 | $permastructs = array( 100 | 'permalink_structure' => '/%year%/%monthnum%/%day%/%postname%/', 101 | 'category_base' => '', 102 | 'tag_base' => '', 103 | ); 104 | foreach( $permastructs as $option_key => $default_value ) { 105 | $filter = 'pre_option_' . $option_key; 106 | $callback = '_wpcom_vip_filter_' . $option_key; 107 | 108 | $option_value = get_option( $option_key ); 109 | 110 | $reapply = has_filter( $filter, $callback ); 111 | // If this value isn't filtered by the VIP, used the default wpcom value 112 | if ( !$reapply ) 113 | $option_value = $default_value; 114 | else 115 | remove_filter( $filter, $callback, 99 ); 116 | // Save the precious 117 | update_option( $option_key, $option_value ); 118 | // Only reapply the filter if it was applied previously 119 | // as it overrides the option value with a global variable 120 | if ( $reapply ) 121 | add_filter( $filter, $callback, 99 ); 122 | } 123 | 124 | // Reconstruct WP_Rewrite and make sure we persist any custom endpoints, etc. 125 | $old_values = array(); 126 | $custom_rules = array( 127 | 'extra_rules', 128 | 'non_wp_rules', 129 | 'endpoints', 130 | ); 131 | foreach( $custom_rules as $key ) { 132 | $old_values[$key] = $wp_rewrite->$key; 133 | } 134 | $wp_rewrite->init(); 135 | foreach( $custom_rules as $key ) { 136 | $wp_rewrite->$key = array_merge( $old_values[$key], $wp_rewrite->$key ); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/vip.php: -------------------------------------------------------------------------------- 1 | provider_name ) && ( 'video' == $data->type || 'rich' == $data->type ) ) { 36 | $html = '
' . $html . '
'; 37 | } 38 | 39 | return $html; 40 | } 41 | -------------------------------------------------------------------------------- /www/wp-content/mu-plugins/wpcom.php: -------------------------------------------------------------------------------- 1 | true, '_builtin' => false ) ); 140 | 141 | if ( ! empty( $available_custom_post_types ) ) { 142 | foreach( $available_custom_post_types as $acpt ) { 143 | $cpt_obj = get_post_type_object( $acpt ); 144 | 145 | if ( ! empty( $cpt_obj ) && isset( $cpt_obj->rewrite ) && isset( $cpt_obj->rewrite['slug'] ) ) { 146 | $reserved_page_slugs[] = $cpt_obj->rewrite['slug']; 147 | } 148 | } 149 | } 150 | 151 | if ( 'page' == $post_type && in_array( $slug, $reserved_page_slugs ) ) { 152 | $is_reserved = true; 153 | } 154 | 155 | return $is_reserved; 156 | } 157 | 158 | // Allow hassle-free Liveblog testing in QS 159 | if ( ! function_exists( 'wpcom_vip_is_liveblog_enabled' ) ) { 160 | function wpcom_vip_is_liveblog_enabled() { 161 | return true; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /www/wp-content/object-cache.php: -------------------------------------------------------------------------------- 1 | add($key, $data, $group, $expire); 22 | } 23 | 24 | function wp_cache_incr($key, $n = 1, $group = '') { 25 | global $wp_object_cache; 26 | 27 | return $wp_object_cache->incr($key, $n, $group); 28 | } 29 | 30 | function wp_cache_decr($key, $n = 1, $group = '') { 31 | global $wp_object_cache; 32 | 33 | return $wp_object_cache->decr($key, $n, $group); 34 | } 35 | 36 | function wp_cache_close() { 37 | global $wp_object_cache; 38 | 39 | return $wp_object_cache->close(); 40 | } 41 | 42 | function wp_cache_delete($key, $group = '') { 43 | global $wp_object_cache; 44 | 45 | return $wp_object_cache->delete($key, $group); 46 | } 47 | 48 | function wp_cache_flush() { 49 | global $wp_object_cache; 50 | 51 | return $wp_object_cache->flush(); 52 | } 53 | 54 | function wp_cache_get($key, $group = '', $force = false) { 55 | global $wp_object_cache; 56 | 57 | return $wp_object_cache->get($key, $group, $force); 58 | } 59 | 60 | function wp_cache_init() { 61 | global $wp_object_cache; 62 | 63 | $wp_object_cache = new WP_Object_Cache(); 64 | } 65 | 66 | function wp_cache_replace($key, $data, $group = '', $expire = 0) { 67 | global $wp_object_cache; 68 | 69 | return $wp_object_cache->replace($key, $data, $group, $expire); 70 | } 71 | 72 | function wp_cache_set($key, $data, $group = '', $expire = 0) { 73 | global $wp_object_cache; 74 | 75 | if ( defined('WP_INSTALLING') == false ) 76 | return $wp_object_cache->set($key, $data, $group, $expire); 77 | else 78 | return $wp_object_cache->delete($key, $group); 79 | } 80 | 81 | function wp_cache_add_global_groups( $groups ) { 82 | global $wp_object_cache; 83 | 84 | $wp_object_cache->add_global_groups($groups); 85 | } 86 | 87 | function wp_cache_add_non_persistent_groups( $groups ) { 88 | global $wp_object_cache; 89 | 90 | $wp_object_cache->add_non_persistent_groups($groups); 91 | } 92 | 93 | class WP_Object_Cache { 94 | var $global_groups = array(); 95 | 96 | var $no_mc_groups = array(); 97 | 98 | var $cache = array(); 99 | var $mc = array(); 100 | var $stats = array(); 101 | var $group_ops = array(); 102 | 103 | var $cache_enabled = true; 104 | var $default_expiration = 0; 105 | 106 | var $debug = false; 107 | 108 | function add($id, $data, $group = 'default', $expire = 0) { 109 | $key = $this->key($id, $group); 110 | 111 | if ( is_object( $data ) ) 112 | $data = clone $data; 113 | 114 | if ( in_array($group, $this->no_mc_groups) ) { 115 | $this->cache[$key] = $data; 116 | return true; 117 | } elseif ( isset($this->cache[$key]) && $this->cache[$key] !== false ) { 118 | return false; 119 | } 120 | 121 | $mc =& $this->get_mc($group); 122 | $expire = ($expire == 0) ? $this->default_expiration : $expire; 123 | $result = $mc->add($key, $data, false, $expire); 124 | 125 | if ( false !== $result ) { 126 | @ ++$this->stats['add']; 127 | $this->group_ops[$group][] = "add $id"; 128 | $this->cache[$key] = $data; 129 | } 130 | 131 | return $result; 132 | } 133 | 134 | function add_global_groups($groups) { 135 | if ( ! is_array($groups) ) 136 | $groups = (array) $groups; 137 | 138 | $this->global_groups = array_merge($this->global_groups, $groups); 139 | $this->global_groups = array_unique($this->global_groups); 140 | } 141 | 142 | function add_non_persistent_groups($groups) { 143 | if ( ! is_array($groups) ) 144 | $groups = (array) $groups; 145 | 146 | $this->no_mc_groups = array_merge($this->no_mc_groups, $groups); 147 | $this->no_mc_groups = array_unique($this->no_mc_groups); 148 | } 149 | 150 | function incr($id, $n = 1, $group = 'default' ) { 151 | $key = $this->key($id, $group); 152 | $mc =& $this->get_mc($group); 153 | $this->cache[ $key ] = $mc->increment( $key, $n ); 154 | return $this->cache[ $key ]; 155 | } 156 | 157 | function decr($id, $n = 1, $group = 'default' ) { 158 | $key = $this->key($id, $group); 159 | $mc =& $this->get_mc($group); 160 | $this->cache[ $key ] = $mc->decrement( $key, $n ); 161 | return $this->cache[ $key ]; 162 | } 163 | 164 | function close() { 165 | 166 | foreach ( $this->mc as $bucket => $mc ) 167 | $mc->close(); 168 | } 169 | 170 | function delete($id, $group = 'default') { 171 | $key = $this->key($id, $group); 172 | 173 | if ( in_array($group, $this->no_mc_groups) ) { 174 | unset($this->cache[$key]); 175 | return true; 176 | } 177 | 178 | $mc =& $this->get_mc($group); 179 | 180 | $result = $mc->delete($key); 181 | 182 | @ ++$this->stats['delete']; 183 | $this->group_ops[$group][] = "delete $id"; 184 | 185 | if ( false !== $result ) 186 | unset($this->cache[$key]); 187 | 188 | return $result; 189 | } 190 | 191 | function flush() { 192 | $is_multisite = ( function_exists( 'is_site_admin' ) || defined( 'CUSTOM_USER_TABLE' ) && defined( 'CUSTOM_USER_META_TABLE' ) ); 193 | 194 | // Abort object cache flushing if on multisite (really, WordPress.com) when not running unit tests 195 | if ( $is_multisite && ! ( defined( 'WP_TESTS_MULTISITE' ) && WP_TESTS_MULTISITE ) ) { 196 | return false; 197 | } 198 | 199 | $ret = true; 200 | foreach ( array_keys($this->mc) as $group ) 201 | $ret &= $this->mc[$group]->flush(); 202 | return $ret; 203 | } 204 | 205 | function get($id, $group = 'default', $force = false) { 206 | $key = $this->key($id, $group); 207 | $mc =& $this->get_mc($group); 208 | 209 | if ( isset($this->cache[$key]) && ( !$force || in_array($group, $this->no_mc_groups) ) ) { 210 | if ( is_object( $this->cache[$key] ) ) 211 | $value = clone $this->cache[$key]; 212 | else 213 | $value = $this->cache[$key]; 214 | } else if ( in_array($group, $this->no_mc_groups) ) { 215 | $this->cache[$key] = $value = false; 216 | } else { 217 | $value = $mc->get($key); 218 | if ( NULL === $value ) 219 | $value = false; 220 | $this->cache[$key] = $value; 221 | } 222 | 223 | @ ++$this->stats['get']; 224 | $this->group_ops[$group][] = "get $id"; 225 | 226 | if ( 'checkthedatabaseplease' === $value ) { 227 | unset( $this->cache[$key] ); 228 | $value = false; 229 | } 230 | 231 | return $value; 232 | } 233 | 234 | function get_multi( $groups ) { 235 | /* 236 | format: $get['group-name'] = array( 'key1', 'key2' ); 237 | */ 238 | $return = array(); 239 | foreach ( $groups as $group => $ids ) { 240 | $mc =& $this->get_mc($group); 241 | foreach ( $ids as $id ) { 242 | $key = $this->key($id, $group); 243 | if ( isset($this->cache[$key]) ) { 244 | if ( is_object( $this->cache[$key] ) ) 245 | $return[$key] = clone $this->cache[$key]; 246 | else 247 | $return[$key] = $this->cache[$key]; 248 | continue; 249 | } else if ( in_array($group, $this->no_mc_groups) ) { 250 | $return[$key] = false; 251 | continue; 252 | } else { 253 | $return[$key] = $mc->get($key); 254 | } 255 | } 256 | if ( $to_get ) { 257 | $vals = $mc->get_multi( $to_get ); 258 | $return = array_merge( $return, $vals ); 259 | } 260 | } 261 | @ ++$this->stats['get_multi']; 262 | $this->group_ops[$group][] = "get_multi $id"; 263 | $this->cache = array_merge( $this->cache, $return ); 264 | return $return; 265 | } 266 | 267 | function key($key, $group) { 268 | if ( empty($group) ) 269 | $group = 'default'; 270 | 271 | if ( false !== array_search($group, $this->global_groups) ) 272 | $prefix = $this->global_prefix; 273 | else 274 | $prefix = $this->blog_prefix; 275 | 276 | return preg_replace('/\s+/', '', WP_CACHE_KEY_SALT . "$prefix$group:$key"); 277 | } 278 | 279 | function replace($id, $data, $group = 'default', $expire = 0) { 280 | $key = $this->key($id, $group); 281 | $expire = ($expire == 0) ? $this->default_expiration : $expire; 282 | $mc =& $this->get_mc($group); 283 | 284 | if ( is_object( $data ) ) 285 | $data = clone $data; 286 | 287 | $result = $mc->replace($key, $data, false, $expire); 288 | if ( false !== $result ) 289 | $this->cache[$key] = $data; 290 | return $result; 291 | } 292 | 293 | function set($id, $data, $group = 'default', $expire = 0) { 294 | $key = $this->key($id, $group); 295 | if ( isset($this->cache[$key]) && ('checkthedatabaseplease' === $this->cache[$key]) ) 296 | return false; 297 | 298 | if ( is_object($data) ) 299 | $data = clone $data; 300 | 301 | $this->cache[$key] = $data; 302 | 303 | if ( in_array($group, $this->no_mc_groups) ) 304 | return true; 305 | 306 | $expire = ($expire == 0) ? $this->default_expiration : $expire; 307 | $mc =& $this->get_mc($group); 308 | $result = $mc->set($key, $data, false, $expire); 309 | 310 | return $result; 311 | } 312 | 313 | function colorize_debug_line($line) { 314 | $colors = array( 315 | 'get' => 'green', 316 | 'set' => 'purple', 317 | 'add' => 'blue', 318 | 'delete' => 'red'); 319 | 320 | $cmd = substr($line, 0, strpos($line, ' ')); 321 | 322 | $cmd2 = "$cmd"; 323 | 324 | return $cmd2 . substr($line, strlen($cmd)) . "\n"; 325 | } 326 | 327 | function stats() { 328 | echo "

\n"; 329 | foreach ( $this->stats as $stat => $n ) { 330 | echo "$stat $n"; 331 | echo "
\n"; 332 | } 333 | echo "

\n"; 334 | echo "

Memcached:

"; 335 | foreach ( $this->group_ops as $group => $ops ) { 336 | if ( !isset($_GET['debug_queries']) && 500 < count($ops) ) { 337 | $ops = array_slice( $ops, 0, 500 ); 338 | echo "Too many to show! Show them anyway.\n"; 339 | } 340 | echo "

$group commands

"; 341 | echo "
\n";
342 | 			$lines = array();
343 | 			foreach ( $ops as $op ) {
344 | 				$lines[] = $this->colorize_debug_line($op);
345 | 			}
346 | 			print_r($lines);
347 | 			echo "
\n"; 348 | } 349 | 350 | if ( $this->debug ) 351 | var_dump($this->memcache_debug); 352 | } 353 | 354 | function &get_mc($group) { 355 | if ( isset($this->mc[$group]) ) 356 | return $this->mc[$group]; 357 | return $this->mc['default']; 358 | } 359 | 360 | function failure_callback($host, $port) { 361 | //error_log("Connection failure for $host:$port\n", 3, '/tmp/memcached.txt'); 362 | } 363 | 364 | function __construct() { 365 | global $memcached_servers; 366 | 367 | if ( isset($memcached_servers) ) 368 | $buckets = $memcached_servers; 369 | else 370 | $buckets = array('127.0.0.1:11211'); 371 | 372 | reset($buckets); 373 | if ( is_int( key($buckets) ) ) 374 | $buckets = array('default' => $buckets); 375 | 376 | foreach ( $buckets as $bucket => $servers) { 377 | $this->mc[$bucket] = new Memcache(); 378 | foreach ( $servers as $server ) { 379 | list ( $node, $port ) = explode(':', $server); 380 | if ( !$port ) 381 | $port = ini_get('memcache.default_port'); 382 | $port = intval($port); 383 | if ( !$port ) 384 | $port = 11211; 385 | $this->mc[$bucket]->addServer($node, $port, true, 1, 1, 15, true, array($this, 'failure_callback')); 386 | $this->mc[$bucket]->setCompressThreshold(20000, 0.2); 387 | } 388 | } 389 | 390 | global $blog_id, $table_prefix; 391 | $this->global_prefix = ''; 392 | $this->blog_prefix = ''; 393 | if ( function_exists( 'is_multisite' ) ) { 394 | $this->global_prefix = ( is_multisite() || defined('CUSTOM_USER_TABLE') && defined('CUSTOM_USER_META_TABLE') ) ? '' : $table_prefix; 395 | $this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':'; 396 | } 397 | 398 | $this->cache_hits =& $this->stats['get']; 399 | $this->cache_misses =& $this->stats['add']; 400 | } 401 | } 402 | ?> 403 | -------------------------------------------------------------------------------- /www/wp-content/sunrise.php: -------------------------------------------------------------------------------- 1 | get_row( "SELECT * FROM {$wpdb->blogs} WHERE blog_id = 1 LIMIT 1" ); 10 | $current_site = $wpdb->get_row( "SELECT * from {$wpdb->site} WHERE id = '{$current_blog->site_id}' LIMIT 0,1" ); 11 | $current_site->blog_id = 1; 12 | $current_site->domain = $_SERVER['HTTP_HOST']; 13 | } 14 | -------------------------------------------------------------------------------- /www/wp-content/themes/vip/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /www/wp-tests/wp-tests-config.php: -------------------------------------------------------------------------------- 1 |