iThemes Sync - Version 2.0.2

Version Description

Download this release

Release Info

Developer layotte
Plugin Icon 128x128 iThemes Sync
Version 2.0.2
Comparing to
See all releases

Code changes from version 2.0.1 to 2.0.2

Files changed (110) hide show
  1. history.txt +2 -0
  2. init.php +1 -1
  3. lang/ithemes-sync.pot +3 -3
  4. readme.txt +129 -16
  5. trunk/admin.php +0 -233
  6. trunk/api.php +0 -274
  7. trunk/api.txt +0 -60
  8. trunk/ca/index.php +0 -1
  9. trunk/ca/roots.crt +0 -58
  10. trunk/class-ithemes-credentials.php +0 -143
  11. trunk/class-ithemes-sync-json.php +0 -64
  12. trunk/class-ithemes-sync-utf8-encoder.php +0 -343
  13. trunk/client-dashboard.php +0 -413
  14. trunk/css/admin-notice.css +0 -53
  15. trunk/css/client-dashboard.css +0 -147
  16. trunk/css/index.php +0 -1
  17. trunk/css/settings-page.css +0 -195
  18. trunk/css/social-metabox.css +0 -52
  19. trunk/duplicator.php +0 -127
  20. trunk/functions.php +0 -1011
  21. trunk/history.txt +0 -186
  22. trunk/images/index.php +0 -1
  23. trunk/index.php +0 -1
  24. trunk/init.php +0 -54
  25. trunk/js/admin-notice.js +0 -25
  26. trunk/js/index.php +0 -1
  27. trunk/js/settings-page.js +0 -10
  28. trunk/js/social-metabox.js +0 -49
  29. trunk/lang/index.php +0 -1
  30. trunk/lang/ithemes-sync.pot +0 -620
  31. trunk/lib/index.php +0 -1
  32. trunk/lib/updater/admin.php +0 -215
  33. trunk/lib/updater/api.php +0 -301
  34. trunk/lib/updater/api.txt +0 -40
  35. trunk/lib/updater/ca/index.php +0 -1
  36. trunk/lib/updater/ca/roots.crt +0 -58
  37. trunk/lib/updater/class-ithemes-credentials.php +0 -143
  38. trunk/lib/updater/css/index.php +0 -1
  39. trunk/lib/updater/css/settings-page.css +0 -67
  40. trunk/lib/updater/functions.php +0 -61
  41. trunk/lib/updater/history.txt +0 -38
  42. trunk/lib/updater/images/index.php +0 -1
  43. trunk/lib/updater/index.php +0 -1
  44. trunk/lib/updater/information.php +0 -56
  45. trunk/lib/updater/init.php +0 -54
  46. trunk/lib/updater/keys.php +0 -165
  47. trunk/lib/updater/load.php +0 -54
  48. trunk/lib/updater/packages.php +0 -223
  49. trunk/lib/updater/server.php +0 -217
  50. trunk/lib/updater/settings-page.php +0 -659
  51. trunk/lib/updater/settings.php +0 -336
  52. trunk/lib/updater/updates.php +0 -166
  53. trunk/load-translations.php +0 -21
  54. trunk/load.php +0 -188
  55. trunk/notice-handler.php +0 -106
  56. trunk/notices.php +0 -187
  57. trunk/readme.txt +0 -37
  58. trunk/request-handler.php +0 -459
  59. trunk/server.php +0 -239
  60. trunk/settings-page.php +0 -349
  61. trunk/settings.php +0 -211
  62. trunk/social.php +0 -167
  63. trunk/uninstall.php +0 -22
  64. trunk/upgrader-skin.php +0 -23
  65. trunk/verbs/db-optimization.php +0 -388
  66. trunk/verbs/deauthenticate-user.php +0 -36
  67. trunk/verbs/do-update.php +0 -326
  68. trunk/verbs/get-admin-bar-item-whitelist.php +0 -32
  69. trunk/verbs/get-admin-bar-items.php +0 -32
  70. trunk/verbs/get-admin-menu.php +0 -22
  71. trunk/verbs/get-authentication-token.php +0 -53
  72. trunk/verbs/get-comment-details.php +0 -173
  73. trunk/verbs/get-dashboard-widgets.php +0 -22
  74. trunk/verbs/get-gf-form-entries.php +0 -64
  75. trunk/verbs/get-gf-forms.php +0 -25
  76. trunk/verbs/get-notices.php +0 -40
  77. trunk/verbs/get-options.php +0 -73
  78. trunk/verbs/get-php-details.php +0 -30
  79. trunk/verbs/get-plugin-details.php +0 -30
  80. trunk/verbs/get-post-types.php +0 -29
  81. trunk/verbs/get-posts.php +0 -84
  82. trunk/verbs/get-role-details.php +0 -40
  83. trunk/verbs/get-server-details.php +0 -30
  84. trunk/verbs/get-status-elements.php +0 -28
  85. trunk/verbs/get-status.php +0 -79
  86. trunk/verbs/get-supported-verbs.php +0 -32
  87. trunk/verbs/get-sync-settings.php +0 -30
  88. trunk/verbs/get-theme-details.php +0 -30
  89. trunk/verbs/get-update-details.php +0 -30
  90. trunk/verbs/get-updates.php +0 -32
  91. trunk/verbs/get-user-details.php +0 -52
  92. trunk/verbs/get-wordpress-details.php +0 -30
  93. trunk/verbs/get-wordpress-settings.php +0 -248
  94. trunk/verbs/get-wordpress-users.php +0 -31
  95. trunk/verbs/get-yoast-seo-summary.php +0 -27
  96. trunk/verbs/index.php +0 -1
  97. trunk/verbs/manage-comments.php +0 -344
  98. trunk/verbs/manage-ithemes-licenses.php +0 -111
  99. trunk/verbs/manage-options.php +0 -75
  100. trunk/verbs/manage-plugins.php +0 -215
  101. trunk/verbs/manage-posts.php +0 -136
  102. trunk/verbs/manage-reports.php +0 -107
  103. trunk/verbs/manage-roles.php +0 -100
  104. trunk/verbs/manage-themes.php +0 -189
  105. trunk/verbs/manage-users.php +0 -120
  106. trunk/verbs/set-admin-bar-item-whitelist.php +0 -40
  107. trunk/verbs/update-google-site-verification-token.php +0 -23
  108. trunk/verbs/update-show-sync.php +0 -38
  109. trunk/verbs/verb.php +0 -30
  110. verbs/get-authentication-token.php +2 -1
history.txt CHANGED
@@ -182,3 +182,5 @@
182
  Enhancement: Add ability to read and set most options found Settings pages.
183
  2.0.0 - 2017-06-01 - Lew Ayotte
184
  Initial release to WordPress.org
 
 
182
  Enhancement: Add ability to read and set most options found Settings pages.
183
  2.0.0 - 2017-06-01 - Lew Ayotte
184
  Initial release to WordPress.org
185
+ 2.0.1 - 2017-06-21 - Lew Ayotte
186
+ Bug Fix: Adding code to get-authentication-token verb to set the scheme to https by default if it should be
init.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: iThemes Sync
4
  Plugin URI: http://ithemes.com/sync
5
  Description: Manage updates to your WordPress sites easily in one place.
6
  Author: iThemes
7
- Version: 2.0.0
8
  Author URI: http://ithemes.com/
9
  Domain Path: /lang/
10
  iThemes Package: ithemes-sync
4
  Plugin URI: http://ithemes.com/sync
5
  Description: Manage updates to your WordPress sites easily in one place.
6
  Author: iThemes
7
+ Version: 2.0.1
8
  Author URI: http://ithemes.com/
9
  Domain Path: /lang/
10
  iThemes Package: ithemes-sync
lang/ithemes-sync.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the iThemes Sync package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: iThemes Sync 2.0.0\n"
6
  "Report-Msgid-Bugs-To: http://ithemes.com/support/\n"
7
- "POT-Creation-Date: 2017-06-01 20:02:57+00:00\n"
8
  "PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
@@ -35,7 +35,7 @@ msgstr ""
35
  msgid "iThemes Sync is now hidden from your user again."
36
  msgstr ""
37
 
38
- #. #-#-#-#-# ithemes-sync.pot (iThemes Sync 2.0.0) #-#-#-#-#
39
  #. Plugin Name of the plugin/theme
40
  #: admin.php:168 admin.php:174 settings-page.php:268
41
  msgid "iThemes Sync"
2
  # This file is distributed under the same license as the iThemes Sync package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: iThemes Sync 2.0.1\n"
6
  "Report-Msgid-Bugs-To: http://ithemes.com/support/\n"
7
+ "POT-Creation-Date: 2017-06-21 12:49:59+00:00\n"
8
  "PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
35
  msgid "iThemes Sync is now hidden from your user again."
36
  msgstr ""
37
 
38
+ #. #-#-#-#-# ithemes-sync.pot (iThemes Sync 2.0.1) #-#-#-#-#
39
  #. Plugin Name of the plugin/theme
40
  #: admin.php:168 admin.php:174 settings-page.php:268
41
  msgid "iThemes Sync"
readme.txt CHANGED
@@ -1,34 +1,147 @@
1
  === iThemes Sync ===
2
- Contributors: ithemes, layotte, glennansley
3
- Tags: Manage Multiple Sites, Backup, Security, Migrate, SEO, Manage Updates, Administration, Update Manager, Reports, Reporting, Scheduled Reports, Sync, Google Analytics, Google Webmaster Tools, Optimize, Uptime, iThemes, Customize Dashboard, Client Sites, Maintenance, Management
4
  Requires at least: 4.5
5
- Tested up to: 4.7.3
6
- Stable tag: 2.0.0
7
- License: GPLv2 or later
8
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
10
- == License ==
11
- Released under the terms of the GNU General Public License.
12
 
13
  == Description ==
14
 
15
  = Manage Multiple WordPress Sites From One Dashboard =
16
 
17
- Manage updates (and much more!) for your WordPress websites all in one place. Save time logging in to multiple websites to perform WordPress admin tasks.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  == Installation ==
20
 
21
- 1. Upload the zip file to the `/wp-content/plugins/` directory
22
- 2. Unzip
23
- 3. Activate the plugin through the 'Plugins' menu in WordPress
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  DISCLAIMER: Under no circumstances do we release this plugin with any warranty, implied or otherwise. We cannot be held responsible for any damage that might arise from the use of this plugin.
26
 
27
  == Frequently Asked Questions ==
28
 
29
- https://ithemes.com/sync/#faq
30
 
31
- == Changelog ==
32
 
33
- = 2.0.0 =
34
- * Initial release to WordPress.org
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  === iThemes Sync ===
2
+ Contributors: ithemes, layotte, blepoxp
3
+ Tags: manage multiple Sites, backup, security, migrate, SEO, manage updates, administration, update manager, reports, sync, google analytics, optimize, uptime, ithemes, customize dashboard, client sites, maintenance, management, google webmaster tools, reporting
4
  Requires at least: 4.5
5
+ Tested up to: 4.8
6
+ Stable tag: 2.0.1
7
+ License: GPLv3 or later
8
+ License URI: http://www.gnu.org/licenses/quick-guide-gplv3.html
9
 
10
+ Manage multiple WordPress sites from one dashboard.
 
11
 
12
  == Description ==
13
 
14
  = Manage Multiple WordPress Sites From One Dashboard =
15
 
