modified file upgrade-temp-backup

This commit is contained in:
KawaiiPunk 2025-04-29 21:20:07 +00:00 committed by Gitium
parent 0bc27333c2
commit 5dc2981470
717 changed files with 172984 additions and 0 deletions

View File

@ -0,0 +1,289 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 3.0.2 - 2024-09-06
### Changed
- Internal updates.
## 3.0.1 - 2024-09-06
### Added
- Threats List: Add pagination. [#39058]
### Changed
- Admin menu: change order of Jetpack sub-menu items. [#39095]
- Updated package dependencies. [#39176]
### Fixed
- Security Scanning: Adds a background to the scan progress bar. [#38847]
- General: Delete relevant Protect options on deactivation. [#38815]
- Auto Fixers: Disable the unignore threats button when a fixer is in progress. [#38898]
- Security Scanning: Fix the threat fixed on date in the history view. [#39164]
- General: Improves the manual scan link button loading state. [#38897]
## 3.0.0-beta - 2024-08-09
### Added
- Firewall: add dedicated WAF allow and block list toggles [#38265]
- General: add "contact support" links [#38416]
- Security Scanning: add threats history view [#38117]
### Changed
- General: indicate compatibility with the upcoming version of WordPress - 6.6. [#37962]
### Removed
- General: update WordPress version requirements to WordPress 6.5. [#38382]
### Fixed
- Fix an issue where the connection error hook was always resetting the notice [#38120]
- Fix image optimization [#38573]
- Fix in-progress threat fixer loading indicator [#38051]
- Fix threat fix modal title [#38312]
## 2.2.0 - 2024-05-24
### Added
- Add data to WAF logs and a toggle for users to opt-in to share more data with us if needed. [#36377]
- Trigger a red bubble notification when a bad install is detected. [#36449]
### Changed
- Update WordPress minimum version requirement to WordPress 6.4. [#37047]
- Only show installation errors on the plugins page. [#36390]
### Fixed
- Jetpack Protect Footer: ensure that "Go to cloud" links are not shown when on a platform with no firewall support. [#36794]
## 2.1.0 - 2024-03-14
### Added
- Added onboarding flows. [#34649]
- Added firewall standalone mode indicator. [#34840]
### Changed
- General: indicate compatibility with the upcoming version of WordPress, 6.5. [#35820]
- Use blog ID instead of site slug in checkout links. [#35004]
- Updated package dependencies. [#36325]
- Updated package lockfile. [#35672]
### Fixed
- Prevent text orphans in the site scanning header. [#35935]
## 2.0.0 - 2024-01-18
### Changed
- Firewall: use datetime versioning for rules file updates. [#34698]
- General: unify display of notifications across Scan and Firewall screens [#34702]
- General: indicate full compatibility with the latest version of WordPress, 6.4. [#33776]
- General: update PHP requirement to PHP 7.0+ [#34126]
- General: update WordPress version requirements to WordPress 6.3. [#34127]
- General: update package dependencies. [#34882]
- General: update lockfile. [#33607]
### Fixed
- Fix Modal component overflow scrolling. [#34475]
- Fix Popover component styling. [#34424]
- Improved helper script installer logging. [#34297]
## 1.4.2 - 2023-10-19
### Changed
- General: update WordPress version requirements to WordPress 6.2. [#32762] [#32772]
- Updated Jetpack submenu sort order so individual features are alpha-sorted. [#32958]
- Updated method used to render Connection initial state. [#32499]
- Updated package dependencies. [#33692]
## 1.4.1 - 2023-07-18
### Changed
- Brute Force Protection: add access to feature in environments that otherwise do not support the WAF. [#31952]
- General: indicate full compatibility with the latest version of WordPress, 6.3. [#31910]
- Update WordPress version requirements. Now requires version 6.1. [#30120]
- Update package dependencies. [#31952]
### Fixed
- Scan: Fixed sorting of threats by severity. [#31124]
- License Activation: add filtering for unattached and unrevoked licenses within upgrade flow check. [#31086]
## 1.4.0 - 2023-05-05
### Added
- Add brute force protection. [#28401]
### Changed
- General: indicate full compatibility with the latest version of WordPress, 6.2. [#29341]
- Improve the firewall status heading to provide more information based on the current configuration. [#28401]
- Updated package dependencies. [#29480]
## 1.3.0 - 2023-03-13
### Added
- Add ability to toggle automatic and manual firewall rules independently. [#27726]
- Add improved messaging for currently enabled firewall features. [#27845]
- Disable Jetpack Firewall on unsupported environments. [#27939]
- Add link to pricing page for getting started with an existing plan or license key. [#27745]
### Changed
- Updated package dependencies. [#29297]
- Update to React 18. [#28710]
- Use `flex-start`/`flex-end` instead of `start`/`end` for better browser compatibility. [#28530]
### Fixed
- Fix connection button loading indicators. [#28514]
- Fix Protect status report caching. [#28766]
- Remove unnecessary full path from example in UI. [#29037]
- Other assorted fixes for minor bugs and grammar. [#27846] [#28091] [#28397] [#28273]
## 1.2.0 - 2023-01-16
### Added
- Add web application firewall (WAF) features [#27528]
- Add progress bar to site scannnig screen [#27171]
### Fixed
- Poll for scan status while scanner is provisioning [#28275]
- Bug fixes
## 1.1.2 - 2022-11-30
### Changed
- changed description and author [#27618]
- Updated package dependencies. [#27043]
## 1.1.1 - 2022-11-18
### Fixed
- Fix issue with plugin activation.
## 1.1.0 - 2022-11-17
### Added
- Add features for paid Jetpack Scan users, including file and database threats, on-demand scanning, and threat auto-fixers.
### Changed
- Compatibility: WordPress 6.1 compatibility
### Fixed
- Adjust alignment of spinner icon and loading text on the in-progress scan screen.
## 1.0.4 - 2022-08-29
### Fixed
- Fixed NaN error that prevented the pricing interstitial from rendering.
## 1.0.3 - 2022-08-26
### Added
- Added a default 'See all results' label to the mobile navigation button.
- Added a spinner to the in progress scan page in admin
- Added JITM functionality
- Added threat descriptions.
- My Jetpack includes JITMs
### Changed
- Add condition to check plugin activation context before redirecting
### Fixed
- Fixed alignment of long navigation item labels on mobile screen sizes.
## 1.0.2 - 2022-07-27
### Changed
- Updated package dependencies.
### Fixed
- Fix protect admin toolbar icon display when Jetpack enabled and connected
- Minor bug fix - added isset() checks for report data properties
## 1.0.1 - 2022-07-07
### Added
- Added two new FAQ entries
- Protect: record even just after the site is registered
### Changed
- Moved normalization of the Protect status report data to the server side.
- Renamed `master` references to `trunk`
- Reorder JS imports for `import/order` eslint rule.
### Fixed
- Fixed bug that would not display Core vulnerabilities.
- Removed legacy code and documentation and adds new docs for the debug helper plugin.
- Fixed recommendation for plugins that don't have a fix yet
- Protect: Fix visual issue of the Interstitial page
## 1.0.0 - 2022-05-31
### Added
- Add additional tracking events
- Add Alert icon to the error admin page
- Add checks to the Site Health page
- Add custom hook to handle viewport sizes via CSS
- Add error message when adding plugin fails
- Add first approach of Interstitial page
- Add Jetpack Scan to promotion section when site doesn't have Security bundle
- Add missing prop-types module dependency
- Add Navigation dropdown mode and use it for small/medium screens
- Add ProductOffer component
- Add product offer component
- Add title and redirect for vul at wpscan
- Add 'get themes' to synced callables in Protect
- Add installedThemes to the initial state
- Add notifications to the menu item and the admin bar
- Add status polling to the Protect admin page.
- Added details to the FAQ question on how Jetpack Protect is different from other Jetpack products.
- Added Jetpack Protect readme file for the plugin listing.
- Added option to display terms of service below product activation button.
- Added Social card to My Jetpack.
- Added the list of installed plugins to the initial state
- Change ConnectScreen by the Interstitial component
- Creates Status Class
- Empty state screen
- Expose and use IconsCard component
- Flush cache on plugin deactivation
- Footer component
- Handle error in the UI
- Hooks on plugin activation and deactivation
- Hook to read data from the initial state
- Implement Footer
- Implement Add Security bundle workflow
- Introduce Accordion component
- Introduce Navigation component
- Introduce Summary component
- Introduce VulnerabilitiesList component
- JS Components: Introduce Alert component. Add error to ProductOffer components
- More options to the testing api responses
- Record admin page-view and get security from footer events
- Render Security component with data provided by wpcom
- Request and expose to the client the Security bundle data
- Update logo
### Changed
- Add empty state for no vuls
- Add popover at Badge
- Cache empty statuses for a short period of time
- Changed connection screen to the one that does not require a product
- Changed the method used to disconnect
- Changed the wording for the initial screen.
- Change expiration time of plugin cache
- Clean connection data. Update to latest connection API
- Configure Sync to only what we need to sync
- Janitorial: require a more recent version of WordPress now that WP 6.0 is coming out.
- JS Components: Add subTitle prop to ProductOffer component
- JS Components: iterate over Dialog component
- Improve Dialog layout in medium viewport size
- Move VulnerabilitiesList to section hero
- New VulsList
- Redesign Summary component
- Re-implement "Your results will be ready soon" layout
- Re-implement Admin page by using Dialog component
- Remove use of `pnpx` in preparation for pnpm 7.0.
- Replace deprecated external-link variation by using isExternalLink prop
- Require only site level connection
- Truncate items at NavigationGroup
- Tweak footer
- Update Footer and VulsList for small/medium viewport
- Update Navigation to be external controlled
- Update Protect icon
- Update VulnerabilitiesList to remove severity and add fixed in
- Updated package dependencies.
- Update package.json metadata.
- Updates CTA wording to reduce confusion when user already has Jetpack Security Bundle which includes Jetpack Scan
- Update the Status when connection is established
- Use data provided by My Jetpack to render Product offer
- Use weight Button prop to style the "learn more" footer link
- Use a different copy when there are no found vulnerabilities but there are still some unchecked items
### Removed
- Removed Full Sync from loaded modules as Full Sync Immediately is present by default now
### Fixed
- Adjust spacing and overflow properties of the navigation labels to improve display of long names.
- Fix Connectino initialization
- Fix fatal when checking whether site site has vuls
- Fix right margin in primary layout

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,11 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="jetpack-protect" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe900;" glyph-name="protect" d="M891.73 737.552l-376.745 171.248-376.744-171.248v-255.284c0-217.615 139.767-423.66 336.854-488.663 25.898-8.54 53.883-8.54 79.78 0 197.089 65.004 336.855 271.048 336.855 488.663v255.284zM221.962 482.268v201.375l293.023 133.193 293.023-133.193v-201.375c0-184.909-119.726-356.506-279.357-409.155-8.863-2.924-18.465-2.924-27.333 0-159.627 52.649-279.355 224.246-279.355 409.155zM547.958 377.569h-65.252l-6.214 248.056h77.682l-6.216-248.056zM557.537 289.531c0-22.784-18.642-40.648-42.204-40.648-23.564 0-42.207 17.864-42.207 40.648 0 22.789 18.643 40.653 42.207 40.653 23.562 0 42.204-17.864 42.204-40.653z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,30 @@
@font-face {
font-family: 'jetpack-protect';
src: url('fonts/jetpack-protect.eot?31wpn');
src: url('fonts/jetpack-protect.eot?31wpn#iefix') format('embedded-opentype'),
url('fonts/jetpack-protect.ttf?31wpn') format('truetype'),
url('fonts/jetpack-protect.woff?31wpn') format('woff'),
url('fonts/jetpack-protect.svg?31wpn#jetpack-protect') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
[class^="jp-protect-icon"], [class*=" jp-protect-icon"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'jetpack-protect' !important;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.jp-protect-icon:before {
content: "\e900";
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('jetpack-connection', 'jetpack-script-data', 'moment', 'react', 'react-jsx-runtime', 'wp-api-fetch', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives', 'wp-url'), 'version' => '8d3412963d3c47f0ac0a');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,29 @@
/*
* Exposes number format capability
*
* @copyright Copyright (c) 2013 Kevin van Zonneveld (http://kvz.io) and Contributors (http://phpjs.org/authors).
* @license See CREDITS.md
* @see https://github.com/kvz/phpjs/blob/ffe1356af23a6f2512c84c954dd4e828e92579fa/functions/strings/number_format.js
*/
/**
* React Router DOM v6.2.2
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
/**
* React Router v6.2.2
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,76 @@
{
"name": "automattic/jetpack-protect",
"description": "Social plugin",
"type": "wordpress-plugin",
"license": "GPL-2.0-or-later",
"require": {
"ext-json": "*",
"automattic/jetpack-assets": "^2.3.7",
"automattic/jetpack-admin-ui": "^0.4.5",
"automattic/jetpack-autoloader": "^3.1.0",
"automattic/jetpack-composer-plugin": "^2.0.3",
"automattic/jetpack-config": "^2.0.4",
"automattic/jetpack-my-jetpack": "^4.35.3",
"automattic/jetpack-plugins-installer": "^0.4.3",
"automattic/jetpack-sync": "^3.10.0",
"automattic/jetpack-transport-helper": "^0.2.4",
"automattic/jetpack-plans": "^0.4.10",
"automattic/jetpack-waf": "^0.18.5",
"automattic/jetpack-status": "^4.0.1",
"automattic/jetpack-protect-status": "^0.1.5"
},
"require-dev": {
"yoast/phpunit-polyfills": "^1.1.1",
"automattic/jetpack-changelogger": "^4.2.6",
"automattic/wordbless": "0.4.2"
},
"autoload": {
"classmap": [
"src/"
]
},
"scripts": {
"phpunit": [
"./vendor/phpunit/phpunit/phpunit --colors=always"
],
"test-php": [
"@composer phpunit"
],
"build-development": [
"pnpm run build"
],
"build-production": [
"pnpm run build-production-concurrently"
],
"watch": [
"Composer\\Config::disableProcessTimeout",
"pnpm run watch"
],
"post-install-cmd": "WorDBless\\Composer\\InstallDropin::copy",
"post-update-cmd": "WorDBless\\Composer\\InstallDropin::copy"
},
"repositories": [],
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"mirror-repo": "Automattic/jetpack-protect-plugin",
"autorelease": true,
"autotagger": {
"v": false
},
"release-branch-prefix": "protect",
"wp-plugin-slug": "jetpack-protect",
"wp-svn-autopublish": true,
"version-constants": {
"JETPACK_PROTECT_VERSION": "jetpack-protect.php"
}
},
"config": {
"allow-plugins": {
"roots/wordpress-core-installer": true,
"automattic/jetpack-autoloader": true,
"automattic/jetpack-composer-plugin": true
},
"autoloader-suffix": "c4802e05bbcf59fd3b6350e8d3e5482c_protectⓥ3_0_2"
}
}

View File

@ -0,0 +1,140 @@
<?php
/**
* Plugin Name: Jetpack Protect
* Plugin URI: https://wordpress.org/plugins/jetpack-protect
* Description: Security tools that keep your site safe and sound, from posts to plugins.
* Version: 3.0.2
* Author: Automattic - Jetpack Security team
* Author URI: https://jetpack.com/protect/
* License: GPLv2 or later
* Text Domain: jetpack-protect
*
* @package automattic/jetpack-protect
*/
/*
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
define( 'JETPACK_PROTECT_VERSION', '3.0.2' );
define( 'JETPACK_PROTECT_DIR', plugin_dir_path( __FILE__ ) );
define( 'JETPACK_PROTECT_ROOT_FILE', __FILE__ );
define( 'JETPACK_PROTECT_ROOT_FILE_RELATIVE_PATH', plugin_basename( __FILE__ ) );
define( 'JETPACK_PROTECT_SLUG', 'jetpack-protect' );
define( 'JETPACK_PROTECT_NAME', 'Jetpack Protect' );
define( 'JETPACK_PROTECT_URI', 'https://jetpack.com/jetpack-protect' );
define( 'JETPACK_PROTECT_FOLDER', dirname( plugin_basename( __FILE__ ) ) );
define( 'JETPACK_PROTECT_BASE_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
// Jetpack Autoloader.
$jetpack_autoloader = JETPACK_PROTECT_DIR . 'vendor/autoload_packages.php';
if ( is_readable( $jetpack_autoloader ) ) {
require_once $jetpack_autoloader;
if ( method_exists( \Automattic\Jetpack\Assets::class, 'alias_textdomains_from_file' ) ) {
\Automattic\Jetpack\Assets::alias_textdomains_from_file( JETPACK_PROTECT_DIR . 'jetpack_vendor/i18n-map.php' );
}
} else { // Something very unexpected. Error out gently with an admin_notice and exit loading.
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
__( 'Error loading autoloader file for Jetpack Protect plugin', 'jetpack-protect' )
);
}
// Add a red bubble notification to My Jetpack if the installation is bad.
add_filter(
'my_jetpack_red_bubble_notification_slugs',
function ( $slugs ) {
$slugs['jetpack-protect-plugin-bad-installation'] = array(
'data' => array(
'plugin' => 'Jetpack Protect',
),
);
return $slugs;
}
);
add_action(
'admin_notices',
function () {
if ( get_current_screen()->id !== 'plugins' ) {
return;
}
$message = sprintf(
wp_kses(
/* translators: Placeholder is a link to a support document. */
__( 'Your installation of Jetpack Protect is incomplete. If you installed Jetpack Protect from GitHub, please refer to <a href="%1$s" target="_blank" rel="noopener noreferrer">this document</a> to set up your development environment. Jetpack Protect must have Composer dependencies installed and built via the build command.', 'jetpack-protect' ),
array(
'a' => array(
'href' => array(),
'target' => array(),
'rel' => array(),
),
)
),
'https://github.com/Automattic/jetpack/blob/trunk/docs/development-environment.md#building-your-project'
);
wp_admin_notice(
$message,
array(
'type' => 'error',
'dismissible' => true,
)
);
}
);
return;
}
// Redirect to plugin page when the plugin is activated.
add_action( 'activated_plugin', 'jetpack_protect_plugin_activation' );
/**
* Redirects to plugin page when the plugin is activated
*
* @param string $plugin Path to the plugin file relative to the plugins directory.
*/
function jetpack_protect_plugin_activation( $plugin ) {
if (
JETPACK_PROTECT_ROOT_FILE_RELATIVE_PATH === $plugin &&
( new \Automattic\Jetpack\Paths() )->is_current_request_activating_plugin_from_plugins_screen( JETPACK_PROTECT_ROOT_FILE_RELATIVE_PATH )
) {
wp_safe_redirect( esc_url( admin_url( 'admin.php?page=jetpack-protect' ) ) );
exit;
}
}
// Add "Settings" link to plugins page.
add_filter(
'plugin_action_links_' . JETPACK_PROTECT_FOLDER . '/jetpack-protect.php',
function ( $actions ) {
$settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=jetpack-protect' ) ) . '">' . __( 'Dashboard', 'jetpack-protect' ) . '</a>';
array_unshift( $actions, $settings_link );
return $actions;
}
);
register_activation_hook( __FILE__, array( 'Jetpack_Protect', 'plugin_activation' ) );
register_deactivation_hook( __FILE__, array( 'Jetpack_Protect', 'plugin_deactivation' ) );
// Main plugin class.
new Jetpack_Protect();

View File

@ -0,0 +1,171 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.2] - 2024-08-23
### Changed
- Updated package dependencies. [#39004]
## [2.0.1] - 2024-03-12
### Changed
- Internal updates.
## [2.0.0] - 2023-11-20
### Changed
- Updated required PHP version to >= 7.0. [#34192]
## [1.4.22] - 2023-09-19
- Minor internal updates.
## [1.4.21] - 2023-08-23
### Changed
- Updated package dependencies. [#32605]
## [1.4.20] - 2023-04-10
### Added
- Add Jetpack Autoloader package suggestion. [#29988]
## [1.4.19] - 2023-02-20
### Changed
- Minor internal updates.
## [1.4.18] - 2023-01-11
### Changed
- Updated package dependencies.
## [1.4.17] - 2022-12-02
### Changed
- Updated package dependencies. [#27688]
## [1.4.16] - 2022-11-22
### Changed
- Updated package dependencies. [#27043]
## [1.4.15] - 2022-07-26
### Changed
- Updated package dependencies. [#25158]
## [1.4.14] - 2022-06-21
### Changed
- Renaming master to trunk.
## [1.4.13] - 2022-04-26
### Changed
- Updated package dependencies.
## [1.4.12] - 2022-01-25
### Changed
- Updated package dependencies.
## [1.4.11] - 2022-01-04
### Changed
- Switch to pcov for code coverage.
- Updated package dependencies
## [1.4.10] - 2021-12-14
### Changed
- Updated package dependencies.
## [1.4.9] - 2021-11-02
### Changed
- Set `convertDeprecationsToExceptions` true in PHPUnit config.
- Update PHPUnit configs to include just what needs coverage rather than include everything then try to exclude stuff that doesn't.
## [1.4.8] - 2021-10-13
### Changed
- Updated package dependencies.
## [1.4.7] - 2021-10-12
### Changed
- Updated package dependencies
## [1.4.6] - 2021-09-28
### Changed
- Updated package dependencies.
## [1.4.5] - 2021-08-30
### Changed
- Run composer update on test-php command instead of phpunit
- Tests: update PHPUnit polyfills dependency (yoast/phpunit-polyfills).
- updated annotations versions
## [1.4.4] - 2021-05-25
### Changed
- Updated package dependencies.
## [1.4.3] - 2021-04-08
### Changed
- Packaging and build changes, no change to the package itself.
## [1.4.2] - 2021-03-30
### Added
- Composer alias for dev-master, to improve dependencies
### Changed
- Update package dependencies.
### Fixed
- Use `composer update` rather than `install` in scripts, as composer.lock isn't checked in.
## [1.4.1] - 2021-02-05
- CI: Make tests more generic
## [1.4.0] - 2021-01-20
- Add mirror-repo information to all current composer packages
## [1.3.0] - 2020-12-17
- Coverage Update whitelist for backend tests
- Pin dependencies
- Packages: Update for PHP 8 testing
## [1.2.0] - 2020-09-17
## [1.1.1] - 2020-09-17
- a8c-mc-stats: Do not distribute test files
## [1.1.0] - 2020-08-13
- CI: Try collect js coverage
## 1.0.0 - 2020-07-27
- Creates the MC Stats package
[2.0.2]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.22...v2.0.0
[1.4.22]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.21...v1.4.22
[1.4.21]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.20...v1.4.21
[1.4.20]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.19...v1.4.20
[1.4.19]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.18...v1.4.19
[1.4.18]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.17...v1.4.18
[1.4.17]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.16...v1.4.17
[1.4.16]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.15...v1.4.16
[1.4.15]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.14...v1.4.15
[1.4.14]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.13...v1.4.14
[1.4.13]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.12...v1.4.13
[1.4.12]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.11...v1.4.12
[1.4.11]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.10...v1.4.11
[1.4.10]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.9...v1.4.10
[1.4.9]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.8...v1.4.9
[1.4.8]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.7...v1.4.8
[1.4.7]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.6...v1.4.7
[1.4.6]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.5...v1.4.6
[1.4.5]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.4...v1.4.5
[1.4.4]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.3...v1.4.4
[1.4.3]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.2...v1.4.3
[1.4.2]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.1...v1.4.2
[1.4.1]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.4.0...v1.4.1
[1.4.0]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.3.0...v1.4.0
[1.3.0]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.1.1...v1.2.0
[1.1.1]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.1.0...v1.1.1
[1.1.0]: https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v1.0.0...v1.1.0

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,41 @@
{
"name": "automattic/jetpack-a8c-mc-stats",
"description": "Used to record internal usage stats for Automattic. Not visible to site owners.",
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0"
},
"require-dev": {
"yoast/phpunit-polyfills": "^1.1.1",
"automattic/jetpack-changelogger": "^4.2.6"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
},
"autoload": {
"classmap": [
"src/"
]
},
"scripts": {
"phpunit": [
"./vendor/phpunit/phpunit/phpunit --colors=always"
],
"test-php": [
"@composer phpunit"
]
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"autotagger": true,
"mirror-repo": "Automattic/jetpack-a8c-mc-stats",
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v${old}...v${new}"
},
"branch-alias": {
"dev-trunk": "2.0.x-dev"
}
}
}

View File

@ -0,0 +1,181 @@
<?php
/**
* Jetpack MC Stats package.
*
* @package automattic/jetpack-mc-stats
*/
namespace Automattic\Jetpack;
/**
* Class MC Stats, used to record stats using https://pixel.wp.com/g.gif
*/
class A8c_Mc_Stats {
/**
* Holds the stats to be processed
*
* @var array
*/
private $stats = array();
/**
* Indicates whether to use the transparent pixel (b.gif) instead of the regular smiley (g.gif)
*
* @var boolean
*/
public $use_transparent_pixel = true;
/**
* Class Constructor
*
* @param boolean $use_transparent_pixel Use the transparent pixel instead of the smiley.
*/
public function __construct( $use_transparent_pixel = true ) {
$this->use_transparent_pixel = $use_transparent_pixel;
}
/**
* Store a stat for later output.
*
* @param string $group The stat group.
* @param string $name The stat name to bump.
*
* @return boolean true if stat successfully added
*/
public function add( $group, $name ) {
if ( ! \is_string( $group ) || ! \is_string( $name ) ) {
return false;
}
if ( ! isset( $this->stats[ $group ] ) ) {
$this->stats[ $group ] = array();
}
if ( \in_array( $name, $this->stats[ $group ], true ) ) {
return false;
}
$this->stats[ $group ][] = $name;
return true;
}
/**
* Gets current stats stored to be processed
*
* @return array $stats
*/
public function get_current_stats() {
return $this->stats;
}
/**
* Return the stats from a group in an array ready to be added as parameters in a query string
*
* @param string $group_name The name of the group to retrieve.
* @return array Array with one item, where the key is the prefixed group and the value are all stats concatenated with a comma. If group not found, an empty array will be returned
*/
public function get_group_query_args( $group_name ) {
$stats = $this->get_current_stats();
if ( isset( $stats[ $group_name ] ) && ! empty( $stats[ $group_name ] ) ) {
return array( "x_jetpack-{$group_name}" => implode( ',', $stats[ $group_name ] ) );
}
return array();
}
/**
* Gets a list of trac URLs for every stored URL
*
* @return array An array of URLs
*/
public function get_stats_urls() {
$urls = array();
foreach ( $this->get_current_stats() as $group => $stat ) {
$group_query_string = $this->get_group_query_args( $group );
$urls[] = $this->build_stats_url( $group_query_string );
}
return $urls;
}
/**
* Outputs the tracking pixels for the current stats and empty the stored stats from the object
*
* @return void
*/
public function do_stats() {
$urls = $this->get_stats_urls();
foreach ( $urls as $url ) {
echo '<img src="' . esc_url( $url ) . '" width="1" height="1" style="display:none;" />';
}
$this->stats = array();
}
/**
* Pings the stats server for the current stats and empty the stored stats from the object
*
* @return void
*/
public function do_server_side_stats() {
$urls = $this->get_stats_urls();
foreach ( $urls as $url ) {
$this->do_server_side_stat( $url );
}
$this->stats = array();
}
/**
* Runs stats code for a one-off, server-side.
*
* @param string $url string The URL to be pinged. Should include `x_jetpack-{$group}={$stats}` or whatever we want to store.
*
* @return bool If it worked.
*/
public function do_server_side_stat( $url ) {
$response = wp_remote_get( esc_url_raw( $url ) );
if ( is_wp_error( $response ) ) {
return false;
}
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
return false;
}
return true;
}
/**
* Builds the stats url.
*
* @param array $args array|string The arguments to append to the URL.
*
* @return string The URL to be pinged.
*/
public function build_stats_url( $args ) {
$defaults = array(
'v' => 'wpcom2',
'rand' => md5( wp_rand( 0, 999 ) . time() ),
);
$args = wp_parse_args( $args, $defaults );
$gifname = true === $this->use_transparent_pixel ? 'b.gif' : 'g.gif';
/**
* Filter the URL used as the Stats tracking pixel.
*
* @since-jetpack 2.3.2
* @since 1.0.0
*
* @param string $url Base URL used as the Stats tracking pixel.
*/
$base_url = apply_filters(
'jetpack_stats_base_url',
'https://pixel.wp.com/' . $gifname
);
$url = add_query_arg( $args, $base_url );
return $url;
}
}

View File

@ -0,0 +1,198 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.4.5] - 2024-09-05
### Changed
- Jetpack menu: only register Jetpack admin page for contributor roles and above. [#39081]
## [0.4.4] - 2024-08-29
### Changed
- Admin menu: change order of Jetpack sub-menu items [#39095]
## [0.4.3] - 2024-08-23
### Changed
- Updated package dependencies. [#39004]
## [0.4.2] - 2024-04-22
### Changed
- Internal updates.
## [0.4.1] - 2024-03-12
### Changed
- Internal updates.
## [0.4.0] - 2024-03-01
### Added
- Register menus in network admin as well as regular admin. [#36058]
## [0.3.2] - 2024-01-29
### Fixed
- Wait until 'admin_menu' action to call `add_menu()`, to avoid triggering the l10n load too early. [#35279]
## [0.3.1] - 2023-11-24
## [0.3.0] - 2023-11-20
### Changed
- Updated required PHP version to >= 7.0. [#34192]
## [0.2.25] - 2023-11-14
## [0.2.24] - 2023-10-30
### Fixed
- Handle Akismet submenu even if Jetpack is present, as Jetpack now relies on this package to do so. [#33559]
## [0.2.23] - 2023-09-19
### Changed
- Updated Jetpack submenu sort order so individual features are alpha-sorted. [#32958]
## [0.2.22] - 2023-09-11
### Fixed
- Akismet: update naming to common form [#32908]
## [0.2.21] - 2023-08-23
### Changed
- Updated package dependencies. [#32605]
## [0.2.20] - 2023-04-25
### Fixed
- Avoid errors when used in combination with an older version of the Logo package. [#30136]
## [0.2.19] - 2023-04-10
### Added
- Add Jetpack Autoloader package suggestion. [#29988]
## [0.2.18] - 2023-04-04
### Changed
- Menu icon: update to latest version of the Jetpack logo [#29418]
## [0.2.17] - 2023-02-20
### Changed
- Minor internal updates.
## [0.2.16] - 2023-01-25
### Changed
- Minor internal updates.
## [0.2.15] - 2023-01-11
### Changed
- Updated package dependencies.
## [0.2.14] - 2022-12-02
### Changed
- Updated package dependencies. [#27688]
## [0.2.13] - 2022-11-22
### Changed
- Updated package dependencies. [#27043]
## [0.2.12] - 2022-09-20
### Changed
- Updated package dependencies.
## [0.2.11] - 2022-07-26
### Changed
- Updated package dependencies. [#25158]
## [0.2.10] - 2022-07-12
### Changed
- Updated package dependencies.
## [0.2.9] - 2022-06-21
### Changed
- Renaming master to trunk.
## [0.2.8] - 2022-06-14
### Changed
- Updated package dependencies.
## [0.2.7] - 2022-04-26
### Changed
- Update package.json metadata.
## [0.2.6] - 2022-04-05
### Changed
- Updated package dependencies.
## [0.2.5] - 2022-03-08
### Fixed
- Do not handle Akismet submenu if Jetpack plugin is present
## [0.2.4] - 2022-02-09
### Added
- Support for akismet menu with stand-alone plugins
### Fixed
- Fixes menu order working around a bug in add_submenu_page
## [0.2.3] - 2022-01-25
### Changed
- Updated package dependencies.
## [0.2.2] - 2022-01-18
### Changed
- General: update required node version to v16.13.2
## [0.2.1] - 2022-01-04
### Changed
- Switch to pcov for code coverage.
- Updated package dependencies
## [0.2.0] - 2021-12-14
### Added
- New method to get the top level menu item
## [0.1.1] - 2021-11-17
### Changed
- Set `convertDeprecationsToExceptions` true in PHPUnit config.
- Update PHPUnit configs to include just what needs coverage rather than include everything then try to exclude stuff that doesn't.
## 0.1.0 - 2021-10-13
### Added
- Created the package.
### Changed
- Updated package dependencies.
### Fixed
- Fixing menu visibility issues.
[0.4.5]: https://github.com/Automattic/jetpack-admin-ui/compare/0.4.4...0.4.5
[0.4.4]: https://github.com/Automattic/jetpack-admin-ui/compare/0.4.3...0.4.4
[0.4.3]: https://github.com/Automattic/jetpack-admin-ui/compare/0.4.2...0.4.3
[0.4.2]: https://github.com/Automattic/jetpack-admin-ui/compare/0.4.1...0.4.2
[0.4.1]: https://github.com/Automattic/jetpack-admin-ui/compare/0.4.0...0.4.1
[0.4.0]: https://github.com/Automattic/jetpack-admin-ui/compare/0.3.2...0.4.0
[0.3.2]: https://github.com/Automattic/jetpack-admin-ui/compare/0.3.1...0.3.2
[0.3.1]: https://github.com/Automattic/jetpack-admin-ui/compare/0.3.0...0.3.1
[0.3.0]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.25...0.3.0
[0.2.25]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.24...0.2.25
[0.2.24]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.23...0.2.24
[0.2.23]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.22...0.2.23
[0.2.22]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.21...0.2.22
[0.2.21]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.20...0.2.21
[0.2.20]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.19...0.2.20
[0.2.19]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.18...0.2.19
[0.2.18]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.17...0.2.18
[0.2.17]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.16...0.2.17
[0.2.16]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.15...0.2.16
[0.2.15]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.14...0.2.15
[0.2.14]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.13...0.2.14
[0.2.13]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.12...0.2.13
[0.2.12]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.11...0.2.12
[0.2.11]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.10...0.2.11
[0.2.10]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.9...0.2.10
[0.2.9]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.8...0.2.9
[0.2.8]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.7...0.2.8
[0.2.7]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.6...0.2.7
[0.2.6]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.5...0.2.6
[0.2.5]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.4...0.2.5
[0.2.4]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.3...0.2.4
[0.2.3]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.2...0.2.3
[0.2.2]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.1...0.2.2
[0.2.1]: https://github.com/Automattic/jetpack-admin-ui/compare/0.2.0...0.2.1
[0.2.0]: https://github.com/Automattic/jetpack-admin-ui/compare/0.1.1...0.2.0
[0.1.1]: https://github.com/Automattic/jetpack-admin-ui/compare/0.1.0...0.1.1

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,54 @@
{
"name": "automattic/jetpack-admin-ui",
"description": "Generic Jetpack wp-admin UI elements",
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0"
},
"require-dev": {
"yoast/phpunit-polyfills": "^1.1.1",
"automattic/jetpack-changelogger": "^4.2.6",
"automattic/jetpack-logo": "^2.0.4",
"automattic/wordbless": "dev-master"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
},
"autoload": {
"classmap": [
"src/"
]
},
"scripts": {
"phpunit": [
"./vendor/phpunit/phpunit/phpunit --colors=always"
],
"test-php": [
"@composer phpunit"
],
"post-install-cmd": "WorDBless\\Composer\\InstallDropin::copy",
"post-update-cmd": "WorDBless\\Composer\\InstallDropin::copy"
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"autotagger": true,
"mirror-repo": "Automattic/jetpack-admin-ui",
"textdomain": "jetpack-admin-ui",
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-admin-ui/compare/${old}...${new}"
},
"branch-alias": {
"dev-trunk": "0.4.x-dev"
},
"version-constants": {
"::PACKAGE_VERSION": "src/class-admin-menu.php"
}
},
"config": {
"allow-plugins": {
"roots/wordpress-core-installer": true
}
}
}

View File

@ -0,0 +1,208 @@
<?php
/**
* Admin Menu Registration
*
* @package automattic/jetpack-admin-ui
*/
namespace Automattic\Jetpack\Admin_UI;
/**
* This class offers a wrapper to add_submenu_page and makes sure stand-alone plugin's menu items are always added under the Jetpack top level menu.
* If the Jetpack top level was not previously registered by other plugin, it will be registered here.
*/
class Admin_Menu {
const PACKAGE_VERSION = '0.4.5';
/**
* Whether this class has been initialized
*
* @var boolean
*/
private static $initialized = false;
/**
* List of menu items enqueued to be added
*
* @var array
*/
private static $menu_items = array();
/**
* Initialize the class and set up the main hook
*
* @return void
*/
public static function init() {
if ( ! self::$initialized ) {
self::$initialized = true;
self::handle_akismet_menu();
add_action( 'admin_menu', array( __CLASS__, 'admin_menu_hook_callback' ), 1000 ); // Jetpack uses 998.
add_action( 'network_admin_menu', array( __CLASS__, 'admin_menu_hook_callback' ), 1000 ); // Jetpack uses 998.
}
}
/**
* Handles the Akismet menu item when used alongside other stand-alone plugins
*
* When Jetpack plugin is present, Akismet menu item is moved under the Jetpack top level menu, but if Akismet is active alongside other stand-alone plugins,
* we use this method to move the menu item.
*/
private static function handle_akismet_menu() {
if ( class_exists( 'Akismet_Admin' ) ) {
add_action(
'admin_menu',
function () {
// Prevent Akismet from adding a menu item.
remove_action( 'admin_menu', array( 'Akismet_Admin', 'admin_menu' ), 5 );
// Add an Anti-spam menu item for Jetpack.
self::add_menu( __( 'Akismet Anti-spam', 'jetpack-admin-ui' ), __( 'Akismet Anti-spam', 'jetpack-admin-ui' ), 'manage_options', 'akismet-key-config', array( 'Akismet_Admin', 'display_page' ), 6 );
},
4
);
}
}
/**
* Callback to the admin_menu and network_admin_menu hooks that will register the enqueued menu items
*
* @return void
*/
public static function admin_menu_hook_callback() {
$can_see_toplevel_menu = true;
$jetpack_plugin_present = class_exists( 'Jetpack_React_Page' );
$icon = method_exists( '\Automattic\Jetpack\Assets\Logo', 'get_base64_logo' )
? ( new \Automattic\Jetpack\Assets\Logo() )->get_base64_logo()
: 'dashicons-admin-plugins';
if ( ! $jetpack_plugin_present ) {
add_menu_page(
'Jetpack',
'Jetpack',
'edit_posts',
'jetpack',
'__return_null',
$icon,
3
);
// If Jetpack plugin is not present, user will only be able to see this menu if they have enough capability to at least one of the sub menus being added.
$can_see_toplevel_menu = false;
}
/**
* The add_sub_menu function has a bug and will not keep the right order of menu items.
*
* @see https://core.trac.wordpress.org/ticket/52035
* Let's order the items before registering them.
* Since this all happens after the Jetpack plugin menu items were added, all items will be added after Jetpack plugin items - unless position is very low number (smaller than the number of menu items present in Jetpack plugin).
*/
usort(
self::$menu_items,
function ( $a, $b ) {
$position_a = empty( $a['position'] ) ? 0 : $a['position'];
$position_b = empty( $b['position'] ) ? 0 : $b['position'];
$result = $position_a <=> $position_b;
if ( 0 === $result ) {
$result = strcmp( $a['menu_title'], $b['menu_title'] );
}
return $result;
}
);
foreach ( self::$menu_items as $menu_item ) {
if ( ! current_user_can( $menu_item['capability'] ) ) {
continue;
}
$can_see_toplevel_menu = true;
add_submenu_page(
'jetpack',
$menu_item['page_title'],
$menu_item['menu_title'],
$menu_item['capability'],
$menu_item['menu_slug'],
$menu_item['function'],
$menu_item['position']
);
}
if ( ! $jetpack_plugin_present ) {
remove_submenu_page( 'jetpack', 'jetpack' );
}
if ( ! $can_see_toplevel_menu ) {
remove_menu_page( 'jetpack' );
}
}
/**
* Adds a new submenu to the Jetpack Top level menu
*
* The parameters this method accepts are the same as @see add_submenu_page. This class will
* aggreagate all menu items registered by stand-alone plugins and make sure they all go under the same
* Jetpack top level menu. It will also handle the top level menu registration in case the Jetpack plugin is not present.
*
* @param string $page_title The text to be displayed in the title tags of the page when the menu
* is selected.
* @param string $menu_title The text to be used for the menu.
* @param string $capability The capability required for this menu to be displayed to the user.
* @param string $menu_slug The slug name to refer to this menu by. Should be unique for this menu
* and only include lowercase alphanumeric, dashes, and underscores characters
* to be compatible with sanitize_key().
* @param callable $function The function to be called to output the content for this page.
* @param int $position The position in the menu order this item should appear. Leave empty typically.
*
* @return string The resulting page's hook_suffix
*/
public static function add_menu( $page_title, $menu_title, $capability, $menu_slug, $function, $position = null ) {
self::init();
self::$menu_items[] = compact( 'page_title', 'menu_title', 'capability', 'menu_slug', 'function', 'position' );
/**
* Let's return the page hook so consumers can use.
* We know all pages will be under Jetpack top level menu page, so we can hardcode the first part of the string.
* Using get_plugin_page_hookname here won't work because the top level page is not registered yet.
*/
return 'jetpack_page_' . $menu_slug;
}
/**
* Gets the slug for the first item under the Jetpack top level menu
*
* @return string|null
*/
public static function get_top_level_menu_item_slug() {
global $submenu;
if ( ! empty( $submenu['jetpack'] ) ) {
$item = reset( $submenu['jetpack'] );
if ( isset( $item[2] ) ) {
return $item[2];
}
}
}
/**
* Gets the URL for the first item under the Jetpack top level menu
*
* @param string $fallback If Jetpack menu is not there or no children is found, return this fallback instead. Default to admin_url().
* @return string
*/
public static function get_top_level_menu_item_url( $fallback = false ) {
$slug = self::get_top_level_menu_item_slug();
if ( $slug ) {
$url = menu_page_url( $slug, false );
return $url;
}
$url = $fallback ? $fallback : admin_url();
return $url;
}
}

View File

@ -0,0 +1,3 @@
module.exports = {
extends: [ require.resolve( 'jetpack-js-tools/eslintrc/react' ) ],
};

View File

@ -0,0 +1,611 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.3.7] - 2024-09-05
### Changed
- Internal updates.
## [2.3.6] - 2024-09-05
### Changed
- Updated package dependencies. [#39176]
### Fixed
- Fixed script data not available in block editor iframe [#39221]
## [2.3.5] - 2024-08-29
### Changed
- Updated package dependencies. [#39111]
## [2.3.4] - 2024-08-23
### Changed
- Updated package dependencies. [#39004]
## [2.3.3] - 2024-08-21
### Changed
- i18n loader script & React JSX runtime: load scripts in the footer. [#38929]
## [2.3.2] - 2024-08-15
### Changed
- Updated package dependencies. [#38662]
## [2.3.1] - 2024-08-12
### Fixed
- Fixed variable names. [#38606]
## [2.3.0] - 2024-08-08
### Added
- Added jetpack-initial-state package to consolidate the logic for Initial state. [#38430]
## [2.2.0] - 2024-07-23
### Added
- Assets: Add JSX runtime polyfill `react-jsx-runtime` for WordPress < 6.6. [#38428]
## [2.1.13] - 2024-07-03
### Changed
- Updated package dependencies. [#38132]
## [2.1.12] - 2024-06-05
### Changed
- Updated package dependencies. [#37669]
## [2.1.11] - 2024-05-20
### Changed
- Internal updates.
## [2.1.10] - 2024-05-16
### Added
- Assets: Adding comments to explain why we use variables within translation functions [#37397]
### Changed
- Updated package dependencies. [#37379]
## [2.1.9] - 2024-05-06
### Changed
- Updated package dependencies. [#37147]
## [2.1.8] - 2024-04-22
### Changed
- Internal updates.
## [2.1.7] - 2024-04-08
### Changed
- Updated package dependencies. [#36760]
## [2.1.6] - 2024-03-27
### Changed
- Updated package dependencies. [#36585]
## [2.1.5] - 2024-03-18
### Changed
- Internal updates.
## [2.1.4] - 2024-03-12
### Changed
- Internal updates.
## [2.1.3] - 2024-03-12
### Changed
- Updated package dependencies. [#36325]
## [2.1.2] - 2024-03-04
### Changed
- Updated package dependencies. [#36095]
## [2.1.1] - 2024-02-13
### Changed
- Updated package dependencies. [#35608]
## [2.1.0] - 2024-02-05
### Added
- Add support for script enqueuing strategies implemented in WordPress 6.3 [#34072]
### Changed
- Updated package dependencies. [#35384]
## [2.0.4] - 2024-01-04
### Changed
- Updated package dependencies. [#34815]
## [2.0.3] - 2023-12-11
### Changed
- Updated package dependencies. [#34492]
## [2.0.2] - 2023-12-03
### Changed
- Updated package dependencies. [#34411] [#34427]
## [2.0.1] - 2023-11-21
## [2.0.0] - 2023-11-20
### Changed
- Updated required PHP version to >= 7.0. [#34192]
## [1.18.15] - 2023-11-14
### Changed
- Updated package dependencies. [#34093]
## [1.18.14] - 2023-11-03
## [1.18.13] - 2023-10-19
### Changed
- Updated package dependencies. [#33687]
## [1.18.12] - 2023-10-10
### Changed
- Updated package dependencies. [#33428]
### Fixed
- Pass `false`, not `null`, to `WP_Scripts->add()`. [#33513]
## [1.18.11] - 2023-09-19
- Minor internal updates.
## [1.18.10] - 2023-09-04
### Changed
- Updated package dependencies. [#32803]
## [1.18.9] - 2023-08-23
### Changed
- Updated package dependencies. [#32605]
## [1.18.8] - 2023-08-09
### Changed
- Updated package dependencies. [#32166]
## [1.18.7] - 2023-07-11
### Changed
- Updated package dependencies. [#31785]
## [1.18.6] - 2023-07-05
### Changed
- Updated package dependencies. [#31659]
## [1.18.5] - 2023-06-21
### Changed
- Updated package dependencies. [#31468]
## [1.18.4] - 2023-06-06
### Changed
- Updated package dependencies. [#31129]
## [1.18.3] - 2023-05-15
### Changed
- Internal updates.
## [1.18.2] - 2023-05-02
### Changed
- Updated package dependencies. [#30375]
## [1.18.1] - 2023-04-10
### Added
- Add Jetpack Autoloader package suggestion. [#29988]
## [1.18.0] - 2023-04-04
### Changed
- Async script enqueuing: switch to static method. [#29780]
- Updated package dependencies. [#29854]
## [1.17.34] - 2023-03-20
### Changed
- Updated package dependencies. [#29471]
## [1.17.33] - 2023-03-08
### Changed
- Updated package dependencies. [#29216]
## [1.17.32] - 2023-02-20
### Changed
- Minor internal updates.
## [1.17.31] - 2023-02-15
### Changed
- Update to React 18. [#28710]
## [1.17.30] - 2023-01-25
### Changed
- Minor internal updates.
## [1.17.29] - 2023-01-11
### Changed
- Updated package dependencies.
## [1.17.28] - 2022-12-02
### Changed
- Updated package dependencies.
## [1.17.27] - 2022-11-28
### Changed
- Updated package dependencies. [#27576]
## [1.17.26] - 2022-11-22
### Changed
- Updated package dependencies. [#27043]
## [1.17.25] - 2022-11-08
### Changed
- Updated package dependencies. [#27289]
## [1.17.24] - 2022-11-01
### Changed
- Updated package dependencies.
## [1.17.23] - 2022-10-13
### Changed
- Updated package dependencies. [#26791]
## [1.17.22] - 2022-10-05
### Changed
- Updated package dependencies. [#26568]
## [1.17.21] - 2022-08-25
### Changed
- Updated package dependencies. [#25814]
## [1.17.20] - 2022-07-26
### Changed
- Updated package dependencies. [#25158]
## [1.17.19] - 2022-07-12
### Changed
- Updated package dependencies.
## [1.17.18] - 2022-07-06
### Changed
- Updated package dependencies
## [1.17.17] - 2022-06-21
### Changed
- Renaming master to trunk.
## [1.17.16] - 2022-06-14
## [1.17.15] - 2022-06-08
### Changed
- Reorder JS imports for `import/order` eslint rule. [#24601]
## [1.17.14] - 2022-05-18
### Changed
- Updated package dependencies [#24372]
## [1.17.13] - 2022-05-10
### Changed
- Updated package dependencies. [#24302]
## [1.17.12] - 2022-05-04
### Added
- Add missing JavaScript dependencies, and fix a test. [#24096]
## [1.17.11] - 2022-04-26
### Changed
- Updated package dependencies.
## [1.17.10] - 2022-04-19
### Fixed
- Assets: Defer the enqueued script instead of its translations
## [1.17.9] - 2022-04-05
### Changed
- Updated package dependencies.
## [1.17.8] - 2022-03-29
### Changed
- Updated package dependencies.
## [1.17.7] - 2022-03-23
### Changed
- Updated package dependencies.
## [1.17.6] - 2022-03-02
### Changed
- Updated package dependencies.
## [1.17.5] - 2022-02-16
### Changed
- Updated package dependencies.
## [1.17.4] - 2022-02-09
### Changed
- Updated package dependencies.
## [1.17.3] - 2022-02-02
### Fixed
- Fixed minor coding standard violation.
## [1.17.2] - 2022-02-01
### Changed
- Build: remove unneeded files from production build.
## [1.17.1] - 2022-01-27
### Changed
- Updated package dependencies.
## [1.17.0] - 2022-01-25
### Added
- Accept package path prefixes from jetpack-composer-plugin and use them when lazy-loading JS translations.
- Generate the `wp-jp-i18n-loader` module needed by the new i18n-loader-webpack-plugin.
### Deprecated
- Deprecated the `wp-jp-i18n-state` module.
## [1.16.2] - 2022-01-18
### Fixed
- Handle the case where `WP_LANG_DIR` is in `WP_CONTENT_DIR`, but `WP_CONTENT_DIR` is not in `ABSPATH`.
## [1.16.1] - 2022-01-05
### Fixed
- Don't issue a "doing it wrong" warning for registering aliases during plugin activation.
## [1.16.0] - 2022-01-04
### Added
- Document use of jetpack-assets, jetpack-composer-plugin, and i18n-loader-webpack-plugin together.
### Changed
- Switch to pcov for code coverage.
- Updated package dependencies
- Updated package textdomain from `jetpack` to `jetpack-assets`.
## [1.15.0] - 2021-12-20
### Added
- Add `alias_textdomain()`.
## [1.14.0] - 2021-12-14
### Added
- Generate `wp-jp-i18n-state` script.
## [1.13.1] - 2021-11-22
### Fixed
- Call `_doing_it_wrong` correctly.
## [1.13.0] - 2021-11-22
### Added
- Have `Assets::register_script()` accept a textdomain for `wp_set_script_translations` (and complain if no textdomain is passed when `wp-i18n` is depended on).
### Changed
- Updated package dependencies
### Fixed
- Added missing option doc for `Assets::register_script()`.
## [1.12.0] - 2021-11-15
### Added
- Add `Assets::register_script()` for easier loading of Webpack-built scripts.
## [1.11.10] - 2021-11-02
### Changed
- Set `convertDeprecationsToExceptions` true in PHPUnit config.
- Update PHPUnit configs to include just what needs coverage rather than include everything then try to exclude stuff that doesn't.
## [1.11.9] - 2021-10-13
### Changed
- Updated package dependencies.
## [1.11.8] - 2021-10-06
### Changed
- Updated package dependencies
## [1.11.7] - 2021-09-28
### Changed
- Updated package dependencies.
## [1.11.6] - 2021-08-30
### Changed
- Run composer update on test-php command instead of phpunit
- Tests: update PHPUnit polyfills dependency (yoast/phpunit-polyfills).
- update annotations versions
## [1.11.5] - 2021-05-25
### Changed
- Updated package dependencies.
## [1.11.4] - 2021-04-08
### Changed
- Packaging and build changes, no change to the package itself.
## [1.11.3] - 2021-03-30
### Added
- Composer alias for dev-master, to improve dependencies
### Changed
- Update package dependencies.
### Fixed
- Use `composer update` rather than `install` in scripts, as composer.lock isn't checked in.
## [1.11.2] - 2021-02-23
- CI: Make tests more generic
## [1.11.1] - 2021-01-26
- Add mirror-repo information to all current composer packages
- Monorepo: Reorganize all projects
## [1.11.0] - 2021-01-05
- Update dependency brain/monkey to v2.6.0
## [1.10.0] - 2020-12-08
- Assets: introduce new method to process static resources
- Assets: Use defer for script tags
- Pin dependencies
- Packages: Update for PHP 8 testing
## [1.9.1] - 2020-11-24
- Update dependency brain/monkey to v2.5.0
- Updated PHPCS: Packages and Debugger
## [1.9.0] - 2020-10-27
- Instagram oEmbed: Simplify
## [1.8.0] - 2020-09-29
- Consolidate the Lazy Images package to rely on the Assets package
## [1.7.0] - 2020-08-25
- Packages: Update filenames after #16810
- CI: Try collect js coverage
- Docker: Add package testing shortcut
## [1.6.0] - 2020-07-28
- Various: Use wp_resource_hints
## [1.5.0] - 2020-06-30
- PHPCS: Clean up the packages
- WooCommerce Analytics: avoid 404 error when enqueuing script
## [1.4.0] - 2020-05-26
- Add Jetpack Scan threat notifications
## [1.3.0] - 2020-04-28
- Update dependencies to latest stable
## [1.2.0] - 2020-03-31
- Update dependencies to latest stable
## [1.1.1] - 2020-01-27
- Pin dependency brain/monkey to 2.4.0
## [1.1.0] - 2020-01-14
- Packages: Various improvements for wp.com or self-contained consumers
## [1.0.3] - 2019-11-08
- Packages: Use classmap instead of PSR-4
## [1.0.1] - 2019-10-28
- PHPCS: JITM and Assets packages
- Packages: Add gitattributes files to all packages that need th…
## 1.0.0 - 2019-09-14
- Statically access asset tools
[2.3.7]: https://github.com/Automattic/jetpack-assets/compare/v2.3.6...v2.3.7
[2.3.6]: https://github.com/Automattic/jetpack-assets/compare/v2.3.5...v2.3.6
[2.3.5]: https://github.com/Automattic/jetpack-assets/compare/v2.3.4...v2.3.5
[2.3.4]: https://github.com/Automattic/jetpack-assets/compare/v2.3.3...v2.3.4
[2.3.3]: https://github.com/Automattic/jetpack-assets/compare/v2.3.2...v2.3.3
[2.3.2]: https://github.com/Automattic/jetpack-assets/compare/v2.3.1...v2.3.2
[2.3.1]: https://github.com/Automattic/jetpack-assets/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/Automattic/jetpack-assets/compare/v2.2.0...v2.3.0
[2.2.0]: https://github.com/Automattic/jetpack-assets/compare/v2.1.13...v2.2.0
[2.1.13]: https://github.com/Automattic/jetpack-assets/compare/v2.1.12...v2.1.13
[2.1.12]: https://github.com/Automattic/jetpack-assets/compare/v2.1.11...v2.1.12
[2.1.11]: https://github.com/Automattic/jetpack-assets/compare/v2.1.10...v2.1.11
[2.1.10]: https://github.com/Automattic/jetpack-assets/compare/v2.1.9...v2.1.10
[2.1.9]: https://github.com/Automattic/jetpack-assets/compare/v2.1.8...v2.1.9
[2.1.8]: https://github.com/Automattic/jetpack-assets/compare/v2.1.7...v2.1.8
[2.1.7]: https://github.com/Automattic/jetpack-assets/compare/v2.1.6...v2.1.7
[2.1.6]: https://github.com/Automattic/jetpack-assets/compare/v2.1.5...v2.1.6
[2.1.5]: https://github.com/Automattic/jetpack-assets/compare/v2.1.4...v2.1.5
[2.1.4]: https://github.com/Automattic/jetpack-assets/compare/v2.1.3...v2.1.4
[2.1.3]: https://github.com/Automattic/jetpack-assets/compare/v2.1.2...v2.1.3
[2.1.2]: https://github.com/Automattic/jetpack-assets/compare/v2.1.1...v2.1.2
[2.1.1]: https://github.com/Automattic/jetpack-assets/compare/v2.1.0...v2.1.1
[2.1.0]: https://github.com/Automattic/jetpack-assets/compare/v2.0.4...v2.1.0
[2.0.4]: https://github.com/Automattic/jetpack-assets/compare/v2.0.3...v2.0.4
[2.0.3]: https://github.com/Automattic/jetpack-assets/compare/v2.0.2...v2.0.3
[2.0.2]: https://github.com/Automattic/jetpack-assets/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/Automattic/jetpack-assets/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Automattic/jetpack-assets/compare/v1.18.15...v2.0.0
[1.18.15]: https://github.com/Automattic/jetpack-assets/compare/v1.18.14...v1.18.15
[1.18.14]: https://github.com/Automattic/jetpack-assets/compare/v1.18.13...v1.18.14
[1.18.13]: https://github.com/Automattic/jetpack-assets/compare/v1.18.12...v1.18.13
[1.18.12]: https://github.com/Automattic/jetpack-assets/compare/v1.18.11...v1.18.12
[1.18.11]: https://github.com/Automattic/jetpack-assets/compare/v1.18.10...v1.18.11
[1.18.10]: https://github.com/Automattic/jetpack-assets/compare/v1.18.9...v1.18.10
[1.18.9]: https://github.com/Automattic/jetpack-assets/compare/v1.18.8...v1.18.9
[1.18.8]: https://github.com/Automattic/jetpack-assets/compare/v1.18.7...v1.18.8
[1.18.7]: https://github.com/Automattic/jetpack-assets/compare/v1.18.6...v1.18.7
[1.18.6]: https://github.com/Automattic/jetpack-assets/compare/v1.18.5...v1.18.6
[1.18.5]: https://github.com/Automattic/jetpack-assets/compare/v1.18.4...v1.18.5
[1.18.4]: https://github.com/Automattic/jetpack-assets/compare/v1.18.3...v1.18.4
[1.18.3]: https://github.com/Automattic/jetpack-assets/compare/v1.18.2...v1.18.3
[1.18.2]: https://github.com/Automattic/jetpack-assets/compare/v1.18.1...v1.18.2
[1.18.1]: https://github.com/Automattic/jetpack-assets/compare/v1.18.0...v1.18.1
[1.18.0]: https://github.com/Automattic/jetpack-assets/compare/v1.17.34...v1.18.0
[1.17.34]: https://github.com/Automattic/jetpack-assets/compare/v1.17.33...v1.17.34
[1.17.33]: https://github.com/Automattic/jetpack-assets/compare/v1.17.32...v1.17.33
[1.17.32]: https://github.com/Automattic/jetpack-assets/compare/v1.17.31...v1.17.32
[1.17.31]: https://github.com/Automattic/jetpack-assets/compare/v1.17.30...v1.17.31
[1.17.30]: https://github.com/Automattic/jetpack-assets/compare/v1.17.29...v1.17.30
[1.17.29]: https://github.com/Automattic/jetpack-assets/compare/v1.17.28...v1.17.29
[1.17.28]: https://github.com/Automattic/jetpack-assets/compare/v1.17.27...v1.17.28
[1.17.27]: https://github.com/Automattic/jetpack-assets/compare/v1.17.26...v1.17.27
[1.17.26]: https://github.com/Automattic/jetpack-assets/compare/v1.17.25...v1.17.26
[1.17.25]: https://github.com/Automattic/jetpack-assets/compare/v1.17.24...v1.17.25
[1.17.24]: https://github.com/Automattic/jetpack-assets/compare/v1.17.23...v1.17.24
[1.17.23]: https://github.com/Automattic/jetpack-assets/compare/v1.17.22...v1.17.23
[1.17.22]: https://github.com/Automattic/jetpack-assets/compare/v1.17.21...v1.17.22
[1.17.21]: https://github.com/Automattic/jetpack-assets/compare/v1.17.20...v1.17.21
[1.17.20]: https://github.com/Automattic/jetpack-assets/compare/v1.17.19...v1.17.20
[1.17.19]: https://github.com/Automattic/jetpack-assets/compare/v1.17.18...v1.17.19
[1.17.18]: https://github.com/Automattic/jetpack-assets/compare/v1.17.17...v1.17.18
[1.17.17]: https://github.com/Automattic/jetpack-assets/compare/v1.17.16...v1.17.17
[1.17.16]: https://github.com/Automattic/jetpack-assets/compare/v1.17.15...v1.17.16
[1.17.15]: https://github.com/Automattic/jetpack-assets/compare/v1.17.14...v1.17.15
[1.17.14]: https://github.com/Automattic/jetpack-assets/compare/v1.17.13...v1.17.14
[1.17.13]: https://github.com/Automattic/jetpack-assets/compare/v1.17.12...v1.17.13
[1.17.12]: https://github.com/Automattic/jetpack-assets/compare/v1.17.11...v1.17.12
[1.17.11]: https://github.com/Automattic/jetpack-assets/compare/v1.17.10...v1.17.11
[1.17.10]: https://github.com/Automattic/jetpack-assets/compare/v1.17.9...v1.17.10
[1.17.9]: https://github.com/Automattic/jetpack-assets/compare/v1.17.8...v1.17.9
[1.17.8]: https://github.com/Automattic/jetpack-assets/compare/v1.17.7...v1.17.8
[1.17.7]: https://github.com/Automattic/jetpack-assets/compare/v1.17.6...v1.17.7
[1.17.6]: https://github.com/Automattic/jetpack-assets/compare/v1.17.5...v1.17.6
[1.17.5]: https://github.com/Automattic/jetpack-assets/compare/v1.17.4...v1.17.5
[1.17.4]: https://github.com/Automattic/jetpack-assets/compare/v1.17.3...v1.17.4
[1.17.3]: https://github.com/Automattic/jetpack-assets/compare/v1.17.2...v1.17.3
[1.17.2]: https://github.com/Automattic/jetpack-assets/compare/v1.17.1...v1.17.2
[1.17.1]: https://github.com/Automattic/jetpack-assets/compare/v1.17.0...v1.17.1
[1.17.0]: https://github.com/Automattic/jetpack-assets/compare/v1.16.2...v1.17.0
[1.16.2]: https://github.com/Automattic/jetpack-assets/compare/v1.16.1...v1.16.2
[1.16.1]: https://github.com/Automattic/jetpack-assets/compare/v1.16.0...v1.16.1
[1.16.0]: https://github.com/Automattic/jetpack-assets/compare/v1.15.0...v1.16.0
[1.15.0]: https://github.com/Automattic/jetpack-assets/compare/v1.14.0...v1.15.0
[1.14.0]: https://github.com/Automattic/jetpack-assets/compare/v1.13.1...v1.14.0
[1.13.1]: https://github.com/Automattic/jetpack-assets/compare/v1.13.0...v1.13.1
[1.13.0]: https://github.com/Automattic/jetpack-assets/compare/v1.12.0...v1.13.0
[1.12.0]: https://github.com/Automattic/jetpack-assets/compare/v1.11.10...v1.12.0
[1.11.10]: https://github.com/Automattic/jetpack-assets/compare/v1.11.9...v1.11.10
[1.11.9]: https://github.com/Automattic/jetpack-assets/compare/v1.11.8...v1.11.9
[1.11.8]: https://github.com/Automattic/jetpack-assets/compare/v1.11.7...v1.11.8
[1.11.7]: https://github.com/Automattic/jetpack-assets/compare/v1.11.6...v1.11.7
[1.11.6]: https://github.com/Automattic/jetpack-assets/compare/v1.11.5...v1.11.6
[1.11.5]: https://github.com/Automattic/jetpack-assets/compare/v1.11.4...v1.11.5
[1.11.4]: https://github.com/Automattic/jetpack-assets/compare/v1.11.3...v1.11.4
[1.11.3]: https://github.com/Automattic/jetpack-assets/compare/v1.11.2...v1.11.3
[1.11.2]: https://github.com/Automattic/jetpack-assets/compare/v1.11.1...v1.11.2
[1.11.1]: https://github.com/Automattic/jetpack-assets/compare/v1.11.0...v1.11.1
[1.11.0]: https://github.com/Automattic/jetpack-assets/compare/v1.10.0...v1.11.0
[1.10.0]: https://github.com/Automattic/jetpack-assets/compare/v1.9.1...v1.10.0
[1.9.1]: https://github.com/Automattic/jetpack-assets/compare/v1.9.0...v1.9.1
[1.9.0]: https://github.com/Automattic/jetpack-assets/compare/v1.8.0...v1.9.0
[1.8.0]: https://github.com/Automattic/jetpack-assets/compare/v1.7.0...v1.8.0
[1.7.0]: https://github.com/Automattic/jetpack-assets/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/Automattic/jetpack-assets/compare/v1.5.0...v1.6.0
[1.5.0]: https://github.com/Automattic/jetpack-assets/compare/v1.4.0...v1.5.0
[1.4.0]: https://github.com/Automattic/jetpack-assets/compare/v1.3.0...v1.4.0
[1.3.0]: https://github.com/Automattic/jetpack-assets/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/Automattic/jetpack-assets/compare/v1.1.1...v1.2.0
[1.1.1]: https://github.com/Automattic/jetpack-assets/compare/v1.1.0...v1.1.1
[1.1.0]: https://github.com/Automattic/jetpack-assets/compare/v1.0.3...v1.1.0
[1.0.3]: https://github.com/Automattic/jetpack-assets/compare/v1.0.1...v1.0.3
[1.0.1]: https://github.com/Automattic/jetpack-assets/compare/v1.0.0...v1.0.1

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,25 @@
<?php
/**
* Action Hooks for Jetpack Assets module.
*
* @package automattic/jetpack-assets
*/
// If WordPress's plugin API is available already, use it. If not,
// drop data into `$wp_filter` for `WP_Hook::build_preinitialized_hooks()`.
if ( function_exists( 'add_action' ) ) {
add_action( 'wp_default_scripts', array( Automattic\Jetpack\Assets::class, 'wp_default_scripts_hook' ) );
add_action( 'plugins_loaded', array( Automattic\Jetpack\Assets\Script_Data::class, 'configure' ), 1 );
} else {
global $wp_filter;
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$wp_filter['wp_default_scripts'][10][] = array(
'accepted_args' => 1,
'function' => array( Automattic\Jetpack\Assets::class, 'wp_default_scripts_hook' ),
);
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$wp_filter['plugins_loaded'][1][] = array(
'accepted_args' => 0,
'function' => array( Automattic\Jetpack\Assets\Script_Data::class, 'configure' ),
);
}

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('wp-i18n'), 'version' => 'becd7d9884bc1b331e45');

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '0274966690f87adbeccb');

View File

@ -0,0 +1 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.JetpackScriptDataModule=t():e.JetpackScriptDataModule=t()}(self,(()=>(()=>{var e={729:(e,t,r)=>{"use strict";r.r(t),r.d(t,{getActiveFeatures:()=>a.mH,getAdminUrl:()=>a.hT,getJetpackAdminPageUrl:()=>a.oQ,getMyJetpackUrl:()=>a.e5,getScriptData:()=>a.au,getSiteData:()=>a.sV});var o=r(428),n={};for(const e in o)"default"!==e&&(n[e]=()=>o[e]);r.d(t,n);var a=r(336)},428:()=>{},336:(e,t,r)=>{"use strict";function o(){return window.JetpackScriptData}function n(){return o().site}function a(e=""){return`${o().site.admin_url}${e}`}function i(e=""){return a(`admin.php?page=jetpack${e}`)}function u(e=""){return a(`admin.php?page=my-jetpack${e}`)}function p(){return o().site.plan?.features?.active??[]}r.d(t,{au:()=>o,e5:()=>u,hT:()=>a,mH:()=>p,oQ:()=>i,sV:()=>n})}},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var a=t[o]={exports:{}};return e[o](a,a.exports,r),a.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};return(()=>{"use strict";r.r(o);var e=r(729),t={};for(const r in e)"default"!==r&&(t[r]=()=>e[r]);r.d(o,t)})(),o})()));

View File

@ -0,0 +1,2 @@
/*! For license information please see react-jsx-runtime.js.LICENSE.txt */
(()=>{"use strict";var r={572:(r,e,t)=>{var o=t(609),n=Symbol.for("react.element"),s=Symbol.for("react.fragment"),a=Object.prototype.hasOwnProperty,f=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};function _(r,e,t){var o,s={},_=null,i=null;for(o in void 0!==t&&(_=""+t),void 0!==e.key&&(_=""+e.key),void 0!==e.ref&&(i=e.ref),e)a.call(e,o)&&!p.hasOwnProperty(o)&&(s[o]=e[o]);if(r&&r.defaultProps)for(o in e=r.defaultProps)void 0===s[o]&&(s[o]=e[o]);return{$$typeof:n,type:r,key:_,ref:i,props:s,_owner:f.current}}e.Fragment=s,e.jsx=_,e.jsxs=_},48:(r,e,t)=>{r.exports=t(572)},609:r=>{r.exports=window.React}},e={},t=function t(o){var n=e[o];if(void 0!==n)return n.exports;var s=e[o]={exports:{}};return r[o](s,s.exports,t),s.exports}(48);window.ReactJSXRuntime=t})();

View File

@ -0,0 +1,9 @@
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -0,0 +1,57 @@
{
"name": "automattic/jetpack-assets",
"description": "Asset management utilities for Jetpack ecosystem packages",
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0",
"automattic/jetpack-constants": "^2.0.4"
},
"require-dev": {
"brain/monkey": "2.6.1",
"yoast/phpunit-polyfills": "^1.1.1",
"automattic/jetpack-changelogger": "^4.2.6",
"wikimedia/testing-access-wrapper": "^1.0 || ^2.0 || ^3.0"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
},
"autoload": {
"files": [
"actions.php"
],
"classmap": [
"src/"
]
},
"scripts": {
"build-development": [
"pnpm run build"
],
"build-production": [
"pnpm run build-production"
],
"phpunit": [
"./vendor/phpunit/phpunit/phpunit --colors=always"
],
"test-js": [
"pnpm run test"
],
"test-php": [
"@composer phpunit"
]
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"autotagger": true,
"mirror-repo": "Automattic/jetpack-assets",
"textdomain": "jetpack-assets",
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-assets/compare/v${old}...v${new}"
},
"branch-alias": {
"dev-trunk": "2.3.x-dev"
}
}
}

View File

@ -0,0 +1,769 @@
<?php
/**
* Jetpack Assets package.
*
* @package automattic/jetpack-assets
*/
namespace Automattic\Jetpack;
use Automattic\Jetpack\Assets\Semver;
use Automattic\Jetpack\Constants as Jetpack_Constants;
use InvalidArgumentException;
/**
* Class Assets
*/
class Assets {
/**
* Holds all the scripts handles that should be loaded in a deferred fashion.
*
* @var array
*/
private $defer_script_handles = array();
/**
* The singleton instance of this class.
*
* @var Assets
*/
protected static $instance;
/**
* The registered textdomain mappings.
*
* @var array `array( mapped_domain => array( string target_domain, string target_type, string semver, string path_prefix ) )`.
*/
private static $domain_map = array();
/**
* Constructor.
*
* Static-only class, so nothing here.
*/
private function __construct() {}
// ////////////////////
// region Async script loading
/**
* Get the singleton instance of the class.
*
* @return Assets
*/
public static function instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new Assets();
}
return self::$instance;
}
/**
* A public method for adding the async script.
*
* @deprecated Since 2.1.0, the `strategy` feature should be used instead, with the "defer" setting.
*
* @param string $script_handle Script handle.
*/
public static function add_async_script( $script_handle ) {
_deprecated_function( __METHOD__, '2.1.0' );
wp_script_add_data( $script_handle, 'strategy', 'defer' );
}
/**
* Add an async attribute to scripts that can be loaded deferred.
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
*
* @deprecated Since 2.1.0, the `strategy` feature should be used instead.
*
* @param string $tag The <script> tag for the enqueued script.
* @param string $handle The script's registered handle.
*/
public function script_add_async( $tag, $handle ) {
_deprecated_function( __METHOD__, '2.1.0' );
if ( empty( $this->defer_script_handles ) ) {
return $tag;
}
if ( in_array( $handle, $this->defer_script_handles, true ) ) {
// phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
return preg_replace( '/<script( [^>]*)? src=/i', '<script defer$1 src=', $tag );
}
return $tag;
}
/**
* A helper function that lets you enqueue scripts in an async fashion.
*
* @deprecated Since 2.1.0 - use the strategy feature instead.
*
* @param string $handle Name of the script. Should be unique.
* @param string $min_path Minimized script path.
* @param string $non_min_path Full Script path.
* @param array $deps Array of script dependencies.
* @param bool $ver The script version.
* @param bool $in_footer Should the script be included in the footer.
*/
public static function enqueue_async_script( $handle, $min_path, $non_min_path, $deps = array(), $ver = false, $in_footer = true ) {
_deprecated_function( __METHOD__, '2.1.0' );
wp_enqueue_script( $handle, self::get_file_url_for_environment( $min_path, $non_min_path ), $deps, $ver, $in_footer );
wp_script_add_data( $handle, 'strategy', 'defer' );
}
// endregion .
// ////////////////////
// region Utils
/**
* Given a minified path, and a non-minified path, will return
* a minified or non-minified file URL based on whether SCRIPT_DEBUG is set and truthy.
*
* If $package_path is provided, then the minified or non-minified file URL will be generated
* relative to the root package directory.
*
* Both `$min_base` and `$non_min_base` can be either full URLs, or are expected to be relative to the
* root Jetpack directory.
*
* @param string $min_path minified path.
* @param string $non_min_path non-minified path.
* @param string $package_path Optional. A full path to a file inside a package directory
* The URL will be relative to its directory. Default empty.
* Typically this is done by passing __FILE__ as the argument.
*
* @return string The URL to the file
* @since 1.0.3
* @since-jetpack 5.6.0
*/
public static function get_file_url_for_environment( $min_path, $non_min_path, $package_path = '' ) {
$path = ( Jetpack_Constants::is_defined( 'SCRIPT_DEBUG' ) && Jetpack_Constants::get_constant( 'SCRIPT_DEBUG' ) )
? $non_min_path
: $min_path;
/*
* If the path is actually a full URL, keep that.
* We look for a host value, since enqueues are sometimes without a scheme.
*/
$file_parts = wp_parse_url( $path );
if ( ! empty( $file_parts['host'] ) ) {
$url = $path;
} else {
$plugin_path = empty( $package_path ) ? Jetpack_Constants::get_constant( 'JETPACK__PLUGIN_FILE' ) : $package_path;
$url = plugins_url( $path, $plugin_path );
}
/**
* Filters the URL for a file passed through the get_file_url_for_environment function.
*
* @since 1.0.3
*
* @package assets
*
* @param string $url The URL to the file.
* @param string $min_path The minified path.
* @param string $non_min_path The non-minified path.
*/
return apply_filters( 'jetpack_get_file_for_environment', $url, $min_path, $non_min_path );
}
/**
* Passes an array of URLs to wp_resource_hints.
*
* @since 1.5.0
*
* @param string|array $urls URLs to hint.
* @param string $type One of the supported resource types: dns-prefetch (default), preconnect, prefetch, or prerender.
*/
public static function add_resource_hint( $urls, $type = 'dns-prefetch' ) {
add_filter(
'wp_resource_hints',
function ( $hints, $resource_type ) use ( $urls, $type ) {
if ( $resource_type === $type ) {
// Type casting to array required since the function accepts a single string.
foreach ( (array) $urls as $url ) {
$hints[] = $url;
}
}
return $hints;
},
10,
2
);
}
/**
* Serve a WordPress.com static resource via a randomized wp.com subdomain.
*
* @since 1.9.0
*
* @param string $url WordPress.com static resource URL.
*
* @return string $url
*/
public static function staticize_subdomain( $url ) {
// Extract hostname from URL.
$host = wp_parse_url( $url, PHP_URL_HOST );
// Explode hostname on '.'.
$exploded_host = explode( '.', $host );
// Retrieve the name and TLD.
if ( count( $exploded_host ) > 1 ) {
$name = $exploded_host[ count( $exploded_host ) - 2 ];
$tld = $exploded_host[ count( $exploded_host ) - 1 ];
// Rebuild domain excluding subdomains.
$domain = $name . '.' . $tld;
} else {
$domain = $host;
}
// Array of Automattic domains.
$domains_allowed = array( 'wordpress.com', 'wp.com' );
// Return $url if not an Automattic domain.
if ( ! in_array( $domain, $domains_allowed, true ) ) {
return $url;
}
if ( \is_ssl() ) {
return preg_replace( '|https?://[^/]++/|', 'https://s-ssl.wordpress.com/', $url );
}
/*
* Generate a random subdomain id by taking the modulus of the crc32 value of the URL.
* Valid values are 0, 1, and 2.
*/
$static_counter = abs( crc32( basename( $url ) ) % 3 );
return preg_replace( '|://[^/]+?/|', "://s$static_counter.wp.com/", $url );
}
/**
* Resolve '.' and '..' components in a path or URL.
*
* @since 1.12.0
* @param string $path Path or URL.
* @return string Normalized path or URL.
*/
public static function normalize_path( $path ) {
$parts = wp_parse_url( $path );
if ( ! isset( $parts['path'] ) ) {
return $path;
}
$ret = '';
$ret .= isset( $parts['scheme'] ) ? $parts['scheme'] . '://' : '';
if ( isset( $parts['user'] ) || isset( $parts['pass'] ) ) {
$ret .= $parts['user'] ?? '';
$ret .= isset( $parts['pass'] ) ? ':' . $parts['pass'] : '';
$ret .= '@';
}
$ret .= $parts['host'] ?? '';
$ret .= isset( $parts['port'] ) ? ':' . $parts['port'] : '';
$pp = explode( '/', $parts['path'] );
if ( '' === $pp[0] ) {
$ret .= '/';
array_shift( $pp );
}
$i = 0;
while ( $i < count( $pp ) ) { // phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
if ( '' === $pp[ $i ] || '.' === $pp[ $i ] || 0 === $i && '..' === $pp[ $i ] ) {
array_splice( $pp, $i, 1 );
} elseif ( '..' === $pp[ $i ] ) {
array_splice( $pp, --$i, 2 );
} else {
++$i;
}
}
$ret .= implode( '/', $pp );
$ret .= isset( $parts['query'] ) ? '?' . $parts['query'] : '';
$ret .= isset( $parts['fragment'] ) ? '#' . $parts['fragment'] : '';
return $ret;
}
// endregion .
// ////////////////////
// region Webpack-built script registration
/**
* Register a Webpack-built script.
*
* Our Webpack-built scripts tend to need a bunch of boilerplate:
* - A call to `Assets::get_file_url_for_environment()` for possible debugging.
* - A call to `wp_register_style()` for extracted CSS, possibly with detection of RTL.
* - Loading of dependencies and version provided by `@wordpress/dependency-extraction-webpack-plugin`.
* - Avoiding WPCom's broken minifier.
*
* This wrapper handles all of that.
*
* @since 1.12.0
* @since 2.1.0 Add a new `strategy` option to leverage WP >= 6.3 script strategy feature. The `async` option is deprecated.
* @param string $handle Name of the script. Should be unique across both scripts and styles.
* @param string $path Minimized script path.
* @param string $relative_to File that `$path` is relative to. Pass `__FILE__`.
* @param array $options Additional options:
* - `asset_path`: (string|null) `.asset.php` to load. Default is to base it on `$path`.
* - `async`: (bool) Set true to register the script as deferred, like `Assets::enqueue_async_script()`. Deprecated in favor of `strategy`.
* - `css_dependencies`: (string[]) Additional style dependencies to queue.
* - `css_path`: (string|null) `.css` to load. Default is to base it on `$path`.
* - `dependencies`: (string[]) Additional script dependencies to queue.
* - `enqueue`: (bool) Set true to enqueue the script immediately.
* - `in_footer`: (bool) Set true to register script for the footer.
* - `media`: (string) Media for the css file. Default 'all'.
* - `minify`: (bool|null) Set true to pass `minify=true` in the query string, or `null` to suppress the normal `minify=false`.
* - `nonmin_path`: (string) Non-minified script path.
* - `strategy`: (string) Specify a script strategy to use, eg. `defer` or `async`. Default is `""`.
* - `textdomain`: (string) Text domain for the script. Required if the script depends on wp-i18n.
* - `version`: (string) Override the version from the `asset_path` file.
* @phan-param array{asset_path?:?string,async?:bool,css_dependencies?:string[],css_path?:?string,dependencies?:string[],enqueue?:bool,in_footer?:bool,media?:string,minify?:?bool,nonmin_path?:string,strategy?:string,textdomain?:string,version?:string} $options
* @throws \InvalidArgumentException If arguments are invalid.
*/
public static function register_script( $handle, $path, $relative_to, array $options = array() ) {
if ( substr( $path, -3 ) !== '.js' ) {
throw new \InvalidArgumentException( '$path must end in ".js"' );
}
if ( isset( $options['async'] ) ) {
_deprecated_argument( __METHOD__, '2.1.0', 'The `async` option is deprecated in favor of `strategy`' );
}
$dir = dirname( $relative_to );
$base = substr( $path, 0, -3 );
$options += array(
'asset_path' => "$base.asset.php",
'async' => false,
'css_dependencies' => array(),
'css_path' => "$base.css",
'dependencies' => array(),
'enqueue' => false,
'in_footer' => false,
'media' => 'all',
'minify' => false,
'strategy' => '',
'textdomain' => null,
);
'@phan-var array{asset_path:?string,async:bool,css_dependencies:string[],css_path:?string,dependencies:string[],enqueue:bool,in_footer:bool,media:string,minify:?bool,nonmin_path?:string,strategy:string,textdomain:string,version?:string} $options'; // Phan gets confused by the array addition.
if ( is_string( $options['css_path'] ) && $options['css_path'] !== '' && substr( $options['css_path'], -4 ) !== '.css' ) {
throw new \InvalidArgumentException( '$options[\'css_path\'] must end in ".css"' );
}
if ( isset( $options['nonmin_path'] ) ) {
$url = self::get_file_url_for_environment( $path, $options['nonmin_path'], $relative_to );
} else {
$url = plugins_url( $path, $relative_to );
}
$url = self::normalize_path( $url );
if ( null !== $options['minify'] ) {
$url = add_query_arg( 'minify', $options['minify'] ? 'true' : 'false', $url );
}
if ( $options['asset_path'] && file_exists( "$dir/{$options['asset_path']}" ) ) {
$asset = require "$dir/{$options['asset_path']}"; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.NotAbsolutePath
$options['dependencies'] = array_merge( $asset['dependencies'], $options['dependencies'] );
$options['css_dependencies'] = array_merge(
array_filter(
$asset['dependencies'],
function ( $d ) {
return wp_style_is( $d, 'registered' );
}
),
$options['css_dependencies']
);
$ver = $options['version'] ?? $asset['version'];
} else {
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$ver = $options['version'] ?? @filemtime( "$dir/$path" );
}
if ( $options['async'] && '' === $options['strategy'] ) { // Handle the deprecated `async` option
$options['strategy'] = 'defer';
}
wp_register_script(
$handle,
$url,
$options['dependencies'],
$ver,
array(
'in_footer' => $options['in_footer'],
'strategy' => $options['strategy'],
)
);
if ( $options['textdomain'] ) {
// phpcs:ignore Jetpack.Functions.I18n.DomainNotLiteral
wp_set_script_translations( $handle, $options['textdomain'] );
} elseif ( in_array( 'wp-i18n', $options['dependencies'], true ) ) {
_doing_it_wrong(
__METHOD__,
/* translators: %s is the script handle. */
esc_html( sprintf( __( 'Script "%s" depends on wp-i18n but does not specify "textdomain"', 'jetpack-assets' ), $handle ) ),
''
);
}
if ( is_string( $options['css_path'] ) && $options['css_path'] !== '' && file_exists( "$dir/{$options['css_path']}" ) ) {
$csspath = $options['css_path'];
if ( is_rtl() ) {
$rtlcsspath = substr( $csspath, 0, -4 ) . '.rtl.css';
if ( file_exists( "$dir/$rtlcsspath" ) ) {
$csspath = $rtlcsspath;
}
}
$url = self::normalize_path( plugins_url( $csspath, $relative_to ) );
if ( null !== $options['minify'] ) {
$url = add_query_arg( 'minify', $options['minify'] ? 'true' : 'false', $url );
}
wp_register_style( $handle, $url, $options['css_dependencies'], $ver, $options['media'] );
wp_script_add_data( $handle, 'Jetpack::Assets::hascss', true );
} else {
wp_script_add_data( $handle, 'Jetpack::Assets::hascss', false );
}
if ( $options['enqueue'] ) {
self::enqueue_script( $handle );
}
}
/**
* Enqueue a script registered with `Assets::register_script`.
*
* @since 1.12.0
* @param string $handle Name of the script. Should be unique across both scripts and styles.
*/
public static function enqueue_script( $handle ) {
wp_enqueue_script( $handle );
if ( wp_scripts()->get_data( $handle, 'Jetpack::Assets::hascss' ) ) {
wp_enqueue_style( $handle );
}
}
/**
* 'wp_default_scripts' action handler.
*
* This registers the `wp-jp-i18n-loader` script for use by Webpack bundles built with
* `@automattic/i18n-loader-webpack-plugin`.
*
* @since 1.14.0
* @param \WP_Scripts $wp_scripts WP_Scripts instance.
*/
public static function wp_default_scripts_hook( $wp_scripts ) {
$data = array(
'baseUrl' => false,
'locale' => determine_locale(),
'domainMap' => array(),
'domainPaths' => array(),
);
$lang_dir = Jetpack_Constants::get_constant( 'WP_LANG_DIR' );
$content_dir = Jetpack_Constants::get_constant( 'WP_CONTENT_DIR' );
$abspath = Jetpack_Constants::get_constant( 'ABSPATH' );
// Note: str_starts_with() is not used here, as wp-includes/compat.php may not be loaded at this point.
if ( strpos( $lang_dir, $content_dir ) === 0 ) {
$data['baseUrl'] = content_url( substr( trailingslashit( $lang_dir ), strlen( trailingslashit( $content_dir ) ) ) );
} elseif ( strpos( $lang_dir, $abspath ) === 0 ) {
$data['baseUrl'] = site_url( substr( trailingslashit( $lang_dir ), strlen( untrailingslashit( $abspath ) ) ) );
}
foreach ( self::$domain_map as $from => list( $to, $type, , $path ) ) {
$data['domainMap'][ $from ] = ( 'core' === $type ? '' : "{$type}/" ) . $to;
if ( '' !== $path ) {
$data['domainPaths'][ $from ] = trailingslashit( $path );
}
}
/**
* Filters the i18n state data for use by Webpack bundles built with
* `@automattic/i18n-loader-webpack-plugin`.
*
* @since 1.14.0
* @package assets
* @param array $data The state data to generate. Expected fields are:
* - `baseUrl`: (string|false) The URL to the languages directory. False if no URL could be determined.
* - `locale`: (string) The locale for the page.
* - `domainMap`: (string[]) A mapping from Composer package textdomains to the corresponding
* `plugins/textdomain` or `themes/textdomain` (or core `textdomain`, but that's unlikely).
* - `domainPaths`: (string[]) A mapping from Composer package textdomains to the corresponding package
* paths.
*/
$data = apply_filters( 'jetpack_i18n_state', $data );
// Can't use self::register_script(), this action is called too early.
if ( file_exists( __DIR__ . '/../build/i18n-loader.asset.php' ) ) {
$path = '../build/i18n-loader.js';
$asset = require __DIR__ . '/../build/i18n-loader.asset.php';
} else {
$path = 'js/i18n-loader.js';
$asset = array(
'dependencies' => array( 'wp-i18n' ),
'version' => filemtime( __DIR__ . "/$path" ),
);
}
$url = self::normalize_path( plugins_url( $path, __FILE__ ) );
$url = add_query_arg( 'minify', 'true', $url );
$handle = 'wp-jp-i18n-loader';
$wp_scripts->add( $handle, $url, $asset['dependencies'], $asset['version'] );
// Ensure the script is loaded in the footer and deferred.
$wp_scripts->add_data( $handle, 'group', 1 );
if ( ! is_array( $data ) ||
! isset( $data['baseUrl'] ) || ! ( is_string( $data['baseUrl'] ) || false === $data['baseUrl'] ) ||
! isset( $data['locale'] ) || ! is_string( $data['locale'] ) ||
! isset( $data['domainMap'] ) || ! is_array( $data['domainMap'] ) ||
! isset( $data['domainPaths'] ) || ! is_array( $data['domainPaths'] )
) {
$wp_scripts->add_inline_script( $handle, 'console.warn( "I18n state deleted by jetpack_i18n_state hook" );' );
} elseif ( ! $data['baseUrl'] ) {
$wp_scripts->add_inline_script( $handle, 'console.warn( "Failed to determine languages base URL. Is WP_LANG_DIR in the WordPress root?" );' );
} else {
$data['domainMap'] = (object) $data['domainMap']; // Ensure it becomes a json object.
$data['domainPaths'] = (object) $data['domainPaths']; // Ensure it becomes a json object.
$wp_scripts->add_inline_script( $handle, 'wp.jpI18nLoader.state = ' . wp_json_encode( $data, JSON_UNESCAPED_SLASHES ) . ';' );
}
// Deprecated state module: Depend on wp-i18n to ensure global `wp` exists and because anything needing this will need that too.
$wp_scripts->add( 'wp-jp-i18n-state', false, array( 'wp-deprecated', $handle ) );
$wp_scripts->add_inline_script( 'wp-jp-i18n-state', 'wp.deprecated( "wp-jp-i18n-state", { alternative: "wp-jp-i18n-loader" } );' );
$wp_scripts->add_inline_script( 'wp-jp-i18n-state', 'wp.jpI18nState = wp.jpI18nLoader.state;' );
// Register the React JSX runtime script - used as a polyfill until we can update JSX transforms. See https://github.com/Automattic/jetpack/issues/38424.
// @todo Remove this when we drop support for WordPress 6.5, as well as the script inclusion in test_wp_default_scripts_hook.
$jsx_url = self::normalize_path( plugins_url( '../build/react-jsx-runtime.js', __FILE__ ) );
$wp_scripts->add( 'react-jsx-runtime', $jsx_url, array( 'react' ), '18.3.1', true );
$wp_scripts->add_data( 'react-jsx-runtime', 'group', 1 );
}
// endregion .
// ////////////////////
// region Textdomain aliasing
/**
* Register a textdomain alias.
*
* Composer packages included in plugins will likely not use the textdomain of the plugin, while
* WordPress's i18n infrastructure will include the translations in the plugin's domain. This
* allows for mapping the package's domain to the plugin's.
*
* Since multiple plugins may use the same package, we include the package's version here so
* as to choose the most recent translations (which are most likely to match the package
* selected by jetpack-autoloader).
*
* @since 1.15.0
* @param string $from Domain to alias.
* @param string $to Domain to alias it to.
* @param string $totype What is the target of the alias: 'plugins', 'themes', or 'core'.
* @param string $ver Version of the `$from` domain.
* @param string $path Path to prepend when lazy-loading from JavaScript.
* @throws InvalidArgumentException If arguments are invalid.
*/
public static function alias_textdomain( $from, $to, $totype, $ver, $path = '' ) {
if ( ! in_array( $totype, array( 'plugins', 'themes', 'core' ), true ) ) {
throw new InvalidArgumentException( 'Type must be "plugins", "themes", or "core"' );
}
if (
did_action( 'wp_default_scripts' ) &&
// Don't complain during plugin activation.
! defined( 'WP_SANDBOX_SCRAPING' )
) {
_doing_it_wrong(
__METHOD__,
sprintf(
/* translators: 1: wp_default_scripts. 2: Name of the domain being aliased. */
esc_html__( 'Textdomain aliases should be registered before the %1$s hook. This notice was triggered by the %2$s domain.', 'jetpack-assets' ),
'<code>wp_default_scripts</code>',
'<code>' . esc_html( $from ) . '</code>'
),
''
);
}
if ( empty( self::$domain_map[ $from ] ) ) {
self::init_domain_map_hooks( $from, array() === self::$domain_map );
self::$domain_map[ $from ] = array( $to, $totype, $ver, $path );
} elseif ( Semver::compare( $ver, self::$domain_map[ $from ][2] ) > 0 ) {
self::$domain_map[ $from ] = array( $to, $totype, $ver, $path );
}
}
/**
* Register textdomain aliases from a mapping file.
*
* The mapping file is simply a PHP file that returns an array
* with the following properties:
* - 'domain': String, `$to`
* - 'type': String, `$totype`
* - 'packages': Array, mapping `$from` to `array( 'path' => $path, 'ver' => $ver )` (or to the string `$ver` for back compat).
*
* @since 1.15.0
* @param string $file Mapping file.
*/
public static function alias_textdomains_from_file( $file ) {
$data = require $file;
foreach ( $data['packages'] as $from => $fromdata ) {
if ( ! is_array( $fromdata ) ) {
$fromdata = array(
'path' => '',
'ver' => $fromdata,
);
}
self::alias_textdomain( $from, $data['domain'], $data['type'], $fromdata['ver'], $fromdata['path'] );
}
}
/**
* Register the hooks for textdomain aliasing.
*
* @param string $domain Domain to alias.
* @param bool $firstcall If this is the first call.
*/
private static function init_domain_map_hooks( $domain, $firstcall ) {
// If WordPress's plugin API is available already, use it. If not,
// drop data into `$wp_filter` for `WP_Hook::build_preinitialized_hooks()`.
if ( function_exists( 'add_filter' ) ) {
$add_filter = 'add_filter';
} else {
$add_filter = function ( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
global $wp_filter;
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$wp_filter[ $hook_name ][ $priority ][] = array(
'accepted_args' => $accepted_args,
'function' => $callback,
);
};
}
$add_filter( "gettext_{$domain}", array( self::class, 'filter_gettext' ), 10, 3 );
$add_filter( "ngettext_{$domain}", array( self::class, 'filter_ngettext' ), 10, 5 );
$add_filter( "gettext_with_context_{$domain}", array( self::class, 'filter_gettext_with_context' ), 10, 4 );
$add_filter( "ngettext_with_context_{$domain}", array( self::class, 'filter_ngettext_with_context' ), 10, 6 );
if ( $firstcall ) {
$add_filter( 'load_script_translation_file', array( self::class, 'filter_load_script_translation_file' ), 10, 3 );
}
}
/**
* Filter for `gettext`.
*
* @since 1.15.0
* @param string $translation Translated text.
* @param string $text Text to translate.
* @param string $domain Text domain.
* @return string Translated text.
*/
public static function filter_gettext( $translation, $text, $domain ) {
if ( $translation === $text ) {
// phpcs:ignore WordPress.WP.I18n -- This is a filter hook to map the text domains from our Composer packages to the domain for a containing plugin. See https://wp.me/p2gHKz-oRh#problem-6-text-domains-in-composer-packages
$newtext = __( $text, self::$domain_map[ $domain ][0] );
if ( $newtext !== $text ) {
return $newtext;
}
}
return $translation;
}
/**
* Filter for `ngettext`.
*
* @since 1.15.0
* @param string $translation Translated text.
* @param string $single The text to be used if the number is singular.
* @param string $plural The text to be used if the number is plural.
* @param int $number The number to compare against to use either the singular or plural form.
* @param string $domain Text domain.
* @return string Translated text.
*/
public static function filter_ngettext( $translation, $single, $plural, $number, $domain ) {
if ( $translation === $single || $translation === $plural ) {
// phpcs:ignore WordPress.WP.I18n -- This is a filter hook to map the text domains from our Composer packages to the domain for a containing plugin. See https://wp.me/p2gHKz-oRh#problem-6-text-domains-in-composer-packages
$translation = _n( $single, $plural, $number, self::$domain_map[ $domain ][0] );
}
return $translation;
}
/**
* Filter for `gettext_with_context`.
*
* @since 1.15.0
* @param string $translation Translated text.
* @param string $text Text to translate.
* @param string $context Context information for the translators.
* @param string $domain Text domain.
* @return string Translated text.
*/
public static function filter_gettext_with_context( $translation, $text, $context, $domain ) {
if ( $translation === $text ) {
// phpcs:ignore WordPress.WP.I18n -- This is a filter hook to map the text domains from our Composer packages to the domain for a containing plugin. See https://wp.me/p2gHKz-oRh#problem-6-text-domains-in-composer-packages
$translation = _x( $text, $context, self::$domain_map[ $domain ][0] );
}
return $translation;
}
/**
* Filter for `ngettext_with_context`.
*
* @since 1.15.0
* @param string $translation Translated text.
* @param string $single The text to be used if the number is singular.
* @param string $plural The text to be used if the number is plural.
* @param int $number The number to compare against to use either the singular or plural form.
* @param string $context Context information for the translators.
* @param string $domain Text domain.
* @return string Translated text.
*/
public static function filter_ngettext_with_context( $translation, $single, $plural, $number, $context, $domain ) {
if ( $translation === $single || $translation === $plural ) {
// phpcs:ignore WordPress.WP.I18n -- This is a filter hook to map the text domains from our Composer packages to the domain for a containing plugin. See https://wp.me/p2gHKz-oRh#problem-6-text-domains-in-composer-packages
$translation = _nx( $single, $plural, $number, $context, self::$domain_map[ $domain ][0] );
}
return $translation;
}
/**
* Filter for `load_script_translation_file`.
*
* @since 1.15.0
* @param string|false $file Path to the translation file to load. False if there isn't one.
* @param string $handle Name of the script to register a translation domain to.
* @param string $domain The text domain.
*/
public static function filter_load_script_translation_file( $file, $handle, $domain ) {
if ( false !== $file && isset( self::$domain_map[ $domain ] ) && ! is_readable( $file ) ) {
// Determine the part of the filename after the domain.
$suffix = basename( $file );
$l = strlen( $domain );
if ( substr( $suffix, 0, $l ) !== $domain || '-' !== $suffix[ $l ] ) {
return $file;
}
$suffix = substr( $suffix, $l );
$lang_dir = Jetpack_Constants::get_constant( 'WP_LANG_DIR' );
// Look for replacement files.
list( $newdomain, $type ) = self::$domain_map[ $domain ];
$newfile = $lang_dir . ( 'core' === $type ? '/' : "/{$type}/" ) . $newdomain . $suffix;
if ( is_readable( $newfile ) ) {
return $newfile;
}
}
return $file;
}
// endregion .
}
// Enable section folding in vim:
// vim: foldmarker=//\ region,//\ endregion foldmethod=marker
// .

View File

@ -0,0 +1,220 @@
<?php
/**
* Jetpack script data.
*
* @package automattic/jetpack-assets
*/
namespace Automattic\Jetpack\Assets;
use Automattic\Jetpack\Assets;
/**
* Class script data
*/
class Script_Data {
const SCRIPT_HANDLE = 'jetpack-script-data';
/**
* Whether the script data has been rendered.
*
* @var bool
*/
private static $did_render_script_data = false;
/**
* Configure.
*/
public static function configure() {
/**
* Ensure that assets are registered on wp_loaded,
* which is fired before *_enqueue_scripts actions.
* It means that when the dependent scripts are registered,
* the scripts here are already registered.
*/
add_action( 'wp_loaded', array( self::class, 'register_assets' ) );
/**
* Notes:
* 1. wp_print_scripts action is fired on both admin and public pages.
* On admin pages, it's fired before admin_enqueue_scripts action,
* which can be a problem if the consumer package uses admin_enqueue_scripts
* to hook into the script data. Thus, we prefer to use admin_print_scripts on admin pages.
* 2. We want to render the script data on print, instead of init or enqueue actions,
* so that the hook callbacks have enough time and information
* to decide whether to update the script data or not.
*/
$hook = is_admin() ? 'admin_print_scripts' : 'wp_print_scripts';
add_action( $hook, array( self::class, 'render_script_data' ), 1 );
add_action( 'enqueue_block_editor_assets', array( self::class, 'render_script_data' ), 1 );
}
/**
* Register assets.
*
* @access private
*/
public static function register_assets() {
Assets::register_script(
self::SCRIPT_HANDLE,
'../build/jetpack-script-data.js',
__FILE__,
array(
'in_footer' => true,
'textdomain' => 'jetpack-assets',
)
);
}
/**
* Render the script data using an inline script.
*
* @access private
*
* @return void
*/
public static function render_script_data() {
// In case of 'enqueue_block_editor_assets' action, this can be called multiple times.
if ( self::$did_render_script_data ) {
return;
}
self::$did_render_script_data = true;
$script_data = is_admin() ? self::get_admin_script_data() : self::get_public_script_data();
$script_data = wp_json_encode(
$script_data,
JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE
);
wp_add_inline_script(
self::SCRIPT_HANDLE,
sprintf( 'window.JetpackScriptData = %s;', $script_data ),
'before'
);
}
/**
* Get the admin script data.
*
* @return array
*/
protected static function get_admin_script_data() {
global $wp_version;
$data = array(
'site' => array(
'admin_url' => esc_url_raw( admin_url() ),
'date_format' => get_option( 'date_format' ),
'icon' => self::get_site_icon(),
'is_multisite' => is_multisite(),
'plan' => array(
// The properties here should be updated by the consumer package/plugin.
// It includes properties like 'product_slug', 'features', etc.
'product_slug' => '',
),
'rest_nonce' => wp_create_nonce( 'wp_rest' ),
'rest_root' => esc_url_raw( rest_url() ),
'title' => self::get_site_title(),
'wp_version' => $wp_version,
'wpcom' => array(
// This should contain the connected site details like blog_id, is_atomic etc.
'blog_id' => 0,
),
),
'user' => array(
'current_user' => self::get_current_user_data(),
),
);
/**
* Filter the admin script data.
*
* When using this filter, ensure that the data is added only if it is used by some script.
* This filter may be called on almost every admin page load. So, one should check if the data is needed/used on that page.
* For example, the social (publicize) data is used only on Social admin page, Jetpack settings page and the post editor.
* So, the social data should be added only on those pages.
*
* @since 2.3.0
*
* @param array $data The script data.
*/
return apply_filters( 'jetpack_admin_js_script_data', $data );
}
/**
* Get the admin script data.
*
* @return array
*/
protected static function get_public_script_data() {
$data = array(
'site' => array(
'icon' => self::get_site_icon(),
'title' => self::get_site_title(),
),
);
/**
* Filter the public script data.
*
* See the docs for `jetpack_admin_js_script_data` filter for more information.
*
* @since 2.3.0
*
* @param array $data The script data.
*/
return apply_filters( 'jetpack_public_js_script_data', $data );
}
/**
* Get the site title.
*
* @return string
*/
protected static function get_site_title() {
$title = get_bloginfo( 'name' );
return $title ? $title : esc_url_raw( ( get_site_url() ) );
}
/**
* Get the site icon.
*
* @return string
*/
protected static function get_site_icon() {
if ( ! has_site_icon() ) {
return '';
}
/**
* Filters the site icon using Photon.
*
* @see https://developer.wordpress.com/docs/photon/
*
* @param string $url The URL of the site icon.
* @param array|string $args An array of arguments, e.g. array( 'w' => '300', 'resize' => array( 123, 456 ) ), or in string form (w=123&h=456).
*/
return apply_filters( 'jetpack_photon_url', get_site_icon_url(), array( 'w' => 64 ) );
}
/**
* Get the current user data.
*
* @return array
*/
protected static function get_current_user_data() {
$current_user = wp_get_current_user();
return array(
'display_name' => $current_user->display_name,
'id' => $current_user->ID,
);
}
}

View File

@ -0,0 +1,121 @@
<?php
/**
* Simple semver version handling.
*
* We use this instead of something like `composer/semver` to avoid
* plugins needing to include yet-another dependency package. The
* amount of code we need here is pretty small.
*
* We use this instead of PHP's `version_compare()` because that doesn't
* handle prerelease versions in the way anyone other than PHP devs would
* expect, and silently breaks on various unexpected input.
*
* @package automattic/jetpack-assets
*/
namespace Automattic\Jetpack\Assets;
use InvalidArgumentException;
/**
* Simple semver version handling.
*/
class Semver {
/**
* Parse a semver version.
*
* @param string $version Version.
* @return array With components:
* - major: (int) Major version.
* - minor: (int) Minor version.
* - patch: (int) Patch version.
* - version: (string) Major.minor.patch.
* - prerelease: (string|null) Pre-release string.
* - buildinfo: (string|null) Build metadata string.
* @throws InvalidArgumentException If the version number is not in a recognized format.
*/
public static function parse( $version ) {
// This is slightly looser than the official version from semver.org, in that leading zeros are allowed.
if ( ! preg_match( '/^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<prerelease>(?:[0-9a-zA-Z-]+)(?:\.(?:[0-9a-zA-Z-]+))*))?(?:\+(?P<buildinfo>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/', $version, $m ) ) {
throw new InvalidArgumentException( "Version number \"$version\" is not in a recognized format." );
}
$info = array(
'major' => (int) $m['major'],
'minor' => (int) $m['minor'],
'patch' => (int) $m['patch'],
'version' => sprintf( '%d.%d.%d', $m['major'], $m['minor'], $m['patch'] ),
'prerelease' => isset( $m['prerelease'] ) && '' !== $m['prerelease'] ? $m['prerelease'] : null,
'buildinfo' => isset( $m['buildinfo'] ) && '' !== $m['buildinfo'] ? $m['buildinfo'] : null,
);
if ( null !== $info['prerelease'] ) {
$sep = '';
$prerelease = '';
foreach ( explode( '.', $info['prerelease'] ) as $part ) {
if ( ctype_digit( $part ) ) {
$part = (int) $part;
}
$prerelease .= $sep . $part;
$sep = '.';
}
$info['prerelease'] = $prerelease;
}
return $info;
}
/**
* Compare two version numbers.
*
* @param string $a First version.
* @param string $b Second version.
* @return int Less than, equal to, or greater than 0 depending on whether `$a` is less than, equal to, or greater than `$b`.
* @throws InvalidArgumentException If the version numbers are not in a recognized format.
*/
public static function compare( $a, $b ) {
$aa = self::parse( $a );
$bb = self::parse( $b );
if ( $aa['major'] !== $bb['major'] ) {
return $aa['major'] - $bb['major'];
}
if ( $aa['minor'] !== $bb['minor'] ) {
return $aa['minor'] - $bb['minor'];
}
if ( $aa['patch'] !== $bb['patch'] ) {
return $aa['patch'] - $bb['patch'];
}
if ( null === $aa['prerelease'] ) {
return null === $bb['prerelease'] ? 0 : 1;
}
if ( null === $bb['prerelease'] ) {
return -1;
}
$aaa = explode( '.', $aa['prerelease'] );
$bbb = explode( '.', $bb['prerelease'] );
$al = count( $aaa );
$bl = count( $bbb );
for ( $i = 0; $i < $al && $i < $bl; $i++ ) {
$a = $aaa[ $i ];
$b = $bbb[ $i ];
if ( ctype_digit( $a ) ) {
if ( ctype_digit( $b ) ) {
if ( (int) $a !== (int) $b ) {
return (int) $a - (int) $b;
}
} else {
return -1;
}
} elseif ( ctype_digit( $b ) ) {
return 1;
} else {
$tmp = strcmp( $a, $b );
if ( 0 !== $tmp ) {
return $tmp;
}
}
}
return $al - $bl;
}
}

View File

@ -0,0 +1,76 @@
const i18n = require( '@wordpress/i18n' );
const { default: md5 } = require( 'md5-es' );
const locationMap = {
plugin: 'plugins/',
theme: 'themes/',
core: '',
};
const hasOwn = ( obj, prop ) => Object.prototype.hasOwnProperty.call( obj, prop );
module.exports = {
state: {
baseUrl: null,
locale: null,
domainMap: {},
domainPaths: {},
},
/**
* Download and register translations for a bundle.
*
* @param {string} path - Bundle path being fetched. May have a query part.
* @param {string} domain - Text domain to register into.
* @param {string} location - Location for the translation: 'plugin', 'theme', or 'core'.
* @return {Promise} Resolved when the translations are registered, or rejected with an `Error`.
*/
async downloadI18n( path, domain, location ) {
const state = this.state;
if ( ! state || typeof state.baseUrl !== 'string' ) {
throw new Error( 'wp.jpI18nLoader.state is not set' );
}
// "en_US" is the default, no translations are needed.
if ( state.locale === 'en_US' ) {
return;
}
// Check that fetch is available.
if ( typeof fetch === 'undefined' ) {
throw new Error( 'Fetch API is not available.' );
}
// Extract any query part and hash the script name like WordPress does.
const pathPrefix = hasOwn( state.domainPaths, domain ) ? state.domainPaths[ domain ] : '';
let hash, query;
const i = path.indexOf( '?' );
if ( i >= 0 ) {
hash = md5.hash( pathPrefix + path.substring( 0, i ) );
query = path.substring( i );
} else {
hash = md5.hash( pathPrefix + path );
query = '';
}
// Download.
const locationAndDomain = hasOwn( state.domainMap, domain )
? state.domainMap[ domain ]
: locationMap[ location ] + domain;
const res = await fetch(
// prettier-ignore
`${ state.baseUrl }${ locationAndDomain }-${ state.locale }-${ hash }.json${ query }`
);
if ( ! res.ok ) {
throw new Error( `HTTP request failed: ${ res.status } ${ res.statusText }` );
}
const data = await res.json();
// Extract the messages from the file and register them.
const localeData = hasOwn( data.locale_data, domain )
? data.locale_data[ domain ]
: data.locale_data.messages;
localeData[ '' ].domain = domain;
i18n.setLocaleData( localeData, domain );
},
};

View File

@ -0,0 +1 @@
export * from '@automattic/jetpack-script-data';

View File

@ -0,0 +1,51 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.7] - 2024-08-26
### Changed
- Updated package dependencies. [#39004]
## [0.2.6] - 2024-04-08
### Changed
- Internal updates.
## [0.2.5] - 2024-03-25
### Fixed
- Backup: change some error messages to not trigger security scanners [#36496]
## [0.2.4] - 2024-03-18
### Changed
- Internal updates.
## [0.2.3] - 2024-03-14
### Changed
- Internal updates.
## [0.2.2] - 2024-02-27
### Added
- Increasing backup version for new endpoint [#35649]
## [0.2.1] - 2024-02-08
### Fixed
- Write helper script to ABSPATH by default, just like we did before [#35508]
## [0.2.0] - 2024-01-04
### Fixed
- Backup: Add namespace versioning to Helper_Script_Manager and other classes. [#34739]
## 0.1.0 - 2023-12-13
### Fixed
- Initial release (improved helper script installer logging). [#34297]
[0.2.7]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.6...v0.2.7
[0.2.6]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.5...v0.2.6
[0.2.5]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v0.1.0...v0.2.0

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,51 @@
{
"name": "automattic/jetpack-backup-helper-script-manager",
"description": "Install / delete helper script for backup and transport server. Not visible to site owners.",
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0"
},
"require-dev": {
"yoast/phpunit-polyfills": "^1.1.1",
"automattic/jetpack-changelogger": "^4.2.6",
"automattic/wordbless": "@dev"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
},
"autoload": {
"classmap": [
"src/"
]
},
"scripts": {
"phpunit": [
"./vendor/phpunit/phpunit/phpunit --colors=always"
],
"test-php": [
"@composer phpunit"
],
"post-install-cmd": "WorDBless\\Composer\\InstallDropin::copy",
"post-update-cmd": "WorDBless\\Composer\\InstallDropin::copy"
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"autotagger": true,
"mirror-repo": "Automattic/jetpack-backup-helper-script-manager",
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-backup-helper-script-manager/compare/v${old}...v${new}"
},
"branch-alias": {
"dev-trunk": "0.2.x-dev"
}
},
"config": {
"allow-plugins": {
"roots/wordpress-core-installer": true,
"automattic/jetpack-autoloader": true,
"automattic/jetpack-composer-plugin": true
}
}
}

View File

@ -0,0 +1,620 @@
<?php
/**
* The Jetpack Backup Helper Script Manager class (implementation).
*
* @package automattic/jetpack-backup
*/
// After changing this file, consider increasing the version number ("VXXX") in all the files using this namespace, in
// order to ensure that the specific version of this file always get loaded. Otherwise, Jetpack autoloader might decide
// to load an older/newer version of the class (if, for example, both the standalone and bundled versions of the plugin
// are installed, or in some other cases).
namespace Automattic\Jetpack\Backup\V0004;
use Exception;
use WP_Error;
use function content_url;
use function get_site_url;
use function is_wp_error;
use function set_url_scheme;
use function trailingslashit;
use function wp_generate_password;
use function wp_http_validate_url;
use function wp_schedule_single_event;
use function wp_upload_dir;
use const ABSPATH;
use const WP_CONTENT_DIR;
/**
* Manage installation, deletion and cleanup of Helper Scripts to assist with backing up Jetpack Sites.
*
* Does *not* use WP_Filesystem, because if there are permissions issues between the webserver's user and the FTP/SSH
* user, then we'll just install the helper script and do a backup/restore using FTP/SSH credentials (that we collect
* ourselves), without using WP_Filesystem in any way.
*
* Also, if we can't write that helper script somewhere (due to writes being inaccessible to the webserver's user, or
* for other reasons), we want to know about it (in the form of an error response), instead of having that helper
* script silently uploaded via FTP/SFTP, so that we could fall back to a backup/restore using credentials.
*
* Lastly, PHP provides us with better error reporting than WP_Filesystem.
*/
class Helper_Script_Manager_Impl {
/**
* Name of a directory that will be created for storing the helper script.
*/
const TEMP_DIRECTORY = 'jetpack-temp';
/**
* How long until the helper script will "expire" and refuse taking requests, in seconds.
*/
const EXPIRY_TIME = 60 * 60 * 8;
/**
* Maximum size of the helper script, in bytes.
*/
const MAX_FILESIZE = 1024 * 1024;
/**
* Associative array of possible places to install a jetpack-temp directory, along with the URL to access each.
*
* Keys specify the full path of install locations, and values point to the equivalent URL.
*
* If null, then install locations will be determined dynamically at the point of an install.
*
* @var array|null
*/
protected $custom_install_locations;
/**
* Filenames to ignore in scandir()'s return value.
*
* @var string[]
*/
protected $scandir_ignored_names = array( '.', '..' );
/**
* Header that the helper script is expected to start with.
*/
const HELPER_HEADER = "<?php /* Jetpack Backup Helper Script */\n";
/**
* Lines that will be written to README in the helper directory.
*/
const README_LINES = array(
'These files have been put on your server by Jetpack to assist with backups, restores, and scans of your ' .
'site content. They are cleaned up automatically when we no longer need them.',
'If you no longer have Jetpack connected to your site, you can delete them manually.',
'If you have questions or need assistance, please contact Jetpack Support at https://jetpack.com/support/',
'If you like to build amazing things with WordPress, you should visit automattic.com/jobs and apply to join ' .
'the fun mention this file when you apply!',
);
/**
* Data that will be written to index.php in the helper directory.
*/
const INDEX_FILE = '<?php // Silence is golden';
/**
* Create Helper Script Manager.
*
* @param array|null $custom_install_locations Associative array of possible places to install a jetpack-temp
* directory, along with the URL to access each.
*/
public function __construct( $custom_install_locations = null ) {
$this->custom_install_locations = $custom_install_locations;
}
/**
* Get either the default install locations, or the ones configured in the constructor.
*
* Has to be done late, i.e. can't be done in constructor, because in __construct() not all constants / functions
* might be available.
*
* @return array<string, string|WP_Error> Array with keys specifying the full path of install locations, and values
* either pointing to the equivalent URL, or being WP_Error if a specific path is not accessible.
*/
public function install_locations() {
if ( $this->custom_install_locations !== null ) {
return $this->custom_install_locations;
}
$abspath_url = get_site_url();
$locations = array();
// Prioritize ABSPATH first, because even though ABSPATH constant's value might be weird sometimes, it's the
// path where the PHP scripts will be most likely be able to get executed.
try {
if ( Throw_On_Errors::t_is_dir( ABSPATH ) ) {
$abspath_dir = Throw_On_Errors::t_realpath( ABSPATH );
$locations[ $abspath_dir ] = $abspath_url;
}
} catch ( Exception $exception ) {
$locations[ ABSPATH ] = new WP_Error(
'abspath_missing',
'Unable to access WordPress root "' . ABSPATH . '": ' . $exception->getMessage(),
array( 'status' => 500 )
);
}
try {
if ( Throw_On_Errors::t_is_dir( WP_CONTENT_DIR ) ) {
$wp_content_dir = Throw_On_Errors::t_realpath( WP_CONTENT_DIR );
// Using content_url() instead of WP_CONTENT_URL as it tests for whether we're using SSL.
$wp_content_url = content_url();
// I think we mess up the order in which we load things somewhere in a test, so "wp-content" and
// "wp-content/uploads/" URLs don't actually have the scheme+host part in them.
if ( ! wp_http_validate_url( $wp_content_url ) ) {
$wp_content_url = $abspath_url . $wp_content_url;
}
$locations[ $wp_content_dir ] = $wp_content_url;
}
} catch ( Exception $exception ) {
$locations[ WP_CONTENT_DIR ] = new WP_Error(
'content_path_missing',
'Unable to access content path "' . WP_CONTENT_DIR . '"' . $exception->getMessage(),
array( 'status' => 500 )
);
}
$upload_dir_info = wp_upload_dir();
$wp_uploads_dir = $upload_dir_info['basedir'];
try {
if ( Throw_On_Errors::t_is_dir( $wp_uploads_dir ) ) {
$wp_uploads_dir = Throw_On_Errors::t_realpath( $wp_uploads_dir );
$wp_uploads_url = $upload_dir_info['baseurl'];
// wp_upload_dir() doesn't check for whether we're using SSL:
//
// https://core.trac.wordpress.org/ticket/25449
//
// so set the scheme manually.
$wp_uploads_url = set_url_scheme( $wp_uploads_url );
if ( ! wp_http_validate_url( $wp_uploads_url ) ) {
$wp_uploads_url = $abspath_url . $wp_uploads_url;
}
$locations[ $wp_uploads_dir ] = $wp_uploads_url;
}
} catch ( Exception $exception ) {
$locations[ $wp_uploads_dir ] = new WP_Error(
'uploads_path_missing',
'Unable to access uploads path "' . $wp_uploads_dir . '"' . $exception->getMessage(),
array( 'status' => 500 )
);
}
return $locations;
}
/**
* Installs a Helper Script, and returns its filesystem path and access url.
*
* @param string $script_body Helper Script file contents.
*
* @return array|WP_Error Either an array containing the filesystem path ("path"), the URL ("url") of the helper
* script, and the WordPress root ("abspath"), or an instance of WP_Error.
*/
public function install_helper_script( $script_body ) {
// Check that the script body contains the correct header.
$actual_header = static::string_starts_with_substring( $script_body, static::HELPER_HEADER );
if ( true !== $actual_header ) {
return new WP_Error(
'bad_header',
'Bad helper script header: 0x' . bin2hex( $actual_header ),
array( 'status' => 400 )
);
}
// Refuse to install a Helper Script that is too large.
$helper_script_size = strlen( $script_body );
if ( $helper_script_size > static::MAX_FILESIZE ) {
return new WP_Error(
'too_big',
"Helper script is bigger ($helper_script_size bytes) " .
'than the max. size (' . static::MAX_FILESIZE . ' bytes)',
array( 'status' => 413 )
);
}
// Replace '[wp_path]' in the Helper Script with the WordPress installation location. Allows the Helper Script
// to find WordPress.
$wp_path_marker = '[wp_path]';
try {
$normalized_abspath = addslashes( Throw_On_Errors::t_realpath( ABSPATH ) );
} catch ( Exception $exception ) {
return new WP_Error(
'abspath_missing',
'Error while resolving ABSPATH "' . ABSPATH . '": ' . $exception->getMessage(),
array( 'status' => 500 )
);
}
$script_body = str_replace(
$wp_path_marker,
$normalized_abspath,
$script_body,
$wp_path_marker_replacement_count
);
if ( 0 === $wp_path_marker_replacement_count ) {
return new WP_Error(
'no_wp_path_marker',
"Helper script does not have the '$wp_path_marker' marker",
array( 'status' => 400 )
);
}
$failure_paths_and_reasons = array();
foreach ( $this->install_locations() as $directory => $url ) {
if ( is_wp_error( $url ) ) {
$failure_paths_and_reasons[] = "directory '$directory': " . $url->get_error_message();
continue;
}
try {
$installed = $this->install_to_location_or_throw( $script_body, $directory, $url );
// Always schedule a cleanup run shortly after EXPIRY_TIME.
wp_schedule_single_event(
time() + static::EXPIRY_TIME + 60,
'jetpack_backup_cleanup_helper_scripts'
);
return array(
'path' => $installed['path'],
'url' => $installed['url'],
'abspath' => Throw_On_Errors::t_realpath( ABSPATH ),
);
} catch ( Exception $exception ) {
$failure_paths_and_reasons[] = "directory '$directory' (URL '$url'): " . $exception->getMessage();
}
}
return new WP_Error(
'all_locations_failed',
'Unable to write the helper script to any install locations; ' .
'tried: ' . implode( ';', $failure_paths_and_reasons ),
array( 'status' => 500 )
);
}
/**
* Install helper script to a directory, or throw an exception.
*
* @param string $script_body Helper script's body.
* @param string $directory Candidate directory to create "jetpack-temp" in and write the helper script.
* @param string $url Base URL that the files in a directory are expected to be available at.
*
* @return string[] Array with "path" (location to the installed helper script) and "url"
* (URL of the installed helper script) keys.
* @throws Exception On I/O errors.
*/
protected function install_to_location_or_throw( $script_body, $directory, $url ) {
if ( ! Throw_On_Errors::t_is_writable( $directory ) ) {
throw new Exception( "Directory '$directory' is not writable" );
}
$temp_dir = trailingslashit( $directory ) . static::TEMP_DIRECTORY;
if ( ! Throw_On_Errors::t_is_dir( $temp_dir ) ) {
Throw_On_Errors::t_mkdir( $temp_dir );
}
$readme_path = trailingslashit( $temp_dir ) . 'README';
Throw_On_Errors::t_file_put_contents( $readme_path, implode( "\n\n", static::README_LINES ) );
$index_path = trailingslashit( $temp_dir ) . 'index.php';
Throw_On_Errors::t_file_put_contents( $index_path, static::INDEX_FILE );
$file_key = wp_generate_password( 10, false );
$file_name = 'jp-helper-' . $file_key . '.php';
$file_path = trailingslashit( $temp_dir ) . $file_name;
// Very unlikely, but check nonetheless.
if ( Throw_On_Errors::t_file_exists( $file_path ) ) {
throw new Exception( "Helper script at '$file_path' already exists" );
}
Throw_On_Errors::t_file_put_contents( $file_path, $script_body );
return array(
'path' => $file_path,
'url' => trailingslashit( $url ) . trailingslashit( static::TEMP_DIRECTORY ) . $file_name,
);
}
/**
* Ensure that the helper script is gone (by deleting it, if needed).
*
* @param string $path Path to the helper script to delete.
*
* @return true|WP_Error True if the file helper script is gone (either it got deleted, or it was never there), or
* WP_Error instance on deletion failures.
*/
public function delete_helper_script( $path ) {
try {
$this->delete_helper_script_or_throw( $path );
} catch ( Exception $exception ) {
return new WP_Error(
'deletion_failure',
"Unable to delete helper script at '$path': " . $exception->getMessage(),
array( 'status' => 500 )
);
}
return true;
}
/**
* Ensure that the helper script is gone (by deleting it, if needed), throw an exception on errors.
*
* @param string $path Path to the helper script to delete.
*
* @return void
* @throws Exception On deletion failures.
*/
protected function delete_helper_script_or_throw( $path ) {
if ( ! Throw_On_Errors::t_file_exists( $path ) ) {
return;
}
if ( ! Throw_On_Errors::t_is_readable( $path ) ) {
throw new Exception( "File '$path' is not readable" );
}
if ( ! Throw_On_Errors::t_is_writable( $path ) ) {
throw new Exception( "File '$path' is not writable" );
}
$helper_script_size = Throw_On_Errors::t_filesize( $path );
// Check this file looks like a JPR helper script.
$helper_header_size = strlen( static::HELPER_HEADER );
if ( $helper_script_size < $helper_header_size ) {
throw new Exception(
"Helper script is smaller ($helper_script_size bytes) " .
"than the expected header ($helper_header_size bytes)"
);
}
if ( $helper_script_size > static::MAX_FILESIZE ) {
throw new Exception(
"Helper script is bigger ($helper_script_size bytes) " .
'than the max. size (' . static::MAX_FILESIZE . ' bytes)'
);
}
$actual_header = static::verify_file_header( $path, static::HELPER_HEADER );
if ( true !== $actual_header ) {
throw new Exception( 'Bad helper script header: 0x' . bin2hex( $actual_header ) );
}
Throw_On_Errors::t_unlink( $path );
$this->delete_helper_directory_if_empty( dirname( $path ) );
}
/**
* Search for Helper Scripts that are suspiciously old, and clean them out.
*
* @return true|WP_Error True if all expired helper scripts got cleaned up successfully, or an instance of
* WP_Error if one or more expired helper scripts didn't manage to get cleaned up.
*/
public function cleanup_expired_helper_scripts() {
try {
$this->cleanup_helper_scripts( time() - static::EXPIRY_TIME );
} catch ( Exception $exception ) {
return new WP_Error(
'cleanup_failed',
'Unable to clean up expired helper scripts: ' . $exception->getMessage(),
array( 'status' => 500 )
);
}
return true;
}
/**
* Search for and delete all Helper Scripts. Used during uninstallation.
*
* @return true|WP_Error True if all helper scripts got deleted successfully, or an instance of WP_Error if one or
* more helper scripts didn't manage to get deleted.
*/
public function delete_all_helper_scripts() {
try {
$this->cleanup_helper_scripts();
} catch ( Exception $exception ) {
return new WP_Error(
'cleanup_failed',
'Unable to clean up all helper scripts: ' . $exception->getMessage(),
array( 'status' => 500 )
);
}
return true;
}
/**
* Search for and delete Helper Scripts. If an $expiry_time is specified, only delete Helper Scripts
* with a mtime older than $expiry_time. Otherwise, delete them all.
*
* @param int|null $expiry_time If specified, only delete scripts older than this UNIX timestamp.
*
* @return void
* @throws Exception If one or more helper scripts doesn't manage to get cleaned up.
*/
protected function cleanup_helper_scripts( $expiry_time = null ) {
$error_messages = array();
foreach ( $this->install_locations() as $directory => $url ) {
if ( is_wp_error( $url ) ) {
$error_messages[] = $url->get_error_message();
continue;
}
$temp_dir = trailingslashit( trailingslashit( $directory ) . static::TEMP_DIRECTORY );
if ( Throw_On_Errors::t_is_dir( $temp_dir ) ) {
// Find expired helper scripts and delete them.
$temp_dir_contents = Throw_On_Errors::t_scandir( $temp_dir );
foreach ( $temp_dir_contents as $name ) {
if ( in_array( $name, $this->scandir_ignored_names, true ) ) {
continue;
}
$full_path = $temp_dir . $name;
$last_modified = Throw_On_Errors::t_filemtime( $full_path );
if ( preg_match( '/^jp-helper-.*\.php$/', $name ) ) {
if ( null === $expiry_time || $last_modified < $expiry_time ) {
try {
$this->delete_helper_script_or_throw( $full_path );
} catch ( Exception $exception ) {
$error_messages[] = $exception->getMessage();
}
}
}
}
// Delete the directory if it's empty now.
$this->delete_helper_directory_if_empty( $temp_dir );
}
}
if ( count( $error_messages ) > 0 ) {
throw new Exception(
'Unable to clean up one or more helper scripts: ' . implode( ';', $error_messages )
);
}
}
/**
* Delete a helper script directory if it's empty.
*
* @param string $dir Path to the helper script directory.
*
* @return bool True if the directory is missing, or was empty and got deleted; false if directory still contains
* something and wasn't deleted.
* @throws Exception On I/O errors.
*/
protected function delete_helper_directory_if_empty( $dir ) {
if ( ! Throw_On_Errors::t_is_dir( $dir ) ) {
return true;
}
// Check that the only remaining files are a README and index.php generated by this system.
$allowed_files_and_headers = array(
'README' => static::README_LINES[0],
'index.php' => static::INDEX_FILE,
);
$dir_contents = Throw_On_Errors::t_scandir( $dir );
if ( count( $dir_contents ) > count( $allowed_files_and_headers ) + count( $this->scandir_ignored_names ) ) {
return false;
}
foreach ( $dir_contents as $name ) {
if ( in_array( $name, $this->scandir_ignored_names, true ) ) {
continue;
}
$full_path = trailingslashit( $dir ) . $name;
if ( ! isset( $allowed_files_and_headers[ $name ] ) ) {
return false;
}
// Verify the file starts with the expected contents.
$actual_header = static::verify_file_header( $full_path, $allowed_files_and_headers[ $name ] );
if ( true !== $actual_header ) {
throw new Exception( "Bad header for file '$full_path': 0x" . bin2hex( $actual_header ) );
}
Throw_On_Errors::t_unlink( $full_path );
}
// If the directory is now empty, delete it.
$dir_contents_after_cleanup = Throw_On_Errors::t_scandir( $dir );
if ( count( $dir_contents_after_cleanup ) <= count( $this->scandir_ignored_names ) ) {
Throw_On_Errors::t_rmdir( $dir );
}
return true;
}
/**
* Test if string starts with a substring, and if it doesn't, return the actual prefix.
*
* @param string $string String to search in.
* @param string $expected_prefix Expected prefix.
*
* @return bool|string True if string starts with a substring, or the actual prefix that was found instead of the
* expected prefix.
*/
protected static function string_starts_with_substring( $string, $expected_prefix ) {
$actual_prefix = substr( $string, 0, strlen( $expected_prefix ) );
if ( $actual_prefix !== $expected_prefix ) {
return $actual_prefix;
}
return true;
}
/**
* Verify that a file exists, is readable, and has the expected header.
*
* @param string $path File to verify.
* @param string $expected_header Header that the file should have.
*
* @return bool|string True if header matches, or an actual header if it doesn't match.
* @throws Exception If the file doesn't exist, isn't readable, or is of the wrong size.
*/
protected static function verify_file_header( $path, $expected_header ) {
if ( ! Throw_On_Errors::t_file_exists( $path ) ) {
throw new Exception( "File '$path' does not exist" );
}
if ( ! Throw_On_Errors::t_is_readable( $path ) ) {
throw new Exception( "File '$path' is not readable" );
}
$file_size = Throw_On_Errors::t_filesize( $path );
// Check this file looks like a JPR helper script.
$expected_header_size = strlen( $expected_header );
if ( $file_size < $expected_header_size ) {
throw new Exception(
"File is smaller ($file_size bytes) " .
"than the expected header ($expected_header_size bytes)"
);
}
if ( $file_size > static::MAX_FILESIZE ) {
throw new Exception(
"File is bigger ($file_size bytes) " .
'than the max. size (' . static::MAX_FILESIZE . ' bytes)'
);
}
$file_contents = Throw_On_Errors::t_file_get_contents( $path );
return static::string_starts_with_substring( $file_contents, $expected_header );
}
}

View File

@ -0,0 +1,89 @@
<?php
/**
* Jetpack Backup Helper Script Manager class (static wrapper).
*
* @package automattic/jetpack-backup
*/
// After changing this file, consider increasing the version number ("VXXX") in all the files using this namespace, in
// order to ensure that the specific version of this file always get loaded. Otherwise, Jetpack autoloader might decide
// to load an older/newer version of the class (if, for example, both the standalone and bundled versions of the plugin
// are installed, or in some other cases).
namespace Automattic\Jetpack\Backup\V0004;
/**
* Manage installation, deletion and cleanup of Helper Scripts to assist with backing up Jetpack Sites.
*
* A static wrapper around an "implementation" class so that it gets autoloaded late, and we always get the latest
* version of the class instead of a random version of it:
*
* https://github.com/Automattic/jetpack/pull/34297#discussion_r1424227489
*/
class Helper_Script_Manager {
/**
* Instance of helper script manager implementation, or null if not initialized yet.
*
* @var Helper_Script_Manager_Impl|null
*/
protected static $impl = null;
/**
* Initialize an instance of helper script manager implementation (if needed).
*
* @return void
*/
protected static function initialize_impl_if_needed() {
if ( null === static::$impl ) {
static::$impl = new Helper_Script_Manager_Impl();
}
}
/**
* Install a Helper Script, and returns its filesystem path and access url.
*
* @param string $script_body Helper Script file contents.
*
* @return array|\WP_Error Either an array containing the filesystem path ("path"), the URL ("url") of the helper
* script, and the WordPress root ("abspath"), or an instance of WP_Error.
*/
public static function install_helper_script( $script_body ) {
static::initialize_impl_if_needed();
return static::$impl->install_helper_script( $script_body );
}
/**
* Ensure that the helper script is gone (by deleting it, if needed).
*
* @param string $path Path to the helper script to delete.
*
* @return true|\WP_Error True if the file helper script is gone (either it got deleted, or it was never there), or
* WP_Error instance on deletion failures.
*/
public static function delete_helper_script( $path ) {
static::initialize_impl_if_needed();
return static::$impl->delete_helper_script( $path );
}
/**
* Search for Helper Scripts that are suspiciously old, and clean them out.
*
* @return true|\WP_Error True if all expired helper scripts got cleaned up successfully, or an instance of
* WP_Error if one or more expired helper scripts didn't manage to get cleaned up.
*/
public static function cleanup_expired_helper_scripts() {
static::initialize_impl_if_needed();
return static::$impl->cleanup_expired_helper_scripts();
}
/**
* Search for and delete all Helper Scripts. Used during uninstallation.
*
* @return true|\WP_Error True if all helper scripts got deleted successfully, or an instance of WP_Error if one or
* more helper scripts didn't manage to get deleted.
*/
public static function delete_all_helper_scripts() {
static::initialize_impl_if_needed();
return static::$impl->delete_all_helper_scripts();
}
}

View File

@ -0,0 +1,498 @@
<?php // phpcs:disable Squiz.Commenting.FileComment.Missing
// phpcs:disable WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting
// phpcs:disable WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_error_reporting
// phpcs:disable WordPress.PHP.IniSet.display_errors_Disallowed
// After changing this file, consider increasing the version number ("VXXX") in all the files using this namespace, in
// order to ensure that the specific version of this file always get loaded. Otherwise, Jetpack autoloader might decide
// to load an older/newer version of the class (if, for example, both the standalone and bundled versions of the plugin
// are installed, or in some other cases).
namespace Automattic\Jetpack\Backup\V0004;
use Exception;
use Throwable;
/**
* Wrappers for functions which throw an exception on errors and warnings instead of silently continuing operation.
*
* PHP is pretty lax with error reporting when doing I/O operations, e.g. a typical I/O helper function returns false,
* null, and/or emits a warning, but the whole PHP application continues operation. It's for the caller of the I/O
* helper function to test the returned result of the function, and notice + act upon I/O errors.
*
* We really want to know about each and every I/O error. Therefore, this class provides wrappers for some common
* (mostly) I/O operations that throw an exception on errors instead of just returning false, null, or something else.
* This wrapper class treats warnings as errors too.
*
* Given that static method names are similar to the ones used by PHP, they're prefixed with "t_" to not erroneously
* trigger various security scanners.
*/
class Throw_On_Errors {
/**
* Execute a callable, throw an exception (together with a descriptive label) on PHP warnings / errors.
*
* @param callable $callable Callable to execute.
* @param string $label Label to add to the thrown exception to clarify what was attempted.
*
* @return mixed Callable's return value, if any.
* @throws Exception On warnings thrown by the callable.
* @noinspection PhpUnusedParameterInspection
*/
private static function throw_on_warnings( $callable, $label ) {
$old_error_reporting = error_reporting( - 1 );
$old_display_errors = ini_set( 'display_errors', 'stderr' );
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler
set_error_handler(
/**
* Temporary error handler.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.set-error-handler
* @see https://www.php.net/manual/en/function.set-error-handler.php
*
* @param int $errno Level of the error raised.
* @param string $errstr Error message.
* @param string|null $errfile Filename that the error was raised in.
* @param int|null $errline Line number where the error was raised.
* @param array|null $errcontext Deprecated, unused.
*
* @return never
* @throws Exception
*/
// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
function ( $errno, $errstr, $errfile = null, $errline = null, $errcontext = null ) {
throw new Exception( "$errstr (file: $errfile; line: $errline)" );
}
);
$result = null;
$error_message = null;
try {
$result = $callable();
} catch ( Throwable $throwable ) {
$error_message = $throwable->getMessage();
}
restore_error_handler();
ini_set( 'display_errors', $old_display_errors );
error_reporting( $old_error_reporting );
if ( $error_message !== null ) {
throw new Exception( "$label failed: $error_message" );
}
return $result;
}
/**
* Return canonicalized absolute pathname, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.realpath
* @see https://www.php.net/manual/en/function.realpath.php
*
* @param string $path Path being checked.
*
* @return string Canonicalized absolute pathname
* @throws Exception On invalid parameters, or if realpath() has returned false or thrown warnings.
*/
public static function t_realpath( $path ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $path ) {
throw new Exception( 'Filename for realpath() is unset' );
}
$label = "realpath( '$path' )";
$realpath_result = static::throw_on_warnings(
function () use ( $path ) {
return realpath( $path );
},
$label
);
if ( false === $realpath_result ) {
throw new Exception( "Unable to $label" );
}
return $realpath_result;
}
/**
* Check whether a file or directory exists, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.file-exists
* @see https://www.php.net/manual/en/function.file-exists.php
*
* @param string $filename Path to the file or directory.
*
* @return bool True if the file or directory specified by filename exists; false otherwise.
* @throws Exception On invalid parameters, or if file_exists() has thrown warnings.
*/
public static function t_file_exists( $filename ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for file_exists() is unset' );
}
return static::throw_on_warnings(
function () use ( $filename ) {
return file_exists( $filename );
},
"file_exists( '$filename' )"
);
}
/**
* Tell whether the filename (or a directory) is readable, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.is-readable
* @see https://www.php.net/manual/en/function.is-readable.php
*
* @param string $filename Filename (or directory) to check.
*
* @return bool True if the filename (or a directory) exists and is readable, false otherwise.
* @throws Exception On invalid parameters, or if is_readable() has thrown warnings.
*/
public static function t_is_readable( $filename ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for is_readable() is unset' );
}
return static::throw_on_warnings(
function () use ( $filename ) {
return is_readable( $filename );
},
"is_readable( '$filename' )"
);
}
/**
* Tell whether the filename (or a directory) is writable, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.is-writable
* @see https://www.php.net/manual/en/function.is-writable.php
*
* @param string $filename Filename (or directory) to check.
*
* @return bool True if the filename (or a directory) exists and is writable, false otherwise.
* @throws Exception On invalid parameters, or if is_writable() has thrown warnings.
*/
public static function t_is_writable( $filename ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for is_writable() is unset' );
}
return static::throw_on_warnings(
function () use ( $filename ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_is_writable
return is_writable( $filename );
},
"is_writable( '$filename' )"
);
}
/**
* Get file size, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.filesize
* @see https://www.php.net/manual/en/function.filesize.php
*
* @param string $filename Path to the file.
*
* @return int Size of the file in bytes
* @throws Exception On invalid parameters, or if filesize() has thrown warnings.
*/
public static function t_filesize( $filename ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for filesize() is unset' );
}
$label = "filesize( '$filename' )";
$filesize_result = static::throw_on_warnings(
function () use ( $filename ) {
return filesize( $filename );
},
$label
);
if ( false === $filesize_result ) {
throw new Exception( "Unable to $label" );
}
return $filesize_result;
}
/**
* Get file modification time, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.filemtime
* @see https://www.php.net/manual/en/function.filemtime.php
*
* @param string $filename Path to the file.
*
* @return int The time the file was last modified
* @throws Exception On invalid parameters, or if filemtime() has thrown warnings.
*/
public static function t_filemtime( $filename ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for filemtime() is unset' );
}
$label = "filemtime( '$filename' )";
$filemtime_result = static::throw_on_warnings(
function () use ( $filename ) {
return filemtime( $filename );
},
$label
);
if ( false === $filemtime_result ) {
throw new Exception( "Unable to $label" );
}
return $filemtime_result;
}
/**
* Tell whether the filename is a directory (follow symlinks), throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.is-dir
* @see https://www.php.net/manual/en/function.is-dir.php
*
* @param string $filename Path to the file.
*
* @return bool True if the filename (or the symlink's target) exists and is a directory, false otherwise.
* @throws Exception On invalid parameters, if is_dir() has thrown warnings, or has failed.
*/
public static function t_is_dir( $filename ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for is_dir() is unset' );
}
return static::throw_on_warnings(
function () use ( $filename ) {
return is_dir( $filename );
},
"is_dir( '$filename' )"
);
}
/**
* Make a directory, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.mkdir
* @see https://www.php.net/manual/en/function.mkdir.php
*
* @param string $directory Directory path.
* @param int $permissions Permissions of the newly created directory.
* @param bool $recursive If true, then any parent directories to the directory specified will also be created,
* with the same permissions.
*
* @return void
* @throws Exception On invalid parameters, if mkdir() has thrown warnings, or has failed.
*/
public static function t_mkdir( $directory, $permissions = 0777, $recursive = false ) {
// PHP 5.x won't complain about permissions being null, so let's do it ourselves.
if ( $permissions === null ) {
throw new Exception( 'Permissions for mkdir() are unset' );
}
$label = "mkdir( '$directory', 0" . decoct( $permissions ) . ', ' . ( $recursive ? 'true' : 'false' ) . ' )';
$mkdir_result = static::throw_on_warnings(
function () use ( $directory, $permissions, $recursive ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_mkdir
return mkdir( $directory, $permissions, $recursive );
},
$label
);
if ( false === $mkdir_result ) {
throw new Exception( "Unable to $label" );
}
}
/**
* List files and directories inside the specified path, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.scandir
* @see https://www.php.net/manual/en/function.scandir.php
*
* @param string $directory Directory that will be scanned.
*
* @return string An array of filenames.
* @throws Exception If scandir() has thrown warnings, or has failed.
*/
public static function t_scandir( $directory ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $directory ) {
throw new Exception( 'Directory for scandir() is unset' );
}
$label = "scandir( '$directory' )";
$scandir_result = static::throw_on_warnings(
function () use ( $directory ) {
return scandir( $directory );
},
$label
);
if ( false === $scandir_result ) {
throw new Exception( "Unable to $label" );
}
return $scandir_result;
}
/**
* Remove a directory, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.rmdir
* @see https://www.php.net/manual/en/function.rmdir.php
*
* @param string $directory Directory path.
*
* @return void
* @throws Exception On invalid parameters, if rmdir() has thrown warnings, or has failed.
*/
public static function t_rmdir( $directory ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $directory ) {
throw new Exception( 'Directory for mkdir() is unset' );
}
$label = "rmdir( '$directory' )";
$rmdir_result = static::throw_on_warnings(
function () use ( $directory ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir
return rmdir( $directory );
},
$label
);
if ( false === $rmdir_result ) {
throw new Exception( "Unable to $label" );
}
}
/**
* Delete a file, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.unlink
* @see https://www.php.net/manual/en/function.unlink.php
*
* @param string $filename Path to the file.
*
* @return void
* @throws Exception If unlink() has thrown warnings, or has failed.
*/
public static function t_unlink( $filename ) {
$label = "unlink( '$filename' )";
$unlink_result = static::throw_on_warnings(
function () use ( $filename ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink
return unlink( $filename );
},
$label
);
if ( false === $unlink_result ) {
throw new Exception( "Unable to $label" );
}
}
/**
* Write data to a file, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.file-put-contents
* @see https://www.php.net/manual/en/function.file-put-contents.php
*
* @param string $filename Path to the file where to write the data.
* @param string $data The data to write.
*
* @return void
* @throws Exception If file_put_contents() has thrown warnings, has failed, or if it didn't write all the bytes.
*/
public static function t_file_put_contents( $filename, $data ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for f_p_c() is unset' );
}
if ( $data === null ) {
throw new Exception( 'Data to write is null' );
}
$data_length = strlen( $data );
// Weird label is intentional, otherwise security scanners find this label suspicious.
$label = "f_p_c( '$filename', $data_length bytes of data )";
$number_of_bytes_written = static::throw_on_warnings(
function () use ( $filename, $data ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
return file_put_contents( $filename, $data );
},
$label
);
if ( false === $number_of_bytes_written ) {
throw new Exception( "Unable to $label" );
}
if ( $number_of_bytes_written !== $data_length ) {
throw new Exception(
"$label was expected to write $data_length bytes, but wrote $number_of_bytes_written bytes"
);
}
}
/**
* Read entire file into a string, throw on warnings / errors.
*
* @see https://php-legacy-docs.zend.com/manual/php5/en/function.file-get-contents
* @see https://www.php.net/manual/en/function.file-get-contents.php
*
* @param string $filename Name of the file to read.
*
* @return string The read data.
* @throws Exception If file_get_contents() has thrown warnings, or has failed.
*/
public static function t_file_get_contents( $filename ) {
// PHP 5.x won't complain about parameter being unset, so let's do it ourselves.
if ( ! $filename ) {
throw new Exception( 'Filename for f_g_c() is unset' );
}
// Weird label is intentional, otherwise security scanners find this label suspicious.
$label = "f_g_c( '$filename' )";
$fgc_result = static::throw_on_warnings(
function () use ( $filename ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
return file_get_contents( $filename );
},
$label
);
if ( false === $fgc_result ) {
throw new Exception( "Unable to $label" );
}
return $fgc_result;
}
}

View File

@ -0,0 +1,90 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.2.11] - 2024-09-05
### Changed
- Update dependencies.
## [0.2.10] - 2024-09-05
### Changed
- Update dependencies.
## [0.2.9] - 2024-08-26
### Changed
- Updated package dependencies. [#39004]
## [0.2.8] - 2024-08-15
### Fixed
- Fix incorrect next-version tokens in php `@since` and/or `@deprecated` docs. [#38869]
## [0.2.7] - 2024-05-06
### Added
- Add missing package dependencies. [#37141]
## [0.2.6] - 2024-03-25
### Changed
- Internal updates.
## [0.2.5] - 2024-03-14
### Changed
- Internal updates.
## [0.2.4] - 2024-01-25
### Fixed
- Chage get_client() visibility so that older versions of boost do not break. [#35240]
## [0.2.3] - 2024-01-22
### Added
- Send current boost version with API requests to handle requests accordingly [#35132]
### Changed
- Jetpack Boost: Use ARRAY_A when decoding from JSON [#35062]
## [0.2.2] - 2023-11-24
### Changed
- Replaced usage of strpos() with str_contains(). [#34137]
- Replaced usage of substr() with str_starts_with() and str_ends_with(). [#34207]
## [0.2.1] - 2023-11-21
### Fixed
- Made abstract static methods in `Automattic\Jetpack\Boost_Core\Lib\Cacheable` abstract, instead of being implemented to always throw. [#34220]
## [0.2.0] - 2023-11-20
### Changed
- Updated required PHP version to >= 7.0. [#34192]
## [0.1.3] - 2023-09-19
- Minor internal updates.
## [0.1.2] - 2023-09-01
### Fixed
- Fix showing default error message and code when parsing cloud response. [#32685]
## [0.1.1] - 2023-08-28
### Changed
- Updated package dependencies. [#32605]
## 0.1.0 - 2023-06-06
### Added
- Introduce new package. [#31163]
[0.2.11]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.10...v0.2.11
[0.2.10]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.9...v0.2.10
[0.2.9]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.8...v0.2.9
[0.2.8]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.7...v0.2.8
[0.2.7]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.6...v0.2.7
[0.2.6]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.5...v0.2.6
[0.2.5]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/Automattic/jetpack-boost-core/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/Automattic/jetpack-boost-core/compare/v0.1.3...v0.2.0
[0.1.3]: https://github.com/Automattic/jetpack-boost-core/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/Automattic/jetpack-boost-core/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/Automattic/jetpack-boost-core/compare/v0.1.0...v0.1.1

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,53 @@
{
"name": "automattic/jetpack-boost-core",
"description": "Core functionality for boost and relevant packages to depend on",
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0",
"automattic/jetpack-connection": "^4.0.0"
},
"require-dev": {
"yoast/phpunit-polyfills": "^1.1.1",
"automattic/jetpack-changelogger": "^4.2.6",
"automattic/wordbless": "dev-master"
},
"autoload": {
"classmap": [
"src/"
]
},
"scripts": {
"phpunit": [
"./vendor/phpunit/phpunit/phpunit --colors=always"
],
"test-php": [
"@composer phpunit"
],
"build-production": "echo 'Add your build step to composer.json, please!'",
"build-development": "echo 'Add your build step to composer.json, please!'",
"post-install-cmd": "WorDBless\\Composer\\InstallDropin::copy",
"post-update-cmd": "WorDBless\\Composer\\InstallDropin::copy"
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
"allow-plugins": {
"roots/wordpress-core-installer": true
}
},
"extra": {
"mirror-repo": "Automattic/jetpack-boost-core",
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-boost-core/compare/v${old}...v${new}"
},
"autotagger": true,
"branch-alias": {
"dev-trunk": "0.2.x-dev"
},
"textdomain": "jetpack-boost-core"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
}
}

View File

@ -0,0 +1,34 @@
<?php
/**
* Boost API Client interface.
*
* @package automattic/jetpack-boost-core
*/
namespace Automattic\Jetpack\Boost_Core\Contracts;
/**
* An interface to build Boost API client.
*
* Communication with Boost back-end should be done through this interface.
*/
interface Boost_API_Client {
/**
* Submit a request to boost API and return response.
*
* @param string $path - Request path.
* @param mixed[] $payload - Request arguments.
* @return mixed
*/
public function post( $path, $payload = array() );
/**
* Make a get request to boost API and return response.
*
* @param string $path - Request path.
* @param mixed[] $query - Query parameters.
* @return mixed
*/
public function get( $path, $query = array() );
}

View File

@ -0,0 +1,110 @@
<?php
/**
* A helper class to help with Boost API interactions.
*
* @package automattic/jetpack-boost-core
*/
namespace Automattic\Jetpack\Boost_Core\Lib;
use Automattic\Jetpack\Boost_Core\Contracts\Boost_API_Client;
/**
* A class that handles the Boost API client.
*
* The communication to the backend is done using this class on top of the Boost_API_Client interface.
*/
class Boost_API {
/**
* The API client instance.
*
* @var Boost_API_Client
*/
private static $api_client;
/**
* Get the API client instance.
*
* @return Boost_API_Client
* @deprecated 3.1.1 Use get(), and post() directly instead.
*/
public static function get_client() {
return self::get_api_client();
}
/**
* Instantiate the API client.
*
* @return Boost_API_Client
*/
private static function get_api_client() {
if ( ! self::$api_client ) {
$class = apply_filters( 'jetpack_boost_api_client_class', WPCOM_Boost_API_Client::class );
self::$api_client = new $class();
}
return self::$api_client;
}
/**
* Make a get request to boost API and return response.
*
* @param string $path - Request path.
* @param mixed[] $query - Query parameters.
* @param mixed[] $args - Request arguments.
* @return array|\WP_Error
*/
public static function get( $path, $query = array(), $args = null ) {
return self::get_api_client()->get( $path, $query, self::merge_args( $args ) );
}
/**
* Submit a request to boost API and return response.
*
* @param string $path - Request path.
* @param mixed[] $payload - Request arguments.
* @param mixed[] $args - Request arguments.
* @return mixed
*/
public static function post( $path, $payload = array(), $args = null ) {
return self::get_api_client()->post( $path, $payload, self::merge_args( $args ) );
}
/**
* Merge the arguments with the defaults.
*
* @param mixed[] $args - Provided arguments.
* @return mixed[]
*/
private static function merge_args( $args ) {
if ( ! is_array( $args ) ) {
$args = wp_parse_args(
$args,
array(
'headers' => self::default_headers(),
)
);
} else {
$args['headers'] = wp_parse_args( $args['headers'] ?? array(), self::default_headers() );
}
return $args;
}
/**
* Get the default headers to include with each request.
*
* @return string[]
*/
public static function default_headers() {
$headers = array(
'Content-Type' => 'application/json; charset=utf-8',
);
if ( defined( 'JETPACK_BOOST_VERSION' ) ) {
$headers['X-Jetpack-Boost-Version'] = JETPACK_BOOST_VERSION;
}
return $headers;
}
}

View File

@ -0,0 +1,134 @@
<?php
/**
* Base abstract class for cacheable value objects.
*
* @package automattic/jetpack-boost-core
*/
namespace Automattic\Jetpack\Boost_Core\Lib;
/**
* Class Cacheable.
*/
abstract class Cacheable implements \JsonSerializable {
/**
* Default cache expiry.
*/
const DEFAULT_EXPIRY = 300; // 5 minutes.
/**
* The ID of this object, if cached as a transient.
*
* @var string|null $cache_id Cache id.
*/
private $cache_id;
/**
* Store the object.
*
* @param int $expiry Expiry in seconds.
*
* @return mixed|void
*/
public function store( $expiry = self::DEFAULT_EXPIRY ) {
if ( ! $this->cache_id ) {
$this->cache_id = $this->generate_cache_id();
}
Transient::set(
static::cache_prefix() . $this->cache_id,
$this->jsonSerialize(),
$expiry
);
return $this->cache_id;
}
/**
* Default implementation for generating cache key. Generates a random ASCII string.
*/
protected function generate_cache_id() {
return wp_generate_password( 20, false );
}
/**
* This is intended to be the reverse of JsonSerializable->jsonSerialize.
*
* @param array $data Serialized data to restore the object from.
*
* @throws \Exception Throw an exception to remind to implement the method in child classes.
*/
abstract public static function jsonUnserialize( $data );
/**
* Fetch an object with the given ID.
*
* @param string $id The object ID.
*
* @return null|mixed
*/
public static function get( $id ) {
$data = Transient::get( static::cache_prefix() . $id, false );
if ( ! $data ) {
return null;
}
$class = get_called_class();
$object = $class::jsonUnserialize( $data, $id );
if ( $object ) {
$object->set_cache_id( $id );
}
return $object;
}
/**
* Set cache id.
*
* This is here so we know how this object was loaded.
*
* @param string $cache_id Cache id.
*/
public function set_cache_id( $cache_id ) {
$this->cache_id = $cache_id;
}
/**
* Getter for the cache ID.
*
* @return string
*/
public function get_cache_id() {
return $this->cache_id;
}
/**
* Delete the cache entry.
*/
public function delete() {
$this->cache_id && static::delete_by_cache_id( $this->cache_id );
}
/**
* Delete all currently cached entries.
*/
public static function clear_cache() {
Transient::delete_by_prefix( static::cache_prefix() );
}
/**
* Delete the cache entry for the given cache id.
*
* @param string $cache_id The cache ID.
*/
public static function delete_by_cache_id( $cache_id ) {
Transient::delete( static::cache_prefix() . $cache_id );
}
/**
* Returns the cache prefix
*
* @throws \Exception Throw an exception to remind to implement the method in child classes.
*/
abstract protected static function cache_prefix();
}

View File

@ -0,0 +1,122 @@
<?php
/**
* Transients for Jetpack Boost.
*
* @package automattic/jetpack-boost-core
*/
namespace Automattic\Jetpack\Boost_Core\Lib;
/**
* Class Transient
*/
class Transient {
const OPTION_PREFIX = 'jb_transient_';
/**
* Get the key with prefix.
*
* @param string $key the key to be prefixed.
*/
public static function key( $key ) {
return static::OPTION_PREFIX . $key;
}
/**
* Updates a cache entry. Creates the cache entry if it doesn't exist.
*
* @param string $key Cache key name.
* @param mixed $value Cache value.
* @param int $expiry Cache expiration in seconds.
*
* @return void
*/
public static function set( $key, $value, $expiry = 0 ) {
if ( 0 === $expiry ) {
$expiry = YEAR_IN_SECONDS;
}
$data = array(
'expire' => time() + $expiry,
'data' => $value,
);
update_option( self::key( $key ), $data, false );
}
/**
* Gets a cache entry.
*
* @param string $key Cache key name.
* @param mixed $default Default value.
*
* @return mixed
*/
public static function get( $key, $default = null ) {
// Ensure everything's there.
$option = get_option( self::key( $key ), $default );
if ( $default === $option || ! isset( $option['expire'] ) || ! isset( $option['data'] )
) {
return $default;
}
// Maybe expire the result instead of returning it.
$expire = $option['expire'];
$data = $option['data'];
if ( false !== $expire && $expire < time() ) {
self::delete( $key );
return $default;
}
return $data;
}
/**
* Delete all `Transient` values with certain prefix from database.
*
* @param string $prefix Cache key prefix.
*/
public static function delete_by_prefix( $prefix ) {
global $wpdb;
/**
* The prefix used in option_name.
*/
$option_prefix = static::key( $prefix );
/**
* LIKE search pattern for the delete query.
*/
$prefix_search_pattern = $wpdb->esc_like( $option_prefix ) . '%';
//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
$option_names = $wpdb->get_col(
$wpdb->prepare(
"
SELECT option_name
FROM $wpdb->options
WHERE `option_name` LIKE %s
",
$prefix_search_pattern
)
);
// phpcs:enable
// Go through each option individually to ensure caches are handled properly.
foreach ( $option_names as $option_name ) {
delete_option( $option_name );
}
}
/**
* Delete a cache entry.
*
* @param string $key Cache key name.
*
* @return void
*/
public static function delete( $key ) {
delete_option( self::key( $key ) );
}
}

View File

@ -0,0 +1,96 @@
<?php
/**
* Implement the URL normalizer.
*
* @package automattic/jetpack-boost-core
*/
namespace Automattic\Jetpack\Boost_Core\Lib;
/**
* Class Url
*/
class Url {
const PARAMS_TO_EXCLUDE = array( 'utm_campaign', 'utm_medium', 'utm_source', 'utm_content', 'fbclid', '_ga', 'jb-disable-modules' );
const PARAMS_TO_NORMALIZE = array( 's' => '' );
/**
* Normalize a URL - right now, just make sure it's absolute.
*
* @param string $url The URL.
*
* @return string
*/
public static function normalize( $url ) {
$url = self::normalize_query_args( $url );
if ( '/' === $url[0] ) {
$url = site_url( $url );
}
return rtrim( $url, '/' );
}
/**
* Returns the current URL.
*
* @return string
*/
public static function get_current_url() {
// Fallback to the site URL if we're unable to determine the URL from $_SERVER global.
$current_url = site_url();
if ( isset( $_SERVER ) && is_array( $_SERVER ) ) {
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitization happens at the end
$scheme = isset( $_SERVER['HTTPS'] ) && 'on' === $_SERVER['HTTPS'] ? 'https' : 'http';
$host = ! empty( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : null;
$path = ! empty( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
// Support for local plugin development and testing using ngrok.
if ( ! empty( $_SERVER['HTTP_X_ORIGINAL_HOST'] ) && str_contains( $_SERVER['HTTP_X_ORIGINAL_HOST'], 'ngrok.io' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- This is validating.
$host = wp_unslash( $_SERVER['HTTP_X_ORIGINAL_HOST'] );
}
// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( $host ) {
$current_url = esc_url_raw( sprintf( '%s://%s%s', $scheme, $host, $path ) );
}
}
return apply_filters( 'jetpack_boost_current_url', $current_url );
}
/**
* Remove and reorder query parameters.
*
* @param string $url URL.
*
* @return string
*/
protected static function normalize_query_args( $url ) {
$exclude_parameters = apply_filters(
'jetpack_boost_excluded_query_parameters',
self::PARAMS_TO_EXCLUDE
);
// Filter out certain parameters that we know don't constitute a different page.
$url = remove_query_arg( $exclude_parameters, $url );
// Extract the query string, sort it and replace it in the current URL.
$parsed_url = wp_parse_url( $url );
if ( ! empty( $parsed_url['query'] ) ) {
parse_str( $parsed_url['query'], $args );
foreach ( self::PARAMS_TO_NORMALIZE as $key => $value ) {
if ( isset( $args[ $key ] ) ) {
$args[ $key ] = $value;
}
}
ksort( $args );
$sorted_query = http_build_query( $args );
$url = str_replace( '?' . $parsed_url['query'], '?' . $sorted_query, $url );
}
return $url;
}
}

View File

@ -0,0 +1,145 @@
<?php
/**
* Utility class.
*
* @package automattic/jetpack-boost-core
*/
namespace Automattic\Jetpack\Boost_Core\Lib;
use Automattic\Jetpack\Connection\Client;
/**
* Class Utils
*/
class Utils {
/**
* Standardize error format.
*
* @param mixed $error Error.
*
* @return array
*/
public static function standardize_error( $error ) {
if ( is_wp_error( $error ) ) {
return array(
'name' => $error->get_error_code(),
'message' => $error->get_error_message(),
);
}
if ( is_string( $error ) ) {
return array(
'name' => 'Error',
'message' => $error,
);
}
if ( is_object( $error ) ) {
return array(
'name' => 'Error',
'message' => json_decode( wp_json_encode( $error ), ARRAY_A ),
);
}
return $error;
}
/**
* Convert relative url to absolute.
*
* @param string $url The URL.
*
* @return string
*/
public static function force_url_to_absolute( $url ) {
if ( str_starts_with( $url, '/' ) ) {
return get_site_url( null, $url );
}
return $url;
}
/**
* Given a post type, look up its label (if available). Returns
* raw post type string if not found.
*
* @param string $post_type Post type to look up.
*
* @return string
*/
public static function get_post_type_label( $post_type ) {
$post_type_object = get_post_type_object( $post_type );
if ( ! $post_type_object ) {
return $post_type;
}
return $post_type_object->labels->name;
}
/**
* Given a taxonomy name, look up its label. Returns raw taxonomy name if
* not found.
*
* @param string $taxonomy_name Taxonomy to look up.
*
* @return string
*/
public static function get_taxonomy_label( $taxonomy_name ) {
$taxonomy = get_taxonomy( $taxonomy_name );
if ( ! $taxonomy ) {
return $taxonomy_name;
}
return $taxonomy->label;
}
/**
* Make a Jetpack-authenticated request to the WPCOM servers
*
* @param string $method Request method.
* @param string $endpoint Endpoint to contact.
* @param array $args Request args.
* @param array $body Request body.
*
* @return \WP_Error|array
*/
public static function send_wpcom_request( $method, $endpoint, $args = null, $body = null ) {
$default_args = array(
'method' => $method,
'headers' => array( 'Content-Type' => 'application/json; charset=utf-8' ),
);
$response = Client::wpcom_json_api_request_as_blog(
$endpoint,
'2',
array_merge( $default_args, empty( $args ) ? array() : $args ),
empty( $body ) ? null : wp_json_encode( $body ),
'wpcom'
);
if ( is_wp_error( $response ) ) {
return $response;
}
// Check for HTTP errors.
$code = wp_remote_retrieve_response_code( $response );
$data = json_decode( wp_remote_retrieve_body( $response ), ARRAY_A );
if ( 200 !== $code ) {
$default_message = sprintf(
/* translators: %d is a numeric HTTP error code */
__( 'HTTP %d while communicating with WordPress.com', 'jetpack-boost-core' ),
$code
);
// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$err_code = empty( $data['statusCode'] ) ? 'http_error' : $data['statusCode'];
$message = empty( $data['error'] ) ? $default_message : $data['error'];
return new \WP_Error( $err_code, $message );
}
return $data;
}
}

View File

@ -0,0 +1,63 @@
<?php
/**
* WPCOM Boost API Client interface.
*
* @package automattic/jetpack-boost-core
*/
namespace Automattic\Jetpack\Boost_Core\Lib;
use Automattic\Jetpack\Boost_Core\Contracts\Boost_API_Client;
/**
* A class that handles the Boost API client.
*
* The communication to the backend is done using this class on top of the Boost_API_Client interface.
*/
class WPCOM_Boost_API_Client implements Boost_API_Client {
/**
* Submit a POST request to boost API and return response.
*
* @param string $path - Request path.
* @param mixed[] $payload - Request payload.
* @param mixed[] $args - Request arguments.
* @return mixed
*/
public function post( $path, $payload = array(), $args = null ) {
return Utils::send_wpcom_request(
'POST',
$this->get_api_path( $path ),
$args,
$payload
);
}
/**
* Make a get request to boost API and return response.
*
* @param string $path - Request path.
* @param mixed[] $query - Query parameters.
* @param mixed[] $args - Request arguments.
* @return mixed
*/
public function get( $path, $query = array(), $args = null ) {
return Utils::send_wpcom_request(
'GET',
add_query_arg( $query, $this->get_api_path( $path ) ),
$args
);
}
/**
* Get the API path for the given path.
*
* @param string $path - Request path.
* @return string
*/
private function get_api_path( $path ) {
$blog_id = (int) \Jetpack_Options::get_option( 'id' );
return sprintf( '/sites/%d/jetpack-boost/%s', $blog_id, $path );
}
}

View File

@ -0,0 +1,106 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.3.12] - 2024-08-26
### Changed
- Updated package dependencies. [#39004]
## [0.3.11] - 2024-04-22
### Changed
- Internal updates.
## [0.3.10] - 2024-04-08
### Changed
- Bump project version. [#36072]
## [0.3.9] - 2024-03-27
### Added
- Use `jetpack_boost_critical_css_environment_changed` hook instead of `handle_environment_change` [#36519]
### Changed
- Speed Score: More accurately detect which modules are active when a speed score is requested. [#36534]
### Fixed
- Updated Jetpack_Boost_Modules placeholder class to match Boost interface [#36598]
## [0.3.8] - 2024-03-25
### Changed
- Internal updates.
## [0.3.7] - 2024-03-18
### Changed
- Internal updates.
## [0.3.6] - 2024-03-14
### Changed
- Internal updates.
## [0.3.5] - 2024-03-01
### Changed
- Add gereric Jetpack_Boost_Modules class for when Boost is uninstalled/not activated. [#36080]
## [0.3.4] - 2024-02-13
### Fixed
- Speed Score: Do not return no-boost score if no boost modules are active [#35327]
## [0.3.3] - 2024-01-22
### Added
- Send current boost version with API requests to handle requests accordingly [#35132]
### Changed
- Jetpack Boost: Use Arrays, not objects [#35062]
## [0.3.2] - 2024-01-15
### Changed
- Internal updates.
## [0.3.1] - 2023-12-14
### Changed
- Internal updates.
## [0.3.0] - 2023-11-20
### Changed
- Updated required PHP version to >= 7.0. [#34192]
## [0.2.2] - 2023-09-19
### Fixed
- Fixed deprecation notice in PHP 8.2. [#33079]
## [0.2.1] - 2023-08-28
### Added
- Add boost speed score history endpoint [#32016]
### Changed
- Updated package dependencies. [#32605]
- Updated package version [#32016]
## [0.2.0] - 2023-06-06
### Changed
- Moved boost core classes to boost-core package [#31163]
- Updated package dependencies. [#31163]
## 0.1.0 - 2023-05-29
### Added
- Add a new package for Boost Speed Score [#30914]
- Add a new argument to `Speed_Score` to identify where the request was made from (e.g. 'boost-plugin', 'jetpack-dashboard', etc). [#31012]
[0.3.12]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.11...v0.3.12
[0.3.11]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.10...v0.3.11
[0.3.10]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.9...v0.3.10
[0.3.9]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.8...v0.3.9
[0.3.8]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.7...v0.3.8
[0.3.7]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.6...v0.3.7
[0.3.6]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.5...v0.3.6
[0.3.5]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.4...v0.3.5
[0.3.4]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.3...v0.3.4
[0.3.3]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.2...v0.3.3
[0.3.2]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.2.2...v0.3.0
[0.2.2]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/Automattic/jetpack-boost-speed-score/compare/v0.1.0...v0.2.0

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,61 @@
{
"name": "automattic/jetpack-boost-speed-score",
"description": "A package that handles the API to generate the speed score.",
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require-dev": {
"yoast/phpunit-polyfills": "^1.1.1",
"automattic/jetpack-changelogger": "^4.2.6",
"brain/monkey": "^2.6"
},
"autoload-dev": {
"psr-4": {
"Automattic\\Jetpack\\Boost_Speed_Score\\Tests\\": "./tests/php"
}
},
"require": {
"php": ">=7.0",
"automattic/jetpack-boost-core": "^0.2.9"
},
"autoload": {
"classmap": [
"src/"
]
},
"scripts": {
"phpunit": [
"./vendor/phpunit/phpunit/phpunit --colors=always"
],
"test-php": [
"@composer phpunit"
],
"build-production": "echo 'Add your build step to composer.json, please!'",
"build-development": "echo 'Add your build step to composer.json, please!'",
"post-install-cmd": "WorDBless\\Composer\\InstallDropin::copy",
"post-update-cmd": "WorDBless\\Composer\\InstallDropin::copy"
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
"allow-plugins": {
"roots/wordpress-core-installer": true
}
},
"extra": {
"mirror-repo": "Automattic/jetpack-boost-speed-score",
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-boost-speed-score/compare/v${old}...v${new}"
},
"autotagger": true,
"branch-alias": {
"dev-trunk": "0.3.x-dev"
},
"textdomain": "jetpack-boost-speed-score",
"version-constants": {
"::PACKAGE_VERSION": "src/class-speed-score.php"
}
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
}
}

View File

@ -0,0 +1,56 @@
<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* Jetpack Boost Active Modules
*
* Since the speed scores API will be used in the Jetpack plugin and in the My Jetpack, if Jetpack Boost
* is uninstalled, all we need is to pass along this placeholder class for the modules that essentially
* tells the API the user doesn't have any Boost modules active.
*
* @package automattic/jetpack/boost_speed_score
*/
namespace Automattic\Jetpack\Boost_Speed_Score;
/**
* Jetpack Boost Modules
*/
class Jetpack_Boost_Modules {
/**
* Holds the singleton instance of the class
*
* @var Jetpack_Boost_Modules
*/
private static $instance = false;
/**
* Singleton
*
* @static
* @return Jetpack_Boost_Modules
*/
public static function init() {
if ( ! self::$instance ) {
self::$instance = new Jetpack_Boost_Modules();
}
return self::$instance;
}
/**
* Returns status of all active boost modules that are also ready
*
* @return array - An empty array. The user will never have active modules when using the Boost Score API
*/
public function get_ready_active_optimization_modules() {
return array();
}
/**
* Returns whether or not the user has active modules
*
* @return false - The user will never have active modules when using the Boost Score API
*/
public function have_enabled_modules() {
return false;
}
}

View File

@ -0,0 +1,138 @@
<?php
/**
* Represents a request to generate an array of speed scores history.
*
* @package automattic/jetpack-boost-speed-score
*/
namespace Automattic\Jetpack\Boost_Speed_Score;
use Automattic\Jetpack\Boost_Core\Lib\Boost_API;
use Automattic\Jetpack\Boost_Core\Lib\Cacheable;
/**
* Class Speed_Score_Graph_History_Request
*/
class Speed_Score_Graph_History_Request extends Cacheable {
/**
* Algorithm to use when defining a hash for the cache.
*/
const CACHE_KEY_HASH_ALGO = 'md5';
/**
* The timestamp start windown in ms.
*
* @var int|float $start timestamp start windown in ms.
*/
private $start;
/**
* The timestamp end windown in ms.
*
* @var int|float $end timestamp end windown in ms.
*/
private $end;
/**
* Number of retries attempted.
*
* @var int $retry_count Number of times this Speed Score request has been retried.
*/
private $retry_count;
/**
* The error returned
*
* @var array $error Speed Scores error.
*/
private $error;
/**
* Used when there's an error.
*
* @var string $status Status.
*/
private $status;
/**
* Constructor.
*
* @param int|float $start timestamp start windown in ms.
* @param int|float $end timestamp end windown in ms.
* @param array $error Speed Scores error.
*/
public function __construct( $start, $end, $error ) {
$this->start = $start;
$this->end = $end;
$this->error = $error;
$this->retry_count = 0;
}
/**
* Convert this object to a plain array for JSON serialization.
*/
#[\ReturnTypeWillChange]
public function jsonSerialize() {
return array(
'start' => $this->start,
'end' => $this->end,
'error' => $this->error,
'retry_count' => $this->retry_count,
);
}
/**
* This is intended to be the reverse of JsonSerializable->jsonSerialize.
*
* @param mixed $data The data to turn into an object.
*
* @return Speed_Score_Graph_History_Request
*/
public static function jsonUnserialize( $data ) {
$object = new Speed_Score_Graph_History_Request(
$data['start'],
$data['end'],
$data['error']
);
if ( ! empty( $data['retry_count'] ) ) {
$object->retry_count = intval( $data['retry_count'] );
}
return $object;
}
/**
* Return the cache prefix.
*
* @return string
*/
protected static function cache_prefix() {
return 'jetpack_boost_speed_scores_graph_history_';
}
/**
* Send a Speed History request to the API.
*
* @return true|\WP_Error True on success, WP_Error on failure.
*/
public function execute() {
$response = Boost_API::get(
'speed-scores-history',
array(
'start' => $this->start,
'end' => $this->end,
)
);
if ( is_wp_error( $response ) ) {
$this->status = 'error';
$this->error = $response->get_error_message();
$this->store();
return $response;
}
return $response;
}
}

View File

@ -0,0 +1,148 @@
<?php
/**
* Speed score history after Jetpack Boost
*
* @package automattic/jetpack-boost-speed-score
*/
namespace Automattic\Jetpack\Boost_Speed_Score;
use Automattic\Jetpack\Boost_Core\Lib\Transient;
/**
* Class Speed_Score_History
*
* @package Automattic\Jetpack\Boost_Speed_Score\Lib
*/
class Speed_Score_History {
const OPTION_PREFIX = 'jetpack_boost_speed_score_history_';
const STALE_TRANSIENT_KEY = 'speed_score_stale_marker';
/**
* Limit the number of recent records to keep.
*/
const LIMIT = 20;
/**
* The list of history entries.
*
* @var array
*/
private $entries;
/**
* URL of the site the speed score belongs to.
*
* @var string
*/
private $url;
/**
* Speed_Score_History constructor.
*
* @param string $url URL of the site the speed scores belong to.
*/
public function __construct( $url ) {
$this->url = $url;
$this->entries = get_option( $this->get_option_name(), array() );
}
/**
* Determine the option_name used to store the speed score data in options table.
*
* @return string
*/
private function get_option_name() {
return static::OPTION_PREFIX . Speed_Score_Request::generate_cache_id_from_url( $this->url );
}
/**
* Get the number of history records currently stored.
*
* @return int
*/
public function count() {
return count( $this->entries );
}
/**
* Find the latest available speed score history record.
*
* @param int $offset Instead of receiving the last one, you can use offset to receive a slightly older speed score.
*
* @return array|null
*/
public function latest( $offset = 0 ) {
$index = $this->count() - ( $offset + 1 );
if ( $index >= 0 ) {
return $this->entries[ $index ];
}
return null;
}
/**
* Find the latest available speed scores.
*
* @param int $offset Instead of receiving the last one, you can use offset to receive a slightly older speed score.
*
* @return array|null
*/
public function latest_scores( $offset = 0 ) {
$index = $this->count() - ( $offset + 1 );
if ( $index >= 0 ) {
return $this->entries[ $index ]['scores'];
}
return null;
}
/**
* Get a timestamp that marks previous history stale.
*
* All speed score before this timestamp are considered stale.
*
* @return array
*/
public static function get_stale_timestamp() {
$last_stale_marker = Transient::get( static::STALE_TRANSIENT_KEY, 0 );
// Any score that is older than 24 hours or before the last stale marker is considered stale.
return max( $last_stale_marker, time() - DAY_IN_SECONDS );
}
/**
* Mark previous speed score as stale.
*
* If a there were significant changes to the site, we want to mark prior speed scores as stale.
*/
public static function mark_stale() {
Transient::set( static::STALE_TRANSIENT_KEY, time() );
}
/**
* Check if the last item in history is stale.
*/
public function is_stale() {
$last_entry = $this->latest();
if ( ! $last_entry ) {
return true;
}
return $last_entry['timestamp'] < self::get_stale_timestamp();
}
/**
* Record a new history entry for speed scores.
*
* @param array $entry The new entry to save.
*/
public function push( $entry ) {
$this->entries[] = $entry;
$this->entries = array_slice( $this->entries, - static::LIMIT );
update_option( $this->get_option_name(), $this->entries, false );
}
}

View File

@ -0,0 +1,324 @@
<?php
/**
* Represents a request to generate a pair of speed scores.
*
* @package automattic/jetpack-boost-speed-score
*/
namespace Automattic\Jetpack\Boost_Speed_Score;
use Automattic\Jetpack\Boost_Core\Lib\Boost_API;
use Automattic\Jetpack\Boost_Core\Lib\Cacheable;
use Automattic\Jetpack\Boost_Core\Lib\Url;
/**
* Class Speed_Score_Request
*/
class Speed_Score_Request extends Cacheable {
/**
* Algorithm to use when defining a hash for the cache.
*/
const CACHE_KEY_HASH_ALGO = 'md5';
/**
* The URL to get the Speed Scores for.
*
* @var string $url Url to get the Speed Scores for.
*/
private $url;
/**
* Active Jetpack Boost modules.
*
* @var string[] $active_modules Active modules.
*/
private $active_modules;
/**
* When the Speed Scores request was created, in seconds since epoch.
*
* @var float $created Speed Scores request creation timestamp.
*/
private $created;
/**
* Current status of the Speed Score request.
*
* @var string $status Speed Scores request status.
*/
private $status;
/**
* Number of retries attempted.
*
* @var int $retry_count Number of times this Speed Score request has been retried.
*/
private $retry_count;
/**
* The error returned
*
* @var array $error Speed Scores error.
*/
private $error;
/**
* Where the Speed Scores request was made from.
*
* @var string $client A string passed to Speed_Score to identify where the request was made from.
*/
private $client;
/**
* Constructor.
*
* @param string $url The URL to get the Speed Scores for.
* @param array $active_modules Active modules.
* @param null $created When the Speed Scores request was created, in seconds since epoch.
* @param string $status Status of the Speed Scores request.
* @param null $error The Speed Scores error.
* @param string $client A string identifying where the request was made from.
*/
public function __construct( $url, $active_modules = array(), $created = null, $status = 'pending', $error = null, $client = null ) {
$this->set_cache_id( self::generate_cache_id_from_url( $url ) );
$this->url = $url;
$this->active_modules = $active_modules;
$this->created = $created === null ? microtime( true ) : $created;
$this->status = $status;
$this->error = $error;
$this->client = $client;
$this->retry_count = 0;
}
/**
* Generate the cache ID from the URL.
*
* @param string $url The URL to get the Speed Scores for.
*
* @return string
*/
public static function generate_cache_id_from_url( $url ) {
return hash( self::CACHE_KEY_HASH_ALGO, $url );
}
/**
* Get the list of active performance modules while this request was created.
*
* @return string[]
*/
public function get_active_modules() {
return $this->active_modules;
}
/**
* Convert this object to a plain array for JSON serialization.
*/
#[\ReturnTypeWillChange]
public function jsonSerialize() {
return array(
'id' => $this->get_cache_id(),
'url' => $this->url,
'active_modules' => $this->get_active_modules(),
'created' => $this->created,
'status' => $this->status,
'error' => $this->error,
'client' => $this->client,
'retry_count' => $this->retry_count,
);
}
/**
* This is intended to be the reverse of JsonSerializable->jsonSerialize.
*
* @param mixed $data The data to turn into an object.
*
* @return Speed_Score_Request
*/
public static function jsonUnserialize( $data ) {
$object = new Speed_Score_Request(
$data['url'],
$data['active_modules'],
$data['created'],
$data['status'],
$data['error'],
$data['client']
);
if ( ! empty( $data['id'] ) ) {
$object->set_cache_id( $data['id'] );
}
if ( ! empty( $data['retry_count'] ) ) {
$object->retry_count = intval( $data['retry_count'] );
}
return $object;
}
/**
* Return the cache prefix.
*
* @return string
*/
protected static function cache_prefix() {
return 'jetpack_boost_speed_scores_';
}
/**
* Send a Speed Scores request to the API.
*
* @return true|\WP_Error True on success, WP_Error on failure.
*/
public function execute() {
$response = Boost_API::post(
'speed-scores',
array(
'request_id' => $this->get_cache_id(),
'url' => Url::normalize( $this->url ),
'active_modules' => $this->active_modules,
'client' => $this->client,
)
);
if ( is_wp_error( $response ) ) {
$this->status = 'error';
$this->error = $response->get_error_message();
$this->store();
return $response;
}
return true;
}
/**
* Is this request pending?
*/
public function is_pending() {
return 'pending' === $this->status;
}
/**
* Did the request fail?
*/
public function is_error() {
return 'error' === $this->status;
}
/**
* Did the request succeed?
*/
public function is_success() {
return 'success' === $this->status;
}
/**
* Poll for updates to this Speed Scores request.
*
* @return true|\WP_Error True on success, WP_Error on failure.
*/
public function poll_update() {
$response = Boost_API::get(
sprintf(
'speed-scores/%s',
$this->get_cache_id()
)
);
if ( is_wp_error( $response ) ) {
// Special case: If the request is not found, restart it.
if ( 'not_found' === $response->get_error_code() ) {
return $this->restart();
}
return $response;
}
switch ( $response['status'] ) {
case 'pending':
// The initial job probably failed, dispatch again if so.
if ( $this->created <= strtotime( '-15 mins' ) ) {
return $this->restart();
}
break;
case 'error':
$this->status = 'error';
$this->error = $response['error'];
$this->store();
break;
case 'success':
$this->status = 'success';
$this->store();
$this->record_history( $response );
break;
default:
return new \WP_Error(
'invalid_response',
__(
'Invalid response from WPCOM API while polling for speed scores',
'jetpack-boost-speed-score'
),
$response
);
}
return true;
}
/**
* Restart this request; useful when WPCOM doesn't recognize the request or it times out.
*/
private function restart() {
// Enforce a maximum number of restarts.
if ( $this->retry_count > 2 ) {
$this->status = 'error';
$this->error = 'Maximum number of retries exceeded';
$this->store();
return new \WP_Error(
'error',
$this->error
);
}
$result = $this->execute();
if ( is_wp_error( $result ) ) {
return $result;
}
$this->created = time();
++$this->retry_count;
$this->store();
return true;
}
/**
* Save the speed score record to history.
*
* @param array $response Response from api.
*/
private function record_history( $response ) {
$history = new Speed_Score_History( $this->url );
$last_history = $history->latest();
$last_scores = $last_history ? $last_history['scores'] : null;
$last_theme = $last_history ? $last_history['theme'] : null;
$current_theme = wp_get_theme()->get( 'Name' );
// Only change if there is a difference from last score or the theme changed.
if ( $last_scores !== $response['scores'] || $current_theme !== $last_theme ) {
$history->push(
array(
'timestamp' => time(),
'scores' => $response['scores'],
'theme' => $current_theme,
)
);
}
}
}

View File

@ -0,0 +1,362 @@
<?php
/**
* Speed Score API endpoints.
*
* @package automattic/jetpack-boost-speed-score
*/
namespace Automattic\Jetpack\Boost_Speed_Score;
use Automattic\Jetpack\Boost_Core\Lib\Utils;
if ( ! defined( 'JETPACK_BOOST_REST_NAMESPACE' ) ) {
define( 'JETPACK_BOOST_REST_NAMESPACE', 'jetpack-boost/v1' );
}
// For use in situations where you want additional namespacing.
if ( ! defined( 'JETPACK_BOOST_REST_PREFIX' ) ) {
define( 'JETPACK_BOOST_REST_PREFIX', '' );
}
/**
* Class Speed_Score
*/
class Speed_Score {
const PACKAGE_VERSION = '0.3.12';
/**
* Array of module slugs that are currently active and can impact speed score.
*
* @var string[]
*/
protected $modules;
/**
* A string representing the client making the request (e.g. 'boost-plugin', 'jetpack-dashboard', etc).
*
* @var string
*/
protected $client;
/**
* Constructor.
*
* @param string[] $modules - Array of module slugs that are currently active and can impact speed score.
* @param string $client - A string representing the client making the request.
*/
public function __construct( $modules, $client ) {
/*
* Plugins using the old version of the package may pass an object instead of an array. Converting the
* object to an array keeps it backward compatible. We will lose the module slugs in case of an object,
* but it is better than a fatal error.
*/
if ( ! is_array( $modules ) ) {
$modules = array();
}
$this->modules = $modules;
$this->client = $client;
add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );
add_action( 'jetpack_boost_deactivate', array( $this, 'clear_speed_score_request_cache' ) );
/**
* Mark the speed score history as stale when the environment changes.
*
* @since 0.3.9 - This hook replaced `handle_environment_change` action.
*/
add_action( 'jetpack_boost_critical_css_environment_changed', array( Speed_Score_History::class, 'mark_stale' ) );
/**
* The `handle_environment_change` action is replaced by `jetpack_boost_critical_css_environment_changed` in Jetpack Boost.
* Keeping the `handle_environment_change` action for backward compatibility.
*/
add_action( 'handle_environment_change', array( Speed_Score_History::class, 'mark_stale' ) );
add_action( 'jetpack_boost_deactivate', array( Speed_Score_History::class, 'mark_stale' ) );
}
/**
* Register Speed Score related REST routes.
*/
public function register_rest_routes() {
register_rest_route(
JETPACK_BOOST_REST_NAMESPACE,
JETPACK_BOOST_REST_PREFIX . '/speed-scores',
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array( $this, 'fetch_speed_score' ),
'permission_callback' => array( $this, 'can_access_speed_scores' ),
)
);
register_rest_route(
JETPACK_BOOST_REST_NAMESPACE,
JETPACK_BOOST_REST_PREFIX . '/speed-scores/refresh',
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array( $this, 'dispatch_speed_score_request' ),
'permission_callback' => array( $this, 'can_access_speed_scores' ),
)
);
register_rest_route(
JETPACK_BOOST_REST_NAMESPACE,
JETPACK_BOOST_REST_PREFIX . '/speed-scores-history',
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array( $this, 'dispatch_speed_score_graph_history_request' ),
'permission_callback' => array( $this, 'can_access_speed_scores' ),
'args' => array(
'start' => array(
'required' => true,
'type' => 'number',
),
'end' => array(
'required' => true,
'type' => 'number',
),
),
)
);
}
/**
* Verify and normalize the URL argument for a request.
*
* @param \WP_REST_Request $request The request object.
*
* @return string|\WP_Error An error to return or the target url.
*/
private function process_url_arg( $request ) {
$params = $request->get_json_params();
if ( ! isset( $params['url'] ) ) {
return new \WP_Error(
'invalid_parameter',
__(
'The url parameter is required',
'jetpack-boost-speed-score'
),
array( 'status' => 400 )
);
}
return Utils::force_url_to_absolute( $params['url'] );
}
/**
* Handler for POST /speed-scores/refresh.
*
* @param \WP_REST_Request $request The request object.
*
* @return \WP_REST_Response|\WP_Error The response.
*/
public function dispatch_speed_score_request( $request ) {
$url = $this->process_url_arg( $request );
if ( is_wp_error( $url ) ) {
return $url;
}
// Create and store the Speed Score request.
$score_request = new Speed_Score_Request( $url, $this->modules, null, 'pending', null, $this->client );
$score_request->store( 1800 ); // Keep the request for 30 minutes even if no one access the results.
// Send the request.
$score_request->execute();
$score_request_no_boost = $this->maybe_dispatch_no_boost_score_request( $url );
return $this->prepare_speed_score_response( $url, $score_request, $score_request_no_boost );
}
/**
* Handler for POST /speed-scores-history.
*
* @param \WP_REST_Request $request The request object.
*
* @return \WP_REST_Response|\WP_Error The response.
*/
public function dispatch_speed_score_graph_history_request( $request ) {
$score_history_request = new Speed_Score_Graph_History_Request( $request->get_param( 'start' ), $request->get_param( 'end' ), array() );
// Send the request.
return $score_history_request->execute();
}
/**
* Remove the string "jb-disable-module" from array of strings.
*
* This is intended to be used by the filter `jetpack_boost_excluded_query_parameters` to allow `jb-disable-module` url parameter during score requests.
*
* @param string[] $params List of parameters to be removed from url.
*
* @return string[] Revised list of parameters to remove from url.
*/
public function allow_jb_disable_module( $params ) {
$index = array_search( 'jb-disable-modules', $params, true );
unset( $params[ $index ] );
return $params;
}
/**
* Handler for POST /speed-scores.
*
* @param \WP_REST_Request $request The request object.
*
* @return \WP_REST_Response|\WP_Error The response.
*/
public function fetch_speed_score( $request ) {
$url = $this->process_url_arg( $request );
if ( is_wp_error( $url ) ) {
return $url;
}
// Poll update if there is an ongoing request for scores with boost disabled.
$url_no_boost = $this->get_boost_modules_disabled_url( $url );
$score_request_no_boost = $this->get_score_request_by_url( $url_no_boost );
if ( $score_request_no_boost && $score_request_no_boost->is_pending() ) {
$response = $score_request_no_boost->poll_update();
if ( is_wp_error( $response ) ) {
return $response;
}
}
// Poll update if there is an ongoing request for scores with boost enabled.
$score_request = $this->get_score_request_by_url( $url );
if ( $score_request && $score_request->is_pending() ) {
$response = $score_request->poll_update();
if ( is_wp_error( $response ) ) {
return $response;
}
}
// If this is a fresh install, there might not be any speed score history. In which case, we want to fetch the initial scores.
// While updating plugin from 1.2 -> 1.3, the history will be missing along with a non-pending score request due to data structure change.
$history = new Speed_Score_History( $url );
if ( null === $history->latest_scores() && ( empty( $score_request ) || ! $score_request->is_pending() ) ) {
return $this->dispatch_speed_score_request( $request );
}
return $this->prepare_speed_score_response( $url, $score_request, $score_request_no_boost );
}
/**
* If it is time to fetch the score without boost, fetch it.
*
* @param string $url Url of the site.
*
* @return Speed_Score_Request
*/
private function maybe_dispatch_no_boost_score_request( $url ) {
// Allow `jb-disable-module` URL param to fetch score without boost modules being active.
add_filter( 'jetpack_boost_excluded_query_parameters', array( $this, 'allow_jb_disable_module' ) );
$url_no_boost = $this->get_boost_modules_disabled_url( $url );
$history = new Speed_Score_History( $url_no_boost );
$score_request = $this->get_score_request_by_url( $url_no_boost );
if (
// If there isn't already a pending request.
( empty( $score_request ) || ! $score_request->is_pending() )
&& ! empty( $this->modules )
&& $history->is_stale()
) {
$score_request = new Speed_Score_Request( $url_no_boost, array(), null, 'pending', null, $this->client ); // Dispatch a new speed score request to measure score without boost.
$score_request->store( 3600 ); // Keep the request for 1 hour even if no one access the results. The value is persisted for 1 hour in wp.com from initial request.
// Send the request.
$score_request->execute();
}
remove_filter( 'jetpack_boost_excluded_query_parameters', array( $this, 'allow_jb_disable_module' ) );
return $score_request;
}
/**
* Get Speed_Score_Request instance by url.
*
* @param string $url Url to get the Speed_Score_Request instance for.
*
* @return Speed_Score_Request
*/
private function get_score_request_by_url( $url ) {
return Speed_Score_Request::get(
Speed_Score_Request::generate_cache_id_from_url( $url )
);
}
/**
* Add query parameters to the url that would disable all boost modules.
*
* @param string $url The original URL we are measuring for score.
*
* @return string
*/
private function get_boost_modules_disabled_url( $url ) {
return add_query_arg( 'jb-disable-modules', 'all', $url );
}
/**
* Can the user access speed scores?
*
* @return bool
*/
public function can_access_speed_scores() {
return current_user_can( 'manage_options' );
}
/**
* Clear speed score request cache on jetpack_boost_deactivate action.
*/
public function clear_speed_score_request_cache() {
Speed_Score_Request::clear_cache();
}
/**
* Prepare the speed score response.
*
* @param string $url URL of the speed is requested for.
* @param Speed_Score_Request $score_request Speed score request.
* @param Speed_Score_Request $score_request_no_boost Speed score request without boost enabled.
*
* @return \WP_Error|\WP_HTTP_Response|\WP_REST_Response
*/
private function prepare_speed_score_response( $url, $score_request, $score_request_no_boost ) {
$history = new Speed_Score_History( $url );
$url_no_boost = $this->get_boost_modules_disabled_url( $url );
$history_no_boost = new Speed_Score_History( $url_no_boost );
$response = array();
if ( ( ! $score_request || $score_request->is_success() ) && ( ! $score_request_no_boost || $score_request_no_boost->is_success() ) ) {
$response['status'] = 'success';
$response['scores'] = array(
'current' => $history->latest_scores(),
'noBoost' => null,
);
// Only include noBoost scores if at least one module is enabled.
if ( $score_request && ! empty( $score_request->get_active_modules() ) ) {
$response['scores']['noBoost'] = $history_no_boost->latest_scores();
}
$response['scores']['isStale'] = $history->is_stale();
} elseif ( ( $score_request && $score_request->is_error() ) || ( $score_request_no_boost && $score_request_no_boost->is_error() ) ) {
// If either request ended up in error, we can just return the one with error so front-end can take action. The relevent url is available on the serialized object.
if ( $score_request->is_error() ) {
// Serialized version of score request contains the status property and error description if any.
$response = $score_request->jsonSerialize();
} else {
$response = $score_request_no_boost->jsonSerialize();
}
} else {
// If no request ended up in error/success as previous conditions dictate, it means that either of them are in pending state.
$response['status'] = 'pending';
}
return rest_ensure_response( $response );
}
}

View File

@ -0,0 +1,256 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.0.4] - 2024-06-24
### Changed
- Internal updates.
## [2.0.3] - 2024-06-03
### Removed
- Remove the Identity Crisis package dev dependency. [#37654]
## [2.0.2] - 2024-05-06
### Changed
- Internal updates.
## [2.0.1] - 2024-03-14
### Changed
- Internal updates.
## [2.0.0] - 2023-11-20
### Changed
- Updated required PHP version to >= 7.0. [#34192]
## [1.15.4] - 2023-09-19
- Minor internal updates.
## [1.15.3] - 2023-06-26
### Changed
- Blaze can now be loaded as a module, instead of relying on the Config package. [#31479]
## [1.15.2] - 2023-04-10
### Added
- Add Jetpack Autoloader package suggestion. [#29988]
## [1.15.1] - 2023-03-28
### Changed
- Minor internal updates.
## [1.15.0] - 2023-03-27
### Added
- Initialize yoast promo package in jetpack plugin [#29641]
## [1.14.0] - 2023-02-20
### Added
- Added the Import package. [#28824]
## [1.13.0] - 2023-01-02
### Added
- Blaze package: Add config initialization, initialization checks for loading. [#28077]
## [1.12.0] - 2022-12-12
### Added
- Config: add option to init stats-admin [#27565]
## [1.11.1] - 2022-11-22
### Changed
- Updated package dependencies. [#27043]
## [1.11.0] - 2022-10-11
### Changed
- Integrate Stats package in Jetpack plugin [#26640]
## [1.10.0] - 2022-09-27
### Added
- Social: Added the option to configure if the plan information should be refreshed as the package is enabled. [#26294]
## [1.9.6] - 2022-08-26
### Changed
- Call ensure_options_$feature methods before the initialization
## [1.9.5] - 2022-08-23
### Changed
- Initialize VideoPress admin UI from the package [#25692]
## [1.9.4] - 2022-08-09
### Changed
- Initialize VideoPress package from the Config pkg [#25385]
## [1.9.3] - 2022-07-26
### Changed
- Updated package dependencies. [#25158]
## [1.9.2] - 2022-06-29
- Updated package dependencies.
## [1.9.1] - 2022-06-21
### Changed
- Renaming master to trunk.
## [1.9.0] - 2022-05-18
### Added
- Configuration for waf package [#24153]
## [1.8.0] - 2022-04-26
### Added
- Added the publicize package to be configured via the config package.
### Changed
- Updated package dependencies.
## [1.7.2] - 2022-04-19
### Added
- Enable WordAds from Config class
## [1.7.1] - 2022-04-06
### Removed
- Removed tracking dependency.
## [1.7.0] - 2022-03-23
### Added
- Search: added search initialization
## [1.6.1] - 2022-02-09
### Added
- Allow sync package consumers to provide custom data settings.
## [1.6.0] - 2022-01-04
### Added
- Accept options for the IDC package.
### Changed
- Updated package textdomain from `jetpack` to `jetpack-config`.
## [1.5.4] - 2021-12-14
### Changed
- Updated package dependencies.
## [1.5.3] - 2021-10-13
### Changed
- Updated package dependencies.
## [1.5.2] - 2021-10-12
### Added
- Add support for the identity-crisis package
## [1.5.1] - 2021-09-28
### Changed
- Updated package dependencies.
## [1.5.0] - 2021-09-22
### Added
- Allow for enabling and initializing new Post_List package from Config package.
## [1.4.7] - 2021-08-31
### Changed
- updates annotations versions.
## [1.4.6] - 2021-05-25
### Changed
- Updated package dependencies.
## [1.4.5] - 2021-04-27
### Changed
- Updated package dependencies.
## [1.4.4] - 2021-03-30
### Added
- Composer alias for dev-master, to improve dependencies
### Changed
- Update package dependencies.
## [1.4.3] - 2021-01-19
- Add mirror-repo information to all current composer packages
- Monorepo: Reorganize all projects
## [1.4.2] - 2020-10-28
- Updated PHPCS: Packages and Debugger
- Config: remove tos and tracking features
- Config: add info about the package dependencies to the package docs
## [1.4.1] - 2020-09-15
- Config: remove tos and tracking features
## [1.4.0] - 2020-08-26
- Config: Remove composer dependencies
- Config: Add connection status check
## [1.3.0] - 2020-06-26
- Config: check for both JITM namespaces
## [1.2.0] - 2020-05-20
- Store the list of active plugins that uses connection in an option
- Implement pre-connection JITMs
- Connection Package: Handle disconnections gracefully
## [1.1.0] - 2020-01-23
- Moved JITM initialization to plugins_loaded.
## [1.0.1] - 2020-01-20
- Move connection manager related logic to after plugins_loaded.
## 1.0.0 - 2020-01-14
- Trying to add deterministic initialization.
[2.0.4]: https://github.com/Automattic/jetpack-config/compare/v2.0.3...v2.0.4
[2.0.3]: https://github.com/Automattic/jetpack-config/compare/v2.0.2...v2.0.3
[2.0.2]: https://github.com/Automattic/jetpack-config/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/Automattic/jetpack-config/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Automattic/jetpack-config/compare/v1.15.4...v2.0.0
[1.15.4]: https://github.com/Automattic/jetpack-config/compare/v1.15.3...v1.15.4
[1.15.3]: https://github.com/Automattic/jetpack-config/compare/v1.15.2...v1.15.3
[1.15.2]: https://github.com/Automattic/jetpack-config/compare/v1.15.1...v1.15.2
[1.15.1]: https://github.com/Automattic/jetpack-config/compare/v1.15.0...v1.15.1
[1.15.0]: https://github.com/Automattic/jetpack-config/compare/v1.14.0...v1.15.0
[1.14.0]: https://github.com/Automattic/jetpack-config/compare/v1.13.0...v1.14.0
[1.13.0]: https://github.com/Automattic/jetpack-config/compare/v1.12.0...v1.13.0
[1.12.0]: https://github.com/Automattic/jetpack-config/compare/v1.11.1...v1.12.0
[1.11.1]: https://github.com/Automattic/jetpack-config/compare/v1.11.0...v1.11.1
[1.11.0]: https://github.com/Automattic/jetpack-config/compare/v1.10.0...v1.11.0
[1.10.0]: https://github.com/Automattic/jetpack-config/compare/v1.9.6...v1.10.0
[1.9.6]: https://github.com/Automattic/jetpack-config/compare/v1.9.5...v1.9.6
[1.9.5]: https://github.com/Automattic/jetpack-config/compare/v1.9.4...v1.9.5
[1.9.4]: https://github.com/Automattic/jetpack-config/compare/v1.9.3...v1.9.4
[1.9.3]: https://github.com/Automattic/jetpack-config/compare/v1.9.2...v1.9.3
[1.9.2]: https://github.com/Automattic/jetpack-config/compare/v1.9.1...v1.9.2
[1.9.1]: https://github.com/Automattic/jetpack-config/compare/v1.9.0...v1.9.1
[1.9.0]: https://github.com/Automattic/jetpack-config/compare/v1.8.0...v1.9.0
[1.8.0]: https://github.com/Automattic/jetpack-config/compare/v1.7.2...v1.8.0
[1.7.2]: https://github.com/Automattic/jetpack-config/compare/v1.7.1...v1.7.2
[1.7.1]: https://github.com/Automattic/jetpack-config/compare/v1.7.0...v1.7.1
[1.7.0]: https://github.com/Automattic/jetpack-config/compare/v1.6.1...v1.7.0
[1.6.1]: https://github.com/Automattic/jetpack-config/compare/v1.6.0...v1.6.1
[1.6.0]: https://github.com/Automattic/jetpack-config/compare/v1.5.4...v1.6.0
[1.5.4]: https://github.com/Automattic/jetpack-config/compare/v1.5.3...v1.5.4
[1.5.3]: https://github.com/Automattic/jetpack-config/compare/v1.5.2...v1.5.3
[1.5.2]: https://github.com/Automattic/jetpack-config/compare/v1.5.1...v1.5.2
[1.5.1]: https://github.com/Automattic/jetpack-config/compare/v1.5.0...v1.5.1
[1.5.0]: https://github.com/Automattic/jetpack-config/compare/v1.4.7...v1.5.0
[1.4.7]: https://github.com/Automattic/jetpack-config/compare/v1.4.6...v1.4.7
[1.4.6]: https://github.com/Automattic/jetpack-config/compare/v1.4.5...v1.4.6
[1.4.5]: https://github.com/Automattic/jetpack-config/compare/v1.4.4...v1.4.5
[1.4.4]: https://github.com/Automattic/jetpack-config/compare/v1.4.3...v1.4.4
[1.4.3]: https://github.com/Automattic/jetpack-config/compare/v1.4.2...v1.4.3
[1.4.2]: https://github.com/Automattic/jetpack-config/compare/v1.4.1...v1.4.2
[1.4.1]: https://github.com/Automattic/jetpack-config/compare/v1.4.0...v1.4.1
[1.4.0]: https://github.com/Automattic/jetpack-config/compare/v1.3.0...v1.4.0
[1.3.0]: https://github.com/Automattic/jetpack-config/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/Automattic/jetpack-config/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/Automattic/jetpack-config/compare/v1.0.1...v1.1.0
[1.0.1]: https://github.com/Automattic/jetpack-config/compare/v1.0.0...v1.0.1

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,68 @@
{
"name": "automattic/jetpack-config",
"description": "Jetpack configuration package that initializes other packages and configures Jetpack's functionality. Can be used as a base for all variants of Jetpack package usage.",
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0"
},
"require-dev": {
"automattic/jetpack-changelogger": "^4.2.4",
"automattic/jetpack-connection": "@dev",
"automattic/jetpack-import": "@dev",
"automattic/jetpack-jitm": "@dev",
"automattic/jetpack-post-list": "@dev",
"automattic/jetpack-publicize": "@dev",
"automattic/jetpack-search": "@dev",
"automattic/jetpack-stats": "@dev",
"automattic/jetpack-stats-admin": "@dev",
"automattic/jetpack-sync": "@dev",
"automattic/jetpack-videopress": "@dev",
"automattic/jetpack-waf": "@dev",
"automattic/jetpack-wordads": "@dev",
"automattic/jetpack-yoast-promo": "@dev"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
},
"autoload": {
"classmap": [
"src/"
]
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"autotagger": true,
"mirror-repo": "Automattic/jetpack-config",
"textdomain": "jetpack-config",
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-config/compare/v${old}...v${new}"
},
"branch-alias": {
"dev-trunk": "2.0.x-dev"
},
"dependencies": {
"test-only": [
"packages/connection",
"packages/import",
"packages/jitm",
"packages/post-list",
"packages/publicize",
"packages/search",
"packages/stats",
"packages/stats-admin",
"packages/sync",
"packages/videopress",
"packages/waf",
"packages/wordads",
"packages/yoast-promo"
]
}
},
"config": {
"allow-plugins": {
"automattic/jetpack-autoloader": true
}
}
}

View File

@ -0,0 +1,455 @@
<?php
/**
* The base Jetpack configuration class file.
*
* @package automattic/jetpack-config
*/
namespace Automattic\Jetpack;
/*
* The Config package does not require the composer packages that
* contain the package classes shown below. The consumer plugin
* must require the corresponding packages to use these features.
*/
use Automattic\Jetpack\Connection\Manager;
use Automattic\Jetpack\Connection\Plugin;
use Automattic\Jetpack\Import\Main as Import_Main;
use Automattic\Jetpack\JITMS\JITM as JITMS_JITM;
use Automattic\Jetpack\Post_List\Post_List;
use Automattic\Jetpack\Publicize\Publicize_Setup;
use Automattic\Jetpack\Search\Initializer as Jetpack_Search_Main;
use Automattic\Jetpack\Stats\Main as Stats_Main;
use Automattic\Jetpack\Stats_Admin\Main as Stats_Admin_Main;
use Automattic\Jetpack\Sync\Main as Sync_Main;
use Automattic\Jetpack\VideoPress\Initializer as VideoPress_Pkg_Initializer;
use Automattic\Jetpack\Waf\Waf_Initializer as Jetpack_Waf_Main;
use Automattic\Jetpack\WordAds\Initializer as Jetpack_WordAds_Main;
/**
* The configuration class.
*/
class Config {
const FEATURE_ENSURED = 1;
const FEATURE_NOT_AVAILABLE = 0;
const FEATURE_ALREADY_ENSURED = -1;
/**
* The initial setting values.
*
* @var Array
*/
protected $config = array(
'jitm' => false,
'connection' => false,
'sync' => false,
'post_list' => false,
'identity_crisis' => false,
'search' => false,
'publicize' => false,
'wordads' => false,
'waf' => false,
'videopress' => false,
'stats' => false,
'stats_admin' => false,
'yoast_promo' => false,
'import' => false,
);
/**
* Initialization options stored here.
*
* @var array
*/
protected $feature_options = array();
/**
* Creates the configuration class instance.
*/
public function __construct() {
/**
* Adding the config handler to run on priority 2 because the class itself is
* being constructed on priority 1.
*/
add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ), 2 );
}
/**
* Require a feature to be initialized. It's up to the package consumer to actually add
* the package to their composer project. Declaring a requirement using this method
* instructs the class to initialize it.
*
* Run the options method (if exists) every time the method is called.
*
* @param String $feature the feature slug.
* @param array $options Additional options, optional.
*/
public function ensure( $feature, array $options = array() ) {
$this->config[ $feature ] = true;
$this->set_feature_options( $feature, $options );
$method_options = 'ensure_options_' . $feature;
if ( method_exists( $this, $method_options ) ) {
$this->{ $method_options }();
}
}
/**
* Runs on plugins_loaded hook priority with priority 2.
*
* @action plugins_loaded
*/
public function on_plugins_loaded() {
if ( $this->config['connection'] ) {
$this->ensure_class( 'Automattic\Jetpack\Connection\Manager' )
&& $this->ensure_feature( 'connection' );
}
if ( $this->config['sync'] ) {
$this->ensure_class( 'Automattic\Jetpack\Sync\Main' )
&& $this->ensure_feature( 'sync' );
}
if ( $this->config['jitm'] ) {
// Check for the JITM class in both namespaces. The namespace was changed in jetpack-jitm v1.6.
( $this->ensure_class( 'Automattic\Jetpack\JITMS\JITM', false )
|| $this->ensure_class( 'Automattic\Jetpack\JITM' ) )
&& $this->ensure_feature( 'jitm' );
}
if ( $this->config['post_list'] ) {
$this->ensure_class( 'Automattic\Jetpack\Post_List\Post_List' )
&& $this->ensure_feature( 'post_list' );
}
if ( $this->config['identity_crisis'] ) {
$this->ensure_class( 'Automattic\Jetpack\Identity_Crisis' )
&& $this->ensure_feature( 'identity_crisis' );
}
if ( $this->config['search'] ) {
$this->ensure_class( 'Automattic\Jetpack\Search\Initializer' )
&& $this->ensure_feature( 'search' );
}
if ( $this->config['publicize'] ) {
$this->ensure_class( 'Automattic\Jetpack\Publicize\Publicize_UI' ) && $this->ensure_class( 'Automattic\Jetpack\Publicize\Publicize' )
&& $this->ensure_feature( 'publicize' );
}
if ( $this->config['wordads'] ) {
$this->ensure_class( 'Automattic\Jetpack\WordAds\Initializer' )
&& $this->ensure_feature( 'wordads' );
}
if ( $this->config['waf'] ) {
$this->ensure_class( 'Automattic\Jetpack\Waf\Waf_Initializer' )
&& $this->ensure_feature( 'waf' );
}
if ( $this->config['videopress'] ) {
$this->ensure_class( 'Automattic\Jetpack\VideoPress\Initializer' ) && $this->ensure_feature( 'videopress' );
}
if ( $this->config['stats'] ) {
$this->ensure_class( 'Automattic\Jetpack\Stats\Main' ) && $this->ensure_feature( 'stats' );
}
if ( $this->config['stats_admin'] ) {
$this->ensure_class( 'Automattic\Jetpack\Stats_Admin\Main' ) && $this->ensure_feature( 'stats_admin' );
}
if ( $this->config['yoast_promo'] ) {
$this->ensure_class( 'Automattic\Jetpack\Yoast_Promo' ) && $this->ensure_feature( 'yoast_promo' );
}
if ( $this->config['import'] ) {
$this->ensure_class( 'Automattic\Jetpack\Import\Main' )
&& $this->ensure_feature( 'import' );
}
}
/**
* Returns true if the required class is available and alerts the user if it's not available
* in case the site is in debug mode.
*
* @param String $classname a fully qualified class name.
* @param Boolean $log_notice whether the E_USER_NOTICE should be generated if the class is not found.
*
* @return Boolean whether the class is available.
*/
protected function ensure_class( $classname, $log_notice = true ) {
$available = class_exists( $classname );
if ( $log_notice && ! $available && defined( 'WP_DEBUG' ) && WP_DEBUG ) {
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
sprintf(
/* translators: %1$s is a PHP class name. */
esc_html__(
'Unable to load class %1$s. Please add the package that contains it using composer and make sure you are requiring the Jetpack autoloader',
'jetpack-config'
),
esc_html( $classname )
),
E_USER_NOTICE
);
}
return $available;
}
/**
* Ensures a feature is enabled, sets it up if it hasn't already been set up.
*
* @param String $feature slug of the feature.
* @return Integer either FEATURE_ENSURED, FEATURE_ALREADY_ENSURED or FEATURE_NOT_AVAILABLE constants.
*/
protected function ensure_feature( $feature ) {
$method = 'enable_' . $feature;
if ( ! method_exists( $this, $method ) ) {
return self::FEATURE_NOT_AVAILABLE;
}
if ( did_action( 'jetpack_feature_' . $feature . '_enabled' ) ) {
return self::FEATURE_ALREADY_ENSURED;
}
$this->{ $method }();
/**
* Fires when a specific Jetpack package feature is initalized using the Config package.
*
* @since 1.1.0
*/
do_action( 'jetpack_feature_' . $feature . '_enabled' );
return self::FEATURE_ENSURED;
}
/**
* Enables the JITM feature.
*/
protected function enable_jitm() {
if ( class_exists( 'Automattic\Jetpack\JITMS\JITM' ) ) {
JITMS_JITM::configure();
} else {
// Provides compatibility with jetpack-jitm <v1.6.
// @phan-suppress-next-line PhanUndeclaredClassMethod
JITM::configure();
}
return true;
}
/**
* Enables the Post_List feature.
*/
protected function enable_post_list() {
Post_List::configure();
return true;
}
/**
* Enables the Sync feature.
*/
protected function enable_sync() {
Sync_Main::configure();
return true;
}
/**
* Enables the Connection feature.
*/
protected function enable_connection() {
Manager::configure();
return true;
}
/**
* Enables the identity-crisis feature.
*/
protected function enable_identity_crisis() {
Identity_Crisis::init();
}
/**
* Enables the search feature.
*/
protected function enable_search() {
Jetpack_Search_Main::init();
}
/**
* Enables the Publicize feature.
*/
protected function enable_publicize() {
Publicize_Setup::configure();
return true;
}
/**
* Handles Publicize options.
*/
protected function ensure_options_publicize() {
$options = $this->get_feature_options( 'publicize' );
if ( ! empty( $options['force_refresh'] ) ) {
Publicize_Setup::$refresh_plan_info = true;
}
}
/**
* Enables WordAds.
*/
protected function enable_wordads() {
Jetpack_WordAds_Main::init();
}
/**
* Enables Waf.
*/
protected function enable_waf() {
Jetpack_Waf_Main::init();
return true;
}
/**
* Enables VideoPress.
*/
protected function enable_videopress() {
VideoPress_Pkg_Initializer::init();
return true;
}
/**
* Enables Stats.
*/
protected function enable_stats() {
Stats_Main::init();
return true;
}
/**
* Enables Stats Admin.
*/
protected function enable_stats_admin() {
Stats_Admin_Main::init();
return true;
}
/**
* Handles VideoPress options
*/
protected function ensure_options_videopress() {
$options = $this->get_feature_options( 'videopress' );
if ( ! empty( $options ) ) {
VideoPress_Pkg_Initializer::update_init_options( $options );
}
return true;
}
/**
* Enables Yoast Promo.
*/
protected function enable_yoast_promo() {
Yoast_Promo::init();
return true;
}
/**
* Enables the Import feature.
*/
protected function enable_import() {
Import_Main::configure();
return true;
}
/**
* Setup the Connection options.
*/
protected function ensure_options_connection() {
$options = $this->get_feature_options( 'connection' );
if ( ! empty( $options['slug'] ) ) {
// The `slug` and `name` are removed from the options because they need to be passed as arguments.
$slug = $options['slug'];
unset( $options['slug'] );
$name = $slug;
if ( ! empty( $options['name'] ) ) {
$name = $options['name'];
unset( $options['name'] );
}
( new Plugin( $slug ) )->add( $name, $options );
}
return true;
}
/**
* Setup the Identity Crisis options.
*
* @return bool
*/
protected function ensure_options_identity_crisis() {
$options = $this->get_feature_options( 'identity_crisis' );
if ( is_array( $options ) && count( $options ) ) {
add_filter(
'jetpack_idc_consumers',
function ( $consumers ) use ( $options ) {
$consumers[] = $options;
return $consumers;
}
);
}
return true;
}
/**
* Setup the Sync options.
*/
protected function ensure_options_sync() {
$options = $this->get_feature_options( 'sync' );
if ( method_exists( 'Automattic\Jetpack\Sync\Main', 'set_sync_data_options' ) ) {
Sync_Main::set_sync_data_options( $options );
}
return true;
}
/**
* Temporary save initialization options for a feature.
*
* @param string $feature The feature slug.
* @param array $options The options.
*
* @return bool
*/
protected function set_feature_options( $feature, array $options ) {
if ( $options ) {
$this->feature_options[ $feature ] = $options;
}
return true;
}
/**
* Get initialization options for a feature from the temporary storage.
*
* @param string $feature The feature slug.
*
* @return array
*/
protected function get_feature_options( $feature ) {
return empty( $this->feature_options[ $feature ] ) ? array() : $this->feature_options[ $feature ];
}
}

View File

@ -0,0 +1,3 @@
module.exports = {
extends: [ require.resolve( 'jetpack-js-tools/eslintrc/react' ) ],
};

View File

@ -0,0 +1,357 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,47 @@
# Security Policy
Full details of the Automattic Security Policy can be found on [automattic.com](https://automattic.com/security/).
## Supported Versions
Generally, only the latest version of Jetpack and its associated plugins have continued support. If a critical vulnerability is found in the current version of a plugin, we may opt to backport any patches to previous versions.
## Reporting a Vulnerability
Our HackerOne program covers the below plugin software, as well as a variety of related projects and infrastructure:
* [Jetpack](https://jetpack.com/)
* Jetpack Backup
* Jetpack Boost
* Jetpack CRM
* Jetpack Protect
* Jetpack Search
* Jetpack Social
* Jetpack VideoPress
**For responsible disclosure of security issues and to be eligible for our bug bounty program, please submit your report via the [HackerOne](https://hackerone.com/automattic) portal.**
Our most critical targets are:
* Jetpack and the Jetpack composer packages (all within this repo)
* Jetpack.com -- the primary marketing site.
* cloud.jetpack.com -- a management site.
* wordpress.com -- the shared management site for both Jetpack and WordPress.com sites.
For more targets, see the `In Scope` section on [HackerOne](https://hackerone.com/automattic).
_Please note that the **WordPress software is a separate entity** from Automattic. Please report vulnerabilities for WordPress through [the WordPress Foundation's HackerOne page](https://hackerone.com/wordpress)._
## Guidelines
We're committed to working with security researchers to resolve the vulnerabilities they discover. You can help us by following these guidelines:
* Follow [HackerOne's disclosure guidelines](https://www.hackerone.com/disclosure-guidelines).
* Pen-testing Production:
* Please **setup a local environment** instead whenever possible. Most of our code is open source (see above).
* If that's not possible, **limit any data access/modification** to the bare minimum necessary to reproduce a PoC.
* **_Don't_ automate form submissions!** That's very annoying for us, because it adds extra work for the volunteers who manage those systems, and reduces the signal/noise ratio in our communication channels.
* To be eligible for a bounty, all of these guidelines must be followed.
* Be Patient - Give us a reasonable time to correct the issue before you disclose the vulnerability.
We also expect you to comply with all applicable laws. You're responsible to pay any taxes associated with your bounties.

View File

@ -0,0 +1,122 @@
# Jetpack Tracking package
A package containing functionality to track events to the a8c Tracks system
## Usage
There are several ways to track events using this package.
* Ajax: Probably the easiest one. You can simply add a class to a link and it will be tracked or you can make your own ajax call
* PHP: Track an event on the backend
* Tracking pixel: An alternative way to track events by dynamically adding a pixel to the DOM
### Tracking via Ajax
This is useful to track simple click events without the need of any additional js. Just add the appropriate class to your links and it will be tracked.
#### 1. enqueue script
Note: Not needed if you are using the Jetpack plugin in the admin context as the script is already loaded by Jetpack.
See `Automattic\Jetpack\Tracking::enqueue_tracks_scripts()`
```PHP
add_action( 'admin_enqueue_scripts', array( new Tracking( 'plugin-slug' ), 'enqueue_tracks_scripts' ) );
```
#### 2. Add the class and the event attributes.
Add the `jptracks` class to any `a` element or to its parent element.
The event needs a name. This can be informed with the `data-jptracks-name` attritbute.
```HTML
<a class="jptracks" data-jptracks-name="my-awesome-event">Click me</a>
```
And that's it. Your event will be tracked. Every time this element is clicked an ajax call will be triggered to the Tracking package and it will send it to wpcom.
**Note:** Event name will be automatically prefixed with `jetpack_`.
#### 3. Additional parameters
You can also inform additional parameters to your event using the `data-jptracks-prop` attribute. Anything in this attr will be stored in the `clicked` attribute in the event.
#### 4. Making your own ajax calls
In your JS you can set up your own ajax calls. Example:
```JS
window.jpTracksAJAX.record_ajax_event( 'my_event_name', 'click', { prop1: value1, prop2: value2 } );
```
**Note:** Event name will be automatically prefixed with `jetpack_`.
##### Waiting for the ajax call to complete before doing anything else
If you need to do a subsequent action but wants to wait for this event to be tracked, you can do the following:
```JS
window.jpTracksAJAX
.record_ajax_event( 'my_event_name', 'click', { prop1: value1, prop2: value2 } )
.always( function() {
// do something
} );
```
### Tracking in PHP
Use `Automattic\Jetpack\Tracking::record_user_event()` to track events on the backend.
```PHP
$connection_manager = new Automattic\Jetpack\Connection\Manager( 'plugin-slug' );
$tracking = new Tracking( 'plugin-slug', $connection_manager );
$tracking->record_user_event(
$event_name,
array(
'property_key' => 'value',
)
);
```
### Tracking pixel
This approach to track events uses `//stats.wp.com/w.js` and dynamically adds a tracking pixel to the DOM to do the tracking.
#### 1. Enqueue the scripts
```PHP
Tracking::register_tracks_functions_scripts( true );
```
#### 2. Inform the user data
```PHP
wp_localize_script(
'my_script',
'varname',
array(
'tracksUserData' => Jetpack_Tracks_Client::get_connected_user_tracks_identity(),
)
);
```
#### 3. Track!
In your JS:
```JS
var tracksUser = varname.tracksUserData;
analytics.initialize( tracksUser.userid, tracksUser.username );
analytics.tracks.recordEvent( 'jetpack_my_event_name', { prop1: value1, prop2: value2 } );
```
## Debugging
You can watch your events being tracked in the browser console. In order to activate that, run the following command in the console:
```JS
localStorage.setItem( 'debug', 'dops:analytics*' );
```

View File

@ -0,0 +1,23 @@
<?php
/**
* Action Hooks for Jetpack connection assets.
*
* @package automattic/jetpack-connection
*/
// If WordPress's plugin API is available already, use it. If not,
// drop data into `$wp_filter` for `WP_Hook::build_preinitialized_hooks()`.
if ( function_exists( 'add_action' ) ) {
add_action(
'plugins_loaded',
array( Automattic\Jetpack\Connection\Connection_Assets::class, 'configure' ),
1
);
} else {
global $wp_filter;
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$wp_filter['plugins_loaded'][1][] = array(
'accepted_args' => 0,
'function' => array( Automattic\Jetpack\Connection\Connection_Assets::class, 'configure' ),
);
}

View File

@ -0,0 +1,79 @@
{
"name": "automattic/jetpack-connection",
"description": "Everything needed to connect to the Jetpack infrastructure",
"type": "jetpack-library",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=7.0",
"automattic/jetpack-a8c-mc-stats": "^2.0.2",
"automattic/jetpack-admin-ui": "^0.4.5",
"automattic/jetpack-assets": "^2.3.7",
"automattic/jetpack-constants": "^2.0.4",
"automattic/jetpack-roles": "^2.0.3",
"automattic/jetpack-status": "^4.0.1",
"automattic/jetpack-redirect": "^2.0.4"
},
"require-dev": {
"automattic/wordbless": "@dev",
"yoast/phpunit-polyfills": "^1.1.1",
"brain/monkey": "2.6.1",
"automattic/jetpack-changelogger": "^4.2.6"
},
"suggest": {
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
},
"autoload": {
"files": [
"actions.php"
],
"classmap": [
"legacy",
"src/",
"src/webhooks",
"src/identity-crisis"
]
},
"scripts": {
"build-production": [
"pnpm run build-production"
],
"build-development": [
"pnpm run build"
],
"phpunit": [
"./vendor/phpunit/phpunit/phpunit --colors=always"
],
"post-install-cmd": "WorDBless\\Composer\\InstallDropin::copy",
"post-update-cmd": "WorDBless\\Composer\\InstallDropin::copy",
"test-php": [
"@composer phpunit"
]
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"autotagger": true,
"mirror-repo": "Automattic/jetpack-connection",
"textdomain": "jetpack-connection",
"version-constants": {
"::PACKAGE_VERSION": "src/class-package-version.php"
},
"changelogger": {
"link-template": "https://github.com/Automattic/jetpack-connection/compare/v${old}...v${new}"
},
"branch-alias": {
"dev-trunk": "4.0.x-dev"
},
"dependencies": {
"test-only": [
"packages/licensing",
"packages/sync"
]
}
},
"config": {
"allow-plugins": {
"roots/wordpress-core-installer": true
}
}
}

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-url'), 'version' => 'f6bce0e6b8e0527839ee');

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('jetpack-script-data', 'react', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives', 'wp-url'), 'version' => '633f5b84c0735e749fc1');

View File

@ -0,0 +1,7 @@
/*
* Exposes number format capability
*
* @copyright Copyright (c) 2013 Kevin van Zonneveld (http://kvz.io) and Contributors (http://phpjs.org/authors).
* @license See CREDITS.md
* @see https://github.com/kvz/phpjs/blob/ffe1356af23a6f2512c84c954dd4e828e92579fa/functions/strings/number_format.js
*/

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => 'd0b88193b5b4008c3108');

View File

@ -0,0 +1 @@
.jetpack-sso-admin-create-user-invite-message{width:550px}.jetpack-sso-admin-create-user-invite-message-link-sso{text-decoration:none}#createuser .form-field textarea{width:25em}#createuser .form-field [type=checkbox]{width:1rem}#custom_email_message_description{color:#646970;font-size:12px;max-width:25rem}

View File

@ -0,0 +1 @@
document.addEventListener("DOMContentLoaded",(function(){const e=document.getElementById("send_user_notification"),d=document.getElementById("user_external_contractor"),t=document.getElementById("invite_user_wpcom"),n=document.getElementById("custom_email_message_block");t&&e&&n&&(t.addEventListener("change",(function(){e.disabled=t.checked,t.checked?(e.checked=!1,d&&(d.disabled=!1),n.style.display="table"):(d&&(d.disabled=!0,d.checked=!1),n.style.display="none")})),t.checked&&(e.disabled=!0,e.checked=!1,n.style.display="table"),t.checked||(d&&(d.disabled=!0),n.style.display="none"))}));

View File

@ -0,0 +1 @@
.jetpack-sso-admin-create-user-invite-message{width:550px}.jetpack-sso-admin-create-user-invite-message-link-sso{text-decoration:none}#createuser .form-field textarea{width:25em}#createuser .form-field [type=checkbox]{width:1rem}#custom_email_message_description{color:#646970;font-size:12px;max-width:25rem}

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '049775f3b0a647a127f9');

View File

@ -0,0 +1 @@
#loginform{padding-bottom:92px;position:relative!important}.jetpack-sso-repositioned #loginform{padding-bottom:26px}#loginform #jetpack-sso-wrap,#loginform #jetpack-sso-wrap *{box-sizing:border-box}#jetpack-sso-wrap__action,#jetpack-sso-wrap__user{display:none}.jetpack-sso-form-display #jetpack-sso-wrap__action,.jetpack-sso-form-display #jetpack-sso-wrap__user{display:block}#jetpack-sso-wrap{bottom:20px;margin-left:-24px;margin-right:-24px;padding:0 24px;position:absolute;width:100%}.jetpack-sso-repositioned #jetpack-sso-wrap{bottom:auto;margin-left:0;margin-right:0;margin-top:16px;padding:0;position:relative}.jetpack-sso-form-display #jetpack-sso-wrap{bottom:auto;margin-left:0;margin-right:0;margin-top:0;padding:0;position:relative}#loginform #jetpack-sso-wrap p{color:#777;margin-bottom:16px}#jetpack-sso-wrap a{display:block;text-align:center;text-decoration:none;width:100%}#jetpack-sso-wrap .jetpack-sso-toggle.wpcom{display:none}.jetpack-sso-form-display #jetpack-sso-wrap .jetpack-sso-toggle.wpcom{display:block}.jetpack-sso-form-display #jetpack-sso-wrap .jetpack-sso-toggle.default,.jetpack-sso-form-display #loginform>div,.jetpack-sso-form-display #loginform>p{display:none}.jetpack-sso-form-display #loginform #jetpack-sso-wrap{display:block}.jetpack-sso-form-display #loginform{padding:26px 24px}.jetpack-sso-or{margin-bottom:16px;position:relative;text-align:center}.jetpack-sso-or:before{background:#dcdcde;content:"";height:1px;left:0;position:absolute;top:50%;width:100%}.jetpack-sso-or span{background:#fff;color:#777;padding:0 8px;position:relative;text-transform:uppercase}#jetpack-sso-wrap .button{align-items:center;display:flex;height:36px;justify-content:center;margin-bottom:16px;width:100%}#jetpack-sso-wrap .button .genericon-wordpress{font-size:24px;margin-right:4px}#jetpack-sso-wrap__user img{border-radius:50%;display:block;margin:0 auto 16px}#jetpack-sso-wrap__user h2{font-size:21px;font-weight:300;margin-bottom:16px;text-align:center}#jetpack-sso-wrap__user h2 span{font-weight:700}.jetpack-sso-wrap__reauth{margin-bottom:16px}.jetpack-sso-form-display #nav{display:none}.jetpack-sso-form-display #backtoblog{margin:24px 0 0}.jetpack-sso-clear:after{clear:both;content:"";display:table}

Some files were not shown because too many files have changed in this diff Show More