16
+ Manage updates (and much more!) for all your WordPress websites from one central dashboard. With iThemes Sync, there’s no more logging in to multiple websites to perform WordPress admin tasks. Let iThemes Sync be your personal WordPress website assistant with features for WordPress management productivity. See all [20+ ways iThemes Sync will save you time in your WordPress workflow](https://ithemes.com/2015/06/17/20-ways-ithemes-sync-will-save-you-time/).
17
+
18
+ = Maintained and Supported by iThemes =
19
+
20
+ iThemes has been building WordPress tools since 2008, including iThemes Security, our [WordPress security plugin](http://ithemes.com/security) and BackupBuddy, our [WordPress backup plugin](http://ithemes.com/purchase/backupbuddy)
21
+
22
+ = One Central Dashboard to Save You Loads of Time =
23
+ iThemes Sync allows you to manage and maintain multiple WordPress websites from one central dashboard. Instead of having to login to each individual website, iTheme Sync gives you one place to view important website data and perform remote WordPress admin actions. Easily switch to iThemes Sync’s individual site view to perform site-specific admin actions such as running WordPress plugin and theme updates, making remote WordPress backups and more.
24
+
25
+ * No More Logging In To Multiple WordPress Websites - Logging in to multiple websites is tedious and time-consuming. No more keeping up with multiple usernames and passwords. With Sync, you have one dashboard for all your WordPress websites.
26
+ * Perform WordPress Admin Actions Remotely - iThemes Sync allows you to perform a host of admin tasks remotely—like installing themes and plugins, managing comments, running updates, adding users and much more.
27
+ * Stay On Top of WordPress Updates - WordPress updates are important both for the security and efficiency of WordPress websites. iThemes Sync totally changes the way you update your WordPress sites—now you can update dozens of sites with click.
28
+ * Bulk Install Themes and Plugins From WordPress.org or Zip Upload - Search and install from WordPress.org and view your WordPress.org profile favorites. Upload theme or plugin zip files or install themes and plugins directly from your iThemes membership.
29
+ * WordPress User Manager - WordPress user management in iThemes Sync allows you view all users on a website, edit user profiles and delete users remotely. With Sync’s Client Dashboard, you can customize how certain users see the WordPress dashboard.
30
+ * WordPress Post & Page Manager - View a list of current posts and pages on your site, including the title, author, date last modified, focus keyword, SEO score and SEO readability.
31
+ * Duplicate Pages & Posts Remotely - Once clicked, you’ll be taken to a new, duplicate post or page on your website.
32
+ * Remotely Login to WordPress & Switch Between User Accounts - Quickly jump to the WordPress Admin dashboard of your WordPress site where you’ll be instantly logged in from iThemes Sync. You can also switch between any WordPress user account registered on the site without sharing password info.
33
+ * WordPress Comment Manager - View all comments (all, approved, pending, spam, trash) and unapprove, mark as spam, or move comments to trash.
34
+ * WordPress Database Optimizations (Pro) - Make sure your WordPress sites are running efficiently with WordPress optimizations. Sync handles actions like cleaning out post revisions, spam comments and more.
35
+ * WordPress Uptime Monitoring (Pro) - Sync Pro offers a way to monitor WordPress uptime, downtime & overall performance for all your WordPress websites. Get notification emails when sites go down and view a history of your overall WordPress performance.
36
+ * SEO Checker + Google Analytics & Google Search Console Reports (Pro) - Track key SEO metrics with Sync's [SEO Checker](https://ithemes.com/2016/11/09/yoast-seo-checker-ithemes-sync/) and Google Analytics & Google Search Console integration. Sync integrates with the Yoast SEO plugin to give you an overview of the health of your SEO efforts.
37
+ * Remote WordPress Backups & WordPress Security Actions - Run remote backups with Sync's integration with BackupBuddy, our WordPress backup plugin, and perform more WordPress security actions from Sync with iThemes Security, our WordPress security plugin.
38
+
39
+ = Features Designed for Freelancers and Agencies =
40
+ Sync Pro was made for anyone managing multiple WordPress sites. If you're building sites for clients, you'll love how Sync makes caring for client sites easier and more profitable.
41
+
42
+ * WordPress Maintenance Reports - Sync Pro includes in-depth WordPress maintenance reporting to show the work involved in maintaining WordPress websites. Email clients beautiful HTML email reports with a summary of update actions you took to keep their site running smoothly.
43
+ * Customize the WordPress dashboard for clients/users (Pro) - With Sync Pro, you get Client Dashboard, a WordPress role manager that controls which menu items your clients see in their WordPress dashboard. Don't want them have access to plugins, themes or settings? Simplify their dashboard so they only see what they need -- like posts and pages.
44
+ * Show/Hide Sync From the WP Dashboard - To keep your clients or other site users from messing with your Sync authentication or removing the plugin, you can choose to hide or show the plugin in the WordPress dashboard of each site you manage with Sync.
45
+ * Share Your Sync Dashboard with Another User - If you have other people on your team that you'd like to task with helping you maintain sites, this feature is a great way help you easily delegate your workload to other team members.
46
+ * Site Notes and Tags - Sync’s Notes feature is a handy way to keep notations about your Synced sites. For example, if you added customizations to theme or plugin files that could be lost with an update, add a reminder. Tag business sites, personal sites, client sites, live, non-live or however you want to be able identify your sites.
47
+
48
+ = WordPress Security & Monitoring =
49
+
50
+ * Two-factor Authentication - Add an extra layer of protection to your Sync dashboard login with two-factor authentication. Once enabled, Sync will require both a password AND an SMS code sent to your mobile device to log in to the Sync Dashboard.
51
+ * WordPress Uptime Monitoring - Monitor WordPress uptime and know immediately if one of your websites goes down with uptime notification emails. View uptime stats such as total uptime percentage, total downtime, and number of downtimes for WordPress performance monitoring.
52
+ * Whitelist Your IP Address (iThemes Security integration) - Temporarily whitelist your IP Address remotely so you don't get locked out of your website by the iThemes Security plugin's Bad Users feature.
53
+ * Release iThemes Security Lockouts (iThemes Security integration) - View and release any current iThemes Security lockouts.
54
+
55
+ = WordPress Updates =
56
+
57
+ * Daily Notification Emails - Get a daily summary of available WordPress updates as a helpful reminder to log in and run updates. Customize the delivery time your daily notification emails to fit your schedule.
58
+ * One-Click Update All - View a summary of all available updates for all your websites and then update them all with one click.
59
+ * View Plugin Changelogs - View update logs that include all updates made in Sync, including the date of the update, previous version number and new version number.
60
+ * View Updates by Site - The in-depth individual site view gives you a detailed view of the available updates for that site, with more WordPress site management action options.
61
+ * Sort Updates By Theme or Plugin - View a listing of individual theme and plugins you have installed on your websites along with available update information.
62
+ * Ignore Update Option - If you've made customizations to your themes and plugins, an update could overwrite your work. Choose to ignore updates for specific themes and plugins.
63
+
64
+ = WordPress Maintenance Reports for Clients (Pro) =
65
+ Make steady, reliable income for WordPress maintenance with iThemes Sync Pro’s WordPress Maintenance Reports.
66
+
67
+ * Show Clients the Value of What You Do - Detailed website reports are one of the best ways to show clients the value of a monthly [WordPress maintenance](https://ithemes.com/sync/wordpress-maintenance/) plan. Sync Pro's WordPress Maintenance Reports handle the hard work of compiling all the update actions you took, so you can justify the value of what you do.
68
+ * White-label Report Emails - Upload your own logo and set custom colors for the header, footer and button color of report emails to better match your company’s branding.
69
+ * Summarize Update Actions to WordPress Core, Themes & Plugins + More Website Stats - Reports include all update actions taken within a certain timeframe, both from the Sync dashboard and the WordPress dashboard. [See a full list of all of stats included in Sync's WordPress reports](https://ithemes.com/sync/wordpress-report-stats/).
70
+ * Schedule Reports to Automatically Run & Deliver Report Emails - Reports can run on a daily, weekly or monthly basis, and then automatically email reports to clients.
71
+ * Email Beautiful, Interactive HTML Reports to Clients - Reports are delivered as beautiful, interactive HTML reports so clients can get a visual summary of the WordPress maintenance you provide. Sync handles compiling and organizing update actions and key website stats. [See a WordPress maintenance report demo](https://ithemes.com/sync-pro/demo-report.html).
72
+ * SEO Reporting - Summarize key SEO Stats stats in an easy-to-digest format — showing how your client’s sites are doing in Google and where they can improve. [See a WordPress SEO report demo](https://ithemes.com/sync-pro/seo-demo-report.html).
73
+
74
+ = Integrations =
75
+
76
+ * WordPress.org - Search and install themes and plugins from WordPress.org remotely from Sync. View your WordPress.org profile favorites to save time.
77
+ * BackupBuddy - Run remote WordPress backups, download your latest backup file, view number of edits since your last BackupBuddy backup and download ImportBuddy remotely.
78
+ * BackupBuddy Stash - View, download and delete your BackupBuddy Stash backups, and view a graph of the total amount of Stash space you've used.
79
+ * iThemes Security - Temporarily Whitelist your IP Address remotely so you don't get locked out of the website. View and release any iThemes Security lockouts.
80
+ * Google Analytics - Track Google Analytics for multiple WordPress sites. View key metrics from Google Analytics such as traffic, landing pages, keywords, sessions and referrer URLS.
81
+ * Google Search Console - Get a quick summary of Google Search Console data, view search analytics, crawl errors and sitemaps info.
82
+ * Twitter - Automatically share posts and pages to Twitter. Once activated, adds a button to your WordPress post editor to tweet.
83
+ * Yoast SEO - Sync's SEO Checker feature integrates with the Yoast SEO Plugin so you can quickly see the SEO status of the content on your WordPress website.
84
+ * Gravity Forms - From Sync, you can view all the forms you’ve created in Gravity Forms for that site. You can also quickly see how many responses and views each form has received.
85
+ * WP101 Plugin - Easily add a complete series of WordPress onboarding tutorial videos to the WordPress dashboard of your client sites with Sync's WP101 plugin integration.
86
+
87
+ == Changelog ==
88
+
89
+ = 2.0.1 =
90
+ * Adding code to get-authentication-token verb to set the scheme to https by default if it should be
91
+
92
+ = 2.0.0 =
93
+ * Initial Release to wordpress.org
94
 
95
  == Installation ==
96
 
97
+ 1. Signup for your [free iThemes Sync 10 site plan](https://sync.ithemes.com/signup).
98
+ 2. Follow the normal WordPress plugin installation method to install the iThemes Sync plugin on your WordPress website.
99
+ 3. Follow the steps to add your first website to iThemes Sync.
100
+
101
+ For more detailed instructions, check out the [Sync Quick Setup Guide](https://ithemes.com/2013/11/11/how-to-set-up-ithemes-sync/).
102
+
103
+ == Screenshots ==
104
+
105
+ 1. iThemes Sync dashboard home screen with multiple WordPress websites
106
+ 2. Individual site view with remote WordPress admin actions
107
+ 3. Updates view with listing of themes/plugins and available site updates
108
+ 4. Bulk install themes and plugins across multiple sites via zip upload and WordPress.org search
109
+ 5. Uptime monitoring (Pro)
110
+ 6. Run remote backups and download backup files remotely with BackupBuddy integration
111
+ 7. Update sites on the go with mobile-optimized dashboard
112
+ 8. Activate Client Dashboard for certain users. Customize the WordPress dashboard and hide/display menu items (Pro)
113
+ 9. Send clients interactive WordPress maintenance reports that summarize update actions and other key site metrics (Pro)
114
+
115
+
116
+ == License ==
117
+
118
+ This file is part of iThemes Sync. This plugin is released under the terms of the GNU General Public License.
119
 
120
  DISCLAIMER: Under no circumstances do we release this plugin with any warranty, implied or otherwise. We cannot be held responsible for any damage that might arise from the use of this plugin.
121
 
122
  == Frequently Asked Questions ==
123
 
124
+ = Is iThemes Sync free? =
125
 
126
+ You can manage 10 sites totally free for iThemes Sync. If you need additional sites, you can [add more sites to your Sync plan](https://ithemes.com/sync). Some features including Client Dashboard and WordPress Maintenance Reports are Pro-only features and not included in the 10-site free plan.
127
 
128
+ = Do you offer support for free users? =
129
+
130
+ Yes. We handle support for free iThemes Sync users both from the WordPress.org forum and from the [iThemes Help Desk](https://ithemes.com/support). The iThemes Help Desk offers private, ticketed support to protect your privacy.
131
+
132
+ = Is iThemes Sync secure? =
133
+
134
+ Yes. We develop and maintain iThemes Sync according to strict WordPress security standards. We take security seriously; so much so, we have an in-house WordPress security team and have our own WordPress security plugin with over 1 million active installs.
135
+
136
+ To help keep access to iThemes Sync secure, we strongly suggest enabling two-factor authentication for your iTheme Sync account. Using two-factor authentication for your Sync login will help ensure that only you have access to the websites in Sync. Because iThemes Sync allows you to perform WordPress administrator tasks such as installing and uninstalling themes and plugins, adding WordPress user accounts, logging into the WordPress dashboard and more, securing your iThemes Sync account is as important as securing your WordPress administrator account login.
137
+
138
+ = Does iThemes Sync work with WordPress.com sites? =
139
+
140
+ No. iThemes Sync only works with self-hosted WordPress sites.
141
+
142
+ = Help! I’m having problems adding a site to Sync. =
143
+
144
+ iThemes Sync includes an automatic “Add Site" prompt when you first login to the Sync dashboard. If this authentication method fails, try manually installing the iThemes Sync plugin on your WordPress site. Make sure to [create an iThemes account here](https://sync.ithemes.com/signup) and then follow the prompt from the Sync plugin to add your credentials. If you still need help, please open a ticket at the [iThemes Help Desk](https://ithemes.com/support).
145
+
146
+
147
+ Got more questions? [Contact us!](https://ithemes.com/contact “iThemes Contact")
trunk/admin.php DELETED
@@ -1,233 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Set up admin interface.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.2.0
7
-
8
- Version History
9
- 1.0.0 - 2013-10-02 - Chris Jean
10
- Initial version
11
- 1.1.0 - 2013-11-19 - Chris Jean
12
- Added the ability for the show_sync option to control who sees the Sync interface and plugin.
13
- 1.2.0 - 2014-02-14 - Chris Jean
14
- Added support for ?ithemes-sync-force-display=1 in the admin page to force a hidden Sync plugin to display for that specific user.
15
- */
16
-
17
-
18
- require_once( $GLOBALS['ithemes_sync_path'] . '/load-translations.php' );
19
-
20
- class Ithemes_Sync_Admin {
21
- private $page_name = 'ithemes-sync';
22
-
23
- private $page_ref;
24
-
25
-
26
- public function __construct() {
27
- add_action( 'init', array( $this, 'init' ) );
28
- add_action( 'wp_ajax_ithemes_sync_hide_notice', array( $this, 'hide_authenticate_notice' ) );
29
- }
30
-
31
- public function modify_plugins_page() {
32
- add_filter( 'all_plugins', array( $this, 'remove_sync_plugin' ) );
33
- }
34
-
35
- public function remove_sync_plugin( $plugins ) {
36
- unset( $plugins[basename( $GLOBALS['ithemes_sync_path'] ) . '/init.php'] );
37
-
38
- return $plugins;
39
- }
40
-
41
- public function init() {
42
- require_once( $GLOBALS['ithemes_sync_path'] . '/settings.php' );
43
-
44
-
45
- $show_sync = $GLOBALS['ithemes-sync-settings']->get_option( 'show_sync' );
46
-
47
- if ( is_array( $show_sync ) ) {
48
- $show_sync = in_array( get_current_user_id(), $show_sync );
49
- }
50
-
51
- if ( ! $show_sync && current_user_can( 'manage_options' ) ) {
52
- $user_id = get_current_user_id();
53
-
54
- if ( isset( $_GET['ithemes-sync-force-display'] ) ) {
55
- if ( ! empty( $_GET['ithemes-sync-force-display'] ) ) {
56
- $show_sync = true;
57
- set_site_transient( "ithemes-sync-force-display-$user_id", true, 600 );
58
-
59
- add_action( 'all_admin_notices', array( $this, 'show_force_display_notice' ), 0 );
60
- } else {
61
- delete_site_transient( "ithemes-sync-force-display-$user_id" );
62
-
63
- add_action( 'all_admin_notices', array( $this, 'show_force_display_disable_notice' ), 0 );
64
- }
65
- } else if ( false !== get_site_transient( "ithemes-sync-force-display-$user_id" ) ) {
66
- $show_sync = true;
67
-
68
- add_action( 'all_admin_notices', array( $this, 'show_force_display_notice' ), 0 );
69
- }
70
- }
71
-
72
-
73
- if ( $show_sync ) {
74
- if ( ! is_multisite() || is_super_admin() ) {
75
- add_action( 'admin_menu', array( $this, 'add_admin_pages' ) );
76
- }
77
-
78
- add_action( 'network_admin_menu', array( $this, 'add_network_admin_pages' ) );
79
-
80
-
81
- if ( current_user_can( 'manage_options' ) ) {
82
- if ( ! get_site_option( 'ithemes-sync-authenticated' ) && ( empty( $_GET['page'] ) || ( $this->page_name != $_GET['page'] ) ) && ! get_site_option( 'ithemes_sync_hide_authenticate_notice' ) ) {
83
- require_once( $GLOBALS['ithemes_sync_path'] . '/functions.php' );
84
-
85
- $path_url = Ithemes_Sync_Functions::get_url( $GLOBALS['ithemes_sync_path'] );
86
- wp_enqueue_style( 'ithemes-updater-admin-notice-style', "$path_url/css/admin-notice.css" );
87
- wp_enqueue_script( 'ithemes-updater-admin-notice-script', "$path_url/js/admin-notice.js", array( 'jquery' ) );
88
-
89
- add_action( 'all_admin_notices', array( $this, 'show_authenticate_notice' ), 0 );
90
-
91
- delete_site_transient( 'ithemes-sync-activated' );
92
- }
93
- else if ( ! empty( $_GET['activate'] ) && get_site_transient( 'ithemes-sync-activated' ) ) {
94
- require_once( $GLOBALS['ithemes_sync_path'] . '/functions.php' );
95
-
96
- $path_url = Ithemes_Sync_Functions::get_url( $GLOBALS['ithemes_sync_path'] );
97
- wp_enqueue_style( 'ithemes-updater-admin-notice-style', "$path_url/css/admin-notice.css" );
98
- wp_enqueue_script( 'ithemes-updater-admin-notice-script', "$path_url/js/admin-notice.js", array( 'jquery' ) );
99
-
100
- add_action( 'all_admin_notices', array( $this, 'show_activate_notice' ), 0 );
101
-
102
- delete_site_transient( 'ithemes-sync-activated' );
103
- }
104
- }
105
- } else {
106
- add_action( 'load-plugins.php', array( $this, 'modify_plugins_page' ) );
107
- }
108
- }
109
-
110
- public function show_activate_notice() {
111
- if ( is_multisite() && is_network_admin() )
112
- $url = network_admin_url( 'settings.php' ) . "?page={$this->page_name}";
113
- else
114
- $url = admin_url( 'options-general.php' ) . "?page={$this->page_name}";
115
-
116
- ?>
117
- <div class="updated" id="ithemes-sync-notice">
118
- <?php printf( __( 'iThemes Sync is active. <a class="ithemes-sync-notice-button" href="%s">Manage Sync</a> <a class="ithemes-sync-notice-dismiss" href="#">×</a>', 'it-l10n-ithemes-sync' ), $url ); ?>
119
- </div>
120
- <?php
121
-
122
- }
123
-
124
- public function show_authenticate_notice() {
125
- if ( is_multisite() && is_network_admin() )
126
- $url = network_admin_url( 'settings.php' ) . "?page={$this->page_name}";
127
- else
128
- $url = admin_url( 'options-general.php' ) . "?page={$this->page_name}";
129
-
130
- ?>
131
- <div class="updated" id="ithemes-sync-notice">
132
- <?php printf( __( 'iThemes Sync is almost ready. <a class="ithemes-sync-notice-button" href="%s">Set Up Sync</a> <a class="ithemes-sync-notice-hide" href="#">×</a>', 'it-l10n-ithemes-sync' ), $url ); ?>
133
- </div>
134
- <?php
135
-
136
- }
137
-
138
- public function show_force_display_notice() {
139
- $user_id = get_current_user_id();
140
- $time = get_site_option( "_site_transient_timeout_ithemes-sync-force-display-$user_id" );
141
- $time_diff = human_time_diff( time(), $time );
142
-
143
- $url = admin_url( 'index.php?ithemes-sync-force-display=0' );
144
-
145
- ?>
146
- <div class="updated">
147
- <p><?php printf( __( 'iThemes Sync will show for your user for the next %1$s. Click <a href="%2$s">here</a> to hide iThemes Sync again.', 'it-l10n-ithemes-sync' ), $time_diff, $url ); ?></p>
148
- </div>
149
- <?php
150
-
151
- }
152
-
153
- public function show_force_display_disable_notice() {
154
-
155
- ?>
156
- <div class="updated">
157
- <p><?php _e( 'iThemes Sync is now hidden from your user again.', 'it-l10n-ithemes-sync' ); ?></p>
158
- </div>
159
- <?php
160
-
161
- }
162
-
163
- public function hide_authenticate_notice() {
164
- update_site_option( 'ithemes_sync_hide_authenticate_notice', true );
165
- }
166
-
167
- public function add_admin_pages() {
168
- $this->page_ref = add_options_page( __( 'iThemes Sync', 'it-l10n-ithemes-sync' ), __( 'iThemes Sync', 'it-l10n-ithemes-sync' ), 'manage_options', $this->page_name, array( $this, 'settings_index' ) );
169
-
170
- add_action( "load-{$this->page_ref}", array( $this, 'load_settings_page' ) );
171
- }
172
-
173
- public function add_network_admin_pages() {
174
- $this->page_ref = add_submenu_page( 'settings.php', __( 'iThemes Sync', 'it-l10n-ithemes-sync' ), __( 'iThemes Sync', 'it-l10n-ithemes-sync' ), 'manage_options', $this->page_name, array( $this, 'settings_index' ) );
175
-
176
- add_action( "load-{$this->page_ref}", array( $this, 'load_settings_page' ) );
177
- }
178
-
179
- public function load_settings_page() {
180
- require_once( $GLOBALS['ithemes_sync_path'] . '/settings.php' );
181
-
182
- require( $GLOBALS['ithemes_sync_path'] . '/settings-page.php' );
183
- }
184
-
185
- public function settings_index() {
186
- do_action( 'ithemes_sync_settings_page_index' );
187
- }
188
-
189
- private function set_package_details() {
190
- if ( false !== $this->package_details )
191
- return;
192
-
193
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
194
- $this->package_details = Ithemes_Updater_Packages::get_local_details();
195
- }
196
-
197
- private function set_registration_link() {
198
- if ( false !== $this->registration_link )
199
- return;
200
-
201
- $url = admin_url( 'options-general.php' ) . "?page={$this->page_name}";
202
- $this->registration_link = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $url, __( 'Manage iThemes product licenses to receive automatic upgrade support', 'it-l10n-ithemes-sync' ), __( 'License', 'it-l10n-ithemes-sync' ) );
203
- }
204
-
205
- public function filter_plugin_action_links( $actions, $plugin_file, $plugin_data, $context ) {
206
- $this->set_package_details();
207
- $this->set_registration_link();
208
-
209
- if ( isset( $this->package_details[$plugin_file] ) )
210
- $actions[] = $this->registration_link;
211
-
212
- return $actions;
213
- }
214
-
215
- public function filter_theme_action_links( $actions, $theme ) {
216
- $this->set_package_details();
217
- $this->set_registration_link();
218
-
219
- if ( is_object( $theme ) )
220
- $path = basename( $theme->get_stylesheet_directory() ) . '/style.css';
221
- else if ( is_array( $theme ) && isset( $theme['Stylesheet Dir'] ) )
222
- $path = $theme['Stylesheet Dir'] . '/style.css';
223
- else
224
- $path = '';
225
-
226
- if ( isset( $this->package_details[$path] ) )
227
- $actions[] = $this->registration_link;
228
-
229
- return $actions;
230
- }
231
- }
232
-
233
- new Ithemes_Sync_Admin();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/api.php DELETED
@@ -1,274 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Simple API for managing verbs for Sync.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.4.1
7
-
8
- Version History
9
- 1.0.0 - 2013-10-01 - Chris Jean
10
- Initial version
11
- 1.1.0 - 2013-11-18 - Chris Jean
12
- Updated default verbs.
13
- 1.2.0 - 2014-01-20 - Chris Jean
14
- Added: get-status-elements, manage-plugins, and manage-themes.
15
- Added: is_default_status_element(), get_default_status_elements().
16
- 1.2.1 - 2014-02-07 - Chris Jean
17
- When including a verb's file, errors are no longer hidden. This allows for easier detection of verbs with problems.
18
- Better handling of invalid verbs.
19
- 1.3.0 - 2014-03-25 - Chris Jean
20
- Added: get-notices.
21
- 1.4.0 - 2014-07-01 - Chris Jean
22
- Added: get-comment-details, get-options, get-role-details, get-user-details, manage-commments, manage-roles, manage-users.
23
- register() now returns true when a Verb has been successfully registered.
24
- 1.4.1 - 2014-11-10 - Chris Jean
25
- Changed init hook priority to 11 in order to avoid issues with some plugin updates not appearing.
26
- */
27
-
28
-
29
- class Ithemes_Sync_API {
30
- private $verbs = array();
31
-
32
- private $default_verbs = array(
33
- 'db-optimization' => 'Ithemes_Sync_Verb_DB_Optimization',
34
- 'deauthenticate-user' => 'Ithemes_Sync_Verb_Deauthenticate_User',
35
- 'do-update' => 'Ithemes_Sync_Verb_Do_Update',
36
- 'get-admin-bar-item-whitelist' => 'Ithemes_Sync_Verb_Get_Admin_Bar_Item_Whitelist',
37
- 'get-admin-bar-items' => 'Ithemes_Sync_Verb_Get_Admin_Bar_Items',
38
- 'get-admin-menu' => 'Ithemes_Sync_Verb_Get_Admin_Menu',
39
- 'get-authentication-token' => 'Ithemes_Sync_Verb_Get_Authentication_Token',
40
- 'get-comment-details' => 'Ithemes_Sync_Verb_Get_Comment_Details',
41
- 'get-dashboard-widgets' => 'Ithemes_Sync_Verb_Get_Dashboard_Widgets',
42
- 'get-options' => 'Ithemes_Sync_Verb_Get_Options',
43
- 'get-php-details' => 'Ithemes_Sync_Verb_Get_PHP_Details',
44
- 'get-plugin-details' => 'Ithemes_Sync_Verb_Get_Plugin_Details',
45
- 'get-posts' => 'Ithemes_Sync_Verb_Get_Posts',
46
- 'get-post-types' => 'Ithemes_Sync_Verb_Get_Post_Types',
47
- 'get-notices' => 'Ithemes_Sync_Verb_Get_Notices',
48
- 'get-role-details' => 'Ithemes_Sync_Verb_Get_Role_Details',
49
- 'get-server-details' => 'Ithemes_Sync_Verb_Get_Server_Details',
50
- 'get-status' => 'Ithemes_Sync_Verb_Get_Status',
51
- 'get-status-elements' => 'Ithemes_Sync_Verb_Get_Status_Elements',
52
- 'get-supported-verbs' => 'Ithemes_Sync_Verb_Get_Supported_Verbs',
53
- 'get-sync-settings' => 'Ithemes_Sync_Verb_Get_Sync_Settings',
54
- 'get-theme-details' => 'Ithemes_Sync_Verb_Get_Theme_Details',
55
- 'get-update-details' => 'Ithemes_Sync_Verb_Get_Update_Details',
56
- 'get-updates' => 'Ithemes_Sync_Verb_Get_Updates',
57
- 'get-user-details' => 'Ithemes_Sync_Verb_Get_User_Details',
58
- 'get-wordpress-details' => 'Ithemes_Sync_Verb_Get_Wordpress_Details',
59
- 'get-wordpress-settings' => 'Ithemes_Sync_Verb_Get_Wordpress_Settings',
60
- 'get-wordpress-users' => 'Ithemes_Sync_Verb_Get_Wordpress_Users',
61
- 'manage-posts' => 'Ithemes_Sync_Verb_Manage_Posts',
62
- 'manage-comments' => 'Ithemes_Sync_Verb_Manage_Comments',
63
- 'manage-ithemes-licenses' => 'Ithemes_Sync_Verb_Manage_Ithemes_Licenses',
64
- 'manage-options' => 'Ithemes_Sync_Verb_Manage_Options',
65
- 'manage-plugins' => 'Ithemes_Sync_Verb_Manage_Plugins',
66
- 'manage-reports' => 'Ithemes_Sync_Verb_Manage_Reports',
67
- 'manage-roles' => 'Ithemes_Sync_Verb_Manage_Roles',
68
- 'manage-themes' => 'Ithemes_Sync_Verb_Manage_Themes',
69
- 'manage-users' => 'Ithemes_Sync_Verb_Manage_Users',
70
- 'set-admin-bar-item-whitelist' => 'Ithemes_Sync_Verb_Set_Admin_Bar_Item_Whitelist',
71
- 'update-show-sync' => 'Ithemes_Sync_Verb_Update_Show_Sync',
72
- 'update-google-site-verification-token' => 'Ithemes_Sync_Verb_Update_Google_Site_Verification_Token',
73
- );
74
-
75
- public function __construct() {
76
- $GLOBALS['ithemes-sync-api'] = $this;
77
-
78
- require_once( $GLOBALS['ithemes_sync_path'] . '/functions.php' );
79
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
80
-
81
- // Gravity Forms Verbs
82
- if ( class_exists( 'GFForms' ) ) {
83
- $this->default_verbs['get-gf-forms'] = 'Ithemes_Sync_Verb_Get_GF_Forms';
84
- $this->default_verbs['get-gf-form-entries'] = 'Ithemes_Sync_Verb_Get_GF_Form_Entries';
85
- }
86
-
87
- // Yoast SEO Verbs
88
- if ( is_plugin_active( 'wordpress-seo/wp-seo.php' ) ) {
89
- $this->default_verbs['get-yoast-seo-summary'] = 'Ithemes_Sync_Verb_Get_Yoast_SEO_Summary';
90
- }
91
-
92
- add_action( 'init', array( $this, 'init' ), 11 );
93
- }
94
-
95
- public function init() {
96
- require_once( $GLOBALS['ithemes_sync_path'] . "/verbs/verb.php" );
97
-
98
- foreach ( $this->default_verbs as $name => $class ) {
99
- $this->register( $name, $class, $GLOBALS['ithemes_sync_path'] . "/verbs/$name.php" );
100
- }
101
-
102
- do_action( 'ithemes_sync_register_verbs', $this );
103
-
104
- do_action( 'ithemes_sync_verbs_registered' );
105
- }
106
-
107
- public function register( $name, $class, $file = '' ) {
108
- if ( isset( $this->verbs[$name] ) ) {
109
- do_action( 'ithemes-sync-add-log', 'Tried to add a verb name that already exists.', compact( 'name', 'class', 'file' ) );
110
- return false;
111
- }
112
-
113
- $this->verbs[$name] = compact( 'name', 'class', 'file' );
114
-
115
- return true;
116
- }
117
-
118
- public function get_names() {
119
- return array_keys( $this->verbs );
120
- }
121
-
122
- public function get_description( $name ) {
123
- $class = $this->get_class( $name );
124
-
125
- if ( false === $class )
126
- return '';
127
-
128
-
129
- $vars = get_class_vars( $class );
130
-
131
- if ( isset( $vars['description'] ) )
132
- return $vars['description'];
133
-
134
- return '';
135
- }
136
-
137
- public function get_descriptions() {
138
- $names = $this->get_names();
139
- $descriptions = array();
140
-
141
- foreach ( $names as $name )
142
- $descriptions[$name] = $this->get_description( $name );
143
-
144
- return $descriptions;
145
- }
146
-
147
- public function get_status_element( $name ) {
148
- $class = $this->get_class( $name );
149
-
150
- if ( false === $class ) {
151
- return false;
152
- }
153
-
154
-
155
- $vars = get_class_vars( $class );
156
-
157
- if ( ! empty( $vars['status_element_name'] ) ) {
158
- return $vars['status_element_name'];
159
- }
160
-
161
- return false;
162
- }
163
-
164
- public function get_status_elements() {
165
- $names = $this->get_names();
166
- $status_elements = array();
167
-
168
- foreach ( $names as $name ) {
169
- $status_element = $this->get_status_element( $name );
170
-
171
- if ( false !== $status_element ) {
172
- $status_elements[$status_element] = $name;
173
- }
174
- }
175
-
176
- return $status_elements;
177
- }
178
-
179
- public function is_default_status_element( $name ) {
180
- $class = $this->get_class( $name );
181
-
182
- if ( false === $class ) {
183
- return false;
184
- }
185
-
186
-
187
- $vars = get_class_vars( $class );
188
-
189
- if ( ! empty( $vars['show_in_status_by_default'] ) ) {
190
- return $vars['show_in_status_by_default'];
191
- }
192
-
193
- return false;
194
- }
195
-
196
- public function get_default_status_elements() {
197
- $names = $this->get_names();
198
- $default_status_elements = array();
199
-
200
- foreach ( $names as $name ) {
201
- if ( $this->is_default_status_element( $name ) ) {
202
- $default_status_elements[] = $this->get_status_element( $name );
203
- }
204
- }
205
-
206
- return $default_status_elements;
207
- }
208
-
209
- public function run( $name, $arguments = array() ) {
210
- $object = $this->get_object( $name );
211
-
212
- if ( false == $object ) {
213
- return new WP_Error( 'invalid-verb-object', "Unable to find a valid object for the requested verb: $name" );
214
- }
215
-
216
- return $object->run( $arguments );
217
- }
218
-
219
- private function get_class( $name ) {
220
- if ( ! isset( $this->verbs[$name] ) ) {
221
- do_action( 'ithemes-sync-add-log', 'Unable to find requested verb.', array( 'name' => $name ) );
222
- return false;
223
- }
224
-
225
- if ( ! class_exists( $this->verbs[$name]['class'] ) ) {
226
- if ( empty( $this->verbs[$name]['file'] ) ) {
227
- do_action( 'ithemes-sync-add-log', 'Unable to find requested verb\'s class.', $this->verbs[$name] );
228
- return false;
229
- }
230
- else if ( ! is_file( $this->verbs[$name]['file'] ) ) {
231
- do_action( 'ithemes-sync-add-log', 'Unable to find requested verb\'s file.', $this->verbs[$name] );
232
- return false;
233
- }
234
- else {
235
- include_once( $this->verbs[$name]['file'] );
236
-
237
- if ( ! class_exists( $this->verbs[$name]['class'] ) ) {
238
- do_action( 'ithemes-sync-add-log', 'Unable to find requested verb\'s class even after loading its file.', $this->verbs[$name] );
239
- return false;
240
- }
241
-
242
- if ( ! is_subclass_of( $this->verbs[$name]['class'], 'Ithemes_Sync_Verb' ) ) {
243
- do_action( 'ithemes-sync-add-log', 'Verb added without being a subclass of Ithemes_Sync_Verb', $this->verbs[$name] );
244
- return false;
245
- }
246
- }
247
- }
248
-
249
- return $this->verbs[$name]['class'];
250
- }
251
-
252
- private function get_object( $name ) {
253
- if ( ! isset( $this->verbs[$name] ) ) {
254
- do_action( 'ithemes-sync-add-log', 'Unable to find requested verb.', array( 'name' => $name ) );
255
- return false;
256
- }
257
-
258
- if ( ! isset( $this->verbs[$name]['object'] ) ) {
259
- $class = $this->get_class( $name );
260
-
261
- if ( false === $class ) {
262
- return false;
263
- }
264
-
265
- $object = new $class();
266
-
267
- $this->verbs[$name]['object'] = $object;
268
- }
269
-
270
- return $this->verbs[$name]['object'];
271
- }
272
- }
273
-
274
- new Ithemes_Sync_API();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/api.txt DELETED
@@ -1,60 +0,0 @@
1
- #### Notices ####
2
-
3
- Sync can receive notifications from other projects. These notifications are of two kinds: normal and urgent.
4
-
5
-
6
- ## Normal Notices ##
7
-
8
- Normal notices are for providing information that is not urgent but should be made note of when an admin is maintaining the site. They are sent to the server when the server makes status requests or when specifically requesting notices from the site.
9
-
10
- Example:
11
-
12
- function backup_plugin_add_notices( $arguments ) {
13
- $data = array(
14
- 'last_backup' => 1394859600,
15
- 'last_backup_diff_from_now' => 988402,
16
- );
17
-
18
- // The verbose argument can be checked for in order to provide additional information that may not always be necessary.
19
- if ( ! empty( $arguments['verbose'] ) ) {
20
- $data['last_backup_type'] = 'full';
21
- }
22
-
23
- ithemes_sync_add_notice( 'backup_plugin', 'no_recent_backups', 'No recent backups', 'It has been more than a week since the last backup.', $data );
24
-
25
-
26
- // Plugin-specific arguments could be provided to enable additional notices that would be disabled by default.
27
- if ( ! empty( $arguments['backup_plugin_show_extra_notices'] ) ) {
28
- ithemes_sync_add_notice( 'backup_plugin', 'superfluous_notice', 'Superfluous notice', 'I ran out of good ideas, so this is merely an example.' );
29
- // Note how the $data argument is optional in the call above.
30
- }
31
- }
32
- add_action( 'ithemes_sync_add_notices', 'backup_plugin_add_notices' );
33
-
34
- Details about the ithemes_sync_add_notice function:
35
- * @param string $source Uniquely identifies the project that is sending the notice.
36
- * @param string $id Identifies the type of notice. This is to allow the server to differentiate different kinds of notices without having to parse the message.
37
- * @param string $subject A brief subject description of the notice that is fit for presentation to Sync users.
38
- * @param string $message A message that is fit for presentation to Sync users.
39
- * @param array $data Optional. Data that is relevant to the notice. For notices that may be best presented in a graphical manner, this field could be used to send data used to construct the graphic.
40
- * @return bool True. Currently, it always returns true.
41
-
42
-
43
- ## Urgent Notices ##
44
-
45
- Urgent notices are sent immediately to the server so that the administator can be notified directly. These notices are to be used when something important happens on the site that requires immediate attention.
46
-
47
- Example:
48
-
49
- function security_plugin_send_urgent_notice() {
50
- $result = ithemes_sync_send_urgent_notice( 'security_plugin', 'intruder_detected', 'Intruder detected', 'An intruder has been detected on the site.' );
51
- }
52
- add_action( 'init', 'security_plugin_send_urgent_notice' );
53
-
54
- Details about the ithemes_sync_send_urgent_notice function:
55
- * @param string $source Uniquely identifies the project that is sending the notice.
56
- * @param string $id Identifies the type of notice. This is to allow the server to differentiate different kinds of notices without having to parse the message.
57
- * @param string $subject A brief subject description of the notice that is fit for presentation to Sync users.
58
- * @param string $message A message that is fit for presentation to Sync users.
59
- * @param array $data Optional. Data that is relevant to the notice. For notices that may be best presented in a graphical manner, this field could be used to send data used to construct the graphic.
60
- * @return bool|WP_Error True on successful receipt by the server. WP_Error object otherwise. In the event of an error, the notice is queued for sending to the server when it makes a status or notice request.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/ca/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/ca/roots.crt DELETED
@@ -1,58 +0,0 @@
1
- ##
2
- ## CA Root Certificate for api.ithemes.com and s3.amazonaws.com
3
- ##
4
- ## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012
5
- ##
6
-
7
- # @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $
8
-
9
- Go Daddy Class 2 CA
10
- ===================
11
- -----BEGIN CERTIFICATE-----
12
- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
13
- VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
14
- ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
15
- A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
16
- RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
17
- ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
18
- 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
19
- qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
20
- YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
21
- vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
22
- BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
23
- atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
24
- MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
25
- A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
26
- PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
27
- I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
28
- HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
29
- Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
30
- vZ8=
31
- -----END CERTIFICATE-----
32
-
33
- VeriSign Class 3 Public Primary Certification Authority - G5
34
- ============================================================
35
- -----BEGIN CERTIFICATE-----
36
- MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
37
- BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
38
- ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
39
- IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
40
- ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
41
- yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
42
- biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
43
- dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
44
- YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
45
- ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
46
- j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
47
- Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
48
- Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
49
- fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
50
- BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
51
- Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
52
- aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
53
- SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
54
- X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
55
- KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
56
- Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
57
- ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
58
- -----END CERTIFICATE-----
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/class-ithemes-credentials.php DELETED
@@ -1,143 +0,0 @@
1
- <?php
2
-
3
- //-----------------------------------------------------------------------------
4
-
5
- class iThemes_Credentials
6
- {
7
-
8
- //-----------------------------------------------------------------------------
9
-
10
- protected $hash = 'sha256';
11
-
12
- protected $salt_padding = 'wdHVwU&HcYcWnllo%kTUUnxpScy4%ICM29';
13
-
14
- protected $iteration_count = 131072;
15
-
16
- protected $key_length = 64;
17
-
18
- protected $password;
19
-
20
- //-----------------------------------------------------------------------------
21
-
22
- public function __construct($username, $password, $options = array())
23
- {
24
-
25
- $this->username = $username;
26
-
27
- $this->password = $password;
28
-
29
-
30
- if(!empty($options['hash']))
31
- $this->hash = strtolower(trim($options['hash']));
32
-
33
- if(!empty($options['iterations']))
34
- $this->iteration_count = intval($options['iterations']);
35
-
36
- if(!empty($options['salt']))
37
- $this->salt_padding = $options['salt'];
38
-
39
- if(!empty($options['key_length']))
40
- $this->key_length = intval($options['key_length']);
41
-
42
- }
43
-
44
- //-----------------------------------------------------------------------------
45
-
46
- public static function get_password_hash($username, $password, $options = array())
47
- {
48
-
49
- $hasher = new iThemes_Credentials($username, $password, $options);
50
-
51
- return $hasher->get_pbkdf2();
52
-
53
- }
54
-
55
- //-----------------------------------------------------------------------------
56
-
57
- public function get_salt()
58
- {
59
-
60
- return strtolower(trim($this->username)) . $this->salt_padding;
61
-
62
- }
63
-
64
- //-----------------------------------------------------------------------------
65
-
66
- public function get_pbkdf2()
67
- {
68
-
69
- return $this->pbkdf2($this->hash,
70
- $this->password,
71
- $this->get_salt(),
72
- $this->iteration_count,
73
- $this->key_length / 2,
74
- false);
75
-
76
- }
77
-
78
- //-----------------------------------------------------------------------------
79
-
80
- /*
81
- * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
82
- * $algorithm - The hash algorithm to use. Recommended: SHA256
83
- * $password - The password.
84
- * $salt - A salt that is unique to the password.
85
- * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
86
- * $key_length - The length of the derived key in bytes.
87
- * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
88
- * Returns: A $key_length-byte key derived from the password and salt.
89
- *
90
- * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
91
- *
92
- * This implementation of PBKDF2 was originally created by https://defuse.ca
93
- * With improvements by http://www.variations-of-shadow.com
94
- */
95
- private function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
96
- {
97
-
98
- $algorithm = strtolower($algorithm);
99
-
100
- if(!in_array($algorithm, hash_algos(), true))
101
- trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR);
102
-
103
- if($count <= 0 || $key_length <= 0)
104
- trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR);
105
-
106
-
107
- $hash_length = strlen(hash($algorithm, '', true));
108
- $block_count = ceil($key_length / $hash_length);
109
-
110
- $output = '';
111
-
112
- for($i = 1; $i <= $block_count; $i++)
113
- {
114
-
115
- // $i encoded as 4 bytes, big endian.
116
- $last = $salt . pack("N", $i);
117
-
118
- // first iteration
119
- $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
120
-
121
- // perform the other $count - 1 iterations
122
- for ($j = 1; $j < $count; $j++)
123
- {
124
- $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
125
- }
126
-
127
- $output .= $xorsum;
128
-
129
- }
130
-
131
- if($raw_output)
132
- return substr($output, 0, $key_length);
133
- else
134
- return bin2hex(substr($output, 0, $key_length));
135
-
136
- }
137
-
138
- //-----------------------------------------------------------------------------
139
-
140
- }
141
-
142
- //-----------------------------------------------------------------------------
143
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/class-ithemes-sync-json.php DELETED
@@ -1,64 +0,0 @@
1
- <?php
2
-
3
- final class Ithemes_Sync_JSON {
4
- public static function encode( $data ) {
5
- $json = json_encode( $data );
6
-
7
- if ( false !== $json ) {
8
- return $json;
9
- }
10
-
11
- $data = self::get_fixed_data( $data );
12
- $json = json_encode( $data );
13
-
14
- if ( false !== $json ) {
15
- return $json;
16
- }
17
-
18
- return json_encode( 'Encoding error. Unable to JSON encode the data due to an unknown error.' );
19
- }
20
-
21
- private static function get_fixed_data( $data ) {
22
- if ( false !== json_encode( $data ) ) {
23
- return $data;
24
- }
25
-
26
- if ( is_string( $data ) ) {
27
- require_once( $GLOBALS['ithemes_sync_path'] . '/class-ithemes-sync-utf8-encoder.php' );
28
- $data = Ithemes_Sync_UTF8_Encoder::toUTF8( $data );
29
-
30
- if ( false === json_encode( $data ) ) {
31
- return 'INVALID STRING DATA';
32
- }
33
-
34
- return $data;
35
- }
36
-
37
- if ( is_array( $data ) ) {
38
- foreach ( $data as $key => $value ) {
39
- if ( false === json_encode( $key ) ) {
40
- unset( $data[$key] );
41
- $key = self::get_fixed_data( $key );
42
- $data[$key] = $value;
43
- }
44
-
45
- if ( false === json_encode( $value ) ) {
46
- $value = self::get_fixed_data( $value );
47
- $data[$key] = $value;
48
- }
49
- }
50
-
51
- if ( false === json_encode( $data ) ) {
52
- return 'INVALID ARRAY DATA';
53
- }
54
-
55
- return $data;
56
- }
57
-
58
- if ( is_object( $data ) ) {
59
- return 'INVALID CLASS ' . get_class( $data ) . ' DATA';
60
- }
61
-
62
- return 'INVALID DATA (' . gettype( $data ) . ')';
63
- }
64
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/class-ithemes-sync-utf8-encoder.php DELETED
@@ -1,343 +0,0 @@
1
- <?php
2
- /*
3
- Copyright (c) 2008 Sebastián Grignoli
4
- All rights reserved.
5
-
6
- Redistribution and use in source and binary forms, with or without
7
- modification, are permitted provided that the following conditions
8
- are met:
9
- 1. Redistributions of source code must retain the above copyright
10
- notice, this list of conditions and the following disclaimer.
11
- 2. Redistributions in binary form must reproduce the above copyright
12
- notice, this list of conditions and the following disclaimer in the
13
- documentation and/or other materials provided with the distribution.
14
- 3. Neither the name of copyright holders nor the names of its
15
- contributors may be used to endorse or promote products derived
16
- from this software without specific prior written permission.
17
-
18
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20
- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
22
- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
- POSSIBILITY OF SUCH DAMAGE.
29
- */
30
-
31
- /**
32
- * @author "Sebastián Grignoli" <grignoli@gmail.com>
33
- * @package Encoding
34
- * @version 2.0
35
- * @link https://github.com/neitanod/forceutf8
36
- * @example https://github.com/neitanod/forceutf8
37
- * @license Revised BSD
38
- */
39
-
40
- // Modified by Chris Jean of iThemes.com to add backcompat support for PHP 5.2.4.
41
-
42
- class Ithemes_Sync_UTF8_Encoder {
43
-
44
- protected static $win1252ToUtf8 = array(
45
- 128 => "\xe2\x82\xac",
46
-
47
- 130 => "\xe2\x80\x9a",
48
- 131 => "\xc6\x92",
49
- 132 => "\xe2\x80\x9e",
50
- 133 => "\xe2\x80\xa6",
51
- 134 => "\xe2\x80\xa0",
52
- 135 => "\xe2\x80\xa1",
53
- 136 => "\xcb\x86",
54
- 137 => "\xe2\x80\xb0",
55
- 138 => "\xc5\xa0",
56
- 139 => "\xe2\x80\xb9",
57
- 140 => "\xc5\x92",
58
-
59
- 142 => "\xc5\xbd",
60
-
61
-
62
- 145 => "\xe2\x80\x98",
63
- 146 => "\xe2\x80\x99",
64
- 147 => "\xe2\x80\x9c",
65
- 148 => "\xe2\x80\x9d",
66
- 149 => "\xe2\x80\xa2",
67
- 150 => "\xe2\x80\x93",
68
- 151 => "\xe2\x80\x94",
69
- 152 => "\xcb\x9c",
70
- 153 => "\xe2\x84\xa2",
71
- 154 => "\xc5\xa1",
72
- 155 => "\xe2\x80\xba",
73
- 156 => "\xc5\x93",
74
-
75
- 158 => "\xc5\xbe",
76
- 159 => "\xc5\xb8"
77
- );
78
-
79
- protected static $brokenUtf8ToUtf8 = array(
80
- "\xc2\x80" => "\xe2\x82\xac",
81
-
82
- "\xc2\x82" => "\xe2\x80\x9a",
83
- "\xc2\x83" => "\xc6\x92",
84
- "\xc2\x84" => "\xe2\x80\x9e",
85
- "\xc2\x85" => "\xe2\x80\xa6",
86
- "\xc2\x86" => "\xe2\x80\xa0",
87
- "\xc2\x87" => "\xe2\x80\xa1",
88
- "\xc2\x88" => "\xcb\x86",
89
- "\xc2\x89" => "\xe2\x80\xb0",
90
- "\xc2\x8a" => "\xc5\xa0",
91
- "\xc2\x8b" => "\xe2\x80\xb9",
92
- "\xc2\x8c" => "\xc5\x92",
93
-
94
- "\xc2\x8e" => "\xc5\xbd",
95
-
96
-
97
- "\xc2\x91" => "\xe2\x80\x98",
98
- "\xc2\x92" => "\xe2\x80\x99",
99
- "\xc2\x93" => "\xe2\x80\x9c",
100
- "\xc2\x94" => "\xe2\x80\x9d",
101
- "\xc2\x95" => "\xe2\x80\xa2",
102
- "\xc2\x96" => "\xe2\x80\x93",
103
- "\xc2\x97" => "\xe2\x80\x94",
104
- "\xc2\x98" => "\xcb\x9c",
105
- "\xc2\x99" => "\xe2\x84\xa2",
106
- "\xc2\x9a" => "\xc5\xa1",
107
- "\xc2\x9b" => "\xe2\x80\xba",
108
- "\xc2\x9c" => "\xc5\x93",
109
-
110
- "\xc2\x9e" => "\xc5\xbe",
111
- "\xc2\x9f" => "\xc5\xb8"
112
- );
113
-
114
- protected static $utf8ToWin1252 = array(
115
- "\xe2\x82\xac" => "\x80",
116
-
117
- "\xe2\x80\x9a" => "\x82",
118
- "\xc6\x92" => "\x83",
119
- "\xe2\x80\x9e" => "\x84",
120
- "\xe2\x80\xa6" => "\x85",
121
- "\xe2\x80\xa0" => "\x86",
122
- "\xe2\x80\xa1" => "\x87",
123
- "\xcb\x86" => "\x88",
124
- "\xe2\x80\xb0" => "\x89",
125
- "\xc5\xa0" => "\x8a",
126
- "\xe2\x80\xb9" => "\x8b",
127
- "\xc5\x92" => "\x8c",
128
-
129
- "\xc5\xbd" => "\x8e",
130
-
131
-
132
- "\xe2\x80\x98" => "\x91",
133
- "\xe2\x80\x99" => "\x92",
134
- "\xe2\x80\x9c" => "\x93",
135
- "\xe2\x80\x9d" => "\x94",
136
- "\xe2\x80\xa2" => "\x95",
137
- "\xe2\x80\x93" => "\x96",
138
- "\xe2\x80\x94" => "\x97",
139
- "\xcb\x9c" => "\x98",
140
- "\xe2\x84\xa2" => "\x99",
141
- "\xc5\xa1" => "\x9a",
142
- "\xe2\x80\xba" => "\x9b",
143
- "\xc5\x93" => "\x9c",
144
-
145
- "\xc5\xbe" => "\x9e",
146
- "\xc5\xb8" => "\x9f"
147
- );
148
-
149
- static function toUTF8($text){
150
- /**
151
- * Function \ForceUTF8\Encoding::toUTF8
152
- *
153
- * This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8.
154
- *
155
- * It assumes that the encoding of the original string is either Windows-1252 or ISO 8859-1.
156
- *
157
- * It may fail to convert characters to UTF-8 if they fall into one of these scenarios:
158
- *
159
- * 1) when any of these characters: ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞß
160
- * are followed by any of these: ("group B")
161
- * ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶•¸¹º»¼½¾¿
162
- * For example: %ABREPRESENT%C9%BB. «REPRESENTÉ»
163
- * The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB)
164
- * is also a valid unicode character, and will be left unchanged.
165
- *
166
- * 2) when any of these: àáâãäåæçèéêëìíîï are followed by TWO chars from group B,
167
- * 3) when any of these: ðñòó are followed by THREE chars from group B.
168
- *
169
- * @name toUTF8
170
- * @param string $text Any string.
171
- * @return string The same string, UTF8 encoded
172
- *
173
- */
174
-
175
- if(is_array($text))
176
- {
177
- foreach($text as $k => $v)
178
- {
179
- $text[$k] = self::toUTF8($v);
180
- }
181
- return $text;
182
- }
183
-
184
- if(!is_string($text)) {
185
- return $text;
186
- }
187
-
188
- $max = self::strlen($text);
189
-
190
- $buf = "";
191
- for($i = 0; $i < $max; $i++){
192
- $c1 = $text{$i};
193
- if($c1>="\xc0"){ //Should be converted to UTF8, if it's not UTF8 already
194
- $c2 = $i+1 >= $max? "\x00" : $text{$i+1};
195
- $c3 = $i+2 >= $max? "\x00" : $text{$i+2};
196
- $c4 = $i+3 >= $max? "\x00" : $text{$i+3};
197
- if($c1 >= "\xc0" & $c1 <= "\xdf"){ //looks like 2 bytes UTF8
198
- if($c2 >= "\x80" && $c2 <= "\xbf"){ //yeah, almost sure it's UTF8 already
199
- $buf .= $c1 . $c2;
200
- $i++;
201
- } else { //not valid UTF8. Convert it.
202
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
203
- $cc2 = ($c1 & "\x3f") | "\x80";
204
- $buf .= $cc1 . $cc2;
205
- }
206
- } elseif($c1 >= "\xe0" & $c1 <= "\xef"){ //looks like 3 bytes UTF8
207
- if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf"){ //yeah, almost sure it's UTF8 already
208
- $buf .= $c1 . $c2 . $c3;
209
- $i = $i + 2;
210
- } else { //not valid UTF8. Convert it.
211
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
212
- $cc2 = ($c1 & "\x3f") | "\x80";
213
- $buf .= $cc1 . $cc2;
214
- }
215
- } elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8
216
- if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already
217
- $buf .= $c1 . $c2 . $c3 . $c4;
218
- $i = $i + 3;
219
- } else { //not valid UTF8. Convert it.
220
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
221
- $cc2 = ($c1 & "\x3f") | "\x80";
222
- $buf .= $cc1 . $cc2;
223
- }
224
- } else { //doesn't look like UTF8, but should be converted
225
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
226
- $cc2 = (($c1 & "\x3f") | "\x80");
227
- $buf .= $cc1 . $cc2;
228
- }
229
- } elseif(($c1 & "\xc0") == "\x80"){ // needs conversion
230
- if(isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases
231
- $buf .= self::$win1252ToUtf8[ord($c1)];
232
- } else {
233
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
234
- $cc2 = (($c1 & "\x3f") | "\x80");
235
- $buf .= $cc1 . $cc2;
236
- }
237
- } else { // it doesn't need conversion
238
- $buf .= $c1;
239
- }
240
- }
241
- return $buf;
242
- }
243
-
244
- static function toWin1252($text, $option = '') {
245
- if(is_array($text)) {
246
- foreach($text as $k => $v) {
247
- $text[$k] = self::toWin1252($v, $option);
248
- }
249
- return $text;
250
- } elseif(is_string($text)) {
251
- return static::utf8_decode($text, $option);
252
- } else {
253
- return $text;
254
- }
255
- }
256
-
257
- static function toISO8859($text) {
258
- return self::toWin1252($text);
259
- }
260
-
261
- static function toLatin1($text) {
262
- return self::toWin1252($text);
263
- }
264
-
265
- static function fixUTF8($text, $option = ''){
266
- if(is_array($text)) {
267
- foreach($text as $k => $v) {
268
- $text[$k] = self::fixUTF8($v, $option);
269
- }
270
- return $text;
271
- }
272
-
273
- $last = "";
274
- while($last <> $text){
275
- $last = $text;
276
- $text = self::toUTF8(static::utf8_decode($text, $option));
277
- }
278
- $text = self::toUTF8(static::utf8_decode($text, $option));
279
- return $text;
280
- }
281
-
282
- static function UTF8FixWin1252Chars($text){
283
- // If you received an UTF-8 string that was converted from Windows-1252 as it was ISO8859-1
284
- // (ignoring Windows-1252 chars from 80 to 9F) use this function to fix it.
285
- // See: http://en.wikipedia.org/wiki/Windows-1252
286
-
287
- return str_replace(array_keys(self::$brokenUtf8ToUtf8), array_values(self::$brokenUtf8ToUtf8), $text);
288
- }
289
-
290
- static function removeBOM($str=""){
291
- if(substr($str, 0,3) == pack("CCC",0xef,0xbb,0xbf)) {
292
- $str=substr($str, 3);
293
- }
294
- return $str;
295
- }
296
-
297
- protected static function strlen($text){
298
- return (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) ?
299
- mb_strlen($text,'8bit') : strlen($text);
300
- }
301
-
302
- public static function normalizeEncoding($encodingLabel)
303
- {
304
- $encoding = strtoupper($encodingLabel);
305
- $encoding = preg_replace('/[^a-zA-Z0-9\s]/', '', $encoding);
306
- $equivalences = array(
307
- 'ISO88591' => 'ISO-8859-1',
308
- 'ISO8859' => 'ISO-8859-1',
309
- 'ISO' => 'ISO-8859-1',
310
- 'LATIN1' => 'ISO-8859-1',
311
- 'LATIN' => 'ISO-8859-1',
312
- 'UTF8' => 'UTF-8',
313
- 'UTF' => 'UTF-8',
314
- 'WIN1252' => 'ISO-8859-1',
315
- 'WINDOWS1252' => 'ISO-8859-1'
316
- );
317
-
318
- if(empty($equivalences[$encoding])){
319
- return 'UTF-8';
320
- }
321
-
322
- return $equivalences[$encoding];
323
- }
324
-
325
- public static function encode($encodingLabel, $text)
326
- {
327
- $encodingLabel = self::normalizeEncoding($encodingLabel);
328
- if($encodingLabel == 'ISO-8859-1') return self::toLatin1($text);
329
- return self::toUTF8($text);
330
- }
331
-
332
- protected static function utf8_decode($text, $option)
333
- {
334
- if ($option == '' || !function_exists('iconv')) {
335
- $o = utf8_decode(
336
- str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text))
337
- );
338
- } else {
339
- $o = iconv("UTF-8", "Windows-1252" . ($option == 'TRANSLIT' ? '//TRANSLIT' : ($option == 'IGNORE' ? '//IGNORE' : '')), $text);
340
- }
341
- return $o;
342
- }
343
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/client-dashboard.php DELETED
@@ -1,413 +0,0 @@
1
- <?php
2
-
3
- class Ithemes_Sync_Client_Dashboard {
4
-
5
- /**
6
- * @var array List of item IDs to ignore from our list and never send to Sync
7
- */
8
- private $_admin_bar_ignored_items = array(
9
- 'menu-toggle', //This is for admin responsiveness
10
- );
11
-
12
- public function __construct() {
13
- add_action( 'init', array( $this, 'init' ) );
14
- }
15
-
16
- public function init() {
17
- // If this user is supposed to see the client dashboard
18
- if ( get_user_meta( get_current_user_id(), 'ithemes-sync-client-dashboard', true ) ) {
19
- if ( ! get_user_meta( get_current_user_id(), 'ithemes-sync-client-dashboard-no-css', true ) ) {
20
- // Enqueue our admin scripts and styles
21
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_dashboard_scripts' ) );
22
- }
23
-
24
- if ( get_user_meta( get_current_user_id(), 'ithemes-sync-suppress-admin-notices', true ) ) {
25
- add_action( 'network_admin_notices', array( $this, 'admin_notices_start' ), 1 );
26
- add_action( 'user_admin_notices', array( $this, 'admin_notices_start' ), 1 );
27
- add_action( 'admin_notices', array( $this, 'admin_notices_start' ), 1 );
28
- add_action( 'all_admin_notices', array( $this, 'admin_notices_start' ), 1 );
29
- add_action( 'network_admin_notices', array( $this, 'admin_notices_end' ), 999 );
30
- add_action( 'user_admin_notices', array( $this, 'admin_notices_end' ), 999 );
31
- add_action( 'admin_notices', array( $this, 'admin_notices_end' ), 999 );
32
- add_action( 'all_admin_notices', array( $this, 'admin_notices_end' ), 999 );
33
- }
34
-
35
- // Filter menu items
36
- add_action( 'admin_menu', array( $this, 'filter_admin_menu' ), 999999 ); //We want to be last!
37
-
38
- // Filter admin bar items
39
- add_action( 'wp_before_admin_bar_render', array( $this, 'filter_admin_bar_menu' ), 1002 );
40
-
41
- // Filter dashboard widgets - screen_layout_columns fires late but before dashboard widgets are run or referenced in screen options
42
- add_action( 'screen_layout_columns', array( $this, 'filter_dashboard_widgets' ) );
43
-
44
- // Filter welcome panel
45
- add_filter( 'show_welcome_panel', array( $this, 'show_welcome_panel' ) );
46
- }
47
-
48
- add_action( 'admin_menu', array( $this, 'admin_menu' ), 999999 ); //We want to be last!
49
- add_action( 'wp_before_admin_bar_render', array( $this, 'admin_bar_menu' ), 999 );
50
-
51
- add_action( 'switch_theme', array( $this, 'clear_cache' ) );
52
- add_action( 'activate_plugin', array( $this, 'clear_cache' ) );
53
- add_action( 'deactivate_plugin', array( $this, 'clear_cache' ) );
54
- add_action( 'update_option_active_plugins', array( $this, 'clear_cache' ) );
55
- add_action( 'add_option_active_plugins', array( $this, 'clear_cache' ) );
56
-
57
- add_action( 'update_site_option_active_sitewide_plugins', array( $this, 'clear_cache_network' ) );
58
- add_action( 'add_site_option_active_sitewide_plugins', array( $this, 'clear_cache_network' ) );
59
-
60
- /**
61
- * Handle Dashboard Widgets
62
- */
63
- add_action( 'admin_footer-index.php', array( $this, 'dashboard_admin_footer' ) );
64
- }
65
-
66
- public function enqueue_dashboard_scripts() {
67
- // Enqueue an additional CSS file on the admin dashboard
68
- wp_enqueue_style( 'ithemes-sync-client-dashboard', plugins_url( 'css/client-dashboard.css', __FILE__ ), array( 'wp-admin' ), '20140801' );
69
- }
70
-
71
- /**
72
- * @param int User Id
73
- *
74
- * @return array List of menu_slugs to allow in menu. index is top level item, value is array of submenu items (or true for 'all')
75
- */
76
- public function get_allowed_admin_menu_items( $user_id = null ) {
77
- if ( ! $user_id ) {
78
- $user_id = get_current_user_id();
79
- }
80
-
81
- $menu_whitelist = get_user_meta( $user_id, 'ithemes-sync-admin_menu-whitelist', true );
82
-
83
- // If the user's admin_menu whitelist doesn't exist, set it.
84
- if ( ! is_array( $menu_whitelist ) ) {
85
- $menu_whitelist = array(
86
- 'index.php' => array(),
87
- 'edit.php' => true,
88
- 'edit.php?post_type=page' => true,
89
- 'edit-comments.php' => array(),
90
- );
91
- update_user_meta( $user_id, 'ithemes-sync-admin_menu-whitelist', $menu_whitelist );
92
- }
93
-
94
- return apply_filters( 'ithemes-sync-menu-items-whitelist', $menu_whitelist );
95
- }
96
-
97
- public function filter_admin_menu() {
98
- /**
99
- * @var array An array of menu elements. Each element is an array containing:
100
- * [0] - Label
101
- * [1] = capability
102
- * [2] = menu_slug
103
- * [3] = page_title
104
- * [4] = classes
105
- * [5] = hookname
106
- * [6] = icon_url
107
- */
108
- global $menu;
109
-
110
- /**
111
- * @var array An array of arrays of submenu elements, indexed by the menu_slug of the main menu item. Each submenu element is an array containing:
112
- * [0] - Label
113
- * [1] = capability
114
- * [2] = menu_slug
115
- */
116
- global $submenu;
117
-
118
- /**
119
- * @var array List of menu_slugs to allow in menu. index is top level item, value is array of submenu items (or true for 'all')
120
- */
121
- $menu_whitelist = $this->get_allowed_admin_menu_items();
122
-
123
- foreach ( $menu as $pos => $menu_item ) {
124
- if ( 'wp-menu-separator' == $menu_item[4] ) {
125
- continue;
126
- }
127
- if ( ! in_array( $menu_item[2], array_keys( $menu_whitelist ) ) ) {
128
- if ( isset( $submenu[ $menu_item[2] ] ) ) {
129
- unset( $submenu[ $menu_item[2] ] );
130
- }
131
- unset( $menu[ $pos ] );
132
- } elseif ( true !== $menu_whitelist[ $menu_item[2] ] && isset( $submenu[ $menu_item[2] ] ) ) {
133
- foreach ( $submenu[ $menu_item[2] ] as $subpos => $submenu_item ) {
134
- if ( ! in_array( $submenu_item[2], $menu_whitelist[ $menu_item[2] ] ) ) {
135
- unset( $submenu[ $menu_item[2] ][ $subpos ] );
136
- }
137
- }
138
- }
139
- }
140
- }
141
-
142
- public function admin_menu() {
143
- $admin_menu = get_option( 'ithemes-sync-admin_menu' );
144
- if ( false === $admin_menu ) {
145
- /**
146
- * @var array An array of menu elements. Each element is an array containing:
147
- * [0] - Label
148
- * [1] = capability
149
- * [2] = menu_slug
150
- * [3] = page_title
151
- * [4] = classes
152
- * [5] = hookname
153
- * [6] = icon_url
154
- */
155
- global $menu;
156
-
157
- /**
158
- * @var array An array of arrays of submenu elements, indexed by the menu_slug of the main menu item. Each submenu element is an array containing:
159
- * [0] - Label
160
- * [1] = capability
161
- * [2] = menu_slug
162
- */
163
- global $submenu;
164
-
165
- $admin_menu = array();
166
- foreach ( $menu as $menu_item ) {
167
- $admin_menu[$menu_item[2]] = array();
168
- $admin_menu[$menu_item[2]]['label'] = $menu_item[0];
169
-
170
- if ( ! empty( $submenu[$menu_item[2]] ) ) {
171
- $admin_menu[$menu_item[2]]['children'] = array();
172
- foreach ( $submenu[$menu_item[2]] as $submenu_item ) {
173
- $admin_menu[$menu_item[2]]['children'][$submenu_item[2]] = array( 'label' => $submenu_item[0] );
174
- }
175
- }
176
- }
177
-
178
- update_option( 'ithemes-sync-admin_menu', $admin_menu );
179
- }
180
- }
181
-
182
- /**
183
- * @param int User Id
184
- *
185
- * @return array List of dashboard widget ids to allow
186
- */
187
- public function get_allowed_admin_bar_items( $user_id = null ) {
188
- if ( ! $user_id ) {
189
- $user_id = get_current_user_id();
190
- }
191
-
192
- $whitelist = get_user_meta( $user_id, 'ithemes-sync-admin-bar-item-whitelist-' . get_current_blog_id(), true );
193
-
194
- // If the user's admin_menu whitelist doesn't exist, set it.
195
- if ( ! is_array( $whitelist ) ) {
196
- $whitelist = array(
197
- 'wp-logo',
198
- 'about',
199
- 'wp-logo-external',
200
- 'wporg',
201
- 'documentation',
202
- 'support-forums',
203
- 'feedback',
204
- 'site-name',
205
- 'comments',
206
- 'new-content',
207
- 'new-post',
208
- 'new-page',
209
- 'top-secondary',
210
- 'my-account',
211
- 'user-actions',
212
- 'user-info',
213
- 'edit-profile',
214
- 'logout',
215
- );
216
- update_user_meta( $user_id, 'ithemes-sync-admin-bar-item-whitelist-' . get_current_blog_id(), $whitelist );
217
- }
218
-
219
- $whitelist = array_merge( $whitelist, $this->_admin_bar_ignored_items );
220
-
221
- return apply_filters( 'ithemes-sync-admin-bar-item-whitelist-' . get_current_blog_id(), $whitelist );
222
- }
223
-
224
- public function filter_admin_bar_menu() {
225
- global $wp_admin_bar;
226
- $whitelist = $this->get_allowed_admin_bar_items();
227
-
228
- foreach ( $wp_admin_bar->get_nodes() as $node ) {
229
- if ( ! in_array( $node->id, $whitelist ) ) {
230
- $wp_admin_bar->remove_node( $node->id );
231
- }
232
- }
233
- }
234
-
235
- public function admin_bar_menu() {
236
- global $wp_admin_bar;
237
- $meta_key = 'ithemes-sync-admin-bar-items-' . get_current_blog_id();
238
-
239
- if ( is_array( get_user_meta( get_current_user_id(), $meta_key, true ) ) ) {
240
- return true;
241
- }
242
-
243
- $admin_bar = array();
244
- $admin_bar_nodes = $wp_admin_bar->get_nodes();
245
-
246
- $last_count = null;
247
- $iterations = 0;
248
- while ( ! empty( $admin_bar_nodes ) && ++$iterations <= 100 ) {
249
- foreach ( $admin_bar_nodes as $key => $current_node ) {
250
- if ( in_array( $current_node->id, $this->_admin_bar_ignored_items ) ) {
251
- // Don't send ignored items
252
- unset( $admin_bar_nodes[ $key ] );
253
- } elseif ( false == $current_node->parent ) {
254
- // Process parents
255
- $admin_bar[ $current_node->id ] = $this->_create_admin_bar_node( $current_node );
256
- unset( $admin_bar_nodes[ $key ] );
257
- } elseif ( $this->_place_child( $admin_bar, $this->_create_admin_bar_node( $current_node ) ) ) {
258
- // If we placed a child node successfully, remove it
259
- unset( $admin_bar_nodes[ $key ] );
260
- }
261
- }
262
-
263
- /**
264
- * If we haven't parsed any elements out since the last time through
265
- * the loop, break out to avoid an infinite loop. This only happens
266
- * when there are mal-formed admin bar nodes (such as nodes with a
267
- * non-existent parent)
268
- */
269
- if ( $last_count == count( $admin_bar_nodes ) ) {
270
- break;
271
- }
272
- $last_count = count( $admin_bar_nodes );
273
- }
274
-
275
- update_user_meta( get_current_user_id(), $meta_key, $admin_bar );
276
- }
277
-
278
- private function _place_child( &$all_nodes, $child_node ) {
279
- foreach ( $all_nodes as $id => &$node ) {
280
- if ( $id == $child_node->parent ) {
281
- $node->children[ $child_node->id ] = $child_node;
282
- return true;
283
- } elseif ( ! empty( $node->children ) && $this->_place_child( $node->children, $child_node ) ) {
284
- return true;
285
- }
286
- }
287
- return false;
288
- }
289
-
290
- private function _create_admin_bar_node( $node_info ) {
291
- $node = new stdClass();
292
- $node->id = $node_info->id;
293
- $node->title = $node_info->title;
294
- $node->parent = $node_info->parent;
295
- $node->type = $node_info->group? 'group':'item';
296
- $node->children = array();
297
- return $node;
298
- }
299
-
300
- /**
301
- * Clear the cache of our admin_menu and dashboard metaboxes by deleting the option
302
- */
303
- public function clear_cache() {
304
- delete_option( 'ithemes-sync-admin_menu' );
305
- delete_option( 'ithemes-sync-dashboard-metaboxes' );
306
-
307
- $users = get_users( array( 'blog_id' => get_current_blog_id(), 'fields' => array( 'ID' ) ) );
308
- $meta_key = 'ithemes-sync-admin-bar-items-' . get_current_blog_id();
309
- foreach ( $users as $user ) {
310
- delete_user_meta( $user->ID, $meta_key );
311
- }
312
- }
313
-
314
- /**
315
- * Clear the cache of our admin_menu and dashboard metaboxes from the whole
316
- * network (site...ugh) by deleting the option from each site (blog...ugh again)
317
- */
318
- public function clear_cache_network() {
319
- // Get the current site and only clear options from blogs in this site
320
- $site = get_current_site(); // Site = Network? Ugh.
321
- if ( $site && isset( $site->id ) ) {
322
- global $wpdb;
323
- $query = $wpdb->prepare( "SELECT `blog_id` FROM $wpdb->blogs WHERE `site_id`=%d", absint( $site->id ) );
324
- $users = get_users( array( 'blog_id' => 0, 'fields' => array( 'ID' ) ) );
325
- foreach( $wpdb->get_col( $query ) as $blog_id ) {
326
- delete_blog_option( $blog_id, 'ithemes-sync-admin_menu' );
327
- delete_blog_option( $blog_id, 'ithemes-sync-dashboard-metaboxes' );
328
-
329
- $meta_key = 'ithemes-sync-admin-bar-items-' . $blog_id;
330
- foreach ( $users as $user ) {
331
- delete_user_meta( $user->ID, $meta_key );
332
- }
333
- }
334
- }
335
- }
336
-
337
- public function dashboard_admin_footer() {
338
- $meta_box_list = get_option( 'ithemes-sync-dashboard-metaboxes' );
339
- if ( false === $meta_box_list ) {
340
- global $wp_meta_boxes;
341
- $screen = get_current_screen();
342
- $meta_box_list = array();
343
- foreach ( $wp_meta_boxes[$screen->id] as $box_position ) {
344
- foreach ( $box_position as $box_set ) {
345
- foreach ( $box_set as $box ) {
346
- $meta_box_list[ $box['id'] ] = $box['title'];
347
- }
348
- }
349
- }
350
- $meta_box_list['show_welcome_panel'] = _x( 'Welcome', 'Welcome panel' );
351
- update_option( 'ithemes-sync-dashboard-metaboxes', $meta_box_list );
352
- }
353
- }
354
-
355
- /**
356
- * @param int User Id
357
- *
358
- * @return array List of dashboard widget ids to allow
359
- */
360
- public function get_allowed_dashboard_widgets( $user_id = null ) {
361
- if ( ! $user_id ) {
362
- $user_id = get_current_user_id();
363
- }
364
-
365
- $whitelist = get_user_meta( $user_id, 'ithemes-sync-dashboard-widget-whitelist', true );
366
-
367
- // If the user's admin_menu whitelist doesn't exist, set it.
368
- if ( ! is_array( $whitelist ) ) {
369
- $whitelist = array(
370
- 'dashboard_right_now',
371
- 'dashboard_quick_press',
372
- 'show_welcome_panel',
373
- );
374
- update_user_meta( $user_id, 'ithemes-sync-dashboard-widget-whitelist', $whitelist );
375
- }
376
-
377
- return apply_filters( 'ithemes-sync-dashboard-widget-whitelist', $whitelist );
378
- }
379
-
380
- public function filter_dashboard_widgets() {
381
- $screen = get_current_screen();
382
- if ( $screen && 'dashboard' == $screen->id ) {
383
- global $wp_meta_boxes;
384
- $whitelist = $this->get_allowed_dashboard_widgets();
385
-
386
- foreach ( $wp_meta_boxes[$screen->id] as $box_position => $box_position_boxes ) {
387
- foreach ( $box_position_boxes as $priority => $box_set ) {
388
- foreach ( $box_set as $index => $box ) {
389
- if ( ! in_array( $box['id'], $whitelist ) ) {
390
- unset( $wp_meta_boxes[$screen->id][$box_position][$priority][$index] );
391
- }
392
- }
393
- }
394
- }
395
- }
396
- }
397
-
398
- public function show_welcome_panel( $show ) {
399
- if ( ! in_array( 'show_welcome_panel', $this->get_allowed_dashboard_widgets() ) ) {
400
- $show = 0;
401
- }
402
- return $show;
403
- }
404
-
405
- public function admin_notices_start() {
406
- ob_start();
407
- }
408
-
409
- public function admin_notices_end() {
410
- ob_end_clean();
411
- }
412
- }
413
- new Ithemes_Sync_Client_Dashboard();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/css/admin-notice.css DELETED
@@ -1,53 +0,0 @@
1
- #ithemes-sync-notice {
2
- background: #F3FCE6 url('../images/sync-icon.png') .85em center no-repeat;
3
- border: 1px solid #D8E9C1;
4
- border-bottom-width: 2px;
5
- border-radius: 3px;
6
- color: #44654E;
7
- font-size: 14px;
8
- line-height: 1.6;
9
- margin: 1em 0;
10
- padding: 1em .75em 1em 5em;
11
- position: relative;
12
- }
13
-
14
- #ithemes-sync-notice a {
15
- color: #495D68;
16
- font-weight: bold;
17
- text-decoration: none;
18
- }
19
-
20
- #ithemes-sync-notice .ithemes-sync-notice-button {
21
- background: #D8E9C1;
22
- border: 1px solid #B7CC9B;
23
- border-bottom-width: 2px;
24
- border-radius: 3px;
25
- display: inline-block;
26
- margin: -8px 0;
27
- padding: 6px 14px;
28
- -webkit-transition: all .1s linear;
29
- -moz-transition: all .1s linear;
30
- transition: all .1s linear;
31
- }
32
- #ithemes-sync-notice .ithemes-sync-notice-button:hover {
33
- background: #F9FFF0;
34
- }
35
-
36
- #ithemes-sync-notice .ithemes-sync-notice-dismiss,
37
- #ithemes-sync-notice .ithemes-sync-notice-hide {
38
- border: 1px solid transparent;
39
- border-radius: 3px;
40
- display: inline-block;
41
- float: right;
42
- margin: -8px 0;
43
- padding: 6px 14px;
44
- -webkit-transition: all .1s linear;
45
- -moz-transition: all .1s linear;
46
- transition: all .1s linear;
47
- }
48
- #ithemes-sync-notice .ithemes-sync-notice-dismiss:hover,
49
- #ithemes-sync-notice .ithemes-sync-notice-hide:hover {
50
- background: #D8E9C1;
51
- border: 1px solid #B7CC9B;
52
- border-bottom-width: 2px;
53
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/css/client-dashboard.css DELETED
@@ -1,147 +0,0 @@
1
- /**
2
- * Admin bar and left menu adjustments
3
- */
4
-
5
- #wpadminbar {
6
- height: 42px;
7
- }
8
- html.wp-toolbar {
9
- padding-top: 42px;
10
- }
11
- #wpadminbar .quicklinks .ab-empty-item,
12
- #wpadminbar .quicklinks a,
13
- #wpadminbar .shortlink-input {
14
- height: 42px;
15
- }
16
- #wpadminbar .quicklinks a,
17
- #wpadminbar #wp-admin-bar-user-info span {
18
- font-size: 16px;
19
- font-weight: 300;
20
- line-height: 40px;
21
- }
22
- #wpadminbar #wp-admin-bar-user-info span {
23
- height: 26px;
24
- }
25
- #wpadminbar .ab-icon, #wpadminbar .ab-item:before, #wpadminbar>#wp-toolbar>#wp-admin-bar-root-default .ab-icon {
26
- font-size: 26px;
27
- line-height: 1.1em;
28
- }
29
- #wpadminbar .quicklinks > ul > li#wp-admin-bar-my-account > a {
30
- padding: 0 14px;
31
- }
32
- #wpadminbar .quicklinks li#wp-admin-bar-my-account.with-avatar>a img {
33
- width: 26px;
34
- height: 26px;
35
- margin-left: 12px;
36
- }
37
- #adminmenu,
38
- #adminmenu .wp-submenu,
39
- #adminmenuback,
40
- #adminmenuwrap {
41
- width: 200px;
42
- }
43
- #adminmenu {
44
- margin: 0;
45
- }
46
- #wpcontent, #wpfooter {
47
- margin-left: 200px;
48
- }
49
- #adminmenu .wp-submenu {
50
- left: 200px;
51
- }
52
- #adminmenu .wp-submenu a {
53
- font-size: 14px;
54
- font-weight: 300;
55
- }
56
- #adminmenu li.wp-menu-separator {
57
- height: 0;
58
- margin: 0;
59
- }
60
- #adminmenu .wp-not-current-submenu .wp-submenu,
61
- .folded #adminmenu .wp-has-current-submenu .wp-submenu {
62
- min-width: 200px;
63
- }
64
- #adminmenu .wp-submenu-head,
65
- #adminmenu a.menu-top {
66
- font-size: 18px;
67
- font-weight: 300;
68
- line-height: 30px;
69
- min-height: 50px;
70
- }
71
- #adminmenu .wp-submenu-head {
72
- min-height: 34px;
73
- }
74
- div.wp-menu-image:before {
75
- padding: 14px 0;
76
- }
77
- #adminmenu li.wp-has-submenu.wp-not-current-submenu:hover:after {
78
- top: 16px;
79
- }
80
-
81
- #adminmenu .awaiting-mod,
82
- #adminmenu .update-plugins,
83
- #sidemenu li a span.update-plugins {
84
- margin: 7px 0 0 14px;
85
- font-size: 12px;
86
- font-weight: 300;
87
- line-height: 19px;
88
- }
89
-
90
- /**
91
- * Screen wpbody-content area
92
- */
93
-
94
- .wrap {
95
- margin-top: 5px;
96
- }
97
- #poststuff h3,
98
- .metabox-holder h3 {
99
- padding: 14px 18px;
100
- font-size: 16px;
101
- }
102
- .js .meta-box-sortables .postbox .handlediv:before,
103
- .js .sidebar-name .sidebar-name-arrow:before {
104
- right: 18px;
105
- padding: 15px 12px;
106
- }
107
- .tablenav {
108
- height: 48px;
109
- }
110
-
111
- /**
112
- * Buttons and form fields
113
- */
114
-
115
- .wp-core-ui .button,
116
- .wp-core-ui .button-primary,
117
- .wp-core-ui .button-secondary {
118
- font-size: 15px;
119
- height: 40px;
120
- line-height: 38px;
121
- padding: 0px 20px 2px;
122
- }
123
- .wp-core-ui .button-group.button-large .button, .wp-core-ui .button.button-large {
124
- height: 40px;
125
- line-height: 38px;
126
- padding: 0px 20px 2px;
127
- }
128
- .wp-media-buttons span.wp-media-buttons-icon {
129
- line-height: 1em;
130
- }
131
- .wp-admin select {
132
- line-height: 42px;
133
- height: 42px;
134
- }
135
- .search-box input[name="s"],
136
- .tablenav .search-plugins input[name="s"],
137
- .tagsdiv .newtag {
138
- height: 42px;
139
- }
140
- .wp-editor-tabs .wp-switch-editor {
141
- height: 27px;
142
- padding: 12px 12px 4px;
143
- }
144
- .html-active .wp-editor-tabs .switch-html,
145
- .tmce-active .wp-editor-tabs .switch-tmce {
146
- height: 28px;
147
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/css/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/css/settings-page.css DELETED
@@ -1,195 +0,0 @@
1
- @import url('http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,400,300,600,700');
2
-
3
-
4
- .ithemes-sync-wrapper {
5
- font-family: 'Open Sans', helvetica, arial, sans-serif;
6
- font-size: 14px;
7
- line-height: 1.5;
8
- margin: 0;
9
- padding: 2em;
10
- width: 100%;
11
- max-width: 900px;
12
- }
13
-
14
- .ithemes-sync-wrapper p {
15
- margin: 1em 0;
16
- }
17
-
18
- .ithemes-sync-wrapper h2,
19
- .ithemes-sync-wrapper h3,
20
- .ithemes-sync-wrapper h4 {
21
- color: #555555;
22
- font-weight: 300;
23
- margin: 1em 0;
24
- }
25
-
26
- .ithemes-sync-wrapper h2 {
27
- font-family: 'Open Sans', helvetica, arial, sans-serif;
28
- font-size: 2em;
29
- line-height: 1.5;
30
- margin: .5em 0;
31
- padding: 0;
32
- }
33
-
34
- .ithemes-sync-wrapper h3 {
35
- font-size: 1.5em;
36
- margin: .5em 0;
37
- }
38
-
39
-
40
- .ithemes-sync-wrapper .message {
41
- border: none;
42
- border-radius: 0;
43
- -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.04);
44
- box-shadow: 0 1px 1px rgba(0,0,0,.04);
45
- margin: 0 0 2em;
46
- padding: 1em 2em;
47
- }
48
- .ithemes-sync-wrapper .success {
49
- background: #EBF6D7;
50
- border: 1px solid #86a94a;
51
- }
52
-
53
- .ithemes-sync-wrapper .error {
54
- background: #FFEBE8;
55
- border: 1px solid #daa69e;
56
- }
57
-
58
- .ithemes-sync-manage-users,
59
- .ithemes-sync-authorize {
60
- background: #FFF;
61
- border: 1px solid #E5E5E5;
62
- -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.04);
63
- box-shadow: 0 1px 1px rgba(0,0,0,.04);
64
- margin:2em 0;
65
- padding: 1em 2em;
66
- }
67
-
68
- .ithemes-sync-button {
69
- background: #a8d657;
70
- border: none;
71
- border-bottom: 3px solid #86a94a;
72
- -webkit-border-radius: 3px;
73
- -moz-border-radius: 3px;
74
- border-radius: 3px;
75
- clear: both;
76
- color: #13350a;
77
- cursor: pointer;
78
- display: inline-block;
79
- font-size: 1em;
80
- font-weight: 700;
81
- margin-top: 1em;
82
- outline: none;
83
- padding: .75em 3em;
84
- text-align: center;
85
- text-decoration: none;
86
- }
87
-
88
- .ithemes-sync-button:hover {
89
- background: #B8E170;
90
- color: #13350a;
91
- }
92
-
93
- #ithemes-sync-authenticate {
94
- margin: 1em 0;
95
- }
96
- #ithemes-sync-authenticate input {
97
- border: 1px solid #C7C7C7;
98
- -webkit-border-radius: 3px;
99
- -moz-border-radius: 3px;
100
- margin: 1em 0 .5em 0;
101
- }
102
- #ithemes-sync-authenticate input[type="text"],
103
- #ithemes-sync-authenticate input[type="password"] {
104
- border: 1px solid #C7C7C7;
105
- display: block;
106
- font-size: 1.2em;
107
- margin-top: 0;
108
- padding: .5em .75em;
109
- }
110
-
111
- #ithemes-sync-authenticate input[type="submit"] {
112
- background: #a8d657;
113
- border: none;
114
- border-bottom: 3px solid #86a94a;
115
- clear: both;
116
- color: #13350a;
117
- cursor: pointer;
118
- display: block;
119
- font-size: 1em;
120
- font-weight: 700;
121
- margin-top: 2em;
122
- outline: none;
123
- padding: .75em 3em;
124
- }
125
- #ithemes-sync-authenticate input[type="submit"]:hover {
126
- background: #B8E170;
127
- }
128
-
129
- #ithemes-sync-authenticate input[type="submit"]:active {
130
- border-bottom: 3px solid #B8E170;
131
- -webkit-box-shadow: inset 0px 2px 3px #86A94A;
132
- -moz-box-shadow: inset 2px 3px #86A94A;
133
- box-shadow: inset 2px 3px #86A94A
134
- }
135
- #ithemes-sync-authenticate label {
136
- font-size: .875em;
137
- font-weight: 700;
138
- padding-left: 5px;
139
- }
140
-
141
- .ithemes-sync-users {
142
- border: 1px solid #ececec;
143
- margin-bottom: 1em;
144
- padding: 1em 1.5em 2em 1.5em;
145
- }
146
- .ithemes-sync-users + .ithemes-sync-users {
147
- margin-top: 2em;
148
- }
149
-
150
- .ithemes-sync-valid-users {
151
- border-left: 10px solid #A8D657;
152
- }
153
-
154
- .ithemes-sync-invalid-users {
155
- border-left: 10px solid #E86A6A;
156
- }
157
-
158
- .ithemes-sync-users h4 {
159
- font-size: 1.125em;
160
- padding-left: .75em;
161
- }
162
-
163
- .ithemes-sync-users ul {
164
- border: 1px solid #ebebeb;
165
- -webkit-border-radius: 5px;
166
- -moz-border-radius: 5px;
167
- border-radius: 5px;
168
- margin: 0;
169
- }
170
-
171
- .ithemes-sync-users li {
172
- border-bottom: 1px solid #ebebeb;
173
- margin: 0;
174
- overflow: hidden;
175
- padding: .5em 1em;
176
- }
177
- .ithemes-sync-users ul li:hover {
178
- background: #f5f5f5;
179
- }
180
-
181
- .ithemes-sync-users li .user {
182
- color: #666;
183
- font-weight: 700;
184
- float: left;
185
- max-width: 50%;
186
- }
187
-
188
- .ithemes-sync-users li .deauthenticate {
189
- float: right;
190
- }
191
-
192
- .ithemes-sync-users li .deauthenticate a {
193
- color: #e86a6a;
194
- text-decoration: none;
195
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/css/social-metabox.css DELETED
@@ -1,52 +0,0 @@
1
- #ithemes-social {
2
- margin: 1em 0;
3
- }
4
- #ithemes-social .ithemes-social-header {
5
- border-bottom: 1px solid #ddd;
6
- overflow:hidden;
7
- padding: 0 0 5px 0;
8
- }
9
- #ithemes-social .ithemes-social-header h3 {
10
- margin: 0 0 5px 0;
11
- padding: 0;
12
- float:left;
13
- }
14
- #ithemes-social .ithemes-social-header a {
15
- float:right;
16
- }
17
- #ithemes-social .ithemes-social-accounts {
18
- margin: 0;
19
- }
20
- #ithemes-social .ithemes-social-accounts li{
21
- border-bottom: 1px solid #e9e9e9;
22
- padding: 5px 0;
23
- margin: 0;
24
- word-break: break-all;
25
- }
26
- #ithemes-social .ithemes-social-edit-content {
27
- cursor:pointer;
28
- float: right;
29
- }
30
- #ithemes-social .ithemes-social-account-content {
31
- overflow: hidden;
32
- margin: 0 0 .5em 0;
33
- }
34
- #ithemes-social .ithemes-social-account-content textarea {
35
- margin: 1em 0 .25em 0;
36
- }
37
- #ithemes-social .ithemes-social-template-tags {
38
- font-size: 11px;
39
- line-height: 1.1;
40
- float:left;
41
- }
42
- #ithemes-social .ithemes-social-char-count {
43
- float:right;
44
- }
45
- #ithemes-social .ithemes-social-char-count.over {
46
- color: red;
47
- }
48
- #ithemes-social .it-social-notice {
49
- background: #f1f1f1;
50
- padding: 5px;
51
- margin: 5px 0;
52
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/duplicator.php DELETED
@@ -1,127 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Generates and returns the Duplicate Product URL
5
- *
6
- * @since 0.0.0
7
- *
8
- * @params object $post Current post object
9
- * @return string
10
- */
11
- function ithemes_sync_duplicate_post_addon_get_duplicating_url( $post ) {
12
- $args = array(
13
- 'post_type' => $post->post_type,
14
- 'ithemes-sync-duplicate-post-id' => $post->ID,
15
- );
16
-
17
- return add_query_arg( $args, admin_url( 'post-new.php' ) );
18
- }
19
-
20
- /**
21
- * Add Duplicate action from Any Post Types
22
- *
23
- * @since 0.0.0
24
- *
25
- * @params array $actions Current post row actions
26
- * @params object $post Current post object
27
- * @return array
28
- */
29
- function ithemes_sync_duplicate_post_addon_add_duplicate_post_function( $actions, $post ) {
30
- $url = ithemes_sync_duplicate_post_addon_get_duplicating_url( $post );
31
- $actions['ithemes_sync_duplicate'] = '<a class="sync_duplicate_post" id="sync-post-' . $post->ID . '" title="' . __( 'Duplicate Post', 'it-l10n-ithemes-sync' ) . '" href="' . $url . '">Duplicate</a>';
32
-
33
- return $actions;
34
- }
35
- add_filter( 'post_row_actions', 'ithemes_sync_duplicate_post_addon_add_duplicate_post_function', 10, 2 );
36
- add_filter( 'page_row_actions', 'ithemes_sync_duplicate_post_addon_add_duplicate_post_function', 10, 2 );
37
-
38
- /**
39
- * Copies previous post content to new post
40
- *
41
- * @since 0.0.0
42
- *
43
- * @params string $post_content Current WordPress default post content
44
- * @params object $post Current post object
45
- * @return array
46
- */
47
- function ithemes_sync_duplicate_post_addon_default_post_content( $post_content, $post ) {
48
- if ( !empty( $_REQUEST['ithemes-sync-duplicate-post-id'] )
49
- && $duplicate_post_post_id = $_REQUEST['ithemes-sync-duplicate-post-id'] ) {
50
- $duplicate_post_post = get_post( $duplicate_post_post_id );
51
- $post_content = $duplicate_post_post->post_content;
52
- }
53
-
54
- return $post_content;
55
- }
56
- add_filter( 'default_content', 'ithemes_sync_duplicate_post_addon_default_post_content', 10, 2 );
57
-
58
- /**
59
- * Copies previous post title to new post
60
- *
61
- * @since 1.1.2
62
- *
63
- * @params string $post_content Current WordPress default post title
64
- * @params object $post Current post object
65
- * @return array
66
- */
67
- function ithemes_sync_duplicate_post_addon_default_post_title( $post_title, $post ) {
68
- if ( !empty( $_REQUEST['ithemes-sync-duplicate-post-id'] )
69
- && $duplicate_post_post_id = $_REQUEST['ithemes-sync-duplicate-post-id'] ) {
70
- $duplicate_post_post = get_post( $duplicate_post_post_id );
71
- $post_title = $duplicate_post_post->post_title . ' - ' . __( 'copy', 'it-l10n-ithemes-exchange' );
72
- }
73
-
74
- return $post_title;
75
- }
76
- add_filter( 'default_title', 'ithemes_sync_duplicate_post_addon_default_post_title', 10, 2 );
77
-
78
- /**
79
- * Copies previous post content to new excerpt (not really used in Exchange)
80
- *
81
- * @since 1.1.2
82
- *
83
- * @params string $post_content Current WordPress default post excerpt
84
- * @params object $post Current post object
85
- * @return array
86
- */
87
- function ithemes_sync_duplicate_post_addon_default_post_excerpt( $post_excerpt, $post ) {
88
- if ( !empty( $_REQUEST['ithemes-sync-duplicate-post-id'] )
89
- && $duplicate_post_post_id = $_REQUEST['ithemes-sync-duplicate-post-id'] ) {
90
- $duplicate_post_post = get_post( $duplicate_post_post_id );
91
- $post_excerpt = $duplicate_post_post->post_excerpt;
92
- }
93
-
94
- return $post_excerpt;
95
- }
96
- add_filter( 'default_excerpt', 'ithemes_sync_duplicate_post_addon_default_post_excerpt', 10, 2 );
97
-
98
- /**
99
- * Copies previous post meta to new post
100
- *
101
- * @since 1.1.2
102
- *
103
- * @params string $post_type Current WordPress default post type (ignored)
104
- * @params object $post Current post object
105
- * @return array
106
- */
107
- function ithemes_sync_duplicate_post_addon_default_post_meta( $post_type, $post ) {
108
- if ( !empty( $_REQUEST['ithemes-sync-duplicate-post-id'] )
109
- && $duplicate_post_post_id = $_REQUEST['ithemes-sync-duplicate-post-id'] ) {
110
- $duplicate_post_post_meta = get_post_meta( $duplicate_post_post_id );
111
- foreach ( $duplicate_post_post_meta as $key => $values ) {
112
- foreach ( $values as $value ) {
113
- //We do not want to copy ALL of the post meta, some of it is specific to transaction history, etc.
114
- if ( in_array( $key, apply_filters( 'ithemes_sync_duplicate_post_addon_default_post_meta_invalid_keys', array( '_edit_lock', '_edit_last', '_ithemes_sync_transaction_id' ) ) ) ) {
115
- continue;
116
- }
117
- $value = maybe_unserialize( $value );
118
- add_post_meta( $post->ID, $key, $value );
119
-
120
- //Other add-ons might need to perform some extra actions with this new post meta (e.g. Membership)
121
- do_action( 'ithemes_sync_duplicate_post_addon_add_post_meta', $post, $key, $value );
122
- }
123
- }
124
- do_action( 'ithemes_sync_duplicate_post_addon_default_post_meta', $post, $duplicate_post_post_id );
125
- }
126
- }
127
- add_action( 'add_meta_boxes', 'ithemes_sync_duplicate_post_addon_default_post_meta', 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/functions.php DELETED
@@ -1,1011 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Misc functions to assist the Sync code.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.9.0
7
-
8
- Version History
9
- 1.8.0 - 2014-03-28 - Chris Jean
10
- Added find_match_in_file() and get_wordpress_db_version().
11
- get_wordpress_version() now uses find_match_in_file().
12
- 1.8.1 - 2014-04-14 - Chris Jean
13
- The reported WordPress version now uses wp-includes/version.php in order to get a reliable version number.
14
- Added mysqli_get_server_info entry to server status details in the event that WordPress is using mysqli.
15
- 1.8.2 - 2014-05-19 - Chris Jean
16
- Added checks to mysql_get_server_info() and mysqli_get_server_info() calls to avoid notices and errors.
17
- 1.8.3 - 2014-06-23 - Chris Jean
18
- Silenced possible notice-generating function calls by using @.
19
- Replaced direct shell_exec() calls with calls to self::run_shell_command().
20
- 1.8.4 - 2014-06-30 - Chris Jean
21
- Use mysqli_get_host_info instead of mysql_get_host_info when mysqli is being used.
22
- 1.8.5 - 2014-07-11 - Chris Jean
23
- Added is_callable_function() which checks both is_callable() and the disable_functions ini setting to determine if a function is callable.
24
- Replaced is_callable() calls for PHP functions with calls to self::is_callable_function() in order to avoid issues with servers that stop processing after a disabled function is run.
25
- 1.8.6 - 2014-10-23 - Chris Jean
26
- Added a fix to check for functions blacklisted by Suhosin before attempting to execute.
27
- 1.8.7 - 2014-11-06 - Chris Jean
28
- Fixed warnings that can happen when generating memory details on some systems.
29
- 1.9.0 - 2016-07-20 - Lew Ayotte
30
- Added get_upload_reports_dir
31
- */
32
-
33
-
34
- class Ithemes_Sync_Functions {
35
- public static function get_url( $path ) {
36
- $path = str_replace( '\\', '/', $path );
37
- $wp_content_dir = str_replace( '\\', '/', WP_CONTENT_DIR );
38
-
39
- if ( 0 === strpos( $path, $wp_content_dir ) ) {
40
- return content_url( str_replace( $wp_content_dir, '', $path ) );
41
- }
42
-
43
- $abspath = str_replace( '\\', '/', ABSPATH );
44
-
45
- if ( 0 === strpos( $path, $abspath ) ) {
46
- return site_url( str_replace( $abspath, '', $path ) );
47
- }
48
-
49
- $wp_plugin_dir = str_replace( '\\', '/', WP_PLUGIN_DIR );
50
- $wpmu_plugin_dir = str_replace( '\\', '/', WPMU_PLUGIN_DIR );
51
-
52
- if ( 0 === strpos( $path, $wp_plugin_dir ) || 0 === strpos( $path, $wpmu_plugin_dir ) ) {
53
- return plugins_url( basename( $path ), $path );
54
- }
55
-
56
- return false;
57
- }
58
-
59
- public static function get_post_data( $vars, $fill_missing = false, $merge_get_query = false ) {
60
- $data = array();
61
-
62
- foreach ( $vars as $var ) {
63
- if ( isset( $_POST[$var] ) ) {
64
- $clean_var = preg_replace( '/^it-updater-/', '', $var );
65
- $data[$clean_var] = $_POST[$var];
66
- }
67
- else if ( $merge_get_query && isset( $_GET[$var] ) ) {
68
- $clean_var = preg_replace( '/^it-updater-/', '', $var );
69
- $data[$clean_var] = $_GET[$var];
70
- }
71
- else if ( $fill_missing ) {
72
- $data[$var] = '';
73
- }
74
- }
75
-
76
- return stripslashes_deep( $data );
77
- }
78
-
79
- public static function filter_user_has_cap( $capabilities, $caps, $args ) {
80
- foreach ( $caps as $cap ) {
81
- $capabilities[$cap] = 1;
82
- }
83
-
84
- return $capabilities;
85
- }
86
-
87
- public static function get_plugin_details( $args = array() ) {
88
- if ( ! is_callable( 'get_plugins' ) ) {
89
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
90
- }
91
-
92
- if ( ! is_callable( 'get_plugins' ) ) {
93
- return false;
94
- }
95
-
96
-
97
- $plugins = get_plugins();
98
-
99
- $active_plugins = ( is_callable( 'wp_get_active_and_valid_plugins' ) ) ? wp_get_active_and_valid_plugins() : array();
100
- $network_active_plugins = ( is_callable( 'wp_get_active_network_plugins' ) ) ? wp_get_active_network_plugins() : array();
101
- // $mu_plugins = ( is_callable( 'get_mu_plugins' ) ) ? get_mu_plugins() : array();
102
- // $dropins = ( is_callable( 'get_dropins' ) ) ? get_dropins() : array();
103
-
104
- array_walk( $active_plugins, array( __CLASS__, 'strip_plugin_dir' ) );
105
- array_walk( $network_active_plugins, array( __CLASS__, 'strip_plugin_dir' ) );
106
-
107
- foreach ( $plugins as $plugin => $data ) {
108
- if ( in_array( $plugin, $active_plugins ) ) {
109
- $plugins[$plugin]['status'] = 'active';
110
- } else if ( in_array( $plugin, $network_active_plugins ) ) {
111
- $plugins[$plugin]['status'] = 'network_active';
112
- } else {
113
- $plugins[$plugin]['status'] = 'inactive';
114
- }
115
-
116
- if ( empty( $args['verbose'] ) ) {
117
- unset( $plugins[$plugin]['PluginURI'] );
118
- unset( $plugins[$plugin]['Description'] );
119
- unset( $plugins[$plugin]['Author'] );
120
- unset( $plugins[$plugin]['AuthorURI'] );
121
- unset( $plugins[$plugin]['TextDomain'] );
122
- unset( $plugins[$plugin]['DomainPath'] );
123
- unset( $plugins[$plugin]['Title'] );
124
- unset( $plugins[$plugin]['AuthorName'] );
125
- } else {
126
- $path = WP_PLUGIN_DIR . '/' . dirname( $plugin );
127
-
128
- $vcs_details = self::get_repository_directory_details( $path );
129
-
130
- if ( false !== $vcs_details ) {
131
- $plugins[$plugin]['vcs'] = $vcs_details;
132
- }
133
- }
134
- }
135
-
136
-
137
- return $plugins;
138
- }
139
-
140
- public static function get_plugin_data( $path ) {
141
- if ( ! is_callable( 'get_plugin_data' ) ) {
142
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
143
- }
144
-
145
- if ( ! is_callable( 'get_plugin_data' ) ) {
146
- return false;
147
- }
148
-
149
- $wp_plugin_dir = preg_replace( '|\\\|', '/', WP_PLUGIN_DIR );
150
- $path = preg_replace( '|\\\|', '/', $path );
151
-
152
- $path = preg_replace( '/^' . preg_quote( $wp_plugin_dir, '/' ) . '/', '', $path );
153
- $path = preg_replace( '|^/+|', '', $path );
154
- $path = WP_PLUGIN_DIR . "/$path";
155
-
156
- $data = get_plugin_data( $path, false, false );
157
-
158
- return $data;
159
- }
160
-
161
- public static function get_file_data( $file, $type = '' ) {
162
- $headers = array(
163
- 'name' => 'Name',
164
- 'version' => 'Version',
165
- 'description' => 'Description',
166
- 'author' => 'Author',
167
- 'author-uri' => 'Author URI',
168
- 'text-domain' => 'Text Domain',
169
- 'text-domain-path' => 'Domain Path',
170
- 'ithemes-package' => 'iThemes Package',
171
- );
172
-
173
- $plugin_headers = array(
174
- 'plugin-uri' => 'Plugin URI',
175
- 'network' => 'Network',
176
- 'sitewide' => '_sitewide',
177
- );
178
-
179
- $theme_headers = array(
180
- 'theme-uri' => 'ThemeURI',
181
- 'template' => 'Template',
182
- 'status' => 'Status',
183
- 'tags' => 'Tags',
184
- );
185
-
186
-
187
- if ( 'plugin' === $type ) {
188
- $headers = array_merge( $headers, $plugin_headers );
189
- } else if ( 'theme' === $type ) {
190
- $headers = array_merge( $headers, $theme_headers );
191
- }
192
-
193
- return get_file_data( $file, $headers );
194
- }
195
-
196
- public static function find_match_in_file( $file, $expression, $index = false ) {
197
- $fh = fopen( $file, 'r' );
198
-
199
- $data = '';
200
- $retval = false;
201
-
202
- while ( $file_read = fread( $fh, 256 ) ) {
203
- $data .= $file_read;
204
-
205
- if ( preg_match( $expression, $data, $match ) ) {
206
- $retval = $match;
207
- break;
208
- }
209
- }
210
-
211
- fclose( $fh );
212
-
213
- if ( false !== $index ) {
214
- if ( is_array( $retval ) && isset( $retval[$index] ) ) {
215
- return $retval[$index];
216
- } else {
217
- return false;
218
- }
219
- }
220
-
221
- return $retval;
222
- }
223
-
224
- public static function get_wordpress_version() {
225
- return self::find_match_in_file( ABSPATH . WPINC . '/version.php', "/\\\$wp_version\s*=\s*(['\"])([^'\"]+)\\1/", 2 );
226
- }
227
-
228
- public static function get_wordpress_db_version() {
229
- return self::find_match_in_file( ABSPATH . WPINC . '/version.php', "/\\\$wp_db_version\s*=\s*['\"]?(\d+)/", 1 );
230
- }
231
-
232
- public static function strip_plugin_dir( &$path ) {
233
- $path = preg_replace( '|^' . preg_quote( WP_PLUGIN_DIR, '|' ) . '/|', '', $path );
234
- }
235
-
236
- public static function get_theme_details( $args = array() ) {
237
- if ( ! is_callable( 'wp_get_themes' ) ) {
238
- return false;
239
- }
240
-
241
-
242
- $themes = array();
243
-
244
- $active_stylesheet = basename( get_stylesheet_directory() );
245
- $active_template = basename( get_template_directory() );
246
-
247
- foreach ( wp_get_themes() as $dir => $theme ) {
248
- $data = array(
249
- 'name' => $theme['Name'],
250
- 'version' => $theme['Version'],
251
- 'parent' => $theme->parent_theme,
252
- );
253
-
254
- if ( ! empty( $args['verbose'] ) ) {
255
- $data['description'] = $theme['Description'];
256
- $data['author'] = $theme['Author Name'];
257
- $data['author-uri'] = $theme['Author URI'];
258
-
259
-
260
- $vcs_details = self::get_repository_directory_details( $theme['Stylesheet Dir'] );
261
-
262
- if ( false !== $vcs_details ) {
263
- $data['vcs'] = $vcs_details;
264
- }
265
- }
266
-
267
- if ( empty( $data['parent'] ) ) {
268
- unset( $data['parent'] );
269
- } else {
270
- $data['parent'] = $theme->parent()->stylesheet;
271
- }
272
-
273
- if ( $dir == $active_stylesheet ) {
274
- $data['status'] = 'active';
275
- } else if ( $dir == $active_template ) {
276
- $data['status'] = 'active_parent';
277
- } else {
278
- $data['status'] = '';
279
- }
280
-
281
-
282
- $themes[$dir] = $data;
283
- }
284
-
285
-
286
- return $themes;
287
- }
288
-
289
- public static function refresh_plugin_updates() {
290
- require_once( ABSPATH . 'wp-includes/update.php' );
291
-
292
- if ( is_callable( 'wp_update_plugins' ) ) {
293
- return wp_update_plugins();
294
- }
295
-
296
- return false;
297
- }
298
-
299
- public static function refresh_theme_updates() {
300
- require_once( ABSPATH . 'wp-includes/update.php' );
301
-
302
- if ( is_callable( 'wp_update_themes' ) ) {
303
- return wp_update_themes();
304
- }
305
-
306
- return false;
307
- }
308
-
309
- public static function refresh_core_updates() {
310
- require_once( ABSPATH . 'wp-includes/update.php' );
311
-
312
- if ( is_callable( 'wp_version_check' ) ) {
313
- return wp_version_check( array(), true );
314
- }
315
-
316
- return false;
317
- }
318
-
319
- public static function get_update_details( $args = array() ) {
320
- if ( ! empty( $args['ithemes-updater-force-refresh'] ) && isset( $GLOBALS['ithemes-updater-settings'] ) ) {
321
- $GLOBALS['ithemes-updater-settings']->flush( 'forced sync flush' );
322
- }
323
-
324
- $default_args = array(
325
- 'verbose' => false,
326
- 'force_refresh' => false,
327
- );
328
- $args = array_merge( $default_args, $args );
329
-
330
-
331
- $updates = array(
332
- 'plugins' => array(),
333
- 'themes' => array(),
334
- 'translations' => array(),
335
- 'core' => array(),
336
- );
337
-
338
-
339
- if ( is_array( $args['force_refresh'] ) ) {
340
- if ( in_array( 'plugins', $args['force_refresh'] ) ) {
341
- $updates['force-refresh-results']['plugins'] = self::refresh_plugin_updates();
342
- }
343
- if ( in_array( 'themes', $args['force_refresh'] ) ) {
344
- $updates['force-refresh-results']['themes'] = self::refresh_theme_updates();
345
- }
346
- if ( in_array( 'core', $args['force_refresh'] ) ) {
347
- $updates['force-refresh-results']['core'] = self::refresh_core_updates();
348
- }
349
- } else if ( $args['force_refresh'] ) {
350
- $updates['force-refresh-results']['plugins'] = self::refresh_plugin_updates();
351
- $updates['force-refresh-results']['themes'] = self::refresh_theme_updates();
352
- $updates['force-refresh-results']['core'] = self::refresh_core_updates();
353
- }
354
-
355
-
356
- $update_plugins = get_site_transient( 'update_plugins' );
357
-
358
- if ( ! empty( $update_plugins->response ) ) {
359
- $updates['plugins'] = $update_plugins->response;
360
-
361
- if ( empty( $args['verbose'] ) ) {
362
- foreach ( $updates['plugins'] as $plugin => $data ) {
363
- unset( $updates['plugins'][$plugin]->id );
364
- unset( $updates['plugins'][$plugin]->slug );
365
- unset( $updates['plugins'][$plugin]->url );
366
- unset( $updates['plugins'][$plugin]->package );
367
- }
368
- }
369
- }
370
-
371
- if ( ! empty( $update_plugins->translations ) ) {
372
- $updates['translations'] = array_merge( $updates['translations'], $update_plugins->translations );
373
- }
374
-
375
-
376
- $update_themes = get_site_transient( 'update_themes' );
377
-
378
- if ( ! empty( $update_themes->response ) ) {
379
- $updates['themes'] = $update_themes->response;
380
-
381
- if ( empty( $args['verbose'] ) ) {
382
- foreach ( $updates['themes'] as $theme => $data ) {
383
- unset( $updates['themes'][$theme]['package'] );
384
- unset( $updates['themes'][$theme]['url'] );
385
- }
386
- }
387
- }
388
-
389
- if ( ! empty( $update_themes->translations ) ) {
390
- $updates['translations'] = array_merge( $updates['translations'], $update_themes->translations );
391
- }
392
-
393
-
394
- $update_core = get_site_transient( 'update_core' );
395
-
396
- if ( ! empty( $update_core->updates ) ) {
397
- $updates['core'] = $update_core->updates;
398
-
399
- foreach ( $updates['core'] as $index => $update ) {
400
- if ( empty( $update->current ) && ! empty( $update->version ) ) {
401
- $updates['core'][$index]->current = $update->version;
402
- } else if ( empty( $update->version ) && ! empty( $update->current ) ) {
403
- $updates['core'][$index]->version = $update->current;
404
- }
405
-
406
- if ( empty( $args['verbose'] ) ) {
407
- unset( $updates['core'][$index]->download );
408
- unset( $updates['core'][$index]->packages );
409
- unset( $updates['core'][$index]->php_version );
410
- unset( $updates['core'][$index]->mysql_version );
411
- unset( $updates['core'][$index]->new_bundled );
412
- unset( $updates['core'][$index]->partial_version );
413
- }
414
- }
415
- }
416
-
417
- if ( ! empty( $update_core->translations ) ) {
418
- $updates['translations'] = array_merge( $updates['translations'], $update_core->translations );
419
- }
420
-
421
-
422
- return $updates;
423
- }
424
-
425
- public static function get_wordpress_details( $args = array() ) {
426
- $details = array(
427
- 'version' => self::get_wordpress_version(),
428
- 'url' => get_bloginfo( 'url' ),
429
- 'wpurl' => get_bloginfo( 'wpurl' ),
430
- 'login-url' => wp_login_url(),
431
- 'admin-url' => admin_url(),
432
- );
433
-
434
- if ( is_callable( 'is_multisite' ) ) {
435
- if ( is_multisite() ) {
436
- $details['multisite'] = true;
437
-
438
- if ( is_callable( 'get_current_blog_id' ) ) {
439
- $details['blogid'] = get_current_blog_id();
440
- } else if ( isset( $GLOBALS['blogid'] ) ) {
441
- $details['blogid'] = $GLOBALS['blogid'];
442
- }
443
- }
444
- else {
445
- $details['multisite'] = false;
446
- }
447
- }
448
-
449
- if ( ! empty( $args['verbose'] ) ) {
450
- $vcs_details = self::get_repository_directory_details( ABSPATH );
451
-
452
- if ( false !== $vcs_details ) {
453
- $details['vcs'] = $vcs_details;
454
- }
455
- }
456
-
457
- return $details;
458
- }
459
-
460
- public static function get_php_details( $args = array() ) {
461
- $details['display_errors'] = $GLOBALS['ithemes_sync_request_handler']->original_display_errors;
462
- $details['error_reporting'] = $GLOBALS['ithemes_sync_request_handler']->original_error_reporting;
463
-
464
- if ( self::is_callable_function( 'ini_get' ) ) {
465
- $details['disable_functions'] = ini_get( 'disable_functions' );
466
- $details['suhosin.executor.func.blacklist'] = ini_get( 'suhosin.executor.func.blacklist' );
467
- }
468
-
469
-
470
- $functions = array(
471
- 'phpversion',
472
- 'PHP_VERSION',
473
- 'php_sapi_name',
474
- 'PHP_SAPI',
475
- );
476
-
477
- $details = self::get_function_results( $functions, $details );
478
-
479
-
480
- if ( empty( $args['verbose'] ) ) {
481
- return $details;
482
- }
483
-
484
-
485
- $functions = array(
486
- 'zend_version',
487
- 'sys_get_temp_dir',
488
- 'get_loaded_extensions',
489
- );
490
-
491
- $details = self::get_function_results( $functions, $details );
492
-
493
-
494
- if ( self::is_callable_function( 'phpinfo' ) ) {
495
- ob_start();
496
- phpinfo();
497
-
498
- $phpinfo = ob_get_clean();
499
- $phpinfo = preg_replace( '/<[^>]*>/', ' ', $phpinfo );
500
- $phpinfo = html_entity_decode( $phpinfo, ENT_QUOTES );
501
-
502
- $patterns = array(
503
- 'php-version' => '/^\s*PHP Version\s+(.+)\s*$/mi',
504
- 'build-system' => '/^\s*System\s+(.+)\s*$/mi',
505
- 'configure' => '/^\s*Configure Command\s+(.+)\s*$/mi',
506
- 'server-api' => '/^\s*Server API\s+(.+)\s*$/mi',
507
- 'gd-support' => '/^\s*GD Support\s+(.+)\s*$/mi',
508
- 'json-support' => '/^\s*json support\s+(.+)\s*$/mi',
509
- 'mb-support' => '/^\s*Multibyte Support\s+(.+)\s*$/mi',
510
- 'server-software' => '/^\s*SERVER_SOFTWARE\s+(.+)\s*$/mi',
511
- );
512
-
513
- $details['phpinfo'] = self::get_pattern_results( $phpinfo, $patterns );
514
- }
515
-
516
-
517
- return $details;
518
- }
519
-
520
- public static function get_server_details( $args = array() ) {
521
- $details = array(
522
- 'timezone_string' => get_option( 'timezone_string' ),
523
- 'gmt_offset' => get_option( 'gmt_offset' ),
524
- 'ini.date.timezone' => ini_get( 'date.timezone' ),
525
- );
526
-
527
- $timezone = self::run_shell_command( 'date +%Z 2>/dev/null' );
528
-
529
- if ( ! empty( $timezone ) ) {
530
- $details['date +%Z'] = $timezone;
531
- $details['date +%z'] = self::run_shell_command( 'date +%z 2>/dev/null' );
532
- $details['date +%s'] = self::run_shell_command( 'date +%s 2>/dev/null' );
533
- }
534
-
535
-
536
- $functions = array(
537
- 'time',
538
- 'date_default_timezone_get',
539
- 'sys_getloadavg',
540
- 'php_uname',
541
- 'PHP_OS',
542
- 'memory_get_usage',
543
- 'memory_get_peak_usage',
544
- );
545
-
546
- $details = self::get_function_results( $functions, $details );
547
-
548
- if ( ! isset( $GLOBALS['wpdb'] ) || ( empty( $GLOBALS['wpdb']->use_mysqli ) && self::is_callable_function( 'mysql_get_server_info' ) ) ) {
549
- $details['mysql_get_server_info'] = @mysql_get_server_info();
550
- } else if ( isset( $GLOBALS['wpdb']->dbh ) && self::is_callable_function( 'mysqli_get_server_info' ) ) {
551
- $details['mysqli_get_server_info'] = @mysqli_get_server_info( $GLOBALS['wpdb']->dbh );
552
- }
553
-
554
- $details['SERVER_ADDR'] = @$_SERVER['SERVER_ADDR'];
555
-
556
-
557
- if ( empty( $args['verbose'] ) ) {
558
- return $details;
559
- }
560
-
561
-
562
- $functions = array(
563
- 'PHP_EOL',
564
- 'DIRECTORY_SEPARATOR',
565
- );
566
-
567
- $details = self::get_function_results( $functions, $details );
568
-
569
- if ( ! isset( $GLOBALS['wpdb'] ) || ( empty( $GLOBALS['wpdb']->use_mysqli ) && self::is_callable_function( 'mysql_get_host_info' ) ) ) {
570
- $details['mysql_get_host_info'] = @mysql_get_host_info();
571
- } else if ( isset( $GLOBALS['wpdb']->dbh ) && self::is_callable_function( 'mysqli_get_host_info' ) ) {
572
- $details['mysqli_get_host_info'] = @mysqli_get_host_info( $GLOBALS['wpdb']->dbh );
573
- }
574
-
575
- $details['server_ip'] = self::get_server_ip();
576
-
577
-
578
- $commands = array(
579
- 'lsb_release -a',
580
- 'cat /etc/*-release',
581
- 'who',
582
- 'df -h',
583
- 'ps aux|wc -l',
584
- 'ps aux --sort=-%cpu|head -6',
585
- 'ps aux --sort=-%mem|head -6',
586
- );
587
-
588
- $details = self::get_shell_command_results( $commands, $details );
589
-
590
-
591
- $cpuinfo = self::run_shell_command( 'cat /proc/cpuinfo' );
592
-
593
- if ( preg_match_all( '/model name\s*:\s*([^\r\n]+).*?cpu MHz\s*:\s*([^\r\n]+).*?physical id\s*:\s*([^\r\n]+).*?siblings\s*:\s*([^\r\n]+).*?cpu cores\s*:\s*([^\r\n]+)/s', $cpuinfo, $matches, PREG_SET_ORDER ) ) {
594
- foreach ( $matches as $match ) {
595
- $details['cpus'][$match[3]] = array(
596
- 'model' => $match[1],
597
- 'mhz' => $match[2],
598
- 'siblings' => $match[4],
599
- 'cores' => $match[5],
600
- );
601
- }
602
- }
603
-
604
-
605
- $memory_data = self::run_shell_command( '/usr/bin/free|grep -i "^Mem:"' );
606
-
607
- if ( ! empty( $memory_data ) ) {
608
- $memory_data = preg_split( '/\s+/', $memory_data );
609
-
610
- $memory = array(
611
- 'total' => $memory_data[1],
612
- 'used' => $memory_data[2],
613
- 'free' => $memory_data[3],
614
- 'buffers' => $memory_data[5],
615
- 'cache' => $memory_data[6],
616
- );
617
-
618
- $memory['used-real'] = $memory['used'] - $memory['buffers'] - $memory['cache'];
619
- $memory['free-real'] = $memory['total'] - $memory['used-real'];
620
-
621
-
622
- $swap_data = self::run_shell_command( '/usr/bin/free|grep -i "^Swap:"' );
623
-
624
- if ( ! empty( $swap_data ) ) {
625
- $swap_data = preg_split( '/\s+/', $swap_data );
626
-
627
- $memory['swap'] = array(
628
- 'total' => $swap_data[1],
629
- 'used' => $swap_data[2],
630
- 'free' => $swap_data[3],
631
- );
632
- }
633
-
634
-
635
- $details['memory'] = $memory;
636
- } else if ( file_exists( '/proc/meminfo' ) && ( false !== ( $meminfo = file_get_contents( '/proc/meminfo' ) ) ) && preg_match_all( '/^([^:]+):\s+(\d+)/m', $meminfo, $matches, PREG_SET_ORDER ) ) {
637
- $memory_data = array();
638
-
639
- foreach ( $matches as $match ) {
640
- $memory_data[$match[1]] = $match[2];
641
- }
642
-
643
- $memory = array(
644
- 'total' => $memory_data['MemTotal'],
645
- 'used' => (string) ( $memory_data['MemTotal'] - $memory_data['MemFree'] ),
646
- 'free' => $memory_data['MemFree'],
647
- 'buffers' => $memory_data['Buffers'],
648
- 'cache' => $memory_data['Cached'],
649
- );
650
-
651
- $memory['used-real'] = $memory['used'] - $memory['buffers'] - $memory['cache'];
652
- $memory['free-real'] = $memory['total'] - $memory['used-real'];
653
-
654
-
655
- $memory['swap'] = array(
656
- 'total' => $memory_data['SwapTotal'],
657
- 'used' => (string) ( $memory_data['SwapTotal'] - $memory_data['SwapFree'] ),
658
- 'free' => $memory_data['SwapFree'],
659
- );
660
-
661
-
662
- $details['memory'] = $memory;
663
- }
664
-
665
-
666
- return $details;
667
- }
668
-
669
- private static function get_server_ip() {
670
- $data = wp_remote_get( 'http://ithemes.com/utilities/show-remote-ip.php' );
671
-
672
- if ( ! is_wp_error( $data ) && preg_match( '/(\d+\.\d+\.\d+\.\d+)/', $data['body'], $match ) ) {
673
- return $match[1];
674
- }
675
-
676
-
677
- $data = wp_remote_get( 'http://ip4.me/' );
678
-
679
- if ( ! is_wp_error( $data ) && preg_match( '/>(\d+\.\d+\.\d+\.\d+)</', $data['body'], $match ) ) {
680
- return $match[1];
681
- }
682
-
683
-
684
- return false;
685
- }
686
-
687
- private static function get_function_results( $functions, $data = array() ) {
688
- foreach ( $functions as $function ) {
689
- $var = $function;
690
-
691
- if ( false === strpos( $function, '|' ) ) {
692
- $args = array();
693
- } else {
694
- $args = explode( '|', $function );
695
- $function = array_shift( $args );
696
-
697
- if ( ( 1 === count( $args ) ) && ( 0 === strpos( $args[0], '[' ) ) ) {
698
- $new_args = @json_decode( $args[0] );
699
-
700
- if ( ! is_null( $new_args ) ) {
701
- $args = $new_args;
702
- }
703
- }
704
- }
705
-
706
- if ( self::is_callable_function( $function ) ) {
707
- $data[$var] = call_user_func_array( $function, $args );
708
- } else if ( defined( $function ) && empty( $args ) ) {
709
- $data[$var] = constant( $function );
710
- }
711
- }
712
-
713
- return $data;
714
- }
715
-
716
- private static function get_pattern_results( $raw_data, $patterns, $data = array() ) {
717
- foreach ( $patterns as $name => $pattern ) {
718
- if ( preg_match( $pattern, $raw_data, $match ) ) {
719
- $data[$name] = $match[1];
720
- }
721
- }
722
-
723
- return $data;
724
- }
725
-
726
- private static function get_shell_command_results( $commands, $data = array() ) {
727
- foreach ( $commands as $command ) {
728
- $result = self::run_shell_command( $command );
729
-
730
- if ( false !== $result ) {
731
- $data[$command] = $result;
732
- }
733
- }
734
-
735
- return $data;
736
- }
737
-
738
- private static function run_shell_command( $command ) {
739
- $command = 'PATH="$PATH:/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/sbin"; ' . $command;
740
-
741
- if ( self::is_callable_function( 'shell_exec' ) ) {
742
- $result = @shell_exec( $command );
743
-
744
- if ( is_null( $result ) ) {
745
- return false;
746
- }
747
-
748
- return $result;
749
- }
750
-
751
- if ( self::is_callable_function( 'exec' ) ) {
752
- @exec( $command, $results, $status );
753
-
754
- if ( ! empty( $results ) ) {
755
- return implode( "\n", $results );
756
- } else if( empty( $status ) ) {
757
- return '';
758
- } else {
759
- return false;
760
- }
761
- }
762
-
763
- if ( self::is_callable_function( 'system' ) ) {
764
- ob_start();
765
- $return = @system( $command, $status );
766
- $result = ob_get_clean();
767
-
768
- if ( false === $return ) {
769
- return false;
770
- } else if ( ! empty( $result ) ) {
771
- return $result;
772
- } else if ( empty( $status ) ) {
773
- return '';
774
- } else {
775
- return false;
776
- }
777
- }
778
-
779
- if ( self::is_callable_function( 'passthru' ) ) {
780
- ob_start();
781
- $return = @passthru( $command, $status );
782
- $result = ob_get_clean();
783
-
784
- if ( false === $return ) {
785
- return false;
786
- } else if ( ! empty( $result ) ) {
787
- return $result;
788
- } else if ( empty( $status ) ) {
789
- return '';
790
- } else {
791
- return false;
792
- }
793
- }
794
-
795
- return false;
796
- }
797
-
798
- public static function merge_defaults( $values, $defaults, $force = false ) {
799
- if ( ! self::is_associative_array( $defaults ) ) {
800
- if ( ! isset( $values ) ) {
801
- return $defaults;
802
- }
803
-
804
- if ( false === $force ) {
805
- return $values;
806
- }
807
-
808
- if ( isset( $values ) || is_array( $values ) ) {
809
- return $values;
810
- }
811
-
812
- return $defaults;
813
- }
814
-
815
- foreach ( (array) $defaults as $key => $val ) {
816
- if ( ! isset( $values[$key] ) ) {
817
- $values[$key] = null;
818
- }
819
-
820
- $values[$key] = self::merge_defaults( $values[$key], $val, $force );
821
- }
822
-
823
- return $values;
824
- }
825
-
826
- public static function is_associative_array( &$array ) {
827
- if ( ! is_array( $array ) || empty( $array ) ) {
828
- return false;
829
- }
830
-
831
- $next = 0;
832
-
833
- foreach ( $array as $k => $v ) {
834
- if ( $k !== $next++ ) {
835
- return true;
836
- }
837
- }
838
-
839
- return false;
840
- }
841
-
842
- public static function get_users( $query_args = array() ) {
843
- $default_query_args = array(
844
- 'blog_id' => 0,
845
- );
846
- $query_args = array_merge( $default_query_args, $query_args );
847
-
848
- if ( ! empty( $query_args['capability'] ) ) {
849
- $capabilities = (array) $query_args['capability'];
850
- unset( $query_args['capability'] );
851
- }
852
-
853
- $all_users = get_users( $query_args );
854
-
855
- $users = array();
856
-
857
- foreach ( $all_users as $user ) {
858
- if ( ! empty( $capabilities ) ) {
859
- $user_can = true;
860
-
861
- foreach ( (array) $capabilities as $capability ) {
862
- if ( ! user_can( $user, $capability ) ) {
863
- $user_can = false;
864
- break;
865
- }
866
- }
867
-
868
- if ( ! $user_can ) {
869
- continue;
870
- }
871
- }
872
-
873
- $users[$user->ID] = array(
874
- 'login' => $user->data->user_login,
875
- 'display_name' => $user->data->display_name,
876
- );
877
- }
878
-
879
-
880
- return $users;
881
- }
882
-
883
- public static function get_sync_settings( $args = array() ) {
884
- $all_settings = $GLOBALS['ithemes-sync-settings']->get_options();
885
-
886
- if ( ! empty( $args['settings'] ) ) {
887
- $keys = $args['settings'];
888
- } else if ( ! empty( $args['verbose'] ) ) {
889
- $keys = array_keys( $all_settings );
890
-
891
- $keys = array_flip( $keys );
892
- unset( $keys['authentications'] );
893
- $keys = array_flip( $keys );
894
- } else {
895
- $keys = array(
896
- 'show_sync',
897
- );
898
- }
899
-
900
- $settings = array();
901
-
902
- foreach ( $keys as $key ) {
903
- if ( isset( $all_settings[$key] ) ) {
904
- $settings[$key] = $all_settings[$key];
905
- } else {
906
- $settings[$key] = null;
907
- }
908
- }
909
-
910
- if ( ! in_array( 'authentications', $keys ) && isset( $settings['authentications'] ) ) {
911
- unset( $settings['authentications'] );
912
- }
913
-
914
-
915
- return $settings;
916
- }
917
-
918
- public static function get_supported_verbs( $args = array() ) {
919
- if ( ! is_callable( array( $GLOBALS['ithemes-sync-api'], 'get_descriptions' ) ) ) {
920
- return new WP_Error( 'missing-method-api-get_descriptions', 'The Ithemes_Sync_API::get_descriptions function is not callable.' );
921
- }
922
-
923
- return $GLOBALS['ithemes-sync-api']->get_names();
924
- }
925
-
926
- public static function get_status_elements( $args = array() ) {
927
- if ( ! is_callable( array( $GLOBALS['ithemes-sync-api'], 'get_status_elements' ) ) ) {
928
- return new WP_Error( 'missing-method-api-get_status_elements', 'The Ithemes_Sync_API::get_status_elements function is not callable.' );
929
- }
930
-
931
- return $GLOBALS['ithemes-sync-api']->get_status_elements();
932
- }
933
-
934
- public static function get_default_status_elements( $args = array() ) {
935
- if ( ! is_callable( array( $GLOBALS['ithemes-sync-api'], 'get_default_status_elements' ) ) ) {
936
- return new WP_Error( 'missing-method-api-get_default_status_elements', 'The Ithemes_Sync_API::get_default_status_elements function is not callable.' );
937
- }
938
-
939
- return $GLOBALS['ithemes-sync-api']->get_default_status_elements();
940
- }
941
-
942
- public static function set_time_limit( $seconds = 60 ) {
943
- if ( is_callable( 'set_time_limit' ) ) {
944
- @set_time_limit( $seconds );
945
- }
946
- }
947
-
948
- public static function get_repository_directory_details( $path ) {
949
- $vcs_types = array(
950
- '.git' => array(
951
- 'name' => 'git',
952
- ),
953
- '.svn' => array(
954
- 'name' => 'subversion',
955
- ),
956
- '.hg' => array(
957
- 'name' => 'mercurial',
958
- ),
959
- '.bzr' => array(
960
- 'name' => 'bazaar',
961
- ),
962
- );
963
-
964
- foreach ( $vcs_types as $directory => $details ) {
965
- if ( is_dir( "$path/$directory" ) ) {
966
- return $details;
967
- }
968
- }
969
-
970
- return false;
971
- }
972
-
973
- public static function is_callable_function( $function ) {
974
- if ( ! is_callable( $function ) ) {
975
- return false;
976
- }
977
-
978
- $disabled_functions = preg_split( '/\s*,\s*/', (string) ini_get( 'disable_functions' ) );
979
-
980
- if ( in_array( $function, $disabled_functions ) ) {
981
- return false;
982
- }
983
-
984
- $disabled_functions = preg_split( '/\s*,\s*/', (string) ini_get( 'suhosin.executor.func.blacklist' ) );
985
-
986
- if ( in_array( $function, $disabled_functions ) ) {
987
- return false;
988
- }
989
-
990
- return true;
991
- }
992
-
993
- public static function get_upload_reports_dir() {
994
- $wp_upload_dir = wp_upload_dir();
995
- $reports_path = apply_filters( 'get_upload_reports_dir', $wp_upload_dir['basedir'] . '/reports' );
996
-
997
- if ( ! file_exists( $reports_path ) ) {
998
- wp_mkdir_p( $reports_path );
999
- }
1000
-
1001
- return $reports_path;
1002
- }
1003
-
1004
- public static function get_upload_reports_url() {
1005
- $wp_upload_dir = wp_upload_dir();
1006
- $reports_url = apply_filters( 'get_upload_reports_url', $wp_upload_dir['baseurl'] . '/reports' );
1007
-
1008
- return $reports_url;
1009
- }
1010
-
1011
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/history.txt DELETED
@@ -1,186 +0,0 @@
1
- 1.0.0 - 2013-11-11 - Chris Jean
2
- iThemes Sync launch!
3
- 1.1.0 - 2013-11-20 - Chris Jean
4
- Enhancement: Added ability to handle desync user requests from the Sync server.
5
- Enhancement: Now avoids plugin conflicts that caused plugins and themes to not be properly reported and which prevented updates from being successfully applied.
6
- Enhancement: Now supports update reporting for and updating of plugins with updater code that only works with pre-3.0 versions of WordPress.
7
- Enhancement: Now supports sending local server status information back to the Sync server.
8
- 1.1.1 - 2013-11-20 - Chris Jean
9
- Bug Fix: Requests for the plugin settings would return the authentications data. Now, the authentications data must be explicitly requested in order to be retrieved.
10
- 1.1.2 - 2013-11-20 - Chris Jean
11
- Enhancement: By default, pulling update details will not force a flush of all the cached update data. Instead, this can now be specifically requested by the server.
12
- 1.1.3 - 2013-11-22 - Chris Jean
13
- Enhancement: The server will now receive a listing of the supported verbs with a status check. This will help the Sync Dashboard determine if the plugin needs to be upgraded in order to access specific features.
14
- 1.1.4 - 2013-11-26 - Chris Jean
15
- Bug Fix: Removed call to the mysqli_get_server_info() function when pulling server details as it would trigger errors on some systems.
16
- Bug Fix: Removed the /etc/passwd check when pulling server details. This was used to try to count the number of users on the system. It was removed since it triggered hacking attempt notices in the Wordfence plugin.
17
- 1.1.5 - 2013-12-02 - Chris Jean
18
- Bug Fix: Users that are not recognized by the Sync server can now be unsynced. This prevents the issue where users that are unsynced on the server when the site cannot be communicated with (or when the plugin is inactive) cannot be removed from the site.
19
- 1.1.6 - 2013-12-09 - Chris Jean
20
- Bug Fix: Fixed issue that can cause failure to load plugin details on sites that have a different url and wpurl.
21
- 1.1.7 - 2013-12-12 - Chris Jean
22
- Enhancement: Updated the styling to work better with WordPress 3.8.
23
- 1.1.8 - 2013-12-13 - Packaging Bot (lib/updater)
24
- Enhancement: Recently updated plugins and themes no longer report that an update is available.
25
- Enhancement: Added alternate line styling to the listings on the licensing page.
26
- Enhancement: Products with iThemes in the name will now properly capitalize the name.
27
- Enhancement: The updater and licensing system now handle iThemes server outages without causing long page delays or by reporting confusing error messages.
28
- 1.1.9 - 2013-12-13 - Chris Jean
29
- Enhancement: The Sync server can now create requests that force the iThemes updater system to refresh itself.
30
- 1.1.10 - 2013-12-16 - Chris Jean
31
- Enhancement: Added user security privileges when handling requests from the Sync server. This helps avoid issues with some security plugins.
32
- 1.1.11 - 2013-12-18 - Packaging Bot (lib/updater)
33
- Bug Fix: Removed unneeded check on package-info.ithemes.com which was causing performance issues on some sites.
34
- 1.1.12 - 2013-12-19 - Chris Jean
35
- Enhancement: Improved the get-status request so that the Sync server can request only the specific data it needs, causing less load and faster Sync responses.
36
- 1.1.13 - 2013-12-19 - Packaging Bot (lib/updater)
37
- Bug Fix: Licensing will now be universal across all sites of a multisite network. This means that you will only need to license on one site to have the license apply across the entire network.
38
- 1.2.0 - 2014-01-20 - Chris Jean
39
- Enhancement: Added the ability to manage plugins and themes.
40
- Enhancement: get-status requests now support variable display elements.
41
- 1.3.0 - 2014-01-29 - Chris Jean
42
- Enhancement: Added the ability to install plugins and themes.
43
- Bug Fix: Active plugins will be deactivated before uninstalling.
44
- 1.3.1 - 2014-02-03 - Packaging Bot (lib/updater)
45
- Bug Fix: Licensing on SSL-enabled sites now works properly.
46
- 1.3.2 - 2014-02-18 - Chris Jean
47
- Enhancement: Adding ?ithemes-sync-force-display=1 to an admin page URL while logged in as a user that has manage-options privileges will force a site that has Sync hidden to display Sync temporarily for that user.
48
- Enhancement: Data sent back for update requests now includes more data to help identify systems that don't accurately report if the update was successful or not.
49
- Enhancement: Improved error messages for issues communicating with the Sync server.
50
- Enhancement: Added a compatibility check to ensure that Gravity Forms's updates are showing and able to be applied.
51
- Enhancement: Added checks to provide informational messages if more than one iThemes Sync plugin is active on a site.
52
- Enhancement: Improved styling of admin notices on the Settings > iThemes Sync page.
53
- Bug Fix: Increased the amount of time that the plugin will wait for responses from the Sync server when authenticating and deauthenting. This fixes the issue where some servers could not sync or unsync users due to server communication time outs.
54
- 1.3.3 - 2014-02-19 - Chris Jean
55
- Bug Fix: Changed code that caused compatibility issues with some servers.
56
- 1.3.4 - 2014-02-21 - Chris Jean
57
- Bug Fix: Compatibility fix for plugins that corrupt the data sent back to the Sync server.
58
- 1.3.5 - 2014-03-07 - Chris Jean
59
- Enhancement: Valid requests from the Sync server will cause the plugin pretend to be an Administrator user. This is to avoid compatibility issues with some security plugins.
60
- 1.4.0 - 2014-03-28 - Chris Jean
61
- Bug Fix: Updating a WordPress multisite will now properly apply the network upgrade after updating.
62
- Enhancement: Users that are not recognized by the server are now identified on the Settings > iThemes Sync page.
63
- New Feature: Plugins and themes can now send notices to Sync. Details in api.txt.
64
- 1.4.1 - 2014-04-04 - Chris Jean
65
- Enhancement: The notice feature now supports more options, making it ready for use.
66
- 1.4.2 - 2014-04-15 - Chris Jean
67
- Enhancement: Made small adjustments to prepare for WordPress 3.9.
68
- Bug Fix: The WordPress version is now correctly sent back to the Sync server, even when a plugin or other modification modifies the version number. This fixes issues with WordPress updates consistently being available, even when it is up-to-date.
69
- 1.5.0 - 2014-05-20 - Chris Jean
70
- Enhancement: Improved feedback when installing themes and plugins.
71
- Enhancement: Added the ability to install and activate a plugin or theme in one request.
72
- Bug Fix: Notices generated by mysql_get_server_info() and mysqli_get_server_info() are now hidden and will not fill error logs.
73
- 1.5.1 - 2014-06-26 - Chris Jean
74
- Bug Fix: Users can now properly be synced on sites that report the WordPress version incorrectly.
75
- 1.6.0 - 2014-07-01 - Chris Jean
76
- Enhancement: Added ability to manage comments, roles, and users.
77
- 1.6.1 - 2014-07-11 - Chris Jean
78
- Bug Fix: Servers that have strict disable_functions settings that also stop PHP execution when a disabled function is called will no longer cause Sync requests to fail.
79
- 1.6.2 - 2014-07-23 - Chris Jean
80
- Enhancement: Additional user details, such as first name and last name can be requested from the site.
81
- 1.6.3 - 2014-08-22 - Chris Jean
82
- Bug Fix: Caching plugins no longer prevent Sync from reporting and installing available updates.
83
- 1.6.4 - 2014-08-25 - Chris Jean
84
- Bug Fix: Fixed compatibility issue with the Duo Two-Factor Authentication plugin.
85
- 1.6.5 - 2014-10-08 - Chris Jean
86
- Enhancement: Syncing users now uses the new authentication system.
87
- Bug Fix: Fixed warning messages being generated when unauthenticated requests are received.
88
- 1.6.6 - 2014-10-23 - Aaron D. Campbell
89
- Enhancement: Add get-meta, set-meta, and delete-meta actions to manage-users verb
90
- Enhancement: Client Dashboard
91
- 1.6.7 - 2014-10-23 - Chris Jean
92
- Bug Fix: Fixed compatibility issues with functions blacklisted by Suhosin's suhosin.executor.func.blacklist ini setting.
93
- 1.6.8 - 2014-10-28 - Chris Jean
94
- Bug Fix: Fixed infinite loop issue that caused pages for logged in users to fail to load on some sites.
95
- 1.6.9 - 2014-10-31 - Aaron D. Campbell
96
- Bug Fix: Actual fix for possible infinite loop caused by child nodes with no valid parent in admin bar
97
- 1.6.10 - 2014-11-10 - Aaron D. Campbell
98
- Enhancement: Updates to Gravity Forms's verb to allow pagination and proper labeling on Sync side
99
- 1.6.11 - 2014-11-10 - Chris Jean
100
- Enhancement: Added an alternate contaction method using admin-ajax.php in order to avoid communication issues on some systems.
101
- Enhancement: Improved system memory statistics for some Linux systems.
102
- Bug Fix: Corrected a timing issue that prevented updates for some plugins from appearing in the Sync dashboard.
103
- 1.6.12 - 2014-11-14 - Packaging Bot (lib/updater)
104
- Enhancement: Reduced caching to allow updates to appear more quickly.
105
- Enhancement: Authenticating users now uses the new authentication system.
106
- 1.7.0 - 2014-11-18 - Chris Jean
107
- Enhancement: Added the ability to manage iThemes product licenses.
108
- 1.7.1 - 2014-11-24 - Chris Jean
109
- Bug Fix: Data containing non-ASCII characters is now properly parsed.
110
- 1.7.4 - 2015-03-05 - Aaron D. Campbell
111
- Enhancement: Add get-posts and manage-options verbs
112
- Enhancement: Added ability to integrate social sharing
113
- 1.7.5 - 2015-04-22 - Aaron D. Campbell
114
- Bug Fix: Client Dashboard shouldn't hide the hamburger icon used for responsive admin
115
- 1.7.6 - 2015-04-23 - Packaging Bot (lib/updater)
116
- Compatibility Fix: Updated plugin and theme update data format to match changes in WordPress 4.2.
117
- 1.7.7 - 2015-06-22 Chris Jean
118
- Bug Fix: Resolved a fatal error situation that could happen when WordPress attempts to display an error message during plugin or theme upgrades.
119
- 1.7.8 - 2015-07-14 - Packaging Bot (lib/updater)
120
- Enhancement: Updated link to iThemes support.
121
- 1.7.9 - 2015-07-21 - Chris Jean
122
- Bug Fix: An error is no longer sent when a plugin or theme updates to a newer version than the one reported.
123
- 1.8.0 - 2015-08-18 - Chris Jean
124
- Enhancement: Added support for translations being located outside the plugin.
125
- Compatibility Fix: Later priorities for Sync dashboard admin menu filtering to work with certain edge-case plugins.
126
- Bug Fix: Changed path sent to load_plugin_textdomain() in order to properly load translations.
127
- 1.8.1 - 2015-08-24 - Chris Jean
128
- Compatibility Fix: Added support for a define to disable a feature of Sync that sets the WP_ADMIN define to true when handling an authenticated request from the Sync server. This feature exists to prevent compatibility issues with some security plugins yet can also cause a conflict with some plugins. To disable this feature, add the following to the site's wp-config.php file: define( 'ITHEMES_SYNC_SKIP_SET_IS_ADMIN_TO_TRUE', true );
129
- 1.8.2 - 2015-09-25 - Chris Jean
130
- Compatibility Fix: Updated method that the Client Dashboard uses to read admin menu details. This avoids conflicts with some plugins that modify the admin menu later than expected.
131
- 1.8.3 - 2015-11-05 - Chris Jean
132
- Bug Fix: Data from plugins, themes, and other sources that contain non-UTF-8 data are now properly parsed into UTF-8 encoding. This prevents problems communicating between the site and the Sync server when such data are present.
133
- 1.9.0 - 2016-04-22 - Lew Ayotte, Ty Carlson
134
- Enhancement: Adding Core, Plugin, and Theme notices
135
- Enhacnement: Adding more information with Plugin and Theme verbs
136
- Compatibility Fix: Automatically add Sync Server IPs to iThemes Security whitelist
137
- Bug Fix: Handle reporting properly when site is synced to multiple profiles
138
- 1.10.0 - 2016-06-21 - Lew Ayotte
139
- Enhancement: Code efficiency updates
140
- Bug Fix: Fixing invalid path reference
141
- 1.11.0 - 2016-07-28 - Lew Ayotte
142
- Enhancement: Pre-Release to new Whitelabelled Reporting Verbs
143
- Bug Fix: Stop sending empty security notices
144
- 1.12.0 - 2016-08-24 - Lew Ayotte
145
- Enhancement: Federated Login
146
- 1.12.1 - 2016-08-25 - Lew Ayotte
147
- Bug Fix: Removing debug code not needed in live code
148
- 1.13.0 - 2016-08-25 - Lew Ayotte
149
- Enhancement: Extending Federated Login functionality to other User Accounts
150
- 1.14.0 - 2016-08-29 - Lew Ayotte
151
- Improvement: Reduce amount of BackupBuddy noise being sent through to Urgent Notices.
152
- 1.14.1 - 2016-08-29 - Lew Ayotte
153
- Bug Fix: Typo in last commit prevent some BuB notices that are needed
154
- 1.15.0 - 2016-09-02 - Lew Ayotte
155
- Improvement: Extending Federated Login functionality to include subpages to wp-admin
156
- 1.16.0 - 2016-09-28 - Lew Ayotte
157
- Improvement: Extending comment functionality
158
- 1.16.1 - 2016-09-29 - Lew Ayotte
159
- Committing missing code change, no affect on code but needs to be included
160
- 1.17.0 - 2016-11-08 - Lew Ayotte
161
- Improvement: Posts/Pages and Yoast SEO functionality
162
- 1.17.1 - 2016-11-08 - Lew Ayotte
163
- Bug Fix: Removing improper action priority.
164
- 1.17.2 - 2016-11-09 - Lew Ayotte
165
- Bug Fix: Try to set admin user as synced user for activity actions
166
- 1.171.2 - 2016-11-09 - Lew Ayotte
167
- Tagging Version Number Bug
168
- 1.172.0 - 2016-11-14 - Lew Ayotte, Glenn Ansley
169
- Enhancement: Duplicate Posts
170
- Enhancement: Delete Post Revisions
171
- 1.172.1 - 2016-11-28 - Glenn Ansley
172
- Enhancement: Database Optimizations
173
- 1.172.2 - 2016-12-01 - Glenn Ansley
174
- Bug Fix: Workaround to download reports when fopen or openssl are disabled.
175
- 1.173.0 - 2017-01-05 - Lew Ayotte
176
- Enhancement: Google Search Console/Webmaster Tools functionality
177
- 1.173.1 - 2017-01-05 - Lew Ayotte
178
- Enhancement: Change how we store google verification option for Search Console/Webmaster Tools
179
- 1.174.0 - 2017-02-15 - Lew Ayotte, Glenn Ansley
180
- Bug Fix: Fix error when itsec sends data in WP_Error format
181
- 1.175.0 - 2017-02-15 - Glenn Ansley
182
- Enhancement: Add ability to read and set most options found Settings pages.
183
- 2.0.0 - 2017-06-01 - Lew Ayotte
184
- Initial release to WordPress.org
185
- 2.0.1 - 2017-06-21 - Lew Ayotte
186
- Bug Fix: Adding code to get-authentication-token verb to set the scheme to https by default if it should be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/images/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/init.php DELETED
@@ -1,54 +0,0 @@
1
- <?php
2
- /*
3
- Plugin Name: iThemes Sync
4
- Plugin URI: http://ithemes.com/sync
5
- Description: Manage updates to your WordPress sites easily in one place.
6
- Author: iThemes
7
- Version: 2.0.1
8
- Author URI: http://ithemes.com/
9
- Domain Path: /lang/
10
- iThemes Package: ithemes-sync
11
- */
12
-
13
- if ( ! empty( $GLOBALS['ithemes_sync_path'] ) ) {
14
- $active_plugin_path = preg_replace( '|^' . preg_quote( ABSPATH, '|' ) . '|', '', $GLOBALS['ithemes_sync_path'] );
15
- $this_plugin_path = preg_replace( '|^' . preg_quote( ABSPATH, '|' ) . '|', '', dirname( __FILE__ ) );
16
-
17
- if ( $active_plugin_path != $this_plugin_path ) {
18
- $function = 'echo \'<div class="error"><p>';
19
- $function .= sprintf( __( 'Only one iThemes Sync plugin can be active at a time. The plugin at <code>%1$s</code> is running while the plugin at <code>%2$s</code> was skipped in order to prevent errors. Please deactivate the plugin that you do not wish to use.', 'it-l10n-ithemes-sync' ), $active_plugin_path, $this_plugin_path );
20
- $function .= '</p></div>\';';
21
-
22
- $function_ref = create_function( '', $function );
23
-
24
- add_action( 'all_admin_notices', $function_ref, 0 );
25
- }
26
-
27
- return;
28
- }
29
-
30
- $GLOBALS['ithemes_sync_path'] = dirname( __FILE__ );
31
-
32
- require( $GLOBALS['ithemes_sync_path'] . '/load.php' );
33
-
34
- /**
35
- * On activation, set a time, frequency and name of an action hook to be scheduled.
36
- *
37
- * @since 1.12.0
38
- */
39
- function ithemes_sync_activation() {
40
- if ( ! wp_next_scheduled ( 'ithemes_sync_daily_schedule' ) ) {
41
- wp_schedule_event( strtotime( 'Tomorrow 2AM' ), 'daily', 'ithemes_sync_daily_schedule' );
42
- }
43
- }
44
- register_activation_hook( __FILE__, 'ithemes_sync_activation' );
45
-
46
- /**
47
- * On deactivation, remove all functions from the scheduled action hook.
48
- *
49
- * @since 1.12.0
50
- */
51
- function ithemes_sync_deactivation() {
52
- wp_clear_scheduled_hook( 'ithemes_sync_daily_schedule' );
53
- }
54
- register_deactivation_hook( __FILE__, 'ithemes_sync_deactivation' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/js/admin-notice.js DELETED
@@ -1,25 +0,0 @@
1
- jQuery(document).ready(
2
- function() {
3
- jQuery('.ithemes-sync-notice-dismiss').click(
4
- function( e ) {
5
- jQuery('#ithemes-sync-notice').hide();
6
-
7
- return false;
8
- }
9
- );
10
-
11
- jQuery('.ithemes-sync-notice-hide').click(
12
- function( e ) {
13
- jQuery('#ithemes-sync-notice').hide();
14
-
15
- var post_data = {
16
- action: 'ithemes_sync_hide_notice'
17
- };
18
-
19
- jQuery.post( ajaxurl, post_data );
20
-
21
- return false;
22
- }
23
- );
24
- }
25
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/js/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/js/settings-page.js DELETED
@@ -1,10 +0,0 @@
1
- jQuery(document).ready(
2
- function() {
3
- jQuery('.ithemes-sync-wrapper .deauthenticate').click(
4
- function( event ) {
5
- var response = confirm( ithemes_sync_settings.confirm_dialog_text );
6
- return response;
7
- }
8
- );
9
- }
10
- );
 
 
 
 
 
 
 
 
 
 
trunk/js/social-metabox.js DELETED
@@ -1,49 +0,0 @@
1
- (function( $ ) {
2
-
3
- var itSyncSocial = {
4
-
5
- init: function() {
6
- this.bindEvents();
7
-
8
- /** The account list is not shown after post is published, so only call the initial character count method if list exists **/
9
- if ( $('.ithemes-social-accounts').length ) {
10
- this.updateCharCount( $('.ithemes-social-account-content textarea') );
11
- }
12
- },
13
-
14
- bindEvents: function() {
15
- $('#submitpost').on('click', '.ithemes-social-edit-content', this.toggleEdit);
16
- $('#submitpost').on('keyup', '.ithemes-social-account-content textarea', this.onKeyup);
17
- },
18
-
19
- toggleEdit: function(event) {
20
- event.preventDefault();
21
- $(this).siblings('.ithemes-social-account-content').slideToggle('fast');
22
- },
23
-
24
- onKeyup: function(event) {
25
- itSyncSocial.updateCharCount(event.currentTarget);
26
- },
27
-
28
- updateCharCount: function(element) {
29
- var content = $(element).val()
30
- .replace( /\{post_author\}/, jQuery('#post_author_override option:selected').text() )
31
- .replace( /\{post_title\}/, jQuery('#title').val() )
32
- .replace( /\{post_url\}/, '{post_url-twentythree-}' ); //URLs are 23 characters, so we're padding this to that
33
-
34
- var container = $(element).siblings('.ithemes-social-char-count'),
35
- currentLength = content.length,
36
- remaining = 140 - currentLength;
37
- isOver = remaining <= 0 ? true : false;
38
-
39
- container.html(remaining);
40
- isOver ? container.addClass('over') : container.removeClass('over');
41
- }
42
-
43
- };
44
-
45
- jQuery(document).ready( function() {
46
- itSyncSocial.init();
47
- });
48
-
49
- })( jQuery );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lang/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/lang/ithemes-sync.pot DELETED
@@ -1,620 +0,0 @@
1
- # Copyright (C) 2017 iThemes Sync
2
- # This file is distributed under the same license as the iThemes Sync package.
3
- msgid ""
4
- msgstr ""
5
- "Project-Id-Version: iThemes Sync 2.0.1\n"
6
- "Report-Msgid-Bugs-To: http://ithemes.com/support/\n"
7
- "POT-Creation-Date: 2017-06-21 12:49:59+00:00\n"
8
- "PO-Revision-Date: 2017-MO-DA HO:MI+ZONE\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "Plural-Forms: nplurals=2; plural=n != 1;\n"
13
- "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
- "Language-Team: LANGUAGE <LL@li.org>\n"
15
-
16
- #: admin.php:118
17
- msgid ""
18
- "iThemes Sync is active. <a class=\"ithemes-sync-notice-button\" href=\"%s"
19
- "\">Manage Sync</a> <a class=\"ithemes-sync-notice-dismiss\" href=\"#\">×</a>"
20
- msgstr ""
21
-
22
- #: admin.php:132
23
- msgid ""
24
- "iThemes Sync is almost ready. <a class=\"ithemes-sync-notice-button\" href="
25
- "\"%s\">Set Up Sync</a> <a class=\"ithemes-sync-notice-hide\" href=\"#\">×</a>"
26
- msgstr ""
27
-
28
- #: admin.php:147
29
- msgid ""
30
- "iThemes Sync will show for your user for the next %1$s. Click <a href=\"%2$s"
31
- "\">here</a> to hide iThemes Sync again."
32
- msgstr ""
33
-
34
- #: admin.php:157
35
- msgid "iThemes Sync is now hidden from your user again."
36
- msgstr ""
37
-
38
- #. #-#-#-#-# ithemes-sync.pot (iThemes Sync 2.0.1) #-#-#-#-#
39
- #. Plugin Name of the plugin/theme
40
- #: admin.php:168 admin.php:174 settings-page.php:268
41
- msgid "iThemes Sync"
42
- msgstr ""
43
-
44
- #: admin.php:202 lib/updater/admin.php:181
45
- msgid "Manage iThemes product licenses to receive automatic upgrade support"
46
- msgstr ""
47
-
48
- #: admin.php:202 lib/updater/admin.php:181
49
- msgid "License"
50
- msgstr ""
51
-
52
- #: client-dashboard.php:350
53
- msgctxt "Welcome panel"
54
- msgid "Welcome"
55
- msgstr ""
56
-
57
- #: duplicator.php:31
58
- msgid "Duplicate Post"
59
- msgstr ""
60
-
61
- #: duplicator.php:71
62
- msgid "copy"
63
- msgstr ""
64
-
65
- #: init.php:19
66
- msgid ""
67
- "Only one iThemes Sync plugin can be active at a time. The plugin at <code>"
68
- "%1$s</code> is running while the plugin at <code>%2$s</code> was skipped in "
69
- "order to prevent errors. Please deactivate the plugin that you do not wish "
70
- "to use."
71
- msgstr ""
72
-
73
- #: lib/updater/admin.php:140
74
- msgid ""
75
- "To receive automatic updates for %l, use the <a href=\"%s\">iThemes "
76
- "Licensing</a> page found in the Settings menu."
77
- msgstr ""
78
-
79
- #: lib/updater/admin.php:147 lib/updater/admin.php:153
80
- #: lib/updater/settings-page.php:302
81
- msgid "iThemes Licensing"
82
- msgstr ""
83
-
84
- #: lib/updater/api.php:41 lib/updater/api.php:59
85
- msgid ""
86
- "<p>Unable to get changelog data at this time.</p><p>Error <code>%1$s</code>: "
87
- "%2$s</p>"
88
- msgstr ""
89
-
90
- #: lib/updater/api.php:45
91
- msgid ""
92
- "<p>Unable to get changelog data at this time.</p><p>Error: Unrecognized "
93
- "response from <code>wp_remote_get</code>.</p>"
94
- msgstr ""
95
-
96
- #: lib/updater/api.php:49
97
- msgid ""
98
- "<p>Unable to get changelog data at this time.</p><p>Error code <code>%1$s</"
99
- "code>: %2$s</p>"
100
- msgstr ""
101
-
102
- #: lib/updater/api.php:61
103
- msgid ""
104
- "<p>Unable to get changelog data at this time.</p><p>Error: Unrecognized "
105
- "response from iThemes API server.</p>"
106
- msgstr ""
107
-
108
- #: lib/updater/server.php:78
109
- msgid ""
110
- "The server could not be contacted. Requests are delayed for %d minute to "
111
- "allow the server to recover."
112
- msgid_plural ""
113
- "The server could not be contacted. Requests are delayed for %d minutes to "
114
- "allow the server to recover."
115
- msgstr[0] ""
116
- msgstr[1] ""
117
-
118
- #: lib/updater/server.php:155
119
- msgid "The server was unable to be contacted."
120
- msgstr ""
121
-
122
- #: lib/updater/server.php:165
123
- msgid ""
124
- "An error occurred when communicating with the iThemes update server: %s (%s)"
125
- msgstr ""
126
-
127
- #: lib/updater/settings-page.php:77
128
- msgid ""
129
- "Incorrect password. Please make sure that you are supplying your iThemes "
130
- "membership username and password details."
131
- msgstr ""
132
-
133
- #: lib/updater/settings-page.php:81
134
- msgid ""
135
- "Invalid username. Please make sure that you are supplying your iThemes "
136
- "membership username and password details."
137
- msgstr ""
138
-
139
- #: lib/updater/settings-page.php:84
140
- msgid ""
141
- "The licensing server reports that the %1$s (%2$s) product is unknown. Please "
142
- "contact support for assistance."
143
- msgstr ""
144
-
145
- #: lib/updater/settings-page.php:87
146
- msgid ""
147
- "%1$s could not be licensed since the membership account is out of available "
148
- "licenses for this product. You can unlicense the product on other sites or "
149
- "upgrade your membership to one with a higher number of licenses in order to "
150
- "increase the amount of available licenses."
151
- msgstr ""
152
-
153
- #: lib/updater/settings-page.php:90
154
- msgid ""
155
- "%s could not be licensed due to an internal error. Please try to license %s "
156
- "again at a later time. If this problem continues, please contact iThemes "
157
- "support."
158
- msgstr ""
159
-
160
- #: lib/updater/settings-page.php:96
161
- msgid ""
162
- "An unknown error relating to the %1$s product occurred. Please contact "
163
- "iThemes support. Error details: %2$s"
164
- msgstr ""
165
-
166
- #: lib/updater/settings-page.php:98
167
- msgid ""
168
- "An unknown error occurred. Please contact iThemes support. Error details: %s"
169
- msgstr ""
170
-
171
- #: lib/updater/settings-page.php:129 settings-page.php:239
172
- msgid "Settings saved"
173
- msgstr ""
174
-
175
- #: lib/updater/settings-page.php:136
176
- msgid ""
177
- "You must supply an iThemes membership username and password in order to "
178
- "license products."
179
- msgstr ""
180
-
181
- #: lib/updater/settings-page.php:138
182
- msgid ""
183
- "You must supply an iThemes membership username in order to license products."
184
- msgstr ""
185
-
186
- #: lib/updater/settings-page.php:140
187
- msgid ""
188
- "You must supply an iThemes membership password in order to license products."
189
- msgstr ""
190
-
191
- #: lib/updater/settings-page.php:142
192
- msgid ""
193
- "You must select at least one product to license. Ensure that you select the "
194
- "products that you wish to license in the listing below."
195
- msgstr ""
196
-
197
- #: lib/updater/settings-page.php:157
198
- msgid ""
199
- "An unknown server error occurred. Please try to license your products again "
200
- "at another time."
201
- msgstr ""
202
-
203
- #: lib/updater/settings-page.php:177
204
- msgid "Your product subscription has expired"
205
- msgstr ""
206
-
207
- #: lib/updater/settings-page.php:184
208
- msgid "Successfully licensed %l."
209
- msgstr ""
210
-
211
- #: lib/updater/settings-page.php:188 lib/updater/settings-page.php:193
212
- msgid "Unable to license %1$s. Reason: %2$s"
213
- msgstr ""
214
-
215
- #: lib/updater/settings-page.php:201
216
- msgid ""
217
- "You must supply an iThemes membership username and password in order to "
218
- "remove licenses."
219
- msgstr ""
220
-
221
- #: lib/updater/settings-page.php:203
222
- msgid ""
223
- "You must supply an iThemes membership username in order to remove licenses."
224
- msgstr ""
225
-
226
- #: lib/updater/settings-page.php:205
227
- msgid ""
228
- "You must supply an iThemes membership password in order to remove licenses."
229
- msgstr ""
230
-
231
- #: lib/updater/settings-page.php:207
232
- msgid ""
233
- "You must select at least one license to remove. Ensure that you select the "
234
- "licenses that you wish to remove in the listing below."
235
- msgstr ""
236
-
237
- #: lib/updater/settings-page.php:222
238
- msgid ""
239
- "An unknown server error occurred. Please try to remove licenses from your "
240
- "products again at another time."
241
- msgstr ""
242
-
243
- #: lib/updater/settings-page.php:243
244
- msgid "Unknown server error."
245
- msgstr ""
246
-
247
- #: lib/updater/settings-page.php:248
248
- msgid "Successfully removed license from %l."
249
- msgid_plural "Successfully removed licenses from %l."
250
- msgstr[0] ""
251
- msgstr[1] ""
252
-
253
- #: lib/updater/settings-page.php:252
254
- msgid "Unable to remove license from %1$s. Reason: %2$s"
255
- msgstr ""
256
-
257
- #: lib/updater/settings-page.php:324
258
- msgid "Settings"
259
- msgstr ""
260
-
261
- #: lib/updater/settings-page.php:330
262
- msgid "Quick Release Updates"
263
- msgstr ""
264
-
265
- #: lib/updater/settings-page.php:337
266
- msgid "Enable quick release updates"
267
- msgstr ""
268
-
269
- #: lib/updater/settings-page.php:340
270
- msgid ""
271
- "Some products have quick releases that are created to solve specific issues "
272
- "that some users experience. In order to avoid causing users to have updates "
273
- "show up too frequently, automatic updates to these quick releases are "
274
- "disabled by default. Enabling this feature allows quick releases to be "
275
- "available to the automatic update system. Using this option is only "
276
- "recommended if support has requested that you enable it in order to receive "
277
- "a quick release. You should disable this option at a later time after "
278
- "confirming that the quick release solves the issue for you."
279
- msgstr ""
280
-
281
- #: lib/updater/settings-page.php:347
282
- msgid "Save Settings"
283
- msgstr ""
284
-
285
- #: lib/updater/settings-page.php:366 lib/updater/settings-page.php:397
286
- #: lib/updater/settings-page.php:521 lib/updater/settings-page.php:589
287
- msgid "Product"
288
- msgstr ""
289
-
290
- #: lib/updater/settings-page.php:367 lib/updater/settings-page.php:399
291
- msgid "Member"
292
- msgstr ""
293
-
294
- #: lib/updater/settings-page.php:368 lib/updater/settings-page.php:401
295
- msgid "Expiration"
296
- msgstr ""
297
-
298
- #: lib/updater/settings-page.php:369 lib/updater/settings-page.php:402
299
- msgid "Remaining Licenses"
300
- msgstr ""
301
-
302
- #: lib/updater/settings-page.php:385
303
- msgid "Licensed Products"
304
- msgstr ""
305
-
306
- #: lib/updater/settings-page.php:391 lib/updater/settings-page.php:515
307
- msgid "Select All"
308
- msgstr ""
309
-
310
- #: lib/updater/settings-page.php:400
311
- msgid "Product Status"
312
- msgstr ""
313
-
314
- #: lib/updater/settings-page.php:410
315
- msgid "unlimited"
316
- msgstr ""
317
-
318
- #: lib/updater/settings-page.php:451 lib/updater/settings-page.php:545
319
- msgid "Select %s"
320
- msgstr ""
321
-
322
- #: lib/updater/settings-page.php:471
323
- msgid "Remove Licenses"
324
- msgstr ""
325
-
326
- #: lib/updater/settings-page.php:505
327
- msgid "Unlicensed Products"
328
- msgstr ""
329
-
330
- #: lib/updater/settings-page.php:507
331
- msgid ""
332
- "The following products have not been licensed. Licensing a product gives you "
333
- "access to automatic updates from within WordPress."
334
- msgstr ""
335
-
336
- #: lib/updater/settings-page.php:508
337
- msgid ""
338
- "To license products, select the products you wish to license, enter your "
339
- "iThemes membership username and password, and press the License Products "
340
- "button."
341
- msgstr ""
342
-
343
- #: lib/updater/settings-page.php:509
344
- msgid "Need help? <a href=\"%s\">Click here for a quick video tutorial</a>."
345
- msgstr ""
346
-
347
- #: lib/updater/settings-page.php:561
348
- msgid "License Products"
349
- msgstr ""
350
-
351
- #: lib/updater/settings-page.php:581
352
- msgid "Unrecognized Products"
353
- msgstr ""
354
-
355
- #: lib/updater/settings-page.php:583
356
- msgid ""
357
- "The following products were not recognized by the licensing system. This can "
358
- "be due to a bug in the product code, a temporary server issue, or because "
359
- "the product is no longer supported."
360
- msgstr ""
361
-
362
- #: lib/updater/settings-page.php:584
363
- msgid ""
364
- "Please check this page again at a later time to see if the problem resolves "
365
- "itself. If the product remains, please contact <a href=\"%s\">iThemes "
366
- "support</a> and provide them with the details given below."
367
- msgstr ""
368
-
369
- #: lib/updater/settings-page.php:590
370
- msgid "Type"
371
- msgstr ""
372
-
373
- #: lib/updater/settings-page.php:591
374
- msgid "Package"
375
- msgstr ""
376
-
377
- #: lib/updater/settings-page.php:592
378
- msgid "Version"
379
- msgstr ""
380
-
381
- #: lib/updater/settings-page.php:593
382
- msgid "Server Response"
383
- msgstr ""
384
-
385
- #: lib/updater/settings-page.php:603
386
- msgid "Unknown Error"
387
- msgstr ""
388
-
389
- #: lib/updater/settings-page.php:642
390
- msgid "%d day"
391
- msgid_plural "%d days"
392
- msgstr[0] ""
393
- msgstr[1] ""
394
-
395
- #: lib/updater/settings-page.php:644
396
- msgid "%d hour"
397
- msgid_plural "%d hours"
398
- msgstr[0] ""
399
- msgstr[1] ""
400
-
401
- #: lib/updater/settings-page.php:646
402
- msgid "%d minute"
403
- msgid_plural "%d minutes"
404
- msgstr[0] ""
405
- msgstr[1] ""
406
-
407
- #: lib/updater/settings-page.php:648
408
- msgid "%d second"
409
- msgid_plural "%d seconds"
410
- msgstr[0] ""
411
- msgstr[1] ""
412
-
413
- #: lib/updater/settings-page.php:651
414
- msgid "%s ago"
415
- msgstr ""
416
-
417
- #: notice-handler.php:89
418
- msgid "The Sync server returned an unknown response."
419
- msgstr ""
420
-
421
- #: server.php:188
422
- msgid ""
423
- "An unrecognized server response format was received from the iThemes Sync "
424
- "server."
425
- msgstr ""
426
-
427
- #: settings-page.php:54
428
- msgid "Are you sure that you wish to unsync this user?"
429
- msgstr ""
430
-
431
- #: settings-page.php:91 settings-page.php:108 settings-page.php:117
432
- #: settings-page.php:129
433
- msgid "The user could not be synced."
434
- msgstr ""
435
-
436
- #: settings-page.php:96
437
- msgid ""
438
- "<p>The iThemes Sync server was unable to be contacted. WordPress returned "
439
- "the following error when trying to contact the server:</p><p>%1$s</p><p>If "
440
- "you continue to experience problems, please contact <a target=\"_blank\" "
441
- "href=\"%2$s\">iThemes support</a>.</p>"
442
- msgstr ""
443
-
444
- #: settings-page.php:98
445
- msgid ""
446
- "<p>The iThemes Sync server was unable to process the request at this time. "
447
- "Please try again in a few minutes.</p><p>If you continue to experience "
448
- "problems, please contact <a target=\"_blank\" href=\"%s\">iThemes support</"
449
- "a>.</p>"
450
- msgstr ""
451
-
452
- #: settings-page.php:109
453
- msgid ""
454
- "The sync request failed due to a server communication error. The server sent "
455
- "a response that did not include a authentication key."
456
- msgstr ""
457
-
458
- #: settings-page.php:118
459
- msgid ""
460
- "The sync request failed due to a server communication error. The server sent "
461
- "a response that did not include a user ID."
462
- msgstr ""
463
-
464
- #: settings-page.php:138
465
- msgid "Woohoo! Your site has been synced."
466
- msgstr ""
467
-
468
- #: settings-page.php:142
469
- msgid ""
470
- "Your user has now used all of the sites available to be added to Sync. More "
471
- "information can be found on the <a href=\"%s\" target=\"_blank\">iThemes "
472
- "membership panel</a>."
473
- msgstr ""
474
-
475
- #: settings-page.php:144
476
- msgid "Your user can Sync 1 additional site."
477
- msgid_plural "Your user can sync %d additional sites."
478
- msgstr[0] ""
479
- msgstr[1] ""
480
-
481
- #: settings-page.php:160 settings-page.php:172
482
- msgid "The user could not be unsynced."
483
- msgstr ""
484
-
485
- #: settings-page.php:181
486
- msgid "The user was successfully unsynced."
487
- msgstr ""
488
-
489
- #: settings-page.php:266
490
- msgid "Sync This Site"
491
- msgstr ""
492
-
493
- #: settings-page.php:276
494
- msgid "Go Manage Your Synced Sites"
495
- msgstr ""
496
-
497
- #: settings-page.php:279
498
- msgid "Manage Synced Users"
499
- msgstr ""
500
-
501
- #: settings-page.php:281
502
- msgid ""
503
- "Sync allows you to sync your site with multiple users.<br>View the list of "
504
- "synced users below, unsync users if needed, or add additional users below."
505
- msgstr ""
506
-
507
- #: settings-page.php:285
508
- msgid "Synced Users"
509
- msgstr ""
510
-
511
- #: settings-page.php:300
512
- msgid "Invalid Users"
513
- msgstr ""
514
-
515
- #: settings-page.php:302
516
- msgid ""
517
- "The following users were not recognized by the server. Unsync them and "
518
- "resync them again to fix this error."
519
- msgstr ""
520
-
521
- #: settings-page.php:320
522
- msgid "Enter your iThemes username & password to sync this site."
523
- msgstr ""
524
-
525
- #: settings-page.php:322
526
- msgid "Add Users"
527
- msgstr ""
528
-
529
- #: settings-page.php:323
530
- msgid ""
531
- "Add additional users if more than one person will be managing updates for "
532
- "this site.<br>To sync an additional user, enter their iThemes username and "
533
- "password below."
534
- msgstr ""
535
-
536
- #: settings-page.php:327
537
- msgid "Username"
538
- msgstr ""
539
-
540
- #: settings-page.php:330
541
- msgid "Password"
542
- msgstr ""
543
-
544
- #: settings-page.php:333
545
- msgid "Sync"
546
- msgstr ""
547
-
548
- #: settings.php:131
549
- msgid ""
550
- "The user is not authenticated. Could not remove authentication for the user."
551
- msgstr ""
552
-
553
- #: settings.php:197
554
- msgid ""
555
- "A valid user was unable to be found. A valid user is required in order to do "
556
- "a successful ping."
557
- msgstr ""
558
-
559
- #: social.php:86
560
- msgid "Social"
561
- msgstr ""
562
-
563
- #: social.php:102
564
- msgid "This post is already published."
565
- msgstr ""
566
-
567
- #: social.php:119
568
- msgid "Edit"
569
- msgstr ""
570
-
571
- #: social.php:123
572
- msgid "Template Tags"
573
- msgstr ""
574
-
575
- #: verbs/db-optimization.php:96
576
- msgid "Delete Trackback URLs"
577
- msgstr ""
578
-
579
- #: verbs/db-optimization.php:97
580
- msgid ""
581
- "Deletes URLs added to the \"pinged\" and \"to_ping\" columns in your posts "
582
- "table."
583
- msgstr ""
584
-
585
- #: verbs/db-optimization.php:382
586
- msgid "Never"
587
- msgstr ""
588
-
589
- #: verbs/get-wordpress-settings.php:141
590
- msgctxt "timezone date format"
591
- msgid "Y-m-d H:i:s"
592
- msgstr ""
593
-
594
- #: verbs/get-wordpress-settings.php:184
595
- msgid "F j, Y"
596
- msgstr ""
597
-
598
- #: verbs/get-wordpress-settings.php:198
599
- msgid "g:i a"
600
- msgstr ""
601
-
602
- #: verbs/get-wordpress-settings.php:239 verbs/get-wordpress-settings.php:246
603
- msgid "&mdash; Select &mdash;"
604
- msgstr ""
605
-
606
- #. Plugin URI of the plugin/theme
607
- msgid "http://ithemes.com/sync"
608
- msgstr ""
609
-
610
- #. Description of the plugin/theme
611
- msgid "Manage updates to your WordPress sites easily in one place."
612
- msgstr ""
613
-
614
- #. Author of the plugin/theme
615
- msgid "iThemes"
616
- msgstr ""
617
-
618
- #. Author URI of the plugin/theme
619
- msgid "http://ithemes.com/"
620
- msgstr ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/lib/updater/admin.php DELETED
@@ -1,215 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Set up admin interface elements.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.2.2
7
-
8
- Version History
9
- 1.0.0 - 2013-09-19 - Chris Jean
10
- Split off from the old Ithemes_Updater_Init class.
11
- 1.1.0 - 2013-10-02 - Chris Jean
12
- Added support for themes through the filter_plugins_api function (since themes don't have a "View version *** details" feature.
13
- 1.2.0 - 2013-10-23 - Chris Jean
14
- Changed how the licensing page is registered for multisite. It now will only load on multisite sites if the user is a super user (network admin).
15
- Removed the code that handled the setting to show or hide the licensing page on multisite sites.
16
- 1.2.1 - 2013-10-25 - Chris Jean
17
- Added "License" links to Network Admin Plugins and Themes pages.
18
- 1.2.2 - 2014-10-23 - Chris Jean
19
- Updated code formating to WordPress coding standards.
20
- */
21
-
22
-
23
- class Ithemes_Updater_Admin {
24
- private $page_name = 'ithemes-licensing';
25
-
26
- private $package_details = false;
27
- private $registration_link = false;
28
-
29
- private $page_ref;
30
-
31
-
32
- public function __construct() {
33
- require_once( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
34
-
35
- if ( ! is_multisite() || is_super_admin() ) {
36
- add_action( 'admin_menu', array( $this, 'add_admin_pages' ) );
37
- }
38
-
39
- add_action( 'network_admin_menu', array( $this, 'add_network_admin_pages' ) );
40
-
41
- add_action( 'admin_head-plugins.php', array( $this, 'show_activation_message' ) );
42
- add_action( 'admin_head-themes.php', array( $this, 'show_activation_message' ) );
43
- add_action( 'deactivated_plugin', array( $this, 'clear_activation_package' ) );
44
-
45
- add_filter( 'upgrader_pre_install', array( $this, 'filter_upgrader_pre_install' ) );
46
- add_filter( 'upgrader_post_install', array( $this, 'filter_upgrader_post_install' ), 10, 3 );
47
- add_filter( 'plugins_api', array( $this, 'filter_plugins_api' ), 10, 3 );
48
-
49
- if ( ! is_multisite() || is_super_admin() ) {
50
- add_filter( 'plugin_action_links', array( $this, 'filter_plugin_action_links' ), 10, 4 );
51
- add_filter( 'theme_action_links', array( $this, 'filter_theme_action_links' ), 10, 2 );
52
- }
53
-
54
- add_filter( 'network_admin_plugin_action_links', array( $this, 'filter_plugin_action_links' ), 10, 4 );
55
- add_filter( 'network_admin_theme_action_links', array( $this, 'filter_theme_action_links' ), 10, 2 );
56
- }
57
-
58
- public function filter_plugins_api( $value, $action, $args ) {
59
- $options = $GLOBALS['ithemes-updater-settings']->get_options();
60
-
61
- if ( ! isset( $args->slug ) ) {
62
- return $value;
63
- }
64
-
65
- foreach ( (array) $options['update_plugins'] as $path => $data ) {
66
- if ( $data->slug == $args->slug ) {
67
- require_once( $GLOBALS['ithemes_updater_path'] . '/information.php' );
68
- return Ithemes_Updater_Information::get_plugin_information( $path );
69
- }
70
- }
71
-
72
- foreach ( (array) $options['update_themes'] as $path => $data ) {
73
- if ( $path == $args->slug ) {
74
- require_once( $GLOBALS['ithemes_updater_path'] . '/information.php' );
75
- return Ithemes_Updater_Information::get_theme_information( $path );
76
- }
77
- }
78
-
79
- return $value;
80
- }
81
-
82
- public function filter_upgrader_pre_install( $value ) {
83
- $this->set_package_details();
84
-
85
- return $value;
86
- }
87
-
88
- public function filter_upgrader_post_install( $value, $hook_extra, $result ) {
89
- $options = $GLOBALS['ithemes-updater-settings']->queue_flush();
90
-
91
- return $value;
92
- }
93
-
94
- public function clear_activation_package( $deactivated_path ) {
95
- $packages = $GLOBALS['ithemes-updater-settings']->get_packages();
96
- $options = $GLOBALS['ithemes-updater-settings']->get_options();
97
-
98
- $deactivated_path = WP_PLUGIN_DIR . "/$deactivated_path";
99
-
100
- foreach ( $packages as $package => $paths ) {
101
- if ( ! in_array( $deactivated_path, $paths ) || ( count( $paths ) > 1 ) ) {
102
- continue;
103
- }
104
-
105
- $index = array_search( $package, $options['packages'] );
106
-
107
- if ( false === $index ) {
108
- return;
109
- }
110
-
111
- unset( $options['packages'][$index] );
112
- $GLOBALS['ithemes-updater-settings']->update_options( $options );
113
-
114
- return;
115
- }
116
- }
117
-
118
- public function show_activation_message() {
119
- $new_packages = $GLOBALS['ithemes-updater-settings']->get_new_packages();
120
-
121
- if ( empty( $new_packages ) ) {
122
- return;
123
- }
124
-
125
-
126
- natcasesort( $new_packages );
127
- require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
128
- $names = array();
129
-
130
- foreach ( $new_packages as $package ) {
131
- $names = Ithemes_Updater_Functions::get_package_name( $package );
132
- }
133
-
134
- if ( is_multisite() && is_network_admin() ) {
135
- $url = network_admin_url( 'settings.php' ) . "?page={$this->page_name}";
136
- } else {
137
- $url = admin_url( 'options-general.php' ) . "?page={$this->page_name}";
138
- }
139
-
140
- echo '<div class="updated fade"><p>' . wp_sprintf( __( 'To receive automatic updates for %l, use the <a href="%s">iThemes Licensing</a> page found in the Settings menu.', 'it-l10n-ithemes-sync' ), $names, $url ) . '</p></div>';
141
-
142
-
143
- $GLOBALS['ithemes-updater-settings']->update_packages();
144
- }
145
-
146
- public function add_admin_pages() {
147
- $this->page_ref = add_options_page( __( 'iThemes Licensing', 'it-l10n-ithemes-sync' ), __( 'iThemes Licensing', 'it-l10n-ithemes-sync' ), 'manage_options', $this->page_name, array( $this, 'settings_index' ) );
148
-
149
- add_action( "load-{$this->page_ref}", array( $this, 'load_settings_page' ) );
150
- }
151
-
152
- public function add_network_admin_pages() {
153
- $this->page_ref = add_submenu_page( 'settings.php', __( 'iThemes Licensing', 'it-l10n-ithemes-sync' ), __( 'iThemes Licensing', 'it-l10n-ithemes-sync' ), 'manage_options', $this->page_name, array( $this, 'settings_index' ) );
154
-
155
- add_action( "load-{$this->page_ref}", array( $this, 'load_settings_page' ) );
156
- }
157
-
158
- public function load_settings_page() {
159
- require( $GLOBALS['ithemes_updater_path'] . '/settings-page.php' );
160
- }
161
-
162
- public function settings_index() {
163
- do_action( 'ithemes_updater_settings_page_index' );
164
- }
165
-
166
- private function set_package_details() {
167
- if ( false !== $this->package_details ) {
168
- return;
169
- }
170
-
171
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
172
- $this->package_details = Ithemes_Updater_Packages::get_local_details();
173
- }
174
-
175
- private function set_registration_link() {
176
- if ( false !== $this->registration_link ) {
177
- return;
178
- }
179
-
180
- $url = admin_url( 'options-general.php' ) . "?page={$this->page_name}";
181
- $this->registration_link = sprintf( '<a href="%1$s" title="%2$s">%3$s</a>', $url, __( 'Manage iThemes product licenses to receive automatic upgrade support', 'it-l10n-ithemes-sync' ), __( 'License', 'it-l10n-ithemes-sync' ) );
182
- }
183
-
184
- public function filter_plugin_action_links( $actions, $plugin_file, $plugin_data, $context ) {
185
- $this->set_package_details();
186
- $this->set_registration_link();
187
-
188
- if ( isset( $this->package_details[$plugin_file] ) ) {
189
- $actions[] = $this->registration_link;
190
- }
191
-
192
- return $actions;
193
- }
194
-
195
- public function filter_theme_action_links( $actions, $theme ) {
196
- $this->set_package_details();
197
- $this->set_registration_link();
198
-
199
- if ( is_object( $theme ) ) {
200
- $path = basename( $theme->get_stylesheet_directory() ) . '/style.css';
201
- } else if ( is_array( $theme ) && isset( $theme['Stylesheet Dir'] ) ) {
202
- $path = $theme['Stylesheet Dir'] . '/style.css';
203
- } else {
204
- $path = '';
205
- }
206
-
207
- if ( isset( $this->package_details[$path] ) ) {
208
- $actions[] = $this->registration_link;
209
- }
210
-
211
- return $actions;
212
- }
213
- }
214
-
215
- new Ithemes_Updater_Admin();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/api.php DELETED
@@ -1,301 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Provides an easy to use interface for communicating with the iThemes updater server.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.1.1
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- 1.0.1 - 2013-09-19 - Chris Jean
12
- Updated requires to not use dirname().
13
- Updated ithemes-updater-object to ithemes-updater-settings.
14
- 1.1.0 - 2013-10-02 - Chris Jean
15
- Added get_package_changelog().
16
- 1.1.1 - 2014-11-13 - Chris Jean
17
- Improved caching.
18
- Updated code to meet WordPress coding standards.
19
- */
20
-
21
-
22
- class Ithemes_Updater_API {
23
- public static function activate_package( $username, $password, $packages ) {
24
- return self::get_response( 'activate_package', compact( 'username', 'password', 'packages' ), false );
25
- }
26
-
27
- public static function deactivate_package( $username, $password, $packages ) {
28
- return self::get_response( 'deactivate_package', compact( 'username', 'password', 'packages' ), false );
29
- }
30
-
31
- public static function get_package_details( $cache = true ) {
32
- $packages = array();
33
-
34
- return self::get_response( 'get_package_details', compact( 'packages' ), $cache );
35
- }
36
-
37
- public static function get_package_changelog( $package, $cur_version = false ) {
38
- $response = wp_remote_get( 'http://api.ithemes.com/product/changelog?package=' . urlencode( $package ) );
39
-
40
- if ( is_wp_error( $response ) ) {
41
- return sprintf( __( '<p>Unable to get changelog data at this time.</p><p>Error <code>%1$s</code>: %2$s</p>', 'it-l10n-ithemes-sync' ), $response->get_error_code(), $response->get_error_message() );
42
- }
43
-
44
- if ( ! is_array( $response ) || ! isset( $response['body'] ) ) {
45
- return __( '<p>Unable to get changelog data at this time.</p><p>Error: Unrecognized response from <code>wp_remote_get</code>.</p>', 'it-l10n-ithemes-sync' );
46
- }
47
-
48
- if ( isset( $response['response']['code'] ) && ( '200' != $response['response']['code'] ) ) {
49
- return sprintf( __( '<p>Unable to get changelog data at this time.</p><p>Error code <code>%1$s</code>: %2$s</p>', 'it-l10n-ithemes-sync' ), $response['response']['code'], $response['response']['message'] );
50
- }
51
-
52
-
53
- $body = $response['body'];
54
-
55
- if ( '{' === substr( $body, 0, 1 ) ) {
56
- $error = json_decode( $body, true );
57
-
58
- if ( is_array( $error ) && isset( $error['error'] ) && is_array( $error['error'] ) && isset( $error['error']['type'] ) && isset( $error['error']['message'] ) ) {
59
- return sprintf( __( '<p>Unable to get changelog data at this time.</p><p>Error <code>%1$s</code>: %2$s</p>', 'it-l10n-ithemes-sync' ), $error['error']['type'], $error['error']['message'] );
60
- } else {
61
- return __( '<p>Unable to get changelog data at this time.</p><p>Error: Unrecognized response from iThemes API server.</p>', 'it-l10n-ithemes-sync' );
62
- }
63
- }
64
-
65
-
66
- $versions = array();
67
- $version = false;
68
- $depth = 0;
69
-
70
- $lines = preg_split( '/[\n\r]+/', $body );
71
-
72
- foreach ( $lines as $line ) {
73
- if ( preg_match( '/^\d/', $line ) ) {
74
- if ( ! empty( $version ) && ( $depth > 0 ) ) {
75
- while ( $depth-- > 0 ) {
76
- $versions[$version] .= "</ul>\n";
77
- }
78
- }
79
-
80
- $depth = 0;
81
-
82
- $parts = preg_split( '/\s+-\s+/', $line );
83
- $version = $parts[0];
84
-
85
- if ( version_compare( $version, $cur_version, '<=' ) ) {
86
- $version = '';
87
- continue;
88
- }
89
-
90
- $versions[$version] = '';
91
-
92
- continue;
93
- } else if ( preg_match( '/^\S/', $line ) ) {
94
- $version = '';
95
- continue;
96
- } else if ( empty( $version ) ) {
97
- continue;
98
- }
99
-
100
- $line = str_replace( ' ', "\t", $line );
101
- $line = str_replace( "\t", '', $line, $count );
102
- $line = preg_replace( '/^\s+/', '', $line );
103
-
104
- if ( empty( $line ) ) {
105
- continue;
106
- }
107
-
108
- $details = '';
109
-
110
- if ( $count > $depth ) {
111
- $details .= "<ul>\n";
112
- $depth++;
113
- } else if ( $count < $depth ) {
114
- $details .= "</ul>\n";
115
- $depth--;
116
- }
117
-
118
- $details .= "<li>$line</li>\n";
119
-
120
-
121
- $versions[$version] .= $details;
122
- }
123
-
124
- if ( ! empty( $version ) && ( $depth > 0 ) ) {
125
- while ( $depth-- > 0 ) {
126
- $versions[$version] .= "</ul>\n";
127
- }
128
- }
129
-
130
-
131
- uksort( $versions, 'version_compare' );
132
- $versions = array_reverse( $versions );
133
-
134
-
135
- $changelog = '';
136
-
137
- foreach ( $versions as $version => $details ) {
138
- $changelog .= "<h4>$version</h4>\n$details\n";
139
- }
140
-
141
- $changelog = preg_replace( '/\s+$/', '', $changelog );
142
-
143
-
144
- return $changelog;
145
- }
146
-
147
- public static function get_response( $action, $args, $cache ) {
148
- require_once( $GLOBALS['ithemes_updater_path'] . '/server.php' );
149
- require_once( $GLOBALS['ithemes_updater_path'] . '/updates.php' );
150
-
151
-
152
- if ( isset( $args['packages'] ) ) {
153
- $args['packages'] = self::get_request_package_details( $args['packages'] );
154
- }
155
-
156
-
157
- $response = false;
158
- $source = '';
159
- $cached = true;
160
-
161
- $md5 = substr( md5( serialize( $args ) ), 0, 5 );
162
- $time = time();
163
- $cache_var = "it-updater-$action-$md5";
164
-
165
-
166
- if ( $cache ) {
167
- if ( isset( $GLOBALS[$cache_var] ) ) {
168
- $response = $GLOBALS[$cache_var];
169
- $source = 'GLOBALS';
170
- } else if ( false !== ( $transient = get_site_transient( $cache_var ) ) ) {
171
- $response = $transient;
172
- $source = 'transient';
173
- }
174
- }
175
-
176
-
177
- if ( false === $response ) {
178
- $response = call_user_func_array( array( 'Ithemes_Updater_Server', $action ), $args );
179
- $source = 'server';
180
-
181
- if ( is_wp_error( $response ) ) {
182
- return $response;
183
- }
184
-
185
- $cache_length = 86400 * $GLOBALS['ithemes-updater-settings']->get_option( 'timeout-multiplier' );
186
-
187
- set_site_transient( $cache_var, $response, $cache_length );
188
-
189
- $cached = false;
190
- }
191
-
192
-
193
- Ithemes_Updater_Updates::process_server_response( $response, $cached );
194
-
195
- $GLOBALS[$cache_var] = $response;
196
-
197
- return $response;
198
- }
199
-
200
- private static function get_request_package_details( $desired_packages = array() ) {
201
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
202
- require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
203
-
204
-
205
- $all_packages = Ithemes_Updater_Packages::get_local_details();
206
- reset( $desired_packages );
207
-
208
- if ( empty( $desired_packages ) ) {
209
- $desired_packages = $all_packages;
210
- } else if ( is_numeric( key( $desired_packages ) ) ) {
211
- $new_desired_packages = array();
212
-
213
- foreach ( $all_packages as $path => $details ) {
214
- foreach ( $desired_packages as $package ) {
215
- if ( $package != $details['package'] ) {
216
- continue;
217
- }
218
-
219
- $new_desired_packages[$path] = $details;
220
-
221
- break;
222
- }
223
- }
224
-
225
- $desired_packages = $new_desired_packages;
226
- }
227
-
228
-
229
- $packages = array();
230
- $keys = Ithemes_Updater_Keys::get();
231
-
232
-
233
- $package_slugs = array();
234
-
235
- foreach ( $desired_packages as $data ) {
236
- $package_slugs[] = $data['package'];
237
- }
238
-
239
- $legacy_keys = Ithemes_Updater_Keys::get_legacy( $package_slugs );
240
-
241
-
242
- $active_themes = array(
243
- 'stylesheet' => get_stylesheet_directory(),
244
- 'template' => get_template_directory(),
245
- );
246
- $active_themes = array_unique( $active_themes );
247
-
248
- foreach ( $active_themes as $index => $path ) {
249
- $active_themes[$index] = basename( $path );
250
- }
251
-
252
-
253
- foreach ( $desired_packages as $path => $data ) {
254
- $key = ( isset( $keys[$data['package']] ) ) ? $keys[$data['package']] : '';
255
-
256
- $package = array(
257
- 'ver' => $data['installed'],
258
- 'key' => $key,
259
- );
260
-
261
- if ( ! empty( $legacy_keys[$data['package']] ) ) {
262
- $package['old-key'] = $legacy_keys[$data['package']];
263
- }
264
-
265
-
266
- if ( 'plugins' == $data['type'] ) {
267
- $package['active'] = (int) is_plugin_active( $path );
268
- } else {
269
- $dir = dirname( $path );
270
-
271
- $package['active'] = (int) in_array( $dir, $active_themes );
272
-
273
- if ( $package['active'] && ( count( $active_themes ) > 1 ) ) {
274
- if ( $dir == $active_themes['stylesheet'] ) {
275
- $package['child-theme'] = 1;
276
- } else {
277
- $package['parent-theme'] = 1;
278
- }
279
- }
280
- }
281
-
282
-
283
- $package_key = $data['package'];
284
- $counter = 0;
285
-
286
- while ( isset( $packages[$package_key] ) ) {
287
- $package_key = "{$data['package']} ||| " . ++$counter;
288
- }
289
-
290
- $packages[$package_key] = $package;
291
- }
292
-
293
-
294
- if ( ! empty( $legacy_keys ) ) {
295
- Ithemes_Updater_Keys::delete_legacy( array_keys( $legacy_keys ) );
296
- }
297
-
298
-
299
- return $packages;
300
- }
301
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/api.txt DELETED
@@ -1,40 +0,0 @@
1
- # iThemes Updater API #
2
-
3
- This document lists the different API features of the iThemes Updater system.
4
-
5
- Note: This document is in [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown) format.
6
-
7
-
8
- ## Defines ##
9
-
10
- The entire updater system can be disabled by creating a define named ITHEMES_UPDATER_DISABLE with a truthy value. For example, the following could be added to the wp-config.php file to disable the updater system:
11
-
12
- define( 'ITHEMES_UPDATER_DISABLE', true );
13
-
14
-
15
- ## Query Strings ##
16
-
17
- The updater system has built in refresh intervals:
18
-
19
- * One minute - When on the Dashboard > Updates or Settings > iThemes Licensing pages, the data will refresh in one minute intervals. This means that once the data is a minute or older, it will be refreshed.
20
- * One hour - When on the Plugins > Installed Plugins or Appearance > Themes pages, the data will refresh in one hour intervals.
21
- * Twelve hours - On all other pages the data will refresh in twelve hour intervals.
22
-
23
- Note that data is only refreshed when in the WordPress Dashboard (wp-admin). This prevents adding additional load time when people are browsing the site.
24
-
25
- You can force a manual refresh of the data by modifying the URL of the page to include a non-empty query variable named ithemes-updater-force-refresh. This can be helpful if you think that the updater is having a problem and isn't properly refreshing itself.
26
-
27
- For example, if you are on an admin page with a URL of http://example.com/wp-admin/plugins.php, you can force a refresh by changing the URL to the following:
28
-
29
- http://example.com/wp-admin/plugins.php?ithemes-updater-force-refresh=1
30
-
31
- Note that forcing a refresh only works on the WordPress Dashboard and not on the site front-end. In addition, only users with the manage_options capability have the ability to force a refresh. By default, the only users with this capability are the ones in the Administrator role. These restrictions are to help prevent a non-authorized user from consuming server resources by forcing numerous refreshes.
32
-
33
-
34
- Some of our releases have versions with four digits, such as 3.1.1.1. Releases with a four-digit version are quick releases and are meant for rapid bug fix releases (typically in response to a specific support request). If the version on the site is only different by this last digit in a four-digit version (such as currently running 3.1.1.1 when 3.1.1.4 is available), then the updater will not show an update as available. You can force the updater to make such releases available by modifying an admin page URL to include a non-empty query variable named ithemes-updater-force-minor-update.
35
-
36
- For example, if you are on an admin page with a URL of http://example.com/wp-admin/plugins.php, you can force quick bug fix releases to be avaiable by changing the URL to the following:
37
-
38
- http://example.com/wp-admin/plugins.php?ithemes-updater-force-minor-update=1
39
-
40
- Note: The updater now supports a query variable named ithemes-updater-force-quick-release-update. It has the same functionality as ithemes-updater-force-minor-update.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/ca/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/lib/updater/ca/roots.crt DELETED
@@ -1,58 +0,0 @@
1
- ##
2
- ## CA Root Certificate for api.ithemes.com and s3.amazonaws.com
3
- ##
4
- ## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012
5
- ##
6
-
7
- # @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $
8
-
9
- Go Daddy Class 2 CA
10
- ===================
11
- -----BEGIN CERTIFICATE-----
12
- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
13
- VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
14
- ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
15
- A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
16
- RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
17
- ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
18
- 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
19
- qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
20
- YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
21
- vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
22
- BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
23
- atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
24
- MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
25
- A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
26
- PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
27
- I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
28
- HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
29
- Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
30
- vZ8=
31
- -----END CERTIFICATE-----
32
-
33
- VeriSign Class 3 Public Primary Certification Authority - G5
34
- ============================================================
35
- -----BEGIN CERTIFICATE-----
36
- MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
37
- BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
38
- ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
39
- IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
40
- ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
41
- yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
42
- biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
43
- dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
44
- YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
45
- ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
46
- j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
47
- Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
48
- Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
49
- fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
50
- BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
51
- Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
52
- aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
53
- SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
54
- X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
55
- KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
56
- Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
57
- ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
58
- -----END CERTIFICATE-----
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/class-ithemes-credentials.php DELETED
@@ -1,143 +0,0 @@
1
- <?php
2
-
3
- //-----------------------------------------------------------------------------
4
-
5
- class iThemes_Credentials
6
- {
7
-
8
- //-----------------------------------------------------------------------------
9
-
10
- protected $hash = 'sha256';
11
-
12
- protected $salt_padding = 'wdHVwU&HcYcWnllo%kTUUnxpScy4%ICM29';
13
-
14
- protected $iteration_count = 131072;
15
-
16
- protected $key_length = 64;
17
-
18
- protected $password;
19
-
20
- //-----------------------------------------------------------------------------
21
-
22
- public function __construct($username, $password, $options = array())
23
- {
24
-
25
- $this->username = $username;
26
-
27
- $this->password = $password;
28
-
29
-
30
- if(!empty($options['hash']))
31
- $this->hash = strtolower(trim($options['hash']));
32
-
33
- if(!empty($options['iterations']))
34
- $this->iteration_count = intval($options['iterations']);
35
-
36
- if(!empty($options['salt']))
37
- $this->salt_padding = $options['salt'];
38
-
39
- if(!empty($options['key_length']))
40
- $this->key_length = intval($options['key_length']);
41
-
42
- }
43
-
44
- //-----------------------------------------------------------------------------
45
-
46
- public static function get_password_hash($username, $password, $options = array())
47
- {
48
-
49
- $hasher = new iThemes_Credentials($username, $password, $options);
50
-
51
- return $hasher->get_pbkdf2();
52
-
53
- }
54
-
55
- //-----------------------------------------------------------------------------
56
-
57
- public function get_salt()
58
- {
59
-
60
- return strtolower(trim($this->username)) . $this->salt_padding;
61
-
62
- }
63
-
64
- //-----------------------------------------------------------------------------
65
-
66
- public function get_pbkdf2()
67
- {
68
-
69
- return $this->pbkdf2($this->hash,
70
- $this->password,
71
- $this->get_salt(),
72
- $this->iteration_count,
73
- $this->key_length / 2,
74
- false);
75
-
76
- }
77
-
78
- //-----------------------------------------------------------------------------
79
-
80
- /*
81
- * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
82
- * $algorithm - The hash algorithm to use. Recommended: SHA256
83
- * $password - The password.
84
- * $salt - A salt that is unique to the password.
85
- * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
86
- * $key_length - The length of the derived key in bytes.
87
- * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
88
- * Returns: A $key_length-byte key derived from the password and salt.
89
- *
90
- * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
91
- *
92
- * This implementation of PBKDF2 was originally created by https://defuse.ca
93
- * With improvements by http://www.variations-of-shadow.com
94
- */
95
- private function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
96
- {
97
-
98
- $algorithm = strtolower($algorithm);
99
-
100
- if(!in_array($algorithm, hash_algos(), true))
101
- trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR);
102
-
103
- if($count <= 0 || $key_length <= 0)
104
- trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR);
105
-
106
-
107
- $hash_length = strlen(hash($algorithm, '', true));
108
- $block_count = ceil($key_length / $hash_length);
109
-
110
- $output = '';
111
-
112
- for($i = 1; $i <= $block_count; $i++)
113
- {
114
-
115
- // $i encoded as 4 bytes, big endian.
116
- $last = $salt . pack("N", $i);
117
-
118
- // first iteration
119
- $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
120
-
121
- // perform the other $count - 1 iterations
122
- for ($j = 1; $j < $count; $j++)
123
- {
124
- $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
125
- }
126
-
127
- $output .= $xorsum;
128
-
129
- }
130
-
131
- if($raw_output)
132
- return substr($output, 0, $key_length);
133
- else
134
- return bin2hex(substr($output, 0, $key_length));
135
-
136
- }
137
-
138
- //-----------------------------------------------------------------------------
139
-
140
- }
141
-
142
- //-----------------------------------------------------------------------------
143
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/css/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/lib/updater/css/settings-page.css DELETED
@@ -1,67 +0,0 @@
1
- #icon-options-general,
2
- #icon-settings {
3
- background: url( '../images/logo-ithemes.png' ) no-repeat;
4
- }
5
- #ithemes-updater-licensed .subtitle {
6
- background: url( '../images/icon-licensed.png' ) no-repeat;
7
- }
8
- #ithemes-updater-unlicensed .subtitle {
9
- background: url( '../images/icon-unlicensed.png' ) no-repeat;
10
- }
11
- #ithemes-updater-unrecognized .subtitle {
12
- background: url( '../images/icon-unrecognized.png' ) no-repeat;
13
- }
14
- #ithemes-updater-settings .subtitle {
15
- background: url( '../images/icon-settings.png' ) no-repeat;
16
- }
17
-
18
-
19
- .wrap h2 + .error,
20
- .wrap h2 + .updated {
21
- margin-top: 2em;
22
- }
23
- .wrap .subtitle {
24
- font-size: 23px;
25
- line-height: 30px;
26
- margin: 1.5em 0 .5em;
27
- padding: 0 0 0 35px;
28
- }
29
-
30
-
31
- .wrap .widefat.ithemes-updater-listing th,
32
- .wrap .widefat.ithemes-updater-listing td {
33
- padding: 0;
34
- vertical-align: middle;
35
- }
36
- .wrap .widefat.ithemes-updater-listing tfoot td {
37
- padding: 13px 10px;
38
- }
39
- .ithemes-updater-listing label {
40
- display: block;
41
- padding: 10px;
42
- }
43
- .widefat.ithemes-updater-listing th.check-column {
44
- }
45
- .widefat.ithemes-updater-listing th.check-column input {
46
- margin: 0;
47
- }
48
-
49
- .wrap #ithemes-updater-unrecognized .widefat.ithemes-updater-listing th,
50
- .wrap #ithemes-updater-unrecognized .widefat.ithemes-updater-listing td {
51
- padding: 10px;
52
- }
53
-
54
-
55
- .widefat.ithemes-updater-listing tr.expiring {
56
- background-color: #FFFFE0;
57
- }
58
- .widefat.ithemes-updater-listing tr.expiring.alt {
59
- background-color: #F5F5D2;
60
- }
61
-
62
- .widefat.ithemes-updater-listing tr.expired {
63
- background-color: #FFEBE8;
64
- }
65
- .widefat.ithemes-updater-listing tr.expired.alt {
66
- background-color: #F9E1DD;
67
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/functions.php DELETED
@@ -1,61 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Misc functions to assist the updater code.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.0.0
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- */
12
-
13
-
14
- class Ithemes_Updater_Functions {
15
- public static function get_url( $path ) {
16
- $path = str_replace( '\\', '/', $path );
17
- $wp_content_dir = str_replace( '\\', '/', WP_CONTENT_DIR );
18
-
19
- if ( 0 === strpos( $path, $wp_content_dir ) )
20
- return content_url( str_replace( $wp_content_dir, '', $path ) );
21
-
22
- $abspath = str_replace( '\\', '/', ABSPATH );
23
-
24
- if ( 0 === strpos( $path, $abspath ) )
25
- return site_url( str_replace( $abspath, '', $path ) );
26
-
27
- $wp_plugin_dir = str_replace( '\\', '/', WP_PLUGIN_DIR );
28
- $wpmu_plugin_dir = str_replace( '\\', '/', WPMU_PLUGIN_DIR );
29
-
30
- if ( 0 === strpos( $path, $wp_plugin_dir ) || 0 === strpos( $path, $wpmu_plugin_dir ) )
31
- return plugins_url( basename( $path ), $path );
32
-
33
- return false;
34
- }
35
-
36
- public static function get_package_name( $package ) {
37
- $name = str_replace( 'builderchild', 'Builder Child', $package );
38
- $name = str_replace( '-', ' ', $name );
39
- $name = ucwords( $name );
40
- $name = str_replace( 'buddy', 'Buddy', $name );
41
- $name = str_replace( 'Ithemes', 'iThemes', $name );
42
-
43
- return $name;
44
- }
45
-
46
- public static function get_post_data( $vars, $fill_missing = false ) {
47
- $data = array();
48
-
49
- foreach ( $vars as $var ) {
50
- if ( isset( $_POST[$var] ) ) {
51
- $clean_var = preg_replace( '/^it-updater-/', '', $var );
52
- $data[$clean_var] = $_POST[$var];
53
- }
54
- else if ( $fill_missing ) {
55
- $data[$var] = '';
56
- }
57
- }
58
-
59
- return stripslashes_deep( $data );
60
- }
61
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/history.txt DELETED
@@ -1,38 +0,0 @@
1
- 1.0.0 - 2013-04-11 - Chris Jean
2
- Release ready version.
3
- 1.0.1 - 2013-05-01 - Chris Jean
4
- Fixed a compatibility problem with the automatic-updater plugin.
5
- 1.0.2 - 2013-06-21 - Chris Jean
6
- Fixed an issue where requests would fail when made by servers with a non-default value for arg_separator.output in the php.ini file.
7
- 1.1.0 - 2013-10-02 - Chris Jean
8
- Big rewrite to the updater in order to make the code more flexible. This improves compatibility with plugins that allow for remote updating of plugins and themes.
9
- The updater now supports providing changelog details for plugins and themes that have updates available. These details can be viewed by clicking the "View version **** details" link for the appropriate plugin or theme.
10
- 1.2.0 - 2013-10-04 - Chris Jean
11
- Enhancement: When releases with four version digits are released (such as 2.1.0.3), by default, the updater will not offer to update if just this last digit is updated. For instance, it will not automatically offer to update 2.1.0.1 to 2.1.0.3; rather, an automatic upgrade will become available when version 2.1.1 or greater is released. If you wish to force an update to these versions, you can add ithemes-updater-force-minor-update=1 to an admin page request (such as http://domain.com/wp-admin/index.php?ithemes-updater-force-minor-update=1) in order to force the updater make these releases available for an hour. If the update is not performed within the hour, the updater reverts back to default behavior.
12
- Bug Fix: Corrected source of the following error when updating: Download failed. SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
13
- Bug Fix: Corrected source of the following warning: Warning: require_once(/api.php) [function.require-once]: failed to open stream: No such file or directory
14
- 1.2.1 - 2013-10-07 - Chris Jean
15
- Bug Fix: Corrected another source of the following warning which occur immediate after updating the plugin or theme: Warning: require_once(/api.php) [function.require-once]: failed to open stream: No such file or directory
16
- 1.3.0 - 2013-10-23 - Chris Jean
17
- Enhancement: Added a "Quick Release Updates" setting to the bottom of the licensing page. Enabling this option allows the site to receive automatic update notices for product quick releases (releases that do not have automatic update support by default).
18
- Enhancement: Changed how the licensing page works on Multisite. Now it will appear at Settings > iThemes Licensing in the network admin Dashboard and at Settings > iThemes Licensing on sites when the current user is a network admin. This prevents exposing the licensing page to users that don't are not super users and thus should not be performing updates. As this update makes the functionality of the "Licensing Page Access" setting obsolete, the setting has been removed.
19
- Enhancement: Using the ithemes-updater-force-minor-update query string variable will now force a data flush, allowing any available quick release updates to appear instantly.
20
- Enhancement: Added "License" links to the Plugins and Themes pages for the Network Admin Dashboard of multisite installs.
21
- 1.3.1 - 2013-12-13 - Chris Jean
22
- Enhancement: Recently updated plugins and themes no longer report that an update is available.
23
- Enhancement: Added alternate line styling to the listings on the licensing page.
24
- Enhancement: Products with iThemes in the name will now properly capitalize the name.
25
- Enhancement: The updater and licensing system now handle iThemes server outages without causing long page delays or by reporting confusing error messages.
26
- 1.3.2 - 2013-12-18 - Chris Jean
27
- Bug Fix: Removed unneeded check on package-info.ithemes.com which was causing performance issues on some sites.
28
- 1.3.3 - 2013-12-19 - Chris Jean
29
- Bug Fix: Licensing will now be universal across all sites of a multisite network. This means that you will only need to license on one site to have the license apply across the entire network.
30
- 1.3.4 - 2014-02-03 - Chris Jean
31
- Bug Fix: Licensing on SSL-enabled sites now works properly.
32
- 1.4.0 - 2014-11-14 - Chris Jean
33
- Enhancement: Reduced caching to allow updates to appear more quickly.
34
- Enhancement: Authenticating users now uses the new authentication system.
35
- 1.4.1 - 2015-04-23 - Chris Jean
36
- Compatibility Fix: Updated plugin and theme update data format to match changes in WordPress 4.2.
37
- 1.4.2 - 2015-07-14 - Chris Jean
38
- Enhancement: Updated link to iThemes support.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/images/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/lib/updater/index.php DELETED
@@ -1 +0,0 @@
1
- <?php // Silence is golden.
 
trunk/lib/updater/information.php DELETED
@@ -1,56 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Provides details formatted for use in "View version *** details" boxes.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.1.1
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- 1.0.1 - 2013-09-19 - Chris Jean
12
- Updated requires to not use dirname().
13
- 1.1.0 - 2013-10-02 - Chris Jean
14
- Added get_theme_information().
15
- 1.1.1 - 2013-12-18 - Chris Jean
16
- Removed unneeded code that checked package-info.ithemes.com.
17
- */
18
-
19
-
20
- class Ithemes_Updater_Information {
21
- public static function get_theme_information( $path ) {
22
- return self::get_plugin_information( "$path/style.css" );
23
- }
24
-
25
- public static function get_plugin_information( $path ) {
26
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
27
- $details = Ithemes_Updater_Packages::get_full_details();
28
-
29
- if ( ! isset( $details['packages'][$path] ) )
30
- return false;
31
-
32
-
33
- $package = $details['packages'][$path];
34
-
35
- require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
36
- require_once( $GLOBALS['ithemes_updater_path'] . '/information.php' );
37
-
38
- $changelog = Ithemes_Updater_API::get_package_changelog( $package['package'], $details['packages'][$path]['installed'] );
39
-
40
-
41
- $info = array(
42
- 'name' => Ithemes_Updater_Functions::get_package_name( $package['package'] ),
43
- 'slug' => dirname( $path ),
44
- 'version' => $package['available'],
45
- 'author' => '<a href="http://ithemes.com/">iThemes</a>',
46
- 'download_link' => $package['package-url'],
47
-
48
- 'sections' => array(
49
- 'changelog' => $changelog,
50
- ),
51
- );
52
-
53
-
54
- return (object) $info;
55
- }
56
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/init.php DELETED
@@ -1,54 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Load the updater and licensing system without loading unneeded parts.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.2.1
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- 1.0.1 - 2013-05-01 - Chris Jean
12
- Fixed a bug where some plugins caused the filter_update_plugins and filter_update_themes to run when load hadn't run, causing errors.
13
- 1.1.0 - 2013-09-19 - Chris Jean
14
- Complete restructuring of this file as most of the code has been relocated to other files.
15
- 1.2.0 - 2013-12-13 - Chris Jean
16
- Added the ability to force clear the server timeout hold by adding a query variable named ithemes-updater-force-clear-server-timeout-hold to the URL.
17
- 1.2.1 - 2014-10-23 - Chris Jean
18
- Removed ithemes-updater-force-clear-server-timeout-hold code.
19
- */
20
-
21
-
22
- if ( defined( 'ITHEMES_UPDATER_DISABLE' ) && ITHEMES_UPDATER_DISABLE ) {
23
- return;
24
- }
25
-
26
-
27
- $GLOBALS['ithemes_updater_path'] = dirname( __FILE__ );
28
-
29
-
30
- if ( is_admin() ) {
31
- require( $GLOBALS['ithemes_updater_path'] . '/admin.php' );
32
- }
33
-
34
-
35
- function ithemes_updater_filter_update_plugins( $update_plugins ) {
36
- if ( ! class_exists( 'Ithemes_Updater_Settings' ) ) {
37
- require( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
38
- }
39
-
40
- return $GLOBALS['ithemes-updater-settings']->filter_update_plugins( $update_plugins );
41
- }
42
- add_filter( 'site_transient_update_plugins', 'ithemes_updater_filter_update_plugins' );
43
- add_filter( 'transient_update_plugins', 'ithemes_updater_filter_update_plugins' );
44
-
45
-
46
- function ithemes_updater_filter_update_themes( $update_themes ) {
47
- if ( ! class_exists( 'Ithemes_Updater_Settings' ) ) {
48
- require( $GLOBALS['ithemes_updater_path'] . '/settings.php' );
49
- }
50
-
51
- return $GLOBALS['ithemes-updater-settings']->filter_update_themes( $update_themes );
52
- }
53
- add_filter( 'site_transient_update_themes', 'ithemes_updater_filter_update_themes' );
54
- add_filter( 'transient_update_themes', 'ithemes_updater_filter_update_themes' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/keys.php DELETED
@@ -1,165 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Provides license key management.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.0.2
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- 1.0.1 - 2013-09-19 - Chris Jean
12
- Updated requires to no longer use dirname().
13
- 1.0.2 - 2014-10-23 - Chris Jean
14
- Updated code to meet WordPress coding standards.
15
- */
16
-
17
-
18
- class Ithemes_Updater_Keys {
19
- private static $option_name = 'ithemes-updater-keys';
20
-
21
-
22
- public static function get( $packages = array() ) {
23
- $all_keys = get_site_option( self::$option_name, array() );
24
-
25
- if ( '__all__' == $packages ) {
26
- return $all_keys;
27
- }
28
-
29
- if ( empty( $packages ) ) {
30
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
31
- $packages = array_unique( array_values( Ithemes_Updater_Packages::get_all() ) );
32
- }
33
-
34
-
35
- $keys = array();
36
-
37
- foreach ( (array) $packages as $package ) {
38
- if ( ! empty( $all_keys[$package] ) ) {
39
- $keys[$package] = $all_keys[$package];
40
- }
41
- }
42
-
43
-
44
- if ( ! is_array( $packages ) ) {
45
- return $keys[$packages];
46
- }
47
-
48
- return $keys;
49
- }
50
-
51
- public static function set( $new_keys, $key = false ) {
52
- $keys = self::get( '__all__' );
53
-
54
- if ( false === $key ) {
55
- foreach ( $new_keys as $package => $key ) {
56
- $keys[$package] = $key;
57
- }
58
- } else {
59
- $keys[$new_keys] = $key;
60
- }
61
-
62
- update_site_option( self::$option_name, $keys );
63
- }
64
-
65
- private static function get_legacy_slug( $raw_slug ) {
66
- $slug = str_replace( '_', '-', $raw_slug );
67
- $slug = preg_replace( '/^(pluginbuddy|ithemes|it)-/', '', $slug );
68
-
69
- if ( 'boom-bar' == $slug ) {
70
- $slug = 'boombar';
71
- }
72
-
73
- return $slug;
74
- }
75
-
76
- public static function delete_legacy( $packages = array() ) {
77
- if ( ! is_array( $packages ) ) {
78
- $packages = array( $packages );
79
- }
80
-
81
- $data = get_site_option( 'pluginbuddy_plugins', false );
82
-
83
-
84
- $remaining_count = 0;
85
-
86
- foreach ( $data as $index => $entry ) {
87
- if ( ! is_object( $entry ) || empty( $entry->slug ) ) {
88
- continue;
89
- }
90
-
91
- $slug = self::get_legacy_slug( $entry->slug );
92
-
93
- if ( in_array( $slug, $packages ) ) {
94
- unset( $data[$index] );
95
- } else {
96
- $remaining_count++;
97
- }
98
- }
99
-
100
- if ( 0 == $remaining_count ) {
101
- $data = false;
102
- }
103
-
104
-
105
- update_site_option( 'pluginbuddy_plugins', $data );
106
- }
107
-
108
- public static function get_legacy( $packages = array() ) {
109
- $data = get_site_option( 'pluginbuddy_plugins', false );
110
-
111
- if ( empty( $data ) || ! is_array( $data ) ) {
112
- return array();
113
- }
114
-
115
-
116
- $keys = array();
117
-
118
- foreach ( $data as $index => $entry ) {
119
- if ( ! is_object( $entry ) || empty( $entry->slug ) || ! isset( $entry->key ) ) {
120
- continue;
121
- }
122
-
123
- $slug = self::get_legacy_slug( $entry->slug );
124
- $keys[$slug] = $entry->key;
125
- }
126
-
127
-
128
- foreach ( array_keys( $keys ) as $slug ) {
129
- if ( ! isset( $data[$slug] ) ) {
130
- continue;
131
- }
132
-
133
- $entry = $data[$slug];
134
-
135
- if ( ! is_object( $entry ) || empty( $entry->slug ) || empty( $entry->key ) ) {
136
- continue;
137
- }
138
-
139
- $keys[$slug] = $entry->key;
140
- }
141
-
142
-
143
- if ( empty( $packages ) ) {
144
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
145
- $packages = array_unique( array_values( Ithemes_Updater_Packages::get_all() ) );
146
- } else if ( is_string( $packages ) ) {
147
- if ( ! empty( $keys[$packages] ) ) {
148
- return $keys[$packages];
149
- }
150
-
151
- return false;
152
- }
153
-
154
-
155
- $package_keys = array();
156
-
157
- foreach ( $packages as $package ) {
158
- if ( ! empty( $keys[$package] ) ) {
159
- $package_keys[$package] = $keys[$package];
160
- }
161
- }
162
-
163
- return $package_keys;
164
- }
165
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/load.php DELETED
@@ -1,54 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Written by Chris Jean for iThemes.com
5
- */
6
-
7
-
8
- $it_registration_list_version = '1.4.2';
9
- $it_registration_list_library = 'updater';
10
- $it_registration_list_init_file = dirname( __FILE__ ) . '/init.php';
11
-
12
- $GLOBALS['it_classes_registration_list'][$it_registration_list_library][$it_registration_list_version] = $it_registration_list_init_file;
13
-
14
- if ( ! function_exists( 'it_registration_list_init' ) ) {
15
- function it_registration_list_init() {
16
- // The $wp_locale variable is set just before the theme's functions.php file is loaded,
17
- // this acts as a good check to ensure that both the plugins and the theme have loaded.
18
- global $wp_locale;
19
- if ( ! isset( $wp_locale ) )
20
- return;
21
-
22
-
23
- $init_files = array();
24
-
25
- foreach ( (array) $GLOBALS['it_classes_registration_list'] as $library => $versions ) {
26
- $max_version = '-10000';
27
- $init_file = '';
28
-
29
- foreach ( (array) $versions as $version => $file ) {
30
- if ( version_compare( $version, $max_version, '>' ) ) {
31
- $max_version = $version;
32
- $init_file = $file;
33
- }
34
- }
35
-
36
- if ( ! empty( $init_file ) )
37
- $init_files[] = $init_file;
38
- }
39
-
40
- unset( $GLOBALS['it_classes_registration_list'] );
41
-
42
- foreach ( (array) $init_files as $init_file )
43
- require_once( $init_file );
44
-
45
- do_action( 'it_libraries_loaded' );
46
- }
47
-
48
- global $wp_version;
49
-
50
- if ( version_compare( $wp_version, '2.9.7', '>' ) )
51
- add_action( 'after_setup_theme', 'it_registration_list_init' );
52
- else
53
- add_action( 'set_current_user', 'it_registration_list_init' );
54
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/packages.php DELETED
@@ -1,223 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Provides a reliable way of retrieving which projects have updates.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.0.2
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- 1.0.1 - 2013-09-19 - Chris Jean
12
- Added support for 'upgrade' data for a package.
13
- Updated requires to no longer use dirname().
14
- 1.0.2 - 2014-10-23 - Chris Jean
15
- Updated to meet WordPress coding standards.
16
- */
17
-
18
-
19
- class Ithemes_Updater_Packages {
20
- public static function flush() {
21
- unset( $GLOBALS['ithemes-updater-packages-all'] );
22
- }
23
-
24
- public static function get_full_details( $response = false ) {
25
- if ( false === $response ) {
26
- require_once( $GLOBALS['ithemes_updater_path'] . '/api.php' );
27
- $response = Ithemes_Updater_API::get_package_details();
28
- }
29
-
30
- $packages = self::get_local_details();
31
-
32
-
33
- if ( is_wp_error( $response ) ) {
34
- $expiration = time() + 600;
35
-
36
- foreach ( $packages as $path => $data ) {
37
- $packages[$path]['status'] = 'error';
38
-
39
- $packages[$path]['error'] = array(
40
- 'code' => 'unknown',
41
- 'type' => $response->get_error_code(),
42
- 'message' => $response->get_error_message(),
43
- );
44
- }
45
- } else {
46
- $expiration = time() + ( 12 * 3600 );
47
-
48
- foreach ( $packages as $path => $data ) {
49
- if ( empty( $response['packages'][$data['package']] ) ) {
50
- continue;
51
- }
52
-
53
- $package = $response['packages'][$data['package']];
54
-
55
- if ( ! empty( $package['error'] ) ) {
56
- if ( in_array( $package['error']['type'], array( 'ITXAPI_License_Key_Unknown', 'ITXAPI_Updater_Missing_Legacy_Key' ) ) ) {
57
- $packages[$path]['status'] = 'unlicensed';
58
- } else {
59
- $packages[$path]['status'] = 'error';
60
- $packages[$path]['error'] = $package['error'];
61
- }
62
-
63
- continue;
64
- }
65
-
66
-
67
- $key_map = array(
68
- 'status' => 'status',
69
- 'link' => 'package-url',
70
- 'ver' => 'available',
71
- 'used' => 'used',
72
- 'total' => 'total',
73
- 'user' => 'user',
74
- 'sub_expire' => 'expiration',
75
- 'upgrade' => 'upgrade',
76
- );
77
-
78
- foreach ( $key_map as $old => $new ) {
79
- if ( isset( $package[$old] ) ) {
80
- $packages[$path][$new] = $package[$old];
81
- } else {
82
- $packages[$path][$new] = null;
83
- }
84
- }
85
-
86
- if ( isset( $package['link_expire'] ) ) {
87
- $expiration = min( $expiration, $package['link_expire'] );
88
- }
89
- }
90
- }
91
-
92
-
93
- $details = compact( 'packages', 'expiration' );
94
-
95
- return $details;
96
- }
97
-
98
- public static function get_local_details() {
99
- require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
100
-
101
-
102
- $all_packages = self::get_all();
103
- $keys = Ithemes_Updater_Keys::get();
104
-
105
- $packages = array();
106
-
107
- foreach ( $all_packages as $file => $slug ) {
108
- $packages[$slug][] = $file;
109
- }
110
-
111
- foreach ( $packages as $slug => $paths ) {
112
- $packages[$slug] = array_unique( $paths );
113
- }
114
-
115
-
116
- $details = array();
117
-
118
-
119
- foreach ( $packages as $package => $paths ) {
120
- foreach ( $paths as $path ) {
121
- $plugin_path = preg_replace( '/^' . preg_quote( WP_PLUGIN_DIR, '/' ) . '/', '', $path );
122
-
123
- if ( $plugin_path != $path ) {
124
- $type = 'plugin';
125
- $rel_path = preg_replace( '|^[/\\\\]|', '', $plugin_path );
126
-
127
- $plugin_data = get_plugin_data( $path, false, false );
128
- $version = $plugin_data['Version'];
129
- $info_url = $plugin_data['PluginURI'];
130
- } else {
131
- $type = 'theme';
132
- $dir = basename( dirname( $path ) );
133
- $rel_path = "$dir/" . basename( $path );
134
-
135
- if ( function_exists( 'wp_get_theme' ) ) {
136
- $theme_data = wp_get_theme( $dir );
137
-
138
- $version = $theme_data->get( 'Version' );
139
- $info_url = $theme_data->get( 'ThemeURI' );
140
- } else {
141
- $theme_data = get_theme( $dir );
142
-
143
- $version = $theme_data['Version'];
144
- $info_url = '';
145
- }
146
- }
147
-
148
-
149
- $details[$rel_path] = array(
150
- 'type' => $type,
151
- 'package' => $package,
152
- 'installed' => $version,
153
- 'info-url' => $info_url,
154
- 'key' => isset( $keys[$package] ) ? $keys[$package] : '',
155
- );
156
- }
157
- }
158
-
159
-
160
- return $details;
161
- }
162
-
163
- public static function get_all() {
164
- if ( isset( $GLOBALS['ithemes-updater-packages-all'] ) ) {
165
- return $GLOBALS['ithemes-updater-packages-all'];
166
- }
167
-
168
-
169
- $packages = array();
170
-
171
-
172
- // Compatibility fix for WP < 3.1 as the global var is empty by default
173
- if ( empty( $GLOBALS['wp_theme_directories'] ) ) {
174
- get_themes();
175
- }
176
-
177
- $themes = search_theme_directories();
178
-
179
- if ( is_array( $themes ) ) {
180
- foreach ( $themes as $slug => $data ) {
181
- if ( ! file_exists( "{$data['theme_root']}/{$data['theme_file']}" ) ) {
182
- continue;
183
- }
184
-
185
- $headers = get_file_data( "{$data['theme_root']}/{$data['theme_file']}", array( 'package' => 'iThemes Package' ), 'theme' );
186
-
187
- if ( empty( $headers['package'] ) ) {
188
- continue;
189
- }
190
-
191
- $packages["{$data['theme_root']}/{$data['theme_file']}"] = $headers['package'];
192
- }
193
- }
194
-
195
-
196
- require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
197
- $plugins = get_plugins();
198
-
199
- foreach ( $plugins as $file => $data ) {
200
- if ( ! file_exists( WP_PLUGIN_DIR . "/$file" ) ) {
201
- continue;
202
- }
203
-
204
- $headers = get_file_data( WP_PLUGIN_DIR . "/$file", array( 'package' => 'iThemes Package' ), 'plugin' );
205
-
206
- if ( empty( $headers['package'] ) ) {
207
- continue;
208
- }
209
-
210
- $packages[WP_PLUGIN_DIR . "/$file"] = $headers['package'];
211
- }
212
-
213
-
214
- foreach ( $packages as $path => $package ) {
215
- $packages[$path] = strtolower( $package );
216
- }
217
-
218
-
219
- $GLOBALS['ithemes-updater-packages-all'] = $packages;
220
-
221
- return $packages;
222
- }
223
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/server.php DELETED
@@ -1,217 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Provides an easy to use interface for communicating with the iThemes updater server.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.1.0
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- 1.0.1 - 2013-06-21 - Chris Jean
12
- Updated the http_build_query call to force a separator of & in order to avoid issues with servers that change the arg_separator.output php.ini value.
13
- 1.0.2 - 2013-09-19 - Chris Jean
14
- Updated ithemes-updater-object to ithemes-updater-settings.
15
- 1.0.3 - 2013-12-18 - Chris Jean
16
- Updated the way that the site URL is generated to ensure consistency across multisite sites.
17
- 1.0.4 - 2014-01-31 - Chris Jean
18
- Updated to normalize the site URL used for password hash generation and for sending to the server.
19
- 1.1.0 - 2014-10-23 - Chris Jean
20
- Updated auth token generation to use new password hashing.
21
- Added CA patch code.
22
- Updated code to meet WordPress coding standards.
23
- */
24
-
25
-
26
- class Ithemes_Updater_Server {
27
- private static $secure_server_url = 'https://api.ithemes.com/updater';
28
- private static $insecure_server_url = 'http://api.ithemes.com/updater';
29
-
30
- private static $password_iterations = 8;
31
-
32
-
33
- public static function activate_package( $username, $password, $packages ) {
34
- $query = array(
35
- 'user' => $username
36
- );
37
-
38
- $data = array(
39
- 'auth_token' => self::get_password_hash( $username, $password ),
40
- 'packages' => $packages,
41
- );
42
-
43
- return Ithemes_Updater_Server::request( 'package-activate', $query, $data );
44
- }
45
-
46
- public static function deactivate_package( $username, $password, $packages ) {
47
- $query = array(
48
- 'user' => $username
49
- );
50
-
51
- $data = array(
52
- 'auth_token' => self::get_password_hash( $username, $password ),
53
- 'packages' => $packages,
54
- );
55
-
56
- return Ithemes_Updater_Server::request( 'package-deactivate', $query, $data );
57
- }
58
-
59
- public static function get_package_details( $packages ) {
60
- $query = array();
61
-
62
- $data = array(
63
- 'packages' => $packages
64
- );
65
-
66
- return Ithemes_Updater_Server::request( 'package-details', $query, $data );
67
- }
68
-
69
- public static function request( $action, $query = array(), $data = array() ) {
70
- if ( false !== ( $timeout_start = get_site_option( 'ithemes-updater-server-timed-out' ) ) ) {
71
- // Hold off updates for 30 minutes.
72
- $time_remaining = 1800 - ( time() - $timeout_start );
73
- $minutes_remaining = ceil( $time_remaining / 60 );
74
-
75
- if ( $time_remaining < 0 ) {
76
- delete_site_option( 'ithemes-updater-server-timed-out' );
77
- } else {
78
- return new WP_Error( 'ithemes-updater-timed-out-server', sprintf( _n( 'The server could not be contacted. Requests are delayed for %d minute to allow the server to recover.', 'The server could not be contacted. Requests are delayed for %d minutes to allow the server to recover.', $minutes_remaining, 'it-l10n-ithemes-sync' ), $minutes_remaining ) );
79
- }
80
- }
81
-
82
-
83
- if ( isset( $data['auth_token'] ) ) {
84
- $data['iterations'] = self::$password_iterations;
85
- }
86
-
87
-
88
- $site_url = self::get_site_url();
89
-
90
-
91
- $default_query = array(
92
- 'wp' => $GLOBALS['wp_version'],
93
- 'site' => $site_url,
94
- 'timestamp' => time(),
95
- 'auth_version' => '2',
96
- );
97
-
98
- if ( is_multisite() ) {
99
- $default_query['ms'] = 1;
100
- }
101
-
102
- $query = array_merge( $default_query, $query );
103
- $request = "/$action/?" . http_build_query( $query, '', '&' );
104
-
105
- $post_data = array(
106
- 'request' => json_encode( $data ),
107
- );
108
-
109
- $remote_post_args = array(
110
- 'timeout' => 10,
111
- 'body' => $post_data,
112
- );
113
-
114
-
115
- $options = array(
116
- 'use_ca_patch' => false,
117
- 'use_ssl' => true,
118
- );
119
-
120
- $patch_enabled = $GLOBALS['ithemes-updater-settings']->get_option( 'use_ca_patch' );
121
-
122
- if ( $patch_enabled ) {
123
- self::disable_ssl_ca_patch();
124
- }
125
-
126
-
127
- $response = wp_remote_post( self::$secure_server_url . $request, $remote_post_args );
128
-
129
- if ( is_wp_error( $response ) && ( 'connect() timed out!' != $response->get_error_message() ) ) {
130
- self::enable_ssl_ca_patch();
131
- $response = wp_remote_post( self::$secure_server_url . $request, $remote_post_args );
132
-
133
- if ( ! is_wp_error( $response ) ) {
134
- $options['use_ca_patch'] = true;
135
- }
136
- }
137
-
138
- if ( is_wp_error( $response ) && ( 'connect() timed out!' != $response->get_error_message() ) ) {
139
- $response = wp_remote_post( self::$insecure_server_url . $request, $remote_post_args );
140
-
141
- $options['use_ssl'] = false;
142
- }
143
-
144
- if ( ! $options['use_ca_patch'] ) {
145
- self::disable_ssl_ca_patch();
146
- }
147
-
148
- $GLOBALS['ithemes-updater-settings']->update_options( $options );
149
-
150
- if ( is_wp_error( $response ) ) {
151
- if ( 'connect() timed out!' == $response->get_error_message() ) {
152
- // Set option to delay server checks for a period of time.
153
- update_site_option( 'ithemes-updater-server-timed-out', time() );
154
-
155
- return new WP_Error( 'http_request_failed', __( 'The server was unable to be contacted.', 'it-l10n-ithemes-sync' ) );
156
- }
157
-
158
- return $response;
159
- }
160
-
161
-
162
- $body = json_decode( $response['body'], true );
163
-
164
- if ( ! empty( $body['error'] ) ) {
165
- return new WP_Error( $body['error']['type'], sprintf( __( 'An error occurred when communicating with the iThemes update server: %s (%s)', 'it-l10n-ithemes-sync' ), $body['error']['message'], $body['error']['code'] ) );
166
- }
167
-
168
-
169
- return $body;
170
- }
171
-
172
- private static function get_site_url() {
173
- if ( is_callable( 'network_home_url' ) ) {
174
- $site_url = network_home_url();
175
- } else {
176
- $site_url = get_bloginfo( 'url' );
177
- }
178
-
179
- $site_url = preg_replace( '/^https/', 'http', $site_url );
180
- $site_url = preg_replace( '|/$|', '', $site_url );
181
-
182
- return $site_url;
183
- }
184
-
185
- private static function get_password_hash( $username, $password ) {
186
- require_once( ABSPATH . 'wp-includes/class-phpass.php' );
187
- require_once( dirname( __FILE__ ) . '/class-ithemes-credentials.php' );
188
-
189
- $password = iThemes_Credentials::get_password_hash( $username, $password );
190
-
191
- $salted_password = $password . $username . self::get_site_url() . $GLOBALS['wp_version'];
192
- $salted_password = substr( $salted_password, 0, max( strlen( $password ), 512 ) );
193
-
194
- $hasher = new PasswordHash( self::$password_iterations, true );
195
- $auth_token = $hasher->HashPassword( $salted_password );
196
-
197
- return $auth_token;
198
- }
199
-
200
- public static function enable_ssl_ca_patch() {
201
- add_action( 'http_api_curl', array( __CLASS__, 'add_ca_patch_to_curl_opts' ) );
202
- }
203
-
204
- public static function disable_ssl_ca_patch() {
205
- remove_action( 'http_api_curl', array( __CLASS__, 'add_ca_patch_to_curl_opts' ) );
206
- }
207
-
208
- public static function add_ca_patch_to_curl_opts( $handle ) {
209
- $url = curl_getinfo( $handle, CURLINFO_EFFECTIVE_URL );
210
-
211
- if ( ! preg_match( '{^https://(api|downloads)\.ithemes\.com}', $url ) ) {
212
- return;
213
- }
214
-
215
- curl_setopt( $handle, CURLOPT_CAINFO, $GLOBALS['ithemes_updater_path'] . '/ca/roots.crt' );
216
- }
217
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/settings-page.php DELETED
@@ -1,659 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Code to render and manage the settings page for the updater system.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.1.0
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- 1.0.1 - 2013-09-19 - Chris Jean
12
- Updated requires to not use dirname().
13
- Updated ithemes-updater-object to ithemes-updater-settings.
14
- 1.1.0 - 2013-10-23 - Chris Jean
15
- Enhancement: Added the quick_releases setting.
16
- Misc: Removed the show_on_sites setting as it is no longer used.
17
- */
18
-
19
-
20
- class Ithemes_Updater_Settings_Page {
21
- private $page_name = 'ithemes-licensing';
22
-
23
- private $path_url = '';
24
- private $self_url = '';
25
- private $messages = array();
26
- private $message_strings = array();
27
- private $errors = array();
28
- private $soft_errors = array();
29
-
30
-
31
- public function __construct() {
32
- require_once( $GLOBALS['ithemes_updater_path'] . '/functions.php' );
33
- require_once( $GLOBALS['ithemes_updater_path'] . '/api.php' );
34
- require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
35
-
36
-
37
- $this->path_url = Ithemes_Updater_Functions::get_url( $GLOBALS['ithemes_updater_path'] );
38
-
39
- list( $this->self_url ) = explode( '?', $_SERVER['REQUEST_URI'] );
40
- $this->self_url .= '?page=' . $this->page_name;
41
-
42
-
43
- add_action( 'ithemes_updater_settings_page_index', array( $this, 'index' ) );
44
- add_action( 'admin_print_styles', array( $this, 'add_styles' ) );
45
- }
46
-
47
- public function add_styles() {
48
- wp_enqueue_style( 'ithemes-updater-settings-page-style', "{$this->path_url}/css/settings-page.css" );
49
- }
50
-
51
- public function index() {
52
- $post_data = Ithemes_Updater_Functions::get_post_data( array( 'it-updater-username', 'it-updater-password', 'packages', 'action' ), true );
53
-
54
- if ( empty( $post_data['packages'] ) )
55
- $post_data['packages'] = array();
56
-
57
-
58
- $action = $post_data['action'];
59
-
60
- if ( 'license_packages' == $action )
61
- $this->license_packages( $post_data );
62
- else if ( 'unlicense_packages' == $action )
63
- $this->unlicense_packages( $post_data );
64
- else if ( 'save_settings' == $action )
65
- $this->save_settings();
66
-
67
- $this->list_packages( $action, $post_data );
68
- }
69
-
70
- private function get_error_explanation( $error, $package = '' ) {
71
- $code = $error->get_error_code();
72
- $package_name = Ithemes_Updater_Functions::get_package_name( $package );
73
- $message = '';
74
-
75
- switch( $code ) {
76
- case 'ITXAPI_Updater_Bad_Login':
77
- $message = __( 'Incorrect password. Please make sure that you are supplying your iThemes membership username and password details.', 'it-l10n-ithemes-sync' );
78
- break;
79
- case 'ITXAPI_Updater_Username_Unknown':
80
- case 'ITXAPI_Updater_Username_Invalid':
81
- $message = __( 'Invalid username. Please make sure that you are supplying your iThemes membership username and password details.', 'it-l10n-ithemes-sync' );
82
- break;
83
- case 'ITXAPI_Product_Package_Unknown':
84
- $message = sprintf( __( 'The licensing server reports that the %1$s (%2$s) product is unknown. Please contact support for assistance.', 'it-l10n-ithemes-sync' ), $package_name, $package );
85
- break;
86
- case 'ITXAPI_Updater_Too_Many_Sites':
87
- $message = sprintf( __( '%1$s could not be licensed since the membership account is out of available licenses for this product. You can unlicense the product on other sites or upgrade your membership to one with a higher number of licenses in order to increase the amount of available licenses.', 'it-l10n-ithemes-sync' ), $package_name );
88
- break;
89
- case 'ITXAPI_License_Key_Generate_Failed':
90
- $message = sprintf( __( '%s could not be licensed due to an internal error. Please try to license %s again at a later time. If this problem continues, please contact iThemes support.', 'it-l10n-ithemes-sync' ), $package_name );
91
- break;
92
- }
93
-
94
- if ( empty( $message ) ) {
95
- if ( ! empty( $package ) )
96
- $message = sprintf( __( 'An unknown error relating to the %1$s product occurred. Please contact iThemes support. Error details: %2$s', 'it-l10n-ithemes-sync' ), $package_name, $error->get_error_message() . " ($code)" );
97
- else
98
- $message = sprintf( __( 'An unknown error occurred. Please contact iThemes support. Error details: %s', 'it-l10n-ithemes-sync' ), $error->get_error_message() . " ($code)" );
99
- }
100
-
101
- return $message;
102
- }
103
-
104
- private function save_settings() {
105
- check_admin_referer( 'save_settings', 'ithemes_updater_nonce' );
106
-
107
-
108
- $settings_defaults = array(
109
- 'quick_releases' => false,
110
- );
111
-
112
- $settings = array();
113
-
114
- foreach ( $settings_defaults as $var => $val ) {
115
- if ( isset( $_POST[$var] ) )
116
- $settings[$var] = $_POST[$var];
117
- else
118
- $settings[$var] = $val;
119
- }
120
-
121
- if ( $settings['quick_releases'] )
122
- $settings['quick_releases'] = true;
123
-
124
- $GLOBALS['ithemes-updater-settings']->update_options( $settings );
125
-
126
- $GLOBALS['ithemes-updater-settings']->flush( 'settings saved' );
127
-
128
-
129
- $this->messages[] = __( 'Settings saved', 'it-l10n-ithemes-sync' );
130
- }
131
-
132
- private function license_packages( $data ) {
133
- check_admin_referer( 'license_packages', 'ithemes_updater_nonce' );
134
-
135
- if ( empty( $data['username'] ) && empty( $data['password'] ) )
136
- $this->errors[] = __( 'You must supply an iThemes membership username and password in order to license products.', 'it-l10n-ithemes-sync' );
137
- else if ( empty( $data['username'] ) )
138
- $this->errors[] = __( 'You must supply an iThemes membership username in order to license products.', 'it-l10n-ithemes-sync' );
139
- else if ( empty( $data['password'] ) )
140
- $this->errors[] = __( 'You must supply an iThemes membership password in order to license products.', 'it-l10n-ithemes-sync' );
141
- else if ( empty( $data['packages'] ) )
142
- $this->errors[] = __( 'You must select at least one product to license. Ensure that you select the products that you wish to license in the listing below.', 'it-l10n-ithemes-sync' );
143
-
144
- if ( ! empty( $this->errors ) )
145
- return;
146
-
147
-
148
- $response = Ithemes_Updater_API::activate_package( $data['username'], $data['password'], $data['packages'] );
149
-
150
- if ( is_wp_error( $response ) ) {
151
- $this->errors[] = $this->get_error_explanation( $response );
152
-
153
- return;
154
- }
155
-
156
- if ( empty( $response['packages'] ) ) {
157
- $this->errors[] = __( 'An unknown server error occurred. Please try to license your products again at another time.', 'it-l10n-ithemes-sync' );
158
- return;
159
- }
160
-
161
-
162
- uksort( $response['packages'], 'strnatcasecmp' );
163
-
164
- $success = array();
165
- $warn = array();
166
- $fail = array();
167
-
168
- foreach ( $response['packages'] as $package => $data ) {
169
- if ( preg_match( '/ \|\|\| \d+$/', $package ) )
170
- continue;
171
-
172
- $name = Ithemes_Updater_Functions::get_package_name( $package );
173
-
174
- if ( ! empty( $data['key'] ) )
175
- $success[] = $name;
176
- else if ( ! empty( $data['status'] ) && ( 'expired' == $data['status'] ) )
177
- $warn[$name] = __( 'Your product subscription has expired', 'it-l10n-ithemes-sync' );
178
- else
179
- $fail[$name] = $data['error']['message'];
180
- }
181
-
182
-
183
- if ( ! empty( $success ) )
184
- $this->messages[] = wp_sprintf( __( 'Successfully licensed %l.', 'it-l10n-ithemes-sync' ), $success );
185
-
186
- if ( ! empty( $fail ) ) {
187
- foreach ( $fail as $name => $reason )
188
- $this->errors[] = sprintf( __( 'Unable to license %1$s. Reason: %2$s', 'it-l10n-ithemes-sync' ), $name, $reason );
189
- }
190
-
191
- if ( ! empty( $warn ) ) {
192
- foreach ( $warn as $name => $reason )
193
- $this->soft_errors[] = sprintf( __( 'Unable to license %1$s. Reason: %2$s', 'it-l10n-ithemes-sync' ), $name, $reason );
194
- }
195
- }
196
-
197
- private function unlicense_packages( $data ) {
198
- check_admin_referer( 'unlicense_packages', 'ithemes_updater_nonce' );
199
-
200
- if ( empty( $data['username'] ) && empty( $data['password'] ) )
201
- $this->errors[] = __( 'You must supply an iThemes membership username and password in order to remove licenses.', 'it-l10n-ithemes-sync' );
202
- else if ( empty( $data['username'] ) )
203
- $this->errors[] = __( 'You must supply an iThemes membership username in order to remove licenses.', 'it-l10n-ithemes-sync' );
204
- else if ( empty( $data['password'] ) )
205
- $this->errors[] = __( 'You must supply an iThemes membership password in order to remove licenses.', 'it-l10n-ithemes-sync' );
206
- else if ( empty( $data['packages'] ) )
207
- $this->errors[] = __( 'You must select at least one license to remove. Ensure that you select the licenses that you wish to remove in the listing below.', 'it-l10n-ithemes-sync' );
208
-
209
- if ( ! empty( $this->errors ) )
210
- return;
211
-
212
-
213
- $response = Ithemes_Updater_API::deactivate_package( $data['username'], $data['password'], $data['packages'] );
214
-
215
- if ( is_wp_error( $response ) ) {
216
- $this->errors[] = $this->get_error_explanation( $response );
217
-
218
- return;
219
- }
220
-
221
- if ( empty( $response['packages'] ) ) {
222
- $this->errors[] = __( 'An unknown server error occurred. Please try to remove licenses from your products again at another time.', 'it-l10n-ithemes-sync' );
223
- return;
224
- }
225
-
226
-
227
- uksort( $response['packages'], 'strnatcasecmp' );
228
-
229
- $success = array();
230
- $fail = array();
231
-
232
- foreach ( $response['packages'] as $package => $data ) {
233
- if ( preg_match( '/ \|\|\| \d+$/', $package ) )
234
- continue;
235
-
236
- $name = Ithemes_Updater_Functions::get_package_name( $package );
237
-
238
- if ( isset( $data['status'] ) && ( 'inactive' == $data['status'] ) )
239
- $success[] = $name;
240
- else if ( isset( $data['error'] ) && isset( $data['error']['message'] ) )
241
- $fail[$name] = $data['error']['message'];
242
- else
243
- $fail[$name] = __( 'Unknown server error.', 'it-l10n-ithemes-sync' );
244
- }
245
-
246
-
247
- if ( ! empty( $success ) )
248
- $this->messages[] = wp_sprintf( _n( 'Successfully removed license from %l.', 'Successfully removed licenses from %l.', count( $success ), 'it-l10n-ithemes-sync' ), $success );
249
-
250
- if ( ! empty( $fail ) ) {
251
- foreach ( $fail as $name => $reason )
252
- $this->errors[] = sprintf( __( 'Unable to remove license from %1$s. Reason: %2$s', 'it-l10n-ithemes-sync' ), $name, $reason );
253
- }
254
- }
255
-
256
- public function list_packages( $action, $post_data ) {
257
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
258
- $details = Ithemes_Updater_Packages::get_full_details();
259
- $packages = $details['packages'];
260
-
261
- $licensed = array();
262
- $unlicensed = array();
263
- $unrecognized = array();
264
-
265
- foreach ( $packages as $path => $data ) {
266
- $name = Ithemes_Updater_Functions::get_package_name( $data['package'] );
267
- $data['path'] = $path;
268
-
269
- if ( 'unlicensed' == $data['status'] )
270
- $unlicensed[$name] = $data;
271
- else if ( in_array( $data['status'], array( 'active', 'expired' ) ) )
272
- $licensed[$name] = $data;
273
- else
274
- $unrecognized[$name] = $data;
275
- }
276
-
277
-
278
- if ( ! empty( $this->messages ) ) {
279
- foreach ( $this->messages as $message )
280
- echo "<div class=\"updated fade\"><p><strong>$message</strong></p></div>\n";
281
- }
282
-
283
- if ( ! empty( $this->errors ) ) {
284
- foreach ( $this->errors as $error )
285
- echo "<div class=\"error\"><p><strong>$error</strong></p></div>\n";
286
- }
287
-
288
- if ( ! empty( $this->soft_errors ) ) {
289
- foreach ( $this->soft_errors as $error )
290
- echo "<div class=\"error\"><p><strong>$error</strong></p></div>\n";
291
- }
292
-
293
-
294
- ?>
295
- <div class="wrap">
296
- <?php
297
- if ( version_compare( $GLOBALS['wp_version'], '3.7.10', '<=' ) ) {
298
- screen_icon();
299
- }
300
- ?>
301
-
302
- <h2><?php _e( 'iThemes Licensing', 'it-l10n-ithemes-sync' ); ?></h2>
303
-
304
- <?php $this->list_licensed_products( $licensed, $post_data, $action ); ?>
305
-
306
- <?php $this->list_unlicensed_products( $unlicensed, $post_data, $action ); ?>
307
-
308
- <?php $this->list_unrecognized_products( $unrecognized ); ?>
309
-
310
- <?php $this->show_settings(); ?>
311
- </div>
312
- <?php
313
-
314
- }
315
-
316
- private function show_settings() {
317
- $quick_releases = $GLOBALS['ithemes-updater-settings']->get_option( 'quick_releases' );
318
-
319
- ?>
320
- <form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php echo $this->self_url; ?>">
321
- <?php wp_nonce_field( 'save_settings', 'ithemes_updater_nonce' ); ?>
322
-
323
- <div id="ithemes-updater-settings">
324
- <h3 class="subtitle"><?php _e( 'Settings', 'it-l10n-ithemes-sync' ); ?></h3>
325
-
326
- <table class="form-table">
327
- <tbody>
328
- <tr valign="top">
329
- <th scope="row">
330
- <label for="quick_releases"><?php _e( 'Quick Release Updates', 'it-l10n-ithemes-sync' ); ?></label>
331
- </th>
332
- <td>
333
- <?php $checked = ( $quick_releases ) ? ' checked="checked"' : ''; ?>
334
-
335
- <label>
336
- <input id="quick_releases" type="checkbox" name="quick_releases" value="1" <?php echo $checked; ?>/>
337
- <?php _e( 'Enable quick release updates', 'it-l10n-ithemes-sync' ); ?>
338
- </label>
339
-
340
- <p class="description"><?php _e( 'Some products have quick releases that are created to solve specific issues that some users experience. In order to avoid causing users to have updates show up too frequently, automatic updates to these quick releases are disabled by default. Enabling this feature allows quick releases to be available to the automatic update system. Using this option is only recommended if support has requested that you enable it in order to receive a quick release. You should disable this option at a later time after confirming that the quick release solves the issue for you.', 'it-l10n-ithemes-sync' ); ?></p>
341
- </td>
342
- </tr>
343
- </tbody>
344
- </table>
345
-
346
- <p class="submit">
347
- <input id="save_settings" class="button button-primary" type="submit" value="<?php _e( 'Save Settings', 'it-l10n-ithemes-sync' ); ?>" />
348
- <input type="hidden" name="action" value="save_settings" />
349
- </p>
350
- </div>
351
- </form>
352
- <?php
353
-
354
- }
355
-
356
-
357
- private function list_licensed_products( $products, $post_data, $action ) {
358
- if ( empty( $products ) )
359
- return;
360
-
361
- uksort( $products, 'strnatcasecmp' );
362
-
363
- $time = time();
364
-
365
- $headings = array(
366
- __( 'Product', 'it-l10n-ithemes-sync' ),
367
- __( 'Member', 'it-l10n-ithemes-sync' ),
368
- __( 'Expiration', 'it-l10n-ithemes-sync' ),
369
- __( 'Remaining Licenses', 'it-l10n-ithemes-sync' ),
370
- );
371
-
372
- if ( ( 'unlicense_packages' != $action ) || empty( $this->errors ) ) {
373
- $post_data = array(
374
- 'username' => '',
375
- 'password' => '',
376
- 'packages' => array(),
377
- );
378
- }
379
-
380
- ?>
381
- <form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php echo $this->self_url; ?>" autocomplete="off">
382
- <?php wp_nonce_field( 'unlicense_packages', 'ithemes_updater_nonce' ); ?>
383
-
384
- <div class="ithemes-updater-products" id="ithemes-updater-licensed">
385
- <h3 class="subtitle"><?php _e( 'Licensed Products', 'it-l10n-ithemes-sync' ); ?></h3>
386
-
387
- <table class="ithemes-updater-listing widefat">
388
- <thead>
389
- <tr>
390
- <th id="cb" class="manage-column column-cb check-column" scope="col">
391
- <label class="screen-reader-text" for="cb-select-all-1"><?php _e( 'Select All' ); ?></label>
392
- <label>
393
- <input id="cb-select-all-1" type="checkbox" />
394
- </label>
395
- </th>
396
- <th scope="col">
397
- <label for="cb-select-all-1"><?php _e( 'Product', 'it-l10n-ithemes-sync' ); ?></label>
398
- </th>
399
- <th scope="col"><?php _e( 'Member', 'it-l10n-ithemes-sync' ); ?></th>
400
- <th scope="col"><?php _e( 'Product Status', 'it-l10n-ithemes-sync' ); ?></th>
401
- <th scope="col"><?php _e( 'Expiration', 'it-l10n-ithemes-sync' ); ?></th>
402
- <th scope="col"><?php _e( 'Remaining Licenses', 'it-l10n-ithemes-sync' ); ?></th>
403
- </tr>
404
- </thead>
405
- <tbody>
406
- <?php $count = 0; ?>
407
- <?php foreach ( $products as $name => $data ) : ?>
408
- <?php
409
- if ( -1 == $data['total'] )
410
- $remaining = __( 'unlimited', 'it-l10n-ithemes-sync' );
411
- else
412
- $remaining = $data['total'] - $data['used'];
413
-
414
- // if ( 0 == $remaining )
415
- // $remaining .= ' <a class="button-secondary upgrade">' . __( 'Upgrade', 'it-l10n-ithemes-sync' ) . '</a>';
416
-
417
-
418
- $expiration = $this->get_expiration_string( $data['expiration'] );
419
- $expiration = '<time datetime="' . date( 'Y-m-d\TH:i:s\Z', $data['expiration'] ) . '">' . $expiration . '</time>';
420
-
421
-
422
- $time_left = $data['expiration'] - $time;
423
- $class = 'expiring';
424
-
425
- if ( $time_left > ( 86400 * 30 ) )
426
- $class = 'active';
427
- else if ( $time_left <= 0 )
428
- $class = 'expired';
429
-
430
- if ( 'expired' == $data['status'] ) {
431
- $class = 'expired';
432
- $remaining = '&nbsp;';
433
- }
434
-
435
-
436
- $status = ucfirst( $class );
437
-
438
-
439
- if ( ++$count % 2 ) {
440
- $class .= ' alt';
441
- }
442
-
443
-
444
- $check_id = "cb-select-{$data['package']}";
445
-
446
-
447
- $checked = ( in_array( $data['package'], $post_data['packages'] ) ) ? ' checked' : '';
448
- ?>
449
- <tr class="<?php echo $class; ?>">
450
- <th class="check-column" scope="row">
451
- <label class="screen-reader-text" for="<?php echo $check_id; ?>"><?php printf( __( 'Select %s' ), $name ); ?></label>
452
- <label for="<?php echo $check_id; ?>">
453
- <input id="<?php echo $check_id ?>" name="packages[]" value="<?php echo $data['package']; ?>" type="checkbox"<?php echo $checked; ?>>
454
- </label>
455
- </th>
456
- <td>
457
- <label for="<?php echo $check_id; ?>"><?php echo $name; ?></label>
458
- </td>
459
- <td><?php echo $data['user']; ?></td>
460
- <td><?php echo $status; ?></td>
461
- <td><?php echo $expiration; ?></td>
462
- <td><?php echo $remaining; ?></td>
463
- </tr>
464
- <?php endforeach; ?>
465
- </tbody>
466
- <tfoot>
467
- <tr>
468
- <td colspan="6">
469
- <input type="text" name="it-updater-username" placeholder="iThemes Username" value="<?php echo esc_attr( $post_data['username'] ); ?>" autocomplete="off" />
470
- <input type="password" name="it-updater-password" placeholder="Password" value="<?php echo esc_attr( $post_data['password'] ); ?>" />
471
- <input class="button-primary" type="submit" name="submit" value="<?php _e( 'Remove Licenses', 'it-l10n-ithemes-sync' ); ?>" />
472
- <input type="hidden" name="action" value="unlicense_packages" />
473
- </td>
474
- </tr>
475
- </tfoot>
476
- </table>
477
- </div>
478
- </form>
479
- <?php
480
-
481
- }
482
-
483
- private function list_unlicensed_products( $products, $post_data, $action ) {
484
- if ( empty( $products ) )
485
- return;
486
-
487
- uksort( $products, 'strnatcasecmp' );
488
-
489
- if ( ( 'license_packages' != $action ) || empty( $this->errors ) ) {
490
- $post_data = array(
491
- 'username' => '',
492
- 'password' => '',
493
- 'packages' => array(),
494
- );
495
-
496
- foreach ( $products as $name => $data )
497
- $post_data['packages'][] = $data['package'];
498
- }
499
-
500
- ?>
501
- <form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php echo $this->self_url; ?>" autocomplete="off">
502
- <?php wp_nonce_field( 'license_packages', 'ithemes_updater_nonce' ); ?>
503
-
504
- <div class="ithemes-updater-products" id="ithemes-updater-unlicensed">
505
- <h3 class="subtitle"><?php _e( 'Unlicensed Products', 'it-l10n-ithemes-sync' ); ?></h3>
506
-
507
- <p><?php _e( 'The following products have not been licensed. Licensing a product gives you access to automatic updates from within WordPress.', 'it-l10n-ithemes-sync' ); ?></p>
508
- <p><?php _e( 'To license products, select the products you wish to license, enter your iThemes membership username and password, and press the License Products button.', 'it-l10n-ithemes-sync' ); ?></p>
509
- <p><?php printf( __( 'Need help? <a href="%s">Click here for a quick video tutorial</a>.', 'it-l10n-ithemes-sync' ), 'http://ithemes.com/2013/04/11/introducing-the-new-and-improved-ithemes-licensing-system/' ); ?></p>
510
-
511
- <table class="ithemes-updater-listing widefat">
512
- <thead>
513
- <tr>
514
- <th id="cb" class="manage-column column-cb check-column" scope="col">
515
- <label class="screen-reader-text" for="cb-select-all-2"><?php _e( 'Select All' ); ?></label>
516
- <label>
517
- <input id="cb-select-all-2" type="checkbox"<?php if ( count( $post_data['packages'] ) == count( $products ) ) echo ' checked'; ?> />
518
- </label>
519
- </th>
520
- <th scope="col">
521
- <label for="cb-select-all-2"><?php _e( 'Product', 'it-l10n-ithemes-sync' ); ?></label>
522
- </th>
523
- </tr>
524
- </thead>
525
- <tbody>
526
- <?php $count = 0; ?>
527
- <?php foreach ( $products as $name => $data ) : ?>
528
- <?php
529
- $check_id = "cb-select-{$data['package']}";
530
-
531
- if ( 'license_packages' == $action )
532
- $checked = ( in_array( $data['package'], $post_data['packages'] ) ) ? ' checked' : '';
533
- else
534
- $checked = ' checked';
535
-
536
- if ( ++$count % 2 ) {
537
- $class = 'alt';
538
- } else {
539
- $class = '';
540
- }
541
-
542
- ?>
543
- <tr class="<?php echo $class; ?>">
544
- <th class="check-column" scope="row">
545
- <label class="screen-reader-text" for="<?php echo $check_id; ?>"><?php printf( __( 'Select %s' ), $name ); ?></label>
546
- <label for="<?php echo $check_id; ?>">
547
- <input id="<?php echo $check_id; ?>" name="packages[]" value="<?php echo $data['package']; ?>" type="checkbox" <?php echo $checked; ?>>
548
- </label>
549
- </th>
550
- <td>
551
- <label for="<?php echo $check_id; ?>"><?php echo $name; ?></label>
552
- </td>
553
- </tr>
554
- <?php endforeach; ?>
555
- </tbody>
556
- <tfoot>
557
- <tr>
558
- <td colspan="2">
559
- <input type="text" name="it-updater-username" placeholder="iThemes Username" value="<?php echo esc_attr( $post_data['username'] ); ?>" autocomplete="off" />
560
- <input type="password" name="it-updater-password" placeholder="Password" value="<?php echo esc_attr( $post_data['password'] ); ?>" />
561
- <input class="button-primary" type="submit" name="submit" value="<?php _e( 'License Products', 'it-l10n-ithemes-sync' ); ?>" />
562
- <input type="hidden" name="action" value="license_packages" />
563
- </td>
564
- </tr>
565
- </tfoot>
566
- </table>
567
- </div>
568
- </form>
569
- <?php
570
-
571
- }
572
-
573
- private function list_unrecognized_products( $products ) {
574
- if ( empty( $products ) )
575
- return;
576
-
577
- uksort( $products, 'strnatcasecmp' );
578
-
579
- ?>
580
- <div class="ithemes-updater-products" id="ithemes-updater-unrecognized">
581
- <h3 class="subtitle"><?php _e( 'Unrecognized Products', 'it-l10n-ithemes-sync' ); ?></h3>
582
-
583
- <p><?php _e( 'The following products were not recognized by the licensing system. This can be due to a bug in the product code, a temporary server issue, or because the product is no longer supported.', 'it-l10n-ithemes-sync' ); ?></p>
584
- <p><?php printf( __( 'Please check this page again at a later time to see if the problem resolves itself. If the product remains, please contact <a href="%s">iThemes support</a> and provide them with the details given below.', 'it-l10n-ithemes-sync' ), 'http://ithemes.com/support/' ); ?></p>
585
-
586
- <table class="ithemes-updater-listing widefat">
587
- <thead>
588
- <tr>
589
- <th scope="col"><?php _e( 'Product', 'it-l10n-ithemes-sync' ); ?></th>
590
- <th scope="col"><?php _e( 'Type', 'it-l10n-ithemes-sync' ); ?></th>
591
- <th scope="col"><?php _e( 'Package', 'it-l10n-ithemes-sync' ); ?></th>
592
- <th scope="col"><?php _e( 'Version', 'it-l10n-ithemes-sync' ); ?></th>
593
- <th scope="col"><?php _e( 'Server Response', 'it-l10n-ithemes-sync' ); ?></th>
594
- </tr>
595
- </thead>
596
- <tbody>
597
- <?php $count = 0; ?>
598
- <?php foreach ( $products as $name => $data ) : ?>
599
- <?php
600
- if ( ( 'error' == $data['status'] ) && ( ! empty( $data['error']['message'] ) ) )
601
- $response = "{$data['error']['message']} ({$data['error']['code']})";
602
- else
603
- $response = __( 'Unknown Error', 'it-l10n-ithemes-sync' );
604
-
605
- if ( ++$count % 2 ) {
606
- $class = 'alt';
607
- } else {
608
- $class = '';
609
- }
610
- ?>
611
- <tr class="<?php echo $class; ?>">
612
- <td><?php echo $name; ?></td>
613
- <td><?php echo $data['type']; ?></td>
614
- <td><?php echo $data['package']; ?></td>
615
- <td><?php echo $data['installed']; ?></td>
616
- <td><?php echo $response; ?></td>
617
- </tr>
618
- <?php endforeach; ?>
619
- </tbody>
620
- </table>
621
- </div>
622
- <?php
623
-
624
- }
625
-
626
- private function get_expiration_string( $expiration_timestamp ) {
627
- $time = time();
628
-
629
- $time_left = $expiration_timestamp - $time;
630
-
631
- $expired = false;
632
-
633
- if ( $time_left < 0 ) {
634
- $expired = true;
635
- $time_left = abs( $time_left );
636
- }
637
-
638
- if ( $time_left > ( 86400 * 30 ) )
639
- $expiration = date( 'Y-m-d', $expiration_timestamp );
640
- else {
641
- if ( $time_left > 86400 )
642
- $expiration = sprintf( _n( '%d day', '%d days', intval( $time_left / 86400 ), 'it-l10n-ithemes-sync' ), intval( $time_left / 86400 ) );
643
- else if ( $time_left > 3600 )
644
- $expiration = sprintf( _n( '%d hour', '%d hours', intval( $time_left / 3600 ), 'it-l10n-ithemes-sync' ), intval( $time_left / 3600 ) );
645
- else if ( $time_left > 60 )
646
- $expiration = sprintf( _n( '%d minute', '%d minutes', intval( $time_left / 60 ), 'it-l10n-ithemes-sync' ), intval( $time_left / 60 ) );
647
- else
648
- $expiration = sprintf( _n( '%d second', '%d seconds', $time_left, 'it-l10n-ithemes-sync' ), intval( $time_left / 60 ) );
649
-
650
- if ( $expired )
651
- $expiration = sprintf( __( '%s ago', 'it-l10n-ithemes-sync' ), $expiration );
652
- }
653
-
654
- return $expiration;
655
- }
656
- }
657
-
658
-
659
- new Ithemes_Updater_Settings_Page();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/settings.php DELETED
@@ -1,336 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Central management of options storage and registered packages.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.3.0
7
-
8
- Version History
9
- 1.0.0 - 2013-09-19 - Chris Jean
10
- Split off from the old Ithemes_Updater_Init class.
11
- 1.0.1 - 2013-09-20 - Chris Jean
12
- Fixed bug where the old ithemes-updater-object global was being referenced.
13
- 1.1.0 - 2013-10-04 - Chris Jean
14
- Enhancement: Added handler for GET query variable: ithemes-updater-force-minor-update.
15
- Bug Fix: Changed URL regex for applying the CA patch to only apply to links for api.ithemes.com and not the S3 links.
16
- Bug Fix: A check to ensure that the $GLOBALS['ithemes_updater_path'] variable is set properly.
17
- Misc: Updated file reference for ca/cacert.crt to ca/roots.crt.
18
- 1.2.0 - 2013-10-23 - Chris Jean
19
- Enhancement: Added the quick_releases setting.
20
- Enhancement: Added an explicit flush when the ithemes-updater-force-minor-update query variable is used
21
- Misc: Removed the show_on_sites setting as it is no longer needed.
22
- 1.3.0 - 2014-10-23 - Chris Jean
23
- Improved flushing system.
24
- Reduced cache timeout durations.
25
- Added timeout multiplier.
26
- Removed CA patch code as it's now handled in the server code.
27
- Updated code to meet WordPress coding standards.
28
- */
29
-
30
-
31
- class Ithemes_Updater_Settings {
32
- private $option_name = 'ithemes-updater-cache';
33
-
34
- private $packages = array();
35
- private $new_packages = array();
36
- private $options = false;
37
- private $options_modified = false;
38
- private $do_flush = false;
39
- private $initialized = false;
40
- private $plugins_cleaned = false;
41
- private $themes_cleaned = false;
42
-
43
- private $default_options = array(
44
- 'timeout-multiplier' => 1,
45
- 'expiration' => 0,
46
- 'timestamp' => 0,
47
- 'packages' => array(),
48
- 'update_plugins' => array(),
49
- 'update_themes' => array(),
50
- 'use_ca_patch' => false,
51
- 'use_ssl' => true,
52
- 'quick_releases' => false,
53
- );
54
-
55
-
56
- public function __construct() {
57
- $GLOBALS['ithemes-updater-settings'] = $this;
58
-
59
- add_action( 'init', array( $this, 'init' ) );
60
- add_action( 'shutdown', array( $this, 'shutdown' ) );
61
- }
62
-
63
- public function init() {
64
- if ( $this->initialized ) {
65
- return;
66
- }
67
-
68
- $this->initialized = true;
69
-
70
- if ( ! isset( $GLOBALS['ithemes_updater_path'] ) ) {
71
- $GLOBALS['ithemes_updater_path'] = dirname( __FILE__ );
72
- }
73
-
74
- $this->load();
75
-
76
- do_action( 'ithemes_updater_register', $this );
77
-
78
- $this->new_packages = array_diff( array_keys( $this->packages ), $this->options['packages'] );
79
-
80
-
81
- if ( isset( $_GET['ithemes-updater-force-quick-release-update'] ) && ! isset( $_GET['ithemes-updater-force-minor-update'] ) ) {
82
- $_GET['ithemes-updater-force-minor-update'] = $_GET['ithemes-updater-force-quick-release-update'];
83
- }
84
-
85
-
86
- $flushed = false;
87
-
88
-
89
- if ( isset( $_GET['ithemes-updater-force-minor-update'] ) && current_user_can( 'manage_options' ) ) {
90
- if ( $_GET['ithemes-updater-force-minor-update'] ) {
91
- $this->options['force_minor_version_update'] = time() + 3600;
92
- $this->update_options( $this->options );
93
-
94
- $this->flush( 'forced minor version update' );
95
- $flushed = true;
96
- } else {
97
- unset( $this->options['force_minor_version_update'] );
98
- $this->update_options( $this->options );
99
-
100
- $this->flush( 'unset forced minor version update' );
101
- $flushed = true;
102
- }
103
- } else if ( isset( $this->options['force_minor_version_update'] ) && ( $this->options['force_minor_version_update'] < time() ) ) {
104
- unset( $this->options['force_minor_version_update'] );
105
- $this->update_options( $this->options );
106
- }
107
-
108
-
109
- if ( ! $flushed ) {
110
- if ( ! empty( $_GET['ithemes-updater-force-refresh'] ) && current_user_can( 'manage_options' ) ) {
111
- $this->flush( 'forced' );
112
- } else if ( empty( $this->options['expiration'] ) || ( $this->options['expiration'] <= time() ) ) {
113
- $this->flush( 'expired' );
114
- } else if ( $this->is_expired( $this->options['timestamp'] ) ) {
115
- $this->flush( 'got stale' );
116
- } else if ( ! empty( $this->new_packages ) ) {
117
- $this->flush( 'new packages' );
118
- }
119
- }
120
- }
121
-
122
- public function load() {
123
- if ( false !== $this->options ) {
124
- return;
125
- }
126
-
127
- $this->options = get_site_option( $this->option_name, false );
128
-
129
- if ( ( false === $this->options ) || ! is_array( $this->options ) ) {
130
- $this->options = array();
131
- }
132
-
133
- $this->options = array_merge( $this->default_options, $this->options );
134
-
135
- if ( 0 == $this->options['timestamp'] ) {
136
- $this->update();
137
- }
138
- }
139
-
140
- public function shutdown() {
141
- $this->flush();
142
-
143
- if ( $this->options_modified ) {
144
- update_site_option( $this->option_name, $this->options );
145
- }
146
- }
147
-
148
- public function queue_flush() {
149
- $this->do_flush = true;
150
- }
151
-
152
- public function flush( $reason = '' ) {
153
- if ( empty( $reason ) && ! $this->do_flush ) {
154
- return;
155
- }
156
-
157
- $this->do_flush = false;
158
-
159
- $this->update();
160
- }
161
-
162
- public function update() {
163
- $this->init();
164
-
165
- require_once( $GLOBALS['ithemes_updater_path'] . '/updates.php' );
166
-
167
- Ithemes_Updater_Updates::run_update();
168
- }
169
-
170
- public function get_options() {
171
- $this->init();
172
-
173
- return $this->options;
174
- }
175
-
176
- public function get_option( $var ) {
177
- $this->init();
178
-
179
- if ( isset( $this->options[$var] ) ) {
180
- return $this->options[$var];
181
- }
182
-
183
- return null;
184
- }
185
-
186
- public function update_options( $updates ) {
187
- $this->init();
188
-
189
- $this->options = array_merge( $this->options, $updates );
190
- $this->options_modified = true;
191
- }
192
-
193
- public function update_packages() {
194
- $this->update_options( array( 'packages' => array_keys( $this->packages ) ) );
195
- }
196
-
197
- public function get_packages() {
198
- return $this->packages;
199
- }
200
-
201
- public function get_new_packages() {
202
- return $this->new_packages;
203
- }
204
-
205
- public function filter_update_plugins( $update_plugins ) {
206
- if ( ! is_object( $update_plugins ) ) {
207
- return $update_plugins;
208
- }
209
-
210
- if ( ! isset( $update_plugins->response ) || ! is_array( $update_plugins->response ) ) {
211
- $update_plugins->response = array();
212
- }
213
-
214
- $this->flush();
215
-
216
- if ( ! is_array( $this->options ) || ! isset( $this->options['update_plugins'] ) ) {
217
- $this->load();
218
- }
219
-
220
- if ( isset( $this->options['update_plugins'] ) && is_array( $this->options['update_plugins'] ) ) {
221
- if ( ! $this->plugins_cleaned ) {
222
- @include_once( ABSPATH . '/wp-admin/includes/plugin.php' );
223
-
224
- if ( is_callable( 'get_plugin_data' ) ) {
225
- foreach ( $this->options['update_plugins'] as $plugin => $update_data ) {
226
- $plugin_data = get_plugin_data( WP_PLUGIN_DIR . "/$plugin", false, false );
227
-
228
- if ( $plugin_data['Version'] == $update_data->new_version ) {
229
- unset( $this->options['update_plugins'][$plugin] );
230
- $this->plugins_cleaned = true;
231
- }
232
- }
233
- }
234
-
235
- if ( $this->plugins_cleaned ) {
236
- $this->options_modified = true;
237
- }
238
-
239
- $this->plugins_cleaned = true;
240
- }
241
-
242
- $update_plugins->response = array_merge( $update_plugins->response, $this->options['update_plugins'] );
243
- }
244
-
245
- return $update_plugins;
246
- }
247
-
248
- public function filter_update_themes( $update_themes ) {
249
- if ( ! is_object( $update_themes ) ) {
250
- return $update_themes;
251
- }
252
-
253
- if ( ! isset( $update_themes->response ) || ! is_array( $update_themes->response ) ) {
254
- $update_themes->response = array();
255
- }
256
-
257
- $this->flush();
258
-
259
- if ( ! is_array( $this->options ) || ! isset( $this->options['update_themes'] ) ) {
260
- $this->load();
261
- }
262
-
263
- if ( isset( $this->options['update_themes'] ) && is_array( $this->options['update_themes'] ) ) {
264
- if ( ! $this->themes_cleaned ) {
265
- foreach ( $this->options['update_themes'] as $theme => $update_data ) {
266
- $theme_data = wp_get_theme( $theme );
267
-
268
- if ( $theme_data->get( 'Version' ) == $update_data['new_version'] ) {
269
- unset( $this->options['update_themes'][$theme] );
270
- $this->themes_cleaned = true;
271
- }
272
- }
273
-
274
- if ( $this->themes_cleaned ) {
275
- $this->options_modified = true;
276
- }
277
-
278
- $this->themes_cleaned = true;
279
- }
280
-
281
- $update_themes->response = array_merge( $update_themes->response, $this->options['update_themes'] );
282
- }
283
-
284
- return $update_themes;
285
- }
286
-
287
- public function register( $slug, $file ) {
288
- $this->packages[$slug][] = $file;
289
- }
290
-
291
- private function is_expired( $timestamp ) {
292
- $multiplier = $this->get_option( 'timeout-multiplier' );
293
-
294
- if ( $multiplier < 1 ) {
295
- $multiplier = 1;
296
- } else if ( $multiplier > 10 ) {
297
- $multiplier = 10;
298
- }
299
-
300
-
301
- if ( current_user_can( 'update_themes' ) || current_user_can( 'update_plugins' ) ) {
302
- if ( ! empty( $_POST['action'] ) && ( 'heartbeat' == $_POST['action'] ) ) {
303
- $timeout = 43200;
304
- } else {
305
- $page = empty( $_GET['page'] ) ? $GLOBALS['pagenow'] : $_GET['page'];
306
-
307
- switch ( $page ) {
308
- case 'update.php' :
309
- case 'update-core.php' :
310
- case 'ithemes-licensing' :
311
- $timeout = 60;
312
- break;
313
- case 'plugins.php' :
314
- case 'themes.php' :
315
- $timeout = 600;
316
- break;
317
- default :
318
- $timeout = 3600;
319
- }
320
- }
321
- } else {
322
- $timeout = 7200;
323
- }
324
-
325
- $timeout *= $multiplier;
326
-
327
-
328
- if ( $timestamp <= ( time() - $timeout ) ) {
329
- return true;
330
- }
331
-
332
- return false;
333
- }
334
- }
335
-
336
- new Ithemes_Updater_Settings();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
trunk/lib/updater/updates.php DELETED
@@ -1,166 +0,0 @@
1
- <?php
2
-
3
- /*
4
- Provides a simple interface for connecting iThemes' packages with the updater API.
5
- Written by Chris Jean for iThemes.com
6
- Version 1.4.1
7
-
8
- Version History
9
- 1.0.0 - 2013-04-11 - Chris Jean
10
- Release ready
11
- 1.0.1 - 2013-09-19 - Chris Jean
12
- Changed the logic in process_server_response to skip updatable packages that have the 'upgrade' data set to a true value.
13
- Updated requires to not use dirname().
14
- Updated ithemes-updater-object to ithemes-updater-settings.
15
- 1.1.0 - 2013-10-02 - Chris Jean
16
- Updated 'url' data for themes to point to the plugin-install.php file in order to show changelog notes as plugins have.
17
- 1.2.0 - 2013-10-04 - Chris Jean
18
- Added logic to handle skipped updates when force_minor_version_update is set.
19
- 1.2.1 - 2013-10-04 - Chris Jean
20
- Added a fix to prevent the code from executing if it is loaded by an older updater version. This can happen when updating a theme or plugin.
21
- 1.3.0 - 2013-10-23 - Chris Jean
22
- Enhancement: Added support for quick_releases setting to force an update to a quick release.
23
- 1.4.0 - 2014-11-13 - Chris Jean
24
- Improved cache flush handling.
25
- Removed server-cache setting change handler.
26
- Added timeout-multiplier setting change handler.
27
- 1.4.1 - 2015-04-23 - Chris Jean
28
- Added "plugin" entry for plugins in order to handle changes in WordPress 4.2.
29
- Added "theme" entry for themes in order to handle changes in WordPress 4.2.
30
- Added support for both "autoupdate" and "upgrade_notice" fields to be supplied from the server.
31
- */
32
-
33
-
34
- class Ithemes_Updater_Updates {
35
- public static function run_update() {
36
- // Prevent the code from running if the code was loaded by an older updater version.
37
- if ( ! isset( $GLOBALS['ithemes_updater_path'] ) ) {
38
- return;
39
- }
40
-
41
- require_once( $GLOBALS['ithemes_updater_path'] . '/api.php' );
42
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
43
- require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
44
-
45
-
46
- $keys = Ithemes_Updater_Keys::get();
47
- $legacy_keys = Ithemes_Updater_Keys::get_legacy();
48
-
49
- if ( empty( $keys ) && empty( $legacy_keys ) ) {
50
- return;
51
- }
52
-
53
-
54
- Ithemes_Updater_API::get_package_details( false );
55
- }
56
-
57
- public static function process_server_response( $response, $cached = false ) {
58
- if ( empty( $response['packages'] ) ) {
59
- return;
60
- }
61
-
62
-
63
- require_once( $GLOBALS['ithemes_updater_path'] . '/keys.php' );
64
- require_once( $GLOBALS['ithemes_updater_path'] . '/packages.php' );
65
-
66
-
67
- $keys = array();
68
-
69
- foreach ( $response['packages'] as $package => $data ) {
70
- if ( isset( $data['key'] ) ) {
71
- $keys[$package] = $data['key'];
72
- } else if ( isset( $data['status'] ) && ( 'inactive' == $data['status'] ) ) {
73
- $keys[$package] = '';
74
- }
75
- }
76
-
77
- Ithemes_Updater_Keys::set( $keys );
78
-
79
-
80
- $details = Ithemes_Updater_Packages::get_full_details( $response );
81
-
82
- $updates = array(
83
- 'update_themes' => array(),
84
- 'update_plugins' => array(),
85
- 'expiration' => $details['expiration'],
86
- );
87
-
88
- if ( ! $cached ) {
89
- $updates['timestamp'] = time();
90
- }
91
-
92
-
93
- if ( isset( $response['timeout_multiplier'] ) ) {
94
- $updates['timeout-multiplier'] = $response['timeout_multiplier'];
95
- }
96
-
97
- if ( ! isset( $updates['timeout-multiplier'] ) || ( $updates['timeout-multiplier'] < 1 ) ) {
98
- $updates['timeout-mulitplier'] = 1;
99