Jetpack by WordPress.com - Version 2.3.8

Version Description

Release Date: May 26, 2016

  • Important security update. Please upgrade immediately.
Download this release

Release Info

Developer samhotchkiss
Plugin Icon 128x128 Jetpack by WordPress.com
Version 2.3.8
Comparing to
See all releases

Code changes from version 2.2.8 to 2.3.8

Files changed (261) hide show
  1. _inc/genericons.css +149 -0
  2. _inc/images/a8c.png +0 -0
  3. _inc/images/alertbox-closeicon-2x.png +0 -0
  4. _inc/images/alertbox-closeicon.png +0 -0
  5. _inc/images/alertbox-clouds-2x.png +0 -0
  6. _inc/images/alertbox-clouds.png +0 -0
  7. _inc/images/align-center-2x.png +0 -0
  8. _inc/images/align-left-2x.png +0 -0
  9. _inc/images/align-none-2x.png +0 -0
  10. _inc/images/align-right-2x.png +0 -0
  11. _inc/images/archive-2x.png +0 -0
  12. _inc/images/arrow-2x.png +0 -0
  13. _inc/images/arrow-pointer-blue-2x.png +0 -0
  14. _inc/images/arrow.png +0 -0
  15. _inc/images/arrows-2x.png +0 -0
  16. _inc/images/arrows-dark-2x.png +0 -0
  17. _inc/images/arrows-dark-vs-2x.png +0 -0
  18. _inc/images/arrows-vs-2x.png +0 -0
  19. _inc/images/atdbuttontr-2x.png +0 -0
  20. _inc/images/audio-2x.png +0 -0
  21. _inc/images/automattic-2x.png +0 -0
  22. _inc/images/automattic.png +0 -0
  23. _inc/images/bubble_bg-2x.png +0 -0
  24. _inc/images/buttons-2x.gif +0 -0
  25. _inc/images/code-2x.png +0 -0
  26. _inc/images/comment-grey-bubble-2x.png +0 -0
  27. _inc/images/date-button-2x.gif +0 -0
  28. _inc/images/default-2x.png +0 -0
  29. _inc/images/delete-2x.png +0 -0
  30. _inc/images/document-2x.png +0 -0
  31. _inc/images/down_arrow-2x.gif +0 -0
  32. _inc/images/footer-clouds-2x.png +0 -0
  33. _inc/images/footer-clouds.png +0 -0
  34. _inc/images/generic-2x.png +0 -0
  35. _inc/images/header-clouds-2x.png +0 -0
  36. _inc/images/header-clouds-small-2x.png +0 -0
  37. _inc/images/header-clouds-small.png +0 -0
  38. _inc/images/header-clouds.png +0 -0
  39. _inc/images/icon-comingsoon-2x.png +0 -0
  40. _inc/images/icon-comingsoon.png +0 -0
  41. _inc/images/icon-pointer-flag-2x.png +0 -0
  42. _inc/images/image-2x.png +0 -0
  43. _inc/images/imgedit-icons-2x.png +0 -0
  44. _inc/images/interactive-2x.png +0 -0
  45. _inc/images/jetpack-closebox-icon.png +0 -0
  46. _inc/images/list-2x.png +0 -0
  47. _inc/images/logo-2x.png +0 -0
  48. _inc/images/logo-small-2x.png +0 -0
  49. _inc/images/logo-small.png +0 -0
  50. _inc/images/logo.png +0 -0
  51. _inc/images/marker-2x.png +0 -0
  52. _inc/images/mask-2x.png +0 -0
  53. _inc/images/media-button-2x.png +0 -0
  54. _inc/images/menuicon-sprite-2x.png +0 -0
  55. _inc/images/menuicon-sprite.png +0 -0
  56. _inc/images/module-clouds-2x.png +0 -0
  57. _inc/images/module-clouds.png +0 -0
  58. _inc/images/module-icons-sprite-2x.png +0 -0
  59. _inc/images/module-icons-sprite.png +0 -0
  60. _inc/images/press-this-2x.png +0 -0
  61. _inc/images/publicize.png +0 -0
  62. _inc/images/resize-2x.gif +0 -0
  63. _inc/images/rss/blue-large.png +0 -0
  64. _inc/images/rss/blue-medium.png +0 -0
  65. _inc/images/rss/blue-small.png +0 -0
  66. _inc/images/rss/green-large.png +0 -0
  67. _inc/images/rss/green-medium.png +0 -0
  68. _inc/images/rss/green-small.png +0 -0
  69. _inc/images/rss/orange-large.png +0 -0
  70. _inc/images/rss/orange-medium.png +0 -0
  71. _inc/images/rss/orange-small.png +0 -0
  72. _inc/images/rss/pink-large.png +0 -0
  73. _inc/images/rss/pink-medium.png +0 -0
  74. _inc/images/rss/purple-large.png +0 -0
  75. _inc/images/rss/purple-medium.png +0 -0
  76. _inc/images/rss/purple-small.png +0 -0
  77. _inc/images/rss/red-large.png +0 -0
  78. _inc/images/rss/red-medium.png +0 -0
  79. _inc/images/rss/red-small.png +0 -0
  80. _inc/images/rss/silver-large.png +0 -0
  81. _inc/images/rss/silver-medium.png +0 -0
  82. _inc/images/rss/silver-small.png +0 -0
  83. _inc/images/screenshots/beautifulmath.png +0 -0
  84. _inc/images/screenshots/carousel.png +0 -0
  85. _inc/images/screenshots/comments.png +0 -0
  86. _inc/images/screenshots/contactform.png +0 -0
  87. _inc/images/screenshots/custom-css.png +0 -0
  88. _inc/images/screenshots/hovercards.png +0 -0
  89. _inc/images/screenshots/likes.png +0 -0
  90. _inc/images/screenshots/mobile-push-notifications.jpg +0 -0
  91. _inc/images/screenshots/notes.png +0 -0
  92. _inc/images/screenshots/post-by-email.png +0 -0
  93. _inc/images/screenshots/publicize.png +0 -0
  94. _inc/images/screenshots/sharing.png +0 -0
  95. _inc/images/screenshots/shortcodes.png +0 -0
  96. _inc/images/screenshots/shortlinks.png +0 -0
  97. _inc/images/screenshots/spelling.png +0 -0
  98. _inc/images/screenshots/stats.png +0 -0
  99. _inc/images/screenshots/subscriptions.png +0 -0
  100. _inc/images/screenshots/tiled-gallery.png +0 -0
  101. _inc/images/screenshots/vaultpress.png +0 -0
  102. _inc/images/screenshots/widgets.png +0 -0
  103. _inc/images/sort-2x.gif +0 -0
  104. _inc/images/spreadsheet-2x.png +0 -0
  105. _inc/images/stars-2x.png +0 -0
  106. _inc/images/status-light-2x.png +0 -0
  107. _inc/images/status-light.png +0 -0
  108. _inc/images/tb-close-2x.png +0 -0
  109. _inc/images/text-2x.png +0 -0
  110. _inc/images/video-2x.png +0 -0
  111. _inc/images/wheel-2x.png +0 -0
  112. _inc/images/wpicons-2x.png +0 -0
  113. _inc/images/xit-2x.gif +0 -0
  114. _inc/jetpack-retina.css +0 -470
  115. _inc/jetpack-rtl.css +114 -122
  116. _inc/jetpack.css +942 -786
  117. _inc/jetpack.js +1 -0
  118. _inc/jquery.spin.js +99 -81
  119. _inc/spin.js +345 -297
  120. class.jetpack-client-server.php +219 -0
  121. class.jetpack-client.php +215 -0
  122. class.jetpack-data.php +42 -0
  123. class.jetpack-debugger.php +353 -0
  124. class.jetpack-error.php +3 -0
  125. class.jetpack-heartbeat.php +121 -0
  126. class.jetpack-options.php +143 -0
  127. class.jetpack-post-images.php +2 -0
  128. class.jetpack-sync.php +713 -0
  129. class.jetpack-user-agent.php +132 -87
  130. class.jetpack.php +3723 -0
  131. class.json-api-endpoints.php +41 -22
  132. class.json-api.php +53 -16
  133. class.photon.php +2 -1
  134. functions.opengraph.php +1 -1
  135. functions.photon.php +2 -2
  136. jetpack.php +35 -4576
  137. languages/jetpack-ar.mo +0 -0
  138. languages/jetpack-az.mo +0 -0
  139. languages/jetpack-bs_BA.mo +0 -0
  140. languages/jetpack-ca.mo +0 -0
  141. languages/jetpack-cs_CZ.mo +0 -0
  142. languages/jetpack-da_DK.mo +0 -0
  143. languages/jetpack-de_DE.mo +0 -0
  144. languages/jetpack-el.mo +0 -0
  145. languages/jetpack-es_ES.mo +0 -0
  146. languages/jetpack-fa_IR.mo +0 -0
  147. languages/jetpack-fi.mo +0 -0
  148. languages/jetpack-fr_FR.mo +0 -0
  149. languages/jetpack-gl_ES.mo +0 -0
  150. languages/jetpack-he_IL.mo +0 -0
  151. languages/jetpack-hr.mo +0 -0
  152. languages/jetpack-hu_HU.mo +0 -0
  153. languages/jetpack-id_ID.mo +0 -0
  154. languages/jetpack-it_IT.mo +0 -0
  155. languages/jetpack-ja.mo +0 -0
  156. languages/jetpack-ko_KR.mo +0 -0
  157. languages/jetpack-lt_LT.mo +0 -0
  158. languages/jetpack-mk_MK.mo +0 -0
  159. languages/jetpack-my_MM.mo +0 -0
  160. languages/jetpack-nb_NO.mo +0 -0
  161. languages/jetpack-nl_NL.mo +0 -0
  162. languages/jetpack-nn_NO.mo +0 -0
  163. languages/jetpack-pl_PL.mo +0 -0
  164. languages/jetpack-pt_BR.mo +0 -0
  165. languages/jetpack-pt_PT.mo +0 -0
  166. languages/jetpack-ro_RO.mo +0 -0
  167. languages/jetpack-ru_RU.mo +0 -0
  168. languages/jetpack-sa_IN.mo +0 -0
  169. languages/jetpack-sk_SK.mo +0 -0
  170. languages/jetpack-sq.mo +0 -0
  171. languages/jetpack-sr_RS.mo +0 -0
  172. languages/jetpack-sv_SE.mo +0 -0
  173. languages/jetpack-th.mo +0 -0
  174. languages/jetpack-tr_TR.mo +0 -0
  175. languages/jetpack-uk.mo +0 -0
  176. languages/jetpack-ur.mo +0 -0
  177. languages/jetpack-zh_CN.mo +0 -0
  178. languages/jetpack-zh_TW.mo +0 -0
  179. locales.php +7 -7
  180. modules/carousel/jetpack-carousel.js +3 -1
  181. modules/carousel/jetpack-carousel.php +1 -1
  182. modules/comments/comments.php +5 -4
  183. modules/contact-form/admin.php +19 -20
  184. modules/contact-form/css/menu-alter.css +56 -0
  185. modules/contact-form/css/rtl/menu-alter-rtl.css +62 -0
  186. modules/contact-form/grunion-contact-form.php +196 -11
  187. modules/contact-form/grunion-form-view.php +4 -4
  188. modules/contact-form/grunion-omnisearch.php +65 -0
  189. modules/contact-form/js/grunion.js +5 -5
  190. modules/contact-form/js/jquery-ui-1.8.4.custom.min.js +0 -185
  191. modules/custom-css/csstidy/class.csstidy_optimise.php +1 -2
  192. modules/custom-css/csstidy/data.inc.php +1 -1
  193. modules/custom-css/custom-css.php +36 -8
  194. modules/custom-post-types/comics.php +467 -0
  195. modules/custom-post-types/comics/admin.css +8 -0
  196. modules/custom-post-types/comics/comics.css +30 -0
  197. modules/custom-post-types/comics/comics.js +118 -0
  198. modules/custom-post-types/comics/rtl/comics-rtl.css +32 -0
  199. modules/custom-post-types/testimonial.php +286 -0
  200. modules/custom-post-types/testimonials.php +0 -0
  201. modules/featured-content/featured-content.php +1 -1
  202. modules/infinite-scroll/infinity.js +4 -5
  203. modules/infinite-scroll/infinity.php +37 -11
  204. modules/infinite-scroll/themes/twentythirteen.css +22 -0
  205. modules/likes.php +20 -13
  206. modules/minileven/theme/pub/minileven/content-gallery.php +2 -2
  207. modules/minileven/theme/pub/minileven/content.php +8 -3
  208. modules/minileven/theme/pub/minileven/inc/custom-header.php +2 -2
  209. modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot +0 -0
  210. modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.svg +46 -22
  211. modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.ttf +0 -0
  212. modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.woff +0 -0
  213. modules/minileven/theme/pub/minileven/inc/tweaks.php +0 -1
  214. modules/minileven/theme/pub/minileven/style.css +24 -4
  215. modules/mobile-push.php +1 -1
  216. modules/module-extras.php +2 -0
  217. modules/module-info.php +47 -1
  218. modules/notes.php +1 -1
  219. modules/omnisearch.php +14 -0
  220. modules/omnisearch/omnisearch-comments.php +48 -0
  221. modules/omnisearch/omnisearch-core.php +181 -0
  222. modules/omnisearch/omnisearch-jetpack.css +35 -0
  223. modules/omnisearch/omnisearch-plugins.php +61 -0
  224. modules/omnisearch/omnisearch-posts.php +122 -0
  225. modules/omnisearch/omnisearch.css +126 -0
  226. modules/omnisearch/rtl/omnisearch-jetpack-rtl.css +37 -0
  227. modules/omnisearch/rtl/omnisearch-rtl.css +128 -0
  228. modules/post-by-email.php +2 -2
  229. modules/publicize/assets/path-logo.png +0 -0
  230. modules/publicize/assets/publicize.css +1 -0
  231. modules/publicize/assets/rtl/publicize-rtl.css +2 -3
  232. modules/publicize/assets/yahoo-logo.png +0 -0
  233. modules/publicize/publicize-jetpack.php +87 -4
  234. modules/publicize/publicize.php +24 -5
  235. modules/publicize/ui.php +5 -5
  236. modules/sharedaddy/admin-sharing.css +3 -0
  237. modules/sharedaddy/admin-sharing.js +16 -0
  238. modules/sharedaddy/images/googleplus1.png +0 -0
  239. modules/sharedaddy/images/googleplus1@2x.png +0 -0
  240. modules/sharedaddy/images/kindle.png +0 -0
  241. modules/sharedaddy/images/kindle@2x.png +0 -0
  242. modules/sharedaddy/sharing-service.php +27 -1
  243. modules/sharedaddy/sharing-sources.php +11 -19
  244. modules/sharedaddy/sharing.css +9 -0
  245. modules/sharedaddy/sharing.js +1 -1
  246. modules/shortcodes/audio.php +6 -1
  247. modules/shortcodes/bandcamp.php +48 -20
  248. modules/shortcodes/slideshow.php +1 -1
  249. modules/social-links.php +10 -0
  250. modules/social-links/social-links.php +169 -0
  251. modules/stats.php +12 -2
  252. modules/subscriptions.php +3 -3
  253. modules/tiled-gallery/tiled-gallery.php +1 -1
  254. modules/tiled-gallery/tiled-gallery/rtl/tiled-gallery-rtl.css +12 -3
  255. modules/tiled-gallery/tiled-gallery/tiled-gallery.css +11 -2
  256. modules/tiled-gallery/tiled-gallery/tiled-gallery.js +6 -3
  257. modules/widgets/facebook-likebox.php +16 -4
  258. modules/widgets/top-posts.php +9 -5
  259. modules/widgets/twitter-timeline.php +20 -14
  260. modules/widgets/twitter.php +0 -434
  261. readme.txt +102 -8
_inc/genericons.css ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* =Webfont, thanks to FontSquirrel.com for conversion!
2
+ -------------------------------------------------------------- */
3
+ @font-face {
4
+ font-family: 'Genericons';
5
+ src: url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot');
6
+ src: url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot?#iefix') format('embedded-opentype'),
7
+ url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.woff') format('woff'),
8
+ url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.ttf') format('truetype'),
9
+ url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.svg#genericonsregular') format('svg');
10
+ font-weight: normal;
11
+ font-style: normal;
12
+ }
13
+
14
+ /**
15
+ * All Genericons
16
+ */
17
+
18
+ .genericon {
19
+ display: inline-block;
20
+ width: 16px;
21
+ height: 16px;
22
+ -webkit-font-smoothing: antialiased;
23
+ font-size: 16px;
24
+ line-height: 1;
25
+ font-family: 'Genericons';
26
+ text-decoration: inherit;
27
+ font-weight: normal;
28
+ font-style: normal;
29
+ vertical-align: top;
30
+ }
31
+
32
+ /**
33
+ * IE7 and IE6 hacks
34
+ */
35
+
36
+ .genericon {
37
+ *overflow: auto;
38
+ *zoom: 1;
39
+ *display: inline;
40
+ }
41
+
42
+ /**
43
+ * Individual icons
44
+ */
45
+
46
+ /* Post formats */
47
+ .genericon-standard:before { content: '\f100'; }
48
+ .genericon-aside:before { content: '\f101'; }
49
+ .genericon-image:before { content: '\f102'; }
50
+ .genericon-gallery:before { content: '\f103'; }
51
+ .genericon-video:before { content: '\f104'; }
52
+ .genericon-status:before { content: '\f105'; }
53
+ .genericon-quote:before { content: '\f106'; }
54
+ .genericon-link:before { content: '\f107'; }
55
+ .genericon-chat:before { content: '\f108'; }
56
+ .genericon-audio:before { content: '\f109'; }
57
+
58
+ /* Social icons */
59
+ .genericon-github:before { content: '\f200'; }
60
+ .genericon-dribbble:before { content: '\f201'; }
61
+ .genericon-twitter:before { content: '\f202'; }
62
+ .genericon-facebook:before { content: '\f203'; }
63
+ .genericon-facebook-alt:before { content: '\f204'; }
64
+ .genericon-wordpress:before { content: '\f205'; }
65
+ .genericon-googleplus:before { content: '\f206'; }
66
+ .genericon-linkedin:before { content: '\f207'; }
67
+ .genericon-linkedin-alt:before { content: '\f208'; }
68
+ .genericon-pinterest:before { content: '\f209'; }
69
+ .genericon-pinterest-alt:before { content: '\f210'; }
70
+ .genericon-flickr:before { content: '\f211'; }
71
+ .genericon-vimeo:before { content: '\f212'; }
72
+ .genericon-youtube:before { content: '\f213'; }
73
+ .genericon-tumblr:before { content: '\f214'; }
74
+ .genericon-instagram:before { content: '\f215'; }
75
+ .genericon-codepen:before { content: '\f216'; }
76
+
77
+ /* Meta icons */
78
+ .genericon-comment:before { content: '\f300'; }
79
+ .genericon-category:before { content: '\f301'; }
80
+ .genericon-tag:before { content: '\f302'; }
81
+ .genericon-time:before { content: '\f303'; }
82
+ .genericon-user:before { content: '\f304'; }
83
+ .genericon-day:before { content: '\f305'; }
84
+ .genericon-week:before { content: '\f306'; }
85
+ .genericon-month:before { content: '\f307'; }
86
+ .genericon-pinned:before { content: '\f308'; }
87
+
88
+ /* Other icons */
89
+ .genericon-search:before { content: '\f400'; }
90
+ .genericon-unzoom:before { content: '\f401'; }
91
+ .genericon-zoom:before { content: '\f402'; }
92
+ .genericon-show:before { content: '\f403'; }
93
+ .genericon-hide:before { content: '\f404'; }
94
+ .genericon-close:before { content: '\f405'; }
95
+ .genericon-close-alt:before { content: '\f406'; }
96
+ .genericon-trash:before { content: '\f407'; }
97
+ .genericon-star:before { content: '\f408'; }
98
+ .genericon-home:before { content: '\f409'; }
99
+ .genericon-mail:before { content: '\f410'; }
100
+ .genericon-edit:before { content: '\f411'; }
101
+ .genericon-reply:before { content: '\f412'; }
102
+ .genericon-feed:before { content: '\f413'; }
103
+ .genericon-warning:before { content: '\f414'; }
104
+ .genericon-share:before { content: '\f415'; }
105
+ .genericon-attachment:before { content: '\f416'; }
106
+ .genericon-location:before { content: '\f417'; }
107
+ .genericon-checkmark:before { content: '\f418'; }
108
+ .genericon-menu:before { content: '\f419'; }
109
+ .genericon-top:before { content: '\f420'; }
110
+ .genericon-minimize:before { content: '\f421'; }
111
+ .genericon-maximize:before { content: '\f422'; }
112
+ .genericon-404:before { content: '\f423'; }
113
+ .genericon-spam:before { content: '\f424'; }
114
+ .genericon-summary:before { content: '\f425'; }
115
+ .genericon-cloud:before { content: '\f426'; }
116
+ .genericon-key:before { content: '\f427'; }
117
+ .genericon-dot:before { content: '\f428'; }
118
+ .genericon-next:before { content: '\f429'; }
119
+ .genericon-previous:before { content: '\f430'; }
120
+ .genericon-expand:before { content: '\f431'; }
121
+ .genericon-collapse:before { content: '\f432'; }
122
+ .genericon-dropdown:before { content: '\f433'; }
123
+ .genericon-dropdown-left:before { content: '\f434'; }
124
+ .genericon-top:before { content: '\f435'; }
125
+ .genericon-draggable:before { content: '\f436'; }
126
+ .genericon-phone:before { content: '\f437'; }
127
+ .genericon-send-to-phone:before { content: '\f438'; }
128
+ .genericon-plugin:before { content: '\f439'; }
129
+ .genericon-cloud-download:before { content: '\f440'; }
130
+ .genericon-cloud-upload:before { content: '\f441'; }
131
+ .genericon-external:before { content: '\f442'; }
132
+ .genericon-document:before { content: '\f443'; }
133
+ .genericon-book:before { content: '\f444'; }
134
+ .genericon-cog:before { content: '\f445'; }
135
+ .genericon-unapprove:before { content: '\f446'; }
136
+ .genericon-cart:before { content: '\f447'; }
137
+ .genericon-pause:before { content: '\f448'; }
138
+ .genericon-stop:before { content: '\f449'; }
139
+ .genericon-skip-back:before { content: '\f450'; }
140
+ .genericon-skip-ahead:before { content: '\f451'; }
141
+ .genericon-play:before { content: '\f452'; }
142
+ .genericon-tablet:before { content: '\f453'; }
143
+ .genericon-send-to-tablet:before { content: '\f454'; }
144
+
145
+ /* Generic shapes */
146
+ .genericon-uparrow:before { content: '\f500'; }
147
+ .genericon-rightarrow:before { content: '\f501'; }
148
+ .genericon-downarrow:before { content: '\f502'; }
149
+ .genericon-leftarrow:before { content: '\f503'; }
_inc/images/a8c.png CHANGED
Binary file
_inc/images/alertbox-closeicon-2x.png CHANGED
Binary file
_inc/images/alertbox-closeicon.png CHANGED
Binary file
_inc/images/alertbox-clouds-2x.png CHANGED
Binary file
_inc/images/alertbox-clouds.png CHANGED
Binary file
_inc/images/align-center-2x.png DELETED
Binary file
_inc/images/align-left-2x.png DELETED
Binary file
_inc/images/align-none-2x.png DELETED
Binary file
_inc/images/align-right-2x.png DELETED
Binary file
_inc/images/archive-2x.png DELETED
Binary file
_inc/images/arrow-2x.png CHANGED
Binary file
_inc/images/arrow-pointer-blue-2x.png DELETED
Binary file
_inc/images/arrow.png CHANGED
Binary file
_inc/images/arrows-2x.png CHANGED
Binary file
_inc/images/arrows-dark-2x.png DELETED
Binary file
_inc/images/arrows-dark-vs-2x.png DELETED
Binary file
_inc/images/arrows-vs-2x.png DELETED
Binary file
_inc/images/atdbuttontr-2x.png DELETED
Binary file
_inc/images/audio-2x.png DELETED
Binary file
_inc/images/automattic-2x.png CHANGED
Binary file
_inc/images/automattic.png CHANGED
Binary file
_inc/images/bubble_bg-2x.png DELETED
Binary file
_inc/images/buttons-2x.gif DELETED
Binary file
_inc/images/code-2x.png DELETED
Binary file
_inc/images/comment-grey-bubble-2x.png DELETED
Binary file
_inc/images/date-button-2x.gif DELETED
Binary file
_inc/images/default-2x.png DELETED
Binary file
_inc/images/delete-2x.png DELETED
Binary file
_inc/images/document-2x.png DELETED
Binary file
_inc/images/down_arrow-2x.gif DELETED
Binary file
_inc/images/footer-clouds-2x.png CHANGED
Binary file
_inc/images/footer-clouds.png CHANGED
Binary file
_inc/images/generic-2x.png DELETED
Binary file
_inc/images/header-clouds-2x.png CHANGED
Binary file
_inc/images/header-clouds-small-2x.png CHANGED
Binary file
_inc/images/header-clouds-small.png CHANGED
Binary file
_inc/images/header-clouds.png CHANGED
Binary file
_inc/images/icon-comingsoon-2x.png CHANGED
Binary file
_inc/images/icon-comingsoon.png CHANGED
Binary file
_inc/images/icon-pointer-flag-2x.png DELETED
Binary file
_inc/images/image-2x.png DELETED
Binary file
_inc/images/imgedit-icons-2x.png DELETED
Binary file
_inc/images/interactive-2x.png DELETED
Binary file
_inc/images/jetpack-closebox-icon.png CHANGED
Binary file
_inc/images/list-2x.png DELETED
Binary file
_inc/images/logo-2x.png CHANGED
Binary file
_inc/images/logo-small-2x.png CHANGED
Binary file
_inc/images/logo-small.png CHANGED
Binary file
_inc/images/logo.png CHANGED
Binary file
_inc/images/marker-2x.png DELETED
Binary file
_inc/images/mask-2x.png DELETED
Binary file
_inc/images/media-button-2x.png DELETED
Binary file
_inc/images/menuicon-sprite-2x.png CHANGED
Binary file
_inc/images/menuicon-sprite.png CHANGED
Binary file
_inc/images/module-clouds-2x.png CHANGED
Binary file
_inc/images/module-clouds.png CHANGED
Binary file
_inc/images/module-icons-sprite-2x.png CHANGED
Binary file
_inc/images/module-icons-sprite.png CHANGED
Binary file
_inc/images/press-this-2x.png DELETED
Binary file
_inc/images/publicize.png CHANGED
Binary file
_inc/images/resize-2x.gif DELETED
Binary file
_inc/images/rss/blue-large.png CHANGED
Binary file
_inc/images/rss/blue-medium.png CHANGED
Binary file
_inc/images/rss/blue-small.png CHANGED
Binary file
_inc/images/rss/green-large.png CHANGED
Binary file
_inc/images/rss/green-medium.png CHANGED
Binary file
_inc/images/rss/green-small.png CHANGED
Binary file
_inc/images/rss/orange-large.png CHANGED
Binary file
_inc/images/rss/orange-medium.png CHANGED
Binary file
_inc/images/rss/orange-small.png CHANGED
Binary file
_inc/images/rss/pink-large.png CHANGED
Binary file
_inc/images/rss/pink-medium.png CHANGED
Binary file
_inc/images/rss/purple-large.png CHANGED
Binary file
_inc/images/rss/purple-medium.png CHANGED
Binary file
_inc/images/rss/purple-small.png CHANGED
Binary file
_inc/images/rss/red-large.png CHANGED
Binary file
_inc/images/rss/red-medium.png CHANGED
Binary file
_inc/images/rss/red-small.png CHANGED
Binary file
_inc/images/rss/silver-large.png CHANGED
Binary file
_inc/images/rss/silver-medium.png CHANGED
Binary file
_inc/images/rss/silver-small.png CHANGED
Binary file
_inc/images/screenshots/beautifulmath.png CHANGED
Binary file
_inc/images/screenshots/carousel.png CHANGED
Binary file
_inc/images/screenshots/comments.png CHANGED
Binary file
_inc/images/screenshots/contactform.png CHANGED
Binary file
_inc/images/screenshots/custom-css.png CHANGED
Binary file
_inc/images/screenshots/hovercards.png CHANGED
Binary file
_inc/images/screenshots/likes.png CHANGED
Binary file
_inc/images/screenshots/mobile-push-notifications.jpg CHANGED
Binary file
_inc/images/screenshots/notes.png CHANGED
Binary file
_inc/images/screenshots/post-by-email.png CHANGED
Binary file
_inc/images/screenshots/publicize.png CHANGED
Binary file
_inc/images/screenshots/sharing.png CHANGED
Binary file
_inc/images/screenshots/shortcodes.png CHANGED
Binary file
_inc/images/screenshots/shortlinks.png CHANGED
Binary file
_inc/images/screenshots/spelling.png CHANGED
Binary file
_inc/images/screenshots/stats.png CHANGED
Binary file
_inc/images/screenshots/subscriptions.png CHANGED
Binary file
_inc/images/screenshots/tiled-gallery.png CHANGED
Binary file
_inc/images/screenshots/vaultpress.png CHANGED
Binary file
_inc/images/screenshots/widgets.png CHANGED
Binary file
_inc/images/sort-2x.gif DELETED
Binary file
_inc/images/spreadsheet-2x.png DELETED
Binary file
_inc/images/stars-2x.png DELETED
Binary file
_inc/images/status-light-2x.png CHANGED
Binary file
_inc/images/status-light.png CHANGED
Binary file
_inc/images/tb-close-2x.png DELETED
Binary file
_inc/images/text-2x.png DELETED
Binary file
_inc/images/video-2x.png DELETED
Binary file
_inc/images/wheel-2x.png DELETED
Binary file
_inc/images/wpicons-2x.png DELETED
Binary file
_inc/images/xit-2x.gif DELETED
Binary file
_inc/jetpack-retina.css DELETED
@@ -1,470 +0,0 @@
1
- /* Retina core icons */
2
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
3
- /* TinyMCE buttons */
4
- .wp_themeSkin .mceToolbar span.mce_undo,
5
- .wp_themeSkin .mceToolbar span.mce_redo,
6
- .wp_themeSkin .mceToolbar span.mce_bullist,
7
- .wp_themeSkin .mceToolbar span.mce_numlist,
8
- .wp_themeSkin .mceToolbar span.mce_blockquote,
9
- .wp_themeSkin .mceToolbar span.mce_charmap,
10
- .wp_themeSkin .mceToolbar span.mce_bold,
11
- .wp_themeSkin .mceToolbar span.mce_italic,
12
- .wp_themeSkin .mceToolbar span.mce_underline,
13
- .wp_themeSkin .mceToolbar span.mce_justifyleft,
14
- .wp_themeSkin .mceToolbar span.mce_justifyright,
15
- .wp_themeSkin .mceToolbar span.mce_justifycenter,
16
- .wp_themeSkin .mceToolbar span.mce_justifyfull,
17
- .wp_themeSkin .mceToolbar span.mce_indent,
18
- .wp_themeSkin .mceToolbar span.mce_outdent,
19
- .wp_themeSkin .mceToolbar span.mce_link,
20
- .wp_themeSkin .mceToolbar span.mce_unlink,
21
- .wp_themeSkin .mceToolbar span.mce_help,
22
- .wp_themeSkin .mceToolbar span.mce_removeformat,
23
- .wp_themeSkin .mceToolbar span.mce_fullscreen,
24
- .wp_themeSkin .mceToolbar span.mce_wp_fullscreen,
25
- .wp_themeSkin .mceToolbar span.mce_media,
26
- .wp_themeSkin .mceToolbar span.mce_pastetext,
27
- .wp_themeSkin .mceToolbar span.mce_pasteword,
28
- .wp_themeSkin .mceToolbar span.mce_wp_help,
29
- .wp_themeSkin .mceToolbar span.mce_wp_adv,
30
- .wp_themeSkin .mceToolbar span.mce_wp_more,
31
- .wp_themeSkin .mceToolbar span.mce_strikethrough,
32
- .wp_themeSkin .mceToolbar span.mce_spellchecker,
33
- .wp_themeSkin .mceToolbar span.mce_forecolor,
34
- .wp_themeSkin .mceToolbar .mce_forecolorpicker,
35
- .wp_themeSkin .mceToolbar .mceSplitButton .mce_spellchecker span.mce_spellchecker,
36
- .wp_themeSkin .mceToolbar .mceSplitButton .mce_forecolor span.mce_forecolor,
37
- .wp_themeSkin .mceToolbar .mceSplitButton span.mce_numlist,
38
- .wp_themeSkin .mceToolbar .mceSplitButton span.mce_bullist {
39
- background-image: url('images/wpicons-2x.png');
40
- background-size: 560px 40px;
41
- }
42
-
43
- .view-switch #view-switch-list,
44
- .view-switch .current #view-switch-list,
45
- .view-switch #view-switch-excerpt,
46
- .view-switch .current #view-switch-excerpt {
47
- background-image: url('images/list-2x.png');
48
- background-size: 80px 20px;
49
- }
50
-
51
- .imgedit-crop,
52
- .imgedit-rleft,
53
- .imgedit-rright,
54
- .imgedit-flipv,
55
- .imgedit-fliph,
56
- .imgedit-undo,
57
- .imgedit-redo {
58
- background-image: url('images/imgedit-icons-2x.png');
59
- background-size: 260px 64px;
60
- }
61
-
62
- /* Welcome screen close button */
63
- .welcome-panel .welcome-panel-close:before {
64
- background-image: url('images/xit-2x.gif');
65
- background-size: 20px 10px;
66
- }
67
-
68
- /* Dismiss tag buttons */
69
- .tagchecklist span a, #bulk-titles div a {
70
- background-image: url('images/xit-2x.gif') !important;
71
- background-size: 20px 10px !important;
72
- }
73
- .tagchecklist span a:hover, #bulk-titles div a:hover {
74
- background-image: url('images/xit-2x.gif') !important;
75
- background-size: 20px 10px !important;
76
- }
77
-
78
- /* Pointer dismiss button */
79
- .wp-pointer-buttons a.close::before {
80
- background-image: url('images/xit-2x.gif');
81
- background-size: 20px 10px;
82
- }
83
-
84
- /* Pointer icon */
85
- .wp-pointer-content h3::before {
86
- background-image: url('images/icon-pointer-flag-2x.png');
87
- background-size: 36px 37px;
88
- }
89
-
90
- /* Pointer arrow */
91
- .wp-pointer-arrow {
92
- background-image: url('images/arrow-pointer-blue-2x.png') !important;
93
- background-size: 30px 60px !important;
94
- }
95
-
96
- /* Screen options links */
97
- #screen-meta-links a.show-settings {
98
- background-image: url('images/arrows-2x.png') !important;
99
- background-size: 15px 123px !important;
100
- }
101
- body.admin-color-classic #screen-meta-links a.show-settings {
102
- background-image: url('images/arrows-vs-2x.png') !important;
103
- }
104
-
105
- /* Collapse button divs */
106
- #collapse-button div {
107
- background-image: url('images/arrows-2x.png') !important;
108
- background-size: 15px 123px !important;
109
- }
110
- body.admin-color-classic #collapse-button div {
111
- background-image: url('images/arrows-vs-2x.png') !important;
112
- }
113
-
114
- /* Metabox handle arrows */
115
- .meta-box-sortables .postbox:hover .handlediv {
116
- background-image: url('images/arrows-2x.png') !important;
117
- background-size: 15px 123px !important;
118
- }
119
- body.admin-color-classic .meta-box-sortables .postbox:hover .handlediv {
120
- background-image: url('images/arrows-vs-2x.png') !important;
121
- }
122
-
123
- /* Date button */
124
- .curtime #timestamp {
125
- background-image: url('images/date-button-2x.gif') !important;
126
- background-size: 16px 16px;
127
- display: inline-block;
128
- height: 16px;
129
- }
130
-
131
- /* Comments column bubble */
132
- .column-comments .vers img {
133
- padding-top: 12px;
134
- height: 0;
135
- width: 12px;
136
- background: transparent url('images/comment-grey-bubble-2x.png') no-repeat center center;
137
- background-size: 12px 12px;
138
- }
139
- .post-com-count {
140
- background-image: url('images/bubble_bg-2x.png') !important;
141
- background-size: 18px 100px;
142
- }
143
-
144
- /* Post sorting indicator */
145
- .sorting-indicator {
146
- background-image: url('images/sort-2x.gif');
147
- background-size: 14px 4px;
148
- }
149
-
150
- /* Widget arrows */
151
- .sidebar-name-arrow {
152
- background-image: url('images/arrows-2x.png') !important;
153
- background-size: 15px 123px !important;
154
- }
155
- body.admin-color-classic .sidebar-name-arrow {
156
- background-image: url('images/arrows-vs-2x.png') !important;
157
- }
158
- .sidebar-name:hover .sidebar-name-arrow {
159
- background-image: url('images/arrows-dark-2x.png') !important;
160
- }
161
- body.admin-color-classic .sidebar-name:hover .sidebar-name-arrow {
162
- background-image: url('images/arrows-dark-vs-2x.png') !important;
163
- }
164
- .widget-top a.widget-action {
165
- background-image: url('images/arrows-2x.png') !important;
166
- background-size: 15px 123px !important;
167
- }
168
- body.admin-color-classic .widget-top a.widget-action {
169
- background-image: url('images/arrows-vs-2x.png') !important;
170
- }
171
- .widget-top a.widget-action:hover {
172
- background-image: url('images/arrows-dark-2x.png') !important;
173
- }
174
- body.admin-color-classic .widget-top a.widget-action:hover {
175
- background-image: url('images/arrows-dark-vs-2x.png') !important;
176
- }
177
-
178
- /* Menu editor item arrows */
179
- .item-edit {
180
- background-image: url('images/arrows-2x.png') !important;
181
- background-size: 15px 123px !important;
182
- }
183
- body.admin-color-classic .item-edit {
184
- background-image: url('images/arrows-vs-2x.png') !important;
185
- }
186
- .item-edit:hover {
187
- background-image: url('images/arrows-dark-2x.png') !important;
188
- background-size: 15px 123px !important;
189
- }
190
- body.admin-color-classic .item-edit:hover {
191
- background-image: url('images/arrows-dark-vs-2x.png') !important;
192
- }
193
-
194
- /* Plugin install star ratings */
195
- div.star-holder {
196
- background-image: url('images/stars-2x.png');
197
- background-size: 21px 37px;
198
- }
199
- div.star-holder .star-rating {
200
- background-image: url('images/stars-2x.png');
201
- background-size: 21px 37px;
202
- }
203
-
204
- /* Press This bookmarklet icon */
205
- .pressthis a span {
206
- background-image: url('images/press-this-2x.png');
207
- background-size: 24px 20px;
208
- }
209
-
210
- /* Media button */
211
- #wp-content-media-buttons a.add_media img, #dashboard_quick_press a.add_media img {
212
- padding-top: 15px;
213
- width: 15px;
214
- height: 0;
215
- background: url('images/media-button-2x.png') no-repeat center center;
216
- background-size: 15px 15px;
217
- }
218
-
219
- /* After the Deadline MCE icon */
220
- a#content_AtD img {
221
- padding-top: 20px;
222
- width: 20px;
223
- height: 0;
224
- background: url('images/atdbuttontr-2x.png') no-repeat center center;
225
- background-size: 20px 20px;
226
- }
227
-
228
- /* Resize editor */
229
- #post-body .wp_themeSkin .mceStatusbar a.mceResize {
230
- background-image: url('images/resize-2x.gif') !important;
231
- background-size: 11px 11px !important;
232
- }
233
-
234
- /* MCE dropdowns */
235
- .wp_themeSkin .mceListBox .mceOpen span, .wp_themeSkin .mceSplitButton a.mceOpen {
236
- background-image: url("images/down_arrow-2x.gif") !important;
237
- background-size: 10px 20px;
238
- }
239
-
240
- /* Img overlay buttons */
241
- #wp_editimgbtn, #wp_delimgbtn, #wp_editgallery, #wp_delgallery {
242
- padding-top: 24px !important;
243
- height: 0;
244
- width: 24px;
245
- background: url("images/delete-2x.png") no-repeat center center !important;
246
- background-size: 24px 24px;
247
- }
248
-
249
- #wp_editimgbtn, #wp_delimgbtn, #wp_editgallery, #wp_delgallery {
250
- padding-top: 24px !important;
251
- height: 0;
252
- width: 24px;
253
- background-size: 24px 24px;
254
- }
255
-
256
- #wp_editimgbtn, #wp_editgallery {
257
- background: #eee url("images/image-2x.png") no-repeat center center !important;
258
- }
259
-
260
- #wp_delimgbtn, #wp_delgallery {
261
- background: #eee url("images/delete-2x.png") no-repeat center center !important;
262
- }
263
-
264
- /* AJAX loading spinners */
265
- img.ajax-loading, img.ajax-feedback {
266
- width: 16px;
267
- height: 0;
268
- padding-top: 19px !important;
269
- background: url("images/wpspin_light-2x.gif") no-repeat center center !important;
270
- background-size: 16px 16px;
271
- }
272
-
273
- /* Align buttons (in image properties in the media library) */
274
- .image-align-none-label {
275
- background: url('images/align-none-2x.png') no-repeat center left;
276
- background-size: 21px 15px;
277
- }
278
-
279
- .image-align-left-label {
280
- background: url('images/align-left-2x.png') no-repeat center left;
281
- background-size: 22px 15px;
282
- }
283
-
284
- .image-align-center-label {
285
- background: url('images/align-center-2x.png') no-repeat center left;
286
- background-size: 21px 15px;
287
- }
288
-
289
- .image-align-right-label {
290
- background: url('images/align-right-2x.png') no-repeat center left;
291
- background-size: 22px 15px;
292
- }
293
-
294
- .button,
295
- .submit input,
296
- .button-secondary {
297
- background-color: #f5f5f5;
298
- background-image: -webkit-gradient(linear, left bottom, left top, from(#fff), to(#f2f2f2));
299
- background-image: -webkit-linear-gradient(top, #fff, #f2f2f2);
300
- background-image: -moz-linear-gradient(top, #fff, #f2f2f2);
301
- background-image: -o-linear-gradient(top, #fff, #f2f2f2);
302
- background-image: linear-gradient(to bottom, #fff, #f2f2f2);
303
- }
304
-
305
- .button:active,
306
- .submit input:active,
307
- .button-secondary:active {
308
- background-image: -webkit-gradient(linear, left bottom, left top, from(#f2f2f2), to(#fff));
309
- background-image: -webkit-linear-gradient(top, #f2f2f2, #fff);
310
- background-image: -moz-linear-gradient(top, #f2f2f2, #fff);
311
- background-image: -o-linear-gradient(top, #f2f2f2, #fff);
312
- background-image: linear-gradient(to bottom, #f2f2f2, #fff);
313
- }
314
-
315
- input.button-primary,
316
- button.button-primary,
317
- a.button-primary {
318
- background-color: #21759B;
319
- background-image: -webkit-gradient(linear, left bottom, left top, from(#298bb9), to(#217196));
320
- background-image: -webkit-linear-gradient(top, #298bb9, #217196);
321
- background-image: -moz-linear-gradient(top, #298bb9, #217196);
322
- background-image: -o-linear-gradient(top, #298bb9, #217196);
323
- background-image: linear-gradient(to bottom, #298bb9, #217196);
324
- }
325
-
326
- input.button-primary:active,
327
- button.button-primary:active,
328
- a.button-primary:active {
329
- background-image: -webkit-gradient(linear, left bottom, left top, from(#217196), to(#298bb9));
330
- background-image: -webkit-linear-gradient(top, #217196, #298bb9);
331
- background-image: -moz-linear-gradient(top, #217196, #298bb9);
332
- background-image: -o-linear-gradient(top, #217196, #298bb9);
333
- background-image: linear-gradient(to bottom, #217196, #298bb9);
334
- }
335
-
336
- .admin-color-classic #quicktags,
337
- .admin-color-classic .wp-editor-wrap .wp_themeSkin tr.mceFirst td.mceToolbar {
338
- background-color: #cfdfe9;
339
- background-image: -webkit-gradient(linear, left bottom, left top, from(#eff8ff), to(#d3e2eb));
340
- background-image: -webkit-linear-gradient(top, #eff8ff, #d3e2eb);
341
- background-image: -moz-linear-gradient(top, #eff8ff, #d3e2eb);
342
- background-image: -o-linear-gradient(top, #eff8ff, #d3e2eb);
343
- background-image: linear-gradient(to bottom, #eff8ff, #d3e2eb);
344
- }
345
-
346
- /* Uploader close button */
347
- #TB_closeWindowButton img {
348
- background: url('images/tb-close-2x.png') no-repeat center center;
349
- padding-top: 15px;
350
- width: 15px;
351
- height: 0;
352
- background-size: 15px 15px;
353
- }
354
-
355
- td.media-icon img[src$='wp-includes/images/crystal/archive.png'],
356
- td.A1B1 img[src$='wp-includes/images/crystal/archive.png'] {
357
- background: url('images/archive-2x.png') no-repeat center center;
358
- padding-top: 60px;
359
- width: 46px;
360
- height: 0;
361
- background-size: 46px 60px;
362
- }
363
-
364
- td.media-icon img[src$='wp-includes/images/crystal/audio.png'],
365
- td.A1B1 img[src$='wp-includes/images/crystal/audio.png'] {
366
- background: url('images/audio-2x.png') no-repeat center center;
367
- padding-top: 60px;
368
- width: 46px;
369
- height: 0;
370
- background-size: 46px 60px;
371
- }
372
-
373
- td.media-icon img[src$='wp-includes/images/crystal/code.png'],
374
- td.A1B1 img[src$='wp-includes/images/crystal/code.png'] {
375
- background: url('images/code-2x.png') no-repeat center center;
376
- padding-top: 60px;
377
- width: 46px;
378
- height: 0;
379
- background-size: 46px 60px;
380
- }
381
-
382
- td.media-icon img[src$='wp-includes/images/crystal/default.png'],
383
- td.A1B1 img[src$='wp-includes/images/crystal/default.png'] {
384
- background: url('images/default-2x.png') no-repeat center center;
385
- padding-top: 60px;
386
- width: 46px;
387
- height: 0;
388
- background-size: 46px 60px;
389
- }
390
-
391
- td.media-icon img[src$='wp-includes/images/crystal/document.png'],
392
- td.A1B1 img[src$='wp-includes/images/crystal/document.png'] {
393
- background: url('images/document-2x.png') no-repeat center center;
394
- padding-top: 60px;
395
- width: 46px;
396
- height: 0;
397
- background-size: 46px 60px;
398
- }
399
-
400
- td.media-icon img[src$='wp-includes/images/crystal/interactive.png'],
401
- td.A1B1 img[src$='wp-includes/images/crystal/interactive.png'] {
402
- background: url('images/interactive-2x.png') no-repeat center center;
403
- padding-top: 60px;
404
- width: 46px;
405
- height: 0;
406
- background-size: 46px 60px;
407
- }
408
-
409
- td.media-icon img[src$='wp-includes/images/crystal/spreadsheet.png'],
410
- td.A1B1 img[src$='wp-includes/images/crystal/spreadsheet.png'] {
411
- background: url('images/spreadsheet-2x.png') no-repeat center center;
412
- padding-top: 60px;
413
- width: 46px;
414
- height: 0;
415
- background-size: 46px 60px;
416
- }
417
-
418
- td.media-icon img[src$='wp-includes/images/crystal/text.png'],
419
- td.A1B1 img[src$='wp-includes/images/crystal/text.png'] {
420
- background: url('images/text-2x.png') no-repeat center center;
421
- padding-top: 60px;
422
- width: 46px;
423
- height: 0;
424
- background-size: 46px 60px;
425
- }
426
-
427
- td.media-icon img[src$='wp-includes/images/crystal/video.png'],
428
- td.A1B1 img[src$='wp-includes/images/crystal/video.png'] {
429
- background: url('images/video-2x.png') no-repeat center center;
430
- padding-top: 60px;
431
- width: 46px;
432
- height: 0;
433
- background-size: 46px 60px;
434
- }
435
-
436
- .farbtastic .marker {
437
- background-image: url('images/marker-2x.png');
438
- background-size: 17px 17px;
439
- }
440
-
441
- .farbtastic .wheel {
442
- background-image: url('images/wheel-2x.png');
443
- background-size: 195px 195px;
444
- }
445
-
446
- .farbtastic .overlay {
447
- background-image: url('images/mask-2x.png');
448
- background-size: 101px 101px;
449
- }
450
-
451
- /* Generic admin menu icon */
452
- #adminmenu img[src$='wp-admin/images/generic.png'] {
453
- background: url('images/generic-2x.png') no-repeat center center;
454
- padding-top: 25px;
455
- width: 16px;
456
- height: 0;
457
- background-size: 16px 16px;
458
- }
459
-
460
- /* Editor dialogs close button */
461
- .clearlooks2 .mceClose,
462
- .clearlooks2 .mceMin,
463
- .clearlooks2 .mceMed,
464
- .clearlooks2 .mceMax,
465
- .wp-dialog .ui-dialog-titlebar-close {
466
- background-image: url('images/buttons-2x.gif') !important;
467
- background-size: 116px 48px !important;
468
- }
469
- }
470
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_inc/jetpack-rtl.css CHANGED
@@ -1,128 +1,120 @@
1
- #jp-header #jp-clouds {
2
- background-position: -632px 100%;
3
- }
4
- #jp-header.small #jp-clouds {
5
- background-position: -425px 100%;
6
- }
7
-
8
- #jp-header #jp-clouds #jp-disconnect {
9
- float: left;
10
- margin: -35px 0 0 25px;
11
- text-align: left;
12
- }
13
-
14
- #jp-header #jp-clouds #jp-disconnect a {
15
- background-position: 100% 90%;
16
- padding: 4px 30px 3px 10px;
17
- }
18
- #jp-header #jp-clouds #jp-disconnect a:hover {
19
- background-position: 100% 3%;
20
- }
21
-
22
- #jp-header h3 {
23
- background-position: top right;
24
- right: 25px;
25
- left: auto;
26
- }
27
-
28
- #jp-header p {
29
- right: 390px;
30
- left: auto;
31
- text-align: right;
32
- }
33
-
34
- #jp-info {
35
- margin: 0 28px 0 12px;
36
- }
37
-
38
- #jp-info p {
39
- float:right;
40
- }
41
-
42
- #jp-info a.jp-button {
43
- float: left;
44
- margin: 8px 20px 0 0;
45
- }
46
-
47
- .jp-connect { padding: 10px 0 5px !important; }
48
-
49
- #jetpack-settings > .jetpack-message { margin: 10px 15px 10px 13px }
50
-
51
- .jetpack-message .squeezer {
52
- text-align: right;
53
- }
54
- .jetpack-message h4 {
55
- margin: 0 0 10px 10px;
56
- }
57
-
58
- .more-info {
59
- margin: 0 15px 5px 12px;
60
- background: transparent url( images/header-clouds-sm.png ) bottom right repeat-x;
61
- }
62
- .more-info .jp-close {
63
- left: 0;
64
- right: auto;
65
- padding: 0 6px 0 4px;
66
- -moz-border-radius: 3px;
67
- -webkit-border-radius: 3px;
68
- border-radius: 3px;
69
- -moz-border-radius-topright: 0;
70
- -moz-border-radius-bottomright: 0;
71
- -webkit-border-top-left-radius: 0;
72
- -webkit-border-bottom-left-radius: 0;
73
- border-top-left-radius: 0;
74
- border-bottom-left-radius: 0;
75
- }
76
-
77
- .more-info div.jp-info-img {
78
- float: left;
79
- margin: 0 20px 0 30px;
80
- }
 
 
81
 
82
  .jetpack-module {
83
  float: right;
84
  margin: 0 15px 15px 0;
85
  padding: 15px 15px 35px 0;
86
  }
87
- .jetpack-module div.module-image {
88
- float: left;
89
- margin: 0 10px 5px 0;
90
- -webkit-border-radius: 0;
91
- -moz-border-radius: 0;
92
- border-radius: 0;
93
- -webkit-border-top-right-radius: 5px;
94
- -moz-border-radius-topleft: 5px;
95
- border-top-right-radius: 5px;
96
- -webkit-border-bottom-right-radius: 5px;
97
- -moz-border-radius-bottomleft: 5px;
98
- border-bottom-right-radius: 5px;
99
- }
100
-
101
- .jetpack-module div.module-image p {
102
- -webkit-border-radius: 0;
103
- -moz-border-radius: 0;
104
- border-radius: 0;
105
- -webkit-border-bottom-right-radius: 5px;
106
- -moz-border-radius-bottomleft: 5px;
107
- border-bottom-right-radius: 5px;
108
- }
109
-
110
-
111
- .jetpack-module .jetpack-module-actions {
112
- right: 15px;
113
- left: auto;
114
- }
115
-
116
- .placeholder h3 {
117
- margin-left: 15px;
118
- margin-right: auto;
119
- }
120
-
121
- #jp-footer .automattic {
122
- padding-right: 3px;
123
- padding-left: 0;
124
- }
125
-
126
- #jp-footer .automattic span {
127
- margin: 0 1px 0 5px;
128
- }
1
+ #jp-header #jp-clouds {
2
+ background-position: -632px 100%;
3
+ }
4
+
5
+ #jp-header.small #jp-clouds {
6
+ background-position: -425px 100%;
7
+ }
8
+
9
+ #jp-header #jp-clouds #jp-disconnect {
10
+ float: left;
11
+ margin: -35px 0 0 25px;
12
+ text-align: left;
13
+ }
14
+
15
+ #jp-header #jp-clouds #jp-disconnect a {
16
+ background-position: 100% 90%;
17
+ padding: 4px 30px 3px 10px;
18
+ }
19
+
20
+ #jp-header #jp-clouds #jp-disconnect a:hover {
21
+ background-position: 100% 3%;
22
+ }
23
+
24
+ #jp-header h3 {
25
+ background-position: top right;
26
+ right: 25px;
27
+ left: auto;
28
+ }
29
+
30
+ #jp-header p {
31
+ right: 390px;
32
+ left: auto;
33
+ text-align: right;
34
+ }
35
+
36
+ #jp-info {
37
+ margin: 0 28px 0 12px;
38
+ }
39
+
40
+ #jp-info p {
41
+ float:right;
42
+ }
43
+
44
+ #jp-info a.jp-button {
45
+ float: left;
46
+ margin: 8px 20px 0 0;
47
+ }
48
+
49
+ .jp-connect {
50
+ padding: 10px 0 5px !important;
51
+ }
52
+
53
+ #jetpack-settings > .jetpack-message {
54
+ margin: 10px 15px 10px 13px;
55
+ }
56
+
57
+ .jetpack-message .squeezer {
58
+ text-align: right;
59
+ }
60
+
61
+ .jetpack-message h4 {
62
+ margin: 0 0 10px 10px;
63
+ }
64
+
65
+ .more-info {
66
+ margin: 0 15px 5px 12px;
67
+ background: transparent url(images/header-clouds-sm.png) bottom right repeat-x;
68
+ }
69
+
70
+ .more-info .jp-close {
71
+ left: 0;
72
+ right: auto;
73
+ padding: 0 6px 0 4px;
74
+ border-radius: 3px;
75
+ border-top-left-radius: 0;
76
+ border-bottom-left-radius: 0;
77
+ }
78
+
79
+ .more-info div.jp-info-img {
80
+ float: left;
81
+ margin: 0 20px 0 30px;
82
+ }
83
 
84
  .jetpack-module {
85
  float: right;
86
  margin: 0 15px 15px 0;
87
  padding: 15px 15px 35px 0;
88
  }
89
+
90
+ .jetpack-module div.module-image {
91
+ float: left;
92
+ margin: 0 10px 5px 0;
93
+ border-radius: 0;
94
+ border-top-right-radius: 5px;
95
+ border-bottom-right-radius: 5px;
96
+ }
97
+
98
+ .jetpack-module div.module-image p {
99
+ border-radius: 0;
100
+ border-bottom-right-radius: 5px;
101
+ }
102
+
103
+ .jetpack-module .jetpack-module-actions {
104
+ right: 15px;
105
+ left: auto;
106
+ }
107
+
108
+ .placeholder h3 {
109
+ margin-left: 15px;
110
+ margin-right: auto;
111
+ }
112
+
113
+ #jp-footer .automattic {
114
+ padding-right: 3px;
115
+ padding-left: 0;
116
+ }
117
+
118
+ #jp-footer .automattic span {
119
+ margin: 0 1px 0 5px;
120
+ }
 
 
 
 
 
 
 
 
 
 
_inc/jetpack.css CHANGED
@@ -1,439 +1,566 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  #jp-header {
2
  min-width: 741px;
3
  z-index: 0;
4
  margin: 30px 0 -30px 0;
5
  }
6
- #jp-header.small {
7
- margin-bottom: 50px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  }
9
 
10
- #jp-header #jp-clouds {
11
- position: relative;
12
- background: transparent url( images/header-clouds.png ) -315px 100% repeat-x;
13
- padding-top: 110px;
14
- -webkit-border-radius: 3px;
15
- -moz-border-radius: 3px;
16
- border-radius: 3px;
17
  }
18
- #jp-header.small #jp-clouds {
19
- background: transparent url( images/header-clouds-small.png ) -120px 100% repeat-x;
20
- padding: 50px 0 0 0;
21
- height: 70px;
22
- }
23
-
24
-
25
- #jp-header #jp-clouds #jp-disconnectors {
26
- font-size: 12px;
27
- color: #fff;
28
- float: right;
29
- margin-top: -35px;
30
- text-align: left;
31
- position: relative;
32
- left: -45px;
33
- }
34
-
35
- #jp-header #jp-clouds .jp-disconnect a {
36
- background: #8caa46 url( images/status-light.png ) 3px 85% no-repeat;
37
- display: inline-block;
38
- position: relative;
39
- width: 100%;
40
- height: 1.7em;
41
- overflow: hidden;
42
- padding: 4px 0 3px 30px;
43
- margin: 0 -20px 3px 0;
44
- color: #fff;
45
- text-decoration: none;
46
- border: 1px solid #7a943d;
47
- -moz-border-radius: 5px;
48
- -webkit-border-radius: 5px;
49
- border-radius: 5px;
50
- -moz-box-shadow: inset 0 0 2px rgba( 255, 255, 255, 0.4 );
51
- -webkit-box-shadow: inset 0 0 2px rgba( 255, 255, 255, 0.4 );
52
- box-shadow: inset 0 0 2px rgba( 255, 255, 255, 0.4 );
53
- text-shadow: 0px -1px 0px rgba( 0,0,0,0.3 );
54
- }
55
- #jp-header #jp-clouds .jp-disconnect a:hover {
56
- background: #8caa46 url( images/status-light.png ) 3px -2% no-repeat;
57
- background-color: #839f40;
58
- border-color: #6a8037;
59
- }
60
-
61
- #jp-header #jp-clouds .jp-disconnect div {
62
- position: relative;
63
- line-height: 1.7em;
64
- height: 1.7em;
65
- }
66
-
67
- #jp-header #jp-clouds .jp-disconnect a:hover div,
68
- #jp-header #jp-clouds .jp-disconnect a.clicked div {
69
- top: -1.7em;
70
- }
71
-
72
- /* Retina Header Clouds & Status Light */
73
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
74
- #jp-header #jp-clouds {
75
- background: transparent url( images/header-clouds-2x.png ) -315px 100% repeat-x;
76
- background-size:1600px 400px;
77
- }
78
- #jp-header.small #jp-clouds {
79
- background: transparent url( images/header-clouds-small-2x.png ) -120px 100% repeat-x;
80
- background-size:980px 140px;
81
- }
82
-
83
- #jp-header #jp-clouds .jp-disconnect a {
84
- background: #8caa46 url( images/status-light-2x.png ) 3px 85% no-repeat;
85
- background-size:25px 57px;
86
- }
87
- #jp-header #jp-clouds .jp-disconnect a:hover {
88
- background: #8caa46 url( images/status-light-2x.png ) 3px -2% no-repeat;
89
- background-size:25px 57px;
90
- }
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
  #jp-header h3 {
95
- position: relative;
96
- background: transparent url( images/logo.png ) top left no-repeat;
97
- width: 252px;
98
- height: 200px;
99
- overflow: hidden;
100
- text-indent: -999em;
101
- top: -95px;
102
- left: 25px;
103
- margin: 0;
104
- padding: 0;
105
  }
106
- #jp-header.small h3 {
107
- background: transparent url( images/logo-small.png ) top left no-repeat;
108
- width: 149px;
109
- height: 120px;
110
- top: -35px;
111
- }
112
-
113
- /* Retina Logo */
114
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
115
- #jp-header h3 {
116
- background: transparent url( images/logo-2x.png ) top left no-repeat;
117
- background-size:250px 200px;
118
- }
119
- #jp-header.small h3 {
120
- background: transparent url( images/logo-small-2x.png ) top left no-repeat;
121
- background-size:150px 120px;
122
- }
123
  }
124
 
 
125
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
- #jp-header p {
128
- position: absolute;
129
- left: 390px;
130
- text-align: left;
131
- top: 30px;
132
- width: 48%;
133
- color: #fff;
134
- font-size: 25px;
135
- line-height: 130%;
136
- text-shadow: 0px 1px 1px rgba(0,0,0,0.5);
137
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
138
- -webkit-font-smoothing: antialiased;
139
- }
140
 
141
- #jp-info {
142
- position: relative;
143
- overflow: visible;
144
- z-index: 50;
145
- margin: 0 12px 0 28px;
146
- min-width: 780px;
147
- }
 
 
148
 
149
- #jp-info p {
150
- font-size: 17px;
151
- line-height: 150%;
152
- text-shadow: 0px 1px 0px #fff;
153
- font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
154
- color: #666;
155
- margin: 0 0 40px;
156
- float:left;
157
- width: 58%;
158
- }
159
- #jp-info p.small {
160
- font-size: 14px;
161
- }
162
-
163
- #jp-info a.jp-button {
164
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
165
- float: right;
166
- margin: 8px 0 0 20px;
167
- display: inline-block;
168
- background: #69acce;
169
- -moz-box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
170
- -webkit-box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
171
- box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
172
- padding: 12px 20px;
173
- border: 1px solid #2a8cba;
174
- -moz-border-radius: 5px;
175
- -webkit-border-radius: 5px;
176
- border-radius: 5px;
177
- line-height: 100%;
178
- color: #fff;
179
- text-align: center;
180
- font-size: 20px;
181
- font-weight: bold;
182
- text-decoration: none;
183
- text-shadow: 0px 1px 2px rgba( 0,0,0,0.5);
184
- -webkit-transition-duration: .3s;
185
- -moz-transition-duration: .3s;
186
- cursor: pointer;
187
- }
188
- #jp-info a.jp-button:hover, #jp-info a.jp-button:active {
189
- background-color: #f0a000;
190
- border-color: #c87800;
191
- -webkit-transition-duration: .3s;
192
- outline: none;
193
- -moz-box-shadow: inset 0 0 2px #fff, 0 1px 7px rgba(240,160,0,0.5);
194
- -webkit-box-shadow: inset 0 0 2px #fff, 0 1px 7px rgba(240,160,0,0.5);
195
- box-shadow: inset 0 0 2px #fff, 0 1px 7spx rgba(240,160,0,0.5);
196
- }
197
 
198
  .jetpack-message {
199
  position: relative;
200
  z-index: 100;
201
  border: 1px solid #2a8cba !important;
202
- -moz-border-radius: 3px;
203
- -webkit-border-radius: 3px;
204
  border-radius: 3px;
205
- background: url( images/alertbox-clouds.png ) 100% 100% no-repeat;
206
  background-color: #6aafcf !important;
207
- -webkit-box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
208
- -moz-box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
209
- box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
210
  padding: 18px 90px 8px 15px !important;
211
  overflow: hidden;
212
  line-height: 180%;
213
  }
214
 
215
  /* Retina alertbox clouds */
216
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
217
- .jetpack-message {
218
- background: url( images/alertbox-clouds-2x.png ) 100% 100% no-repeat;
219
- background-size:95px 55px;
220
- }
 
 
 
 
 
221
  }
222
 
223
- .jp-connect { padding: 10px 0 5px !important; }
 
 
224
 
225
- #jetpack-settings > .jetpack-message { margin: 10px 13px 10px 15px }
 
 
226
 
227
- .jetpack-message .squeezer {
228
- max-width: 940px;
229
- margin: 0 0 2px;
230
- padding: 0 10px;
231
- text-align: left;
232
- overflow: hidden;
233
- }
234
- .jetpack-message h4 {
235
- margin: 0 10px 10px 0;
236
- font-size: 18px;
237
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
238
- font-weight: normal;
239
- color: #fff;
240
- text-shadow: 0px 1px 1px rgba(0,0,0,0.4);
241
- -moz-border-radius: 5px;
242
- -webkit-border-radius: 5px;
243
- border-radius: 5px;
244
- display: inline-block;
245
- }
246
 
247
- .jetpack-message h5 {
248
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
249
- margin: 0;
250
- }
 
 
 
 
 
251
 
252
- .jetpack-message .squeezer a, .jetpack-message .squeezer a:visited {
253
- color: #fff;
254
- text-decoration: underline;
255
- }
256
 
257
- .jetpack-message .squeezer a:hover {
258
- color: #f0a000;
259
- }
 
 
260
 
261
- .jetpack-message code, .jetpack-err p {
262
- background: rgba( 0,0,0,0.2 );
263
- font-size: 14px;
264
- padding: 3px 5px !important;
265
- text-shadow: 0px 1px 1px rgba(0,0,0,0.4);
266
- color: #fff;
267
- }
268
 
269
- .jetpack-message p {
270
- margin: -1px 0 0 0 !important;
271
- padding: 0;
272
- display: inline-block;
273
- }
274
- .jetpack-err p {
275
- overflow: hidden;
276
- margin-bottom: 10px !important;
277
- }
278
-
279
- .jetpack-message p a.button-primary {
280
- font-size: 16px !important;
281
- display: inline-block;
282
- padding: 8px 15px;
283
- color: #fff;
284
- text-align: center;
285
- font-size: 20px;
286
- text-decoration: none;
287
- -moz-border-radius: 5px;
288
- -webkit-border-radius: 5px;
289
- border-radius: 5px;
290
- border: 1px solid #8caa46;
291
- background: #b4d278;
292
- -moz-box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
293
- -webkit-box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
294
- box-shadow: inset 0 0 2px rgba( 255,255,255,1), 0 1px 1px rgba( 0,0,0,0.1 );
295
- text-shadow: 0px -1px 0px rgba( 0,0,0,0.3);
296
- -webkit-transition-duration: .3s;
297
- -moz-transition-duration: .3s;
298
- cursor: pointer;
299
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
300
- }
301
- .jetpack-message p a.button-primary:hover, .jetpack-message p a.button-primary:active {
302
- background-color: #f0a000;
303
- border-color: #c87800;
304
- -webkit-transition-duration: .3s;
305
- outline: none;
306
- }
307
-
308
- .inline-message p strong { display: block; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
 
310
  .more-info {
311
- position: relative;
312
- top: -5px;
313
- margin: 0 15px 5px 15px;
314
- height: 230px; /* Have to set height otherwise slideDown() doesn't work. */
315
- padding-right: 15px !important;
316
- padding-bottom: 15px;
317
- clear: both;
318
- overflow: visible !important;
319
- color: #666 !important;
320
- background: transparent url( images/module-clouds.png ) bottom left repeat-x;
321
- background-color: #f0f0f0 !important;
322
- border-color: #dcdcdc !important;
323
- text-shadow: 0px 1px 0px #fff;
324
- -webkit-box-shadow: inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
325
- -moz-box-shadow: inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
326
- box-shadow: inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
327
  }
328
 
329
- /* Retina moreinfo bg clouds */
330
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
331
- .more-info {
332
- background: transparent url( images/module-clouds-2x.png ) bottom left repeat-x;
333
- background-size:980px 140px;
334
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  }
336
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
 
338
- .more-info h4 {
339
- padding: 0;
340
- background: none;
341
- font-weight: normal;
342
- color: #000;
343
- font-size: 19px;
344
- text-shadow: 0px 1px 0px #fff;
345
- }
346
-
347
- .more-info h5 {
348
- margin-left: 0;
349
- font-size: 12px !important;
350
- }
351
- .more-info .arrow {
352
- position: absolute;
353
- width: 29px;
354
- height: 18px;
355
- top: -16px;
356
- left: 0;
357
- background: url( images/arrow.png ) top left no-repeat;
358
- }
359
-
360
- /* Retina module more info arrow */
361
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
362
- .more-info .arrow {
363
- background: url( images/arrow-2x.png ) top left no-repeat;
364
- background-size:29px 16px;
365
- }
366
- }
367
-
368
- .more-info p {
369
- margin: 0 0 10px 0 !important;
370
- font-size: 14px;
371
- font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
372
- line-height: 150%;
373
- display: block;
374
- }
375
-
376
- .more-info ul {
377
- font-size: 14px;
378
- font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
379
- line-height: 150%;
380
- }
381
-
382
- .more-info li {
383
- list-style-type: disc;
384
- list-style-position: inside;
385
- }
386
-
387
- .more-info code {
388
- background: rgba( 0,0,0,0.05 );
389
- font-size: 12px;
390
- padding: 1px;
391
- text-shadow: none;
392
- color: #555;
393
- }
394
-
395
- .more-info .jp-close {
396
- position: absolute;
397
- top: 18px;
398
- right: 0;
399
- background: #888;
400
- background: rgba(0,0,0,0.4);
401
- color: #fff;
402
- font-size: 14px !important;
403
- height: 22px;
404
- line-height: 20px;
405
- padding: 0 6px 0 6px;
406
- font-weight: bold !important;
407
- -moz-border-radius: 3px;
408
- -webkit-border-radius: 3px;
409
- border-radius: 3px;
410
- -moz-border-radius-topright: 0;
411
- -moz-border-radius-bottomright: 0;
412
- -webkit-border-top-right-radius: 0;
413
- -webkit-border-bottom-right-radius: 0;
414
- border-top-right-radius: 0;
415
- border-bottom-right-radius: 0;
416
- cursor: pointer;
417
- text-shadow: 0 1px 0 rgba(0,0,0,0.2);
418
- }
419
- .more-info .jp-close:hover {
420
- background: #69acce;
421
- }
422
-
423
- .more-info div.jp-info-img {
424
- float: right;
425
- width: 320px;
426
- margin: 0 30px 0 20px;
427
- }
428
-
429
- .more-info img.jp-info-img {
430
- padding: 3px;
431
- background: rgba( 255, 255, 255, 0.65 );
432
- border: 5px solid #ddd;
433
- }
434
 
435
  .jetpack-activated {
436
- background: #fffff5 url( images/jp-enabled-bg.jpg ) top left repeat-x !important;
437
  height: 154px;
438
  padding: 60px 0 0 200px !important;
439
  position: relative;
@@ -442,59 +569,55 @@
442
  z-index: 5;
443
  position: relative;
444
  }
445
- .jetpack-activated h3 {
446
- position: relative;
447
- z-index: 5;
448
- color: #444;
449
- font-size: 42px;
450
- font-weight: bold;
451
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
452
- margin: 0;
453
- padding: 0;
454
- background: none;
455
- display: block;
456
- text-transform: uppercase;
457
- }
458
- .jetpack-activated p {
459
- position: relative;
460
- z-index: 3;
461
- top: 3px;
462
- left: 10px;
463
- font-size: 16px;
464
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
465
- font-weight: normal;
466
- color: #666;
467
- background: rgba( 255, 255, 255, 0.75 );
468
- padding: 7px 10px 6px;
469
- -moz-border-radius: 5px;
470
- -webkit-border-radius: 5px;
471
- border-radius: 5px;
472
- display: inline-block;
473
- }
474
- .jetpack-activated .jetpack {
475
- position: absolute;
476
- top: 0;
477
- left: 0;
478
- width: 238px;
479
- height: 214px;
480
- background: url( images/jp-enabled-jetpack.jpg ) top left no-repeat;
481
- z-index: 2;
482
- }
483
- .jetpack-activated .clouds {
484
- position: absolute;
485
- right: 0;
486
- bottom: 0;
487
- width: 566px;
488
- height: 214px;
489
- background: url( images/jp-enabled-clouds.png ) bottom left no-repeat;
490
- z-index: 0;
491
- -webkit-border-bottom-right-radius: 5px;
492
- -moz-border-radius-bottomright: 5px;
493
- border-bottom-right-radius: 5px;
494
- -webkit-box-shadow: inset -7px -7px 10px rgba( 0,0,0,0.05 );
495
- -moz-box-shadow: inset -7px -7px 10px rgba( 0,0,0,0.05 );
496
- box-shadow: inset -7px -7px 10px rgba( 0,0,0,0.05 );
497
- }
498
 
499
  p.jp-help {
500
  padding: 10px 0 15px;
@@ -515,346 +638,397 @@ p.jp-help {
515
  max-height: 220px;
516
  margin: 0 0 15px 15px;
517
  border: 1px solid #dedede;
518
- -moz-border-radius: 3px;
519
- -webkit-border-radius: 3px;
520
  border-radius: 3px;
521
  background: #fff;
522
  padding: 15px 0 35px 15px;
523
- -webkit-box-shadow: inset 0 1px 0 #fff, inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
524
- -moz-box-shadow: inset 0 1px 0 #fff, inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
525
- box-shadow: inset 0 1px 0 #fff, inset 0 0 20px rgba(0,0,0,0.05), 0 1px 2px rgba( 0,0,0,0.1 );
526
- -webkit-transition-duration: .4s;
527
- -moz-transition-duration: .4s
528
  }
 
529
  /*
530
- .jetpack-module:hover {
531
- border-color: #bbb;
532
- -webkit-box-shadow: 0 1px 2px rgba( 0,0,0,0.2 );
533
- -moz-box-shadow: 0 1px 2px rgba( 0,0,0,0.2 );
534
- box-shadow: 0 1px 2px rgba( 0,0,0,0.2 );
535
- -webkit-transition-duration: .4s;
536
- -moz-transition-duration: .4s
537
- }
538
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  .jetpack-module div.module-image {
540
- float: right;
541
- margin: 0 0 5px 10px;
542
- padding: 60px 0 0;
543
- background: #cbe0a1;
544
- width: 80px;
545
- -webkit-border-top-left-radius: 3px;
546
- -moz-border-radius-topleft: 3px;
547
- border-top-left-radius: 3px;
548
- -webkit-border-bottom-left-radius: 3px;
549
- -moz-border-radius-bottomleft: 3px;
550
- border-bottom-left-radius: 3px;
551
- background-repeat: no-repeat;
552
- background-image: url( images/module-icons-sprite.png );
553
- background-size: 2555px 50px; /* remember to update this every time a new module is added! */
554
  }
555
 
 
556
 
557
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
558
- .jetpack-module div.module-image {
559
- background-image: url( images/module-icons-sprite-2x.png );
560
- }
561
- }
562
 
563
- #stats.jetpack-module div.module-image {
564
- background-position: -510px 5px;
565
- }
566
- #comments.jetpack-module div.module-image {
567
- background-position: -1210px 5px;
568
- }
569
- #subscriptions.jetpack-module div.module-image {
570
- background-position: -1009px 5px;
571
- }
572
- #sharedaddy.jetpack-module div.module-image {
573
- background-position: -710px 5px;
574
- }
575
- #after-the-deadline.jetpack-module div.module-image {
576
- background-position: -308px 5px;
577
- }
578
- #vaultpress.jetpack-module div.module-image {
579
- background-position: -910px 5px;
580
- }
581
- #gravatar-hovercards.jetpack-module div.module-image {
582
- background-position: -410px 5px;
583
- }
584
- #contact-form.jetpack-module div.module-image {
585
- background-position: -1107px 5px;
586
- }
587
- #shortlinks.jetpack-module div.module-image {
588
- background-position: -108px 5px;
589
- }
590
- #shortcodes.jetpack-module div.module-image {
591
- background-position: -608px 5px;
592
- }
593
- #latex.jetpack-module div.module-image {
594
- background-position: -208px 5px;
595
- }
596
- #widgets.jetpack-module div.module-image {
597
- background-position: -5px 5px;
598
- }
599
- #enhanced-distribution.jetpack-module div.module-image {
600
- background-position: -808px 5px;
601
- }
602
- #carousel.jetpack-module div.module-image {
603
- background-position: -1325px 5px;
604
- }
605
- #custom-css.jetpack-module div.module-image {
606
- background-position: -1459px 5px;
607
- }
608
- #minileven.jetpack-module div.module-image {
609
- background-position: -1570px 5px;
610
- }
611
- #notes.jetpack-module div.module-image {
612
- background-position: -1806px 5px;
613
- }
614
- #json-api.jetpack-module div.module-image {
615
- background-position: -1689px 5px;
616
- }
617
- #mobile-push.jetpack-module div.module-image {
618
- background-position: -1925px 5px;
619
- }
620
- #publicize.jetpack-module div.module-image {
621
- background-position: -2136px 5px;
622
- }
623
- #post-by-email.jetpack-module div.module-image {
624
- background-position: -2025px 5px;
625
- }
626
- #infinite-scroll.jetpack-module div.module-image {
627
- background-position: -2230px 5px;
628
- }
629
- #photon.jetpack-module div.module-image {
630
- background-position: -2320px 5px;
631
- }
632
- #tiled-gallery.jetpack-module div.module-image {
633
- background-position: -2400px 5px;
634
- }
635
-
636
- #likes.jetpack-module div.module-image {
637
- background-position: -2471px 5px;
638
- }
639
-
640
- .jetpack-module div.module-image p {
641
- background-color: #b4d278;
642
- color: #fff;
643
- text-shadow: 1px 1px 0px rgba(0,0,0,0.2);
644
- text-align: center;
645
- margin: 0;
646
- padding: 0;
647
- clear: both;
648
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
649
- font-weight: bold;
650
- -webkit-font-smoothing: antialiased;
651
- -webkit-border-bottom-left-radius: 2px;
652
- -moz-border-radius-bottomleft: 2px;
653
- border-bottom-left-radius: 2px;
654
- }
655
-
656
- .jetpack-new-module div.module-image p {
657
- background-color: #f5bd4d;
658
- }
659
-
660
- .jetpack-updated-module div.module-image p {
661
- background-color: #6aafcf;
662
- }
663
-
664
- .jetpack-new-module:hover div.module-image p {
665
- background-color: #b4d278;
666
- }
667
-
668
- .jetpack-updated-module:hover div.module-image p {
669
- background-color: #b4d278;
670
- }
671
-
672
- .jetpack-new-module:hover div.module-image span.module-image-free,
673
- .jetpack-updated-module:hover div.module-image span.module-image-free {
674
- display: inline !important;
675
- }
676
-
677
- .jetpack-new-module:hover div.module-image span.module-image-badge,
678
- .jetpack-updated-module:hover div.module-image span.module-image-badge {
679
- display: none;
680
- }
681
-
682
- .jetpack-toggle {
683
- float: right;
684
- padding: 2px 4px 4px;
685
- }
686
- .jetpack-toggle a {
687
- text-decoration: none;
688
- font-weight: bold;
689
- font-size: 180%;
690
- color: #bbb;
691
- }
692
-
693
- .jetpack-active .jetpack-toggle-button:hover { color: #b90000; }
694
-
695
- .jetpack-module h3 {
696
- line-height: 1.1;
697
- margin: 0;
698
- padding: 0;
699
- font-size: 17px;
700
- font-weight: normal;
701
- font-style: normal;
702
- color: #000;
703
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
704
- }
705
 
706
- .jetpack-module-description p {
707
- line-height: 150%;
708
- font-size: 12px;
709
- font-family: Georgia,"Times New Roman","Bitstream Charter",Times,serif;
710
- margin-bottom: 20px;
711
- color: #666;
712
- }
713
 
714
- .jetpack-module .jetpack-module-actions {
715
- position: absolute;
716
- bottom: 20px;
717
- left: 15px;
718
- background: #fff;
719
- display: block;
720
- }
721
 
722
- .jetpack-module .jetpack-module-actions a {
723
- position: relative;
724
- font-weight: bold;
725
- color: #888;
726
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
727
- }
728
 
729
- .jetpack-inactive {
730
- border-color: #eee;
731
- cursor: pointer;
732
- }
733
- .jetpack-inactive *, jetpack-inactive:hover * { -webkit-transition-duration: .4s; -moz-transition-duration: .4s }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
734
 
735
- .jetpack-inactive h3, .jetpack-inactive p, .jetpack-inactive span {
736
- color: #ccc;
737
- }
738
 
739
- .jetpack-inactive .jetpack-configure-button { display: none; }
740
- .jetpack-inactive div.module-image {
741
- opacity: 0.6;
742
- }
743
 
744
- .jetpack-inactive .jetpack-module-description p a {
745
- color: #92b8d0;
746
- }
747
- .jetpack-inactive:hover .jetpack-module-description p a {
748
- color: #5590b7;
749
- }
750
 
 
 
 
751
 
752
- .jetpack-inactive:hover {
753
- border-color: #ddd;
754
- }
 
755
 
756
- .jetpack-inactive:hover h3, .jetpack-inactive:hover p, .jetpack-inactive:hover span {
757
- color: #aaa;
758
- }
 
759
 
760
- .jetpack-inactive:hover div.module-image {
761
- opacity: 0.75;
762
- }
 
763
 
764
- .placeholder {
765
- border-color: #eee !important;
766
- cursor: default !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
767
  }
768
 
769
- .placeholder h3 {
770
- color: #dadada;
771
- margin-top: 55px;
772
- text-align: center;
773
- background: transparent url(images/icon-comingsoon.png) top center no-repeat;
774
- padding: 40px 0 0 0;
775
- margin-right: 15px;
776
- box-shadow: none;
777
- }
778
-
779
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
780
- .placeholder h3 {
781
- background: transparent url(images/icon-comingsoon-2x.png) top center no-repeat;
782
- background-size:32px 32px;
783
- }
784
- }
785
 
786
  #jp-settings-screen {
787
  margin: 0 25px;
788
  }
789
- #jp-settings-screen h3 {
790
- font-size: 18px;
791
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
792
- color: #555;
793
- padding-bottom: 20px;
794
- border-bottom: 1px solid #eee;
795
- }
796
 
797
  p#news-sub {
798
  text-align: center;
799
  }
800
 
801
  #jp-footer {
802
- background: url( images/footer-clouds.png ) top center no-repeat;
803
  margin: 30px 0;
804
  padding-top: 60px;
805
  text-align: center;
806
  }
807
 
808
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
809
- #jp-footer {
810
- background: url( images/footer-clouds-2x.png ) top center no-repeat;
811
- background-size:700px 150px;
812
- }
 
 
 
 
 
813
  }
814
 
 
 
 
 
 
 
 
 
815
 
816
- #jp-footer .automattic {
817
- color: #999;
818
- font-size: 10px;
819
- line-height: 15px;
820
- text-transform: uppercase;
821
- letter-spacing: 3px;
822
- padding-left: 3px;
823
- }
 
 
 
 
 
 
824
 
825
- #jp-footer .automattic span {
826
- text-indent: -999em;
827
- overflow: hidden;
828
- background: url( images/automattic.png ) center top no-repeat;
829
- display: inline-block;
830
- width: 165px;
831
- vertical-align: top;
832
- margin: 0 5px 0 1px;
833
- line-height: 14px;
834
- height: 14px;
835
- filter: alpha(opacity=40);
836
- -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
837
- opacity: 0.5;
838
- }
839
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
840
- #jp-footer .automattic span {
841
- background: url( images/automattic-2x.png ) center top no-repeat;
842
- background-size:165px 14px;
843
- }
844
- }
845
-
846
- #jp-footer p.small {
847
- font-size: 11px;
848
- color: #ccc;
849
  }
850
 
851
- #jp-footer .small a {
852
- text-decoration: none;
853
- }
854
 
855
- #jp-footer .small a:hover {
856
- text-decoration: underline;
857
- }
 
 
 
 
 
 
 
 
 
858
 
859
  #jetpack-configuration code {
860
  font-size: 14px;
@@ -864,7 +1038,11 @@ p#news-sub {
864
  clear: both;
865
  }
866
 
867
- .error, .updated { position: relative; z-index: 100; }
 
 
 
 
868
 
869
  .toplevel_page_jetpack .wrap {
870
  max-width: 983px;
@@ -880,29 +1058,24 @@ p#news-sub {
880
  position: relative;
881
  z-index: 100;
882
  border: 1px solid #ccc !important;
883
- -moz-border-radius: 3px;
884
- -webkit-border-radius: 3px;
885
  border-radius: 3px;
886
  background-color: #efefef !important;
887
- -webkit-box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
888
- -moz-box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
889
- box-shadow: inset 0 0 15px rgba( 0,0,0,0.04 );
890
  padding: 18px 90px 8px 15px !important;
891
  overflow: hidden;
892
  line-height: 180%;
893
  }
894
 
895
- #jetpack-settings > .jp-survey { margin: 10px 13px 40px 15px }
 
 
896
 
897
  .jp-survey h4 {
898
  margin: 0;
899
  font-size: 18px;
900
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
901
  font-weight: normal;
902
  color: #333;
903
  text-shadow: 0 1px 0 #fff;
904
- -moz-border-radius: 5px;
905
- -webkit-border-radius: 5px;
906
  border-radius: 5px;
907
  display: block;
908
  float: left;
@@ -942,50 +1115,40 @@ p#news-sub {
942
  width: 16px;
943
  height: 16px;
944
  text-indent: -9999px;
945
- background: transparent url( images/alertbox-closeicon.png ) no-repeat center center;
946
  border: 0 none;
947
- -moz-border-radius: 0 0 0 5px;
948
- -webkit-border-radius: 0 0 0 5px;
949
- -o-border-radius: 0 0 0 5px;
950
- -ms-border-radius: 0 0 0 5px;
951
  border-radius: 0 0 0 5px;
952
- -moz-box-shadow: none;
953
- -webkit-box-shadow: none;
954
  box-shadow: none;
955
- -webkit-transition-duration: .3s;
956
- -moz-transition-duration: .3s;
957
- -o-transition-duration: .3s;
958
- -ms-transition-duration: .3s;
959
- transition-duration: .3s;
960
  cursor: pointer;
961
  }
962
 
963
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
964
- .jetpack-close-button {
965
- background: transparent url( images/alertbox-closeicon-2x.png ) no-repeat center center;
966
- background-size:16px 16px;
967
- }
 
 
 
 
 
968
  }
969
 
970
  .jetpack-close-button:hover {
971
  background-color: #fff;
972
  border: 0 none;
973
  outline: none;
974
- -webkit-transition-duration: .3s;
975
- -moz-transition-duration: .3s;
976
- -o-transition-duration: .3s;
977
- -ms-transition-duration: .3s;
978
- transition-duration: .3s;
979
  }
980
 
981
  .jetpack-close-button:active {
982
  background-color: #efefef;
983
  border: 0 none;
984
- -webkit-transition-duration: .3s;
985
- -moz-transition-duration: .3s;
986
- -o-transition-duration: .3s;
987
- -ms-transition-duration: .3s;
988
- transition-duration: .3s;
989
  }
990
 
991
  .jetpack-wrap-container {
@@ -1002,17 +1165,13 @@ p#news-sub {
1002
  position: absolute;
1003
  bottom: 5px;
1004
  right: 15px;
1005
- font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,"Bitstream Vera Sans",sans-serif;
1006
  float: right;
1007
  display: inline-block;
1008
  background: #b4d278;
1009
- -moz-box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
1010
- -webkit-box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
1011
- box-shadow: inset 0 0 2px #fff, 0 1px 5px rgba(0,0,0,0.3);
1012
  padding: 8px 15px;
1013
  border: 1px solid #2a8cba;
1014
- -moz-border-radius: 5px;
1015
- -webkit-border-radius: 5px;
1016
  border-radius: 5px;
1017
  line-height: 1.3;
1018
  color: #fff;
@@ -1020,26 +1179,23 @@ p#news-sub {
1020
  font-size: 16px;
1021
  font-weight: bold;
1022
  text-decoration: none;
1023
- text-shadow: 0px 1px 2px rgba( 0,0,0,0.5);
1024
- -webkit-transition-duration: .3s;
1025
- -moz-transition-duration: .3s;
1026
  cursor: pointer;
1027
  }
1028
 
1029
- .jetpack-install-container p a.button-connector:hover, .jetpack-install-container p a.button-connector:active {
 
1030
  background-color: #f0a000;
1031
  border-color: #c87800;
1032
- -webkit-transition-duration: .3s;
1033
  outline: none;
1034
- -moz-box-shadow: inset 0 0 2px #fff, 0 1px 7px rgba(240,160,0,0.5);
1035
- -webkit-box-shadow: inset 0 0 2px #fff, 0 1px 7px rgba(240,160,0,0.5);
1036
- box-shadow: inset 0 0 2px #fff, 0 1px 7spx rgba(240,160,0,0.5);
1037
  }
1038
 
1039
  .jetpack-inline-error, .jetpack-inline-message {
1040
- padding: .5em 1em .5em 1em;
1041
- -moz-border-radius: 3px;
1042
- -webkit-border-radius: 3px;
1043
  border-radius: 3px;
1044
  border-width: 1px;
1045
  border-style: solid;
1
+ /*
2
+ * Consolidate the font-family declarations:
3
+ */
4
+
5
+ #jp-header p,
6
+ #jp-info a.jp-button,
7
+ .jetpack-message h4,
8
+ .jetpack-message h5,
9
+ .jetpack-message p a.button-primary,
10
+ .jetpack-activated h3,
11
+ .jetpack-activated p,
12
+ .jetpack-module div.module-image p,
13
+ .jetpack-module h3,
14
+ .jetpack-module .jetpack-module-actions a,
15
+ #jp-settings-screen h3,
16
+ .jp-survey h4,
17
+ .jetpack-install-container p a.button-connector {
18
+ font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", Verdana, "Bitstream Vera Sans", sans-serif;
19
+ }
20
+
21
+ #jp-info p,
22
+ .more-info p,
23
+ .more-info ul,
24
+ .jetpack-module-description p {
25
+ font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif;
26
+ }
27
+
28
+ /*
29
+ * Jetpack:
30
+ */
31
+
32
+ /* Force the menu not to be sticky, so we can color the arrow. */
33
+ .toplevel_page_jetpack.admin-color-mp6.sticky-menu #adminmenuwrap,
34
+ body[class*=" jetpack_page_jetpack_"].admin-color-mp6.sticky-menu #adminmenuwrap {
35
+ position: relative;
36
+ z-index: auto;
37
+ top: 0;
38
+ }
39
+
40
+ .toplevel_page_jetpack.admin-color-mp6 ul#adminmenu a.wp-has-current-submenu:after,
41
+ .toplevel_page_jetpack.admin-color-mp6 ul#adminmenu > li.current > a.current:after,
42
+ body[class*=" jetpack_page_jetpack_"].admin-color-mp6 ul#adminmenu a.wp-has-current-submenu:after,
43
+ body[class*=" jetpack_page_jetpack_"].admin-color-mp6 ul#adminmenu > li.current > a.current:after {
44
+ border-right-color:#8fad4b;
45
+ }
46
+
47
+ .toplevel_page_jetpack.jetpack-disconnected #wpwrap,
48
+ body[class*=" jetpack_page_jetpack_"].jetpack-disconnected #wpwrap {
49
+ background: url(images/header-clouds.png) -150px -60px repeat-x;
50
+ }
51
+
52
+ .toplevel_page_jetpack.jetpack-disconnected.admin-color-mp6 #wpwrap,
53
+ body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.admin-color-mp6 #wpwrap {
54
+ background-position: -143px -60px;
55
+ }
56
+
57
+ .toplevel_page_jetpack.jetpack-disconnected.folded #wpwrap,
58
+ body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.folded #wpwrap {
59
+ background-position: -263px -60px;
60
+ }
61
+
62
+ .toplevel_page_jetpack.jetpack-disconnected.admin-color-mp6.folded #wpwrap,
63
+ body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.admin-color-mp6.folded #wpwrap {
64
+ background-position: -257px -60px;
65
+ }
66
+
67
+ .toplevel_page_jetpack.jetpack-connected #wpwrap,
68
+ body[class*=" jetpack_page_jetpack_"].jetpack-connected #wpwrap {
69
+ background: url(images/header-clouds-small.png) 45px 0 repeat-x;
70
+ }
71
+
72
+ .toplevel_page_jetpack.jetpack-connected.admin-color-mp6 #wpwrap,
73
+ body[class*=" jetpack_page_jetpack_"].jetpack-connected.admin-color-mp6 #wpwrap {
74
+ background-position: 52px 0;
75
+ }
76
+
77
+ .toplevel_page_jetpack.jetpack-connected.folded #wpwrap,
78
+ body[class*=" jetpack_page_jetpack_"].jetpack-connected.folded #wpwrap {
79
+ background-position: -68px 0;
80
+ }
81
+
82
+ .toplevel_page_jetpack.jetpack-connected.admin-color-mp6.folded #wpwrap,
83
+ body[class*=" jetpack_page_jetpack_"].jetpack-connected.admin-color-mp6.folded #wpwrap {
84
+ background-position: -62px 0;
85
+ }
86
+
87
+ @media only screen and (max-width: 900px) {
88
+
89
+ .toplevel_page_jetpack.jetpack-disconnected.auto-fold #wpwrap,
90
+ body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.auto-fold #wpwrap {
91
+ background-position: -263px -60px;
92
+ }
93
+
94
+ .toplevel_page_jetpack.jetpack-disconnected.admin-color-mp6.auto-fold #wpwrap,
95
+ body[class*=" jetpack_page_jetpack_"].jetpack-disconnected.admin-color-mp6.auto-fold #wpwrap {
96
+ background-position: -257px -60px;
97
+ }
98
+
99
+ .toplevel_page_jetpack.jetpack-connected.auto-fold #wpwrap,
100
+ body[class*=" jetpack_page_jetpack_"].jetpack-connected.auto-fold #wpwrap {
101
+ background-position: -68px 0;
102
+ }
103
+
104
+ .toplevel_page_jetpack.jetpack-connected.admin-color-mp6.auto-fold #wpwrap,
105
+ body[class*=" jetpack_page_jetpack_"].jetpack-connected.admin-color-mp6.auto-fold #wpwrap {
106
+ background-position: -62px 0;
107
+ }
108
+
109
+ }
110
+
111
+ .toplevel_page_jetpack.screen-meta-wrap {
112
+ position: absolute;
113
+ top: 0;
114
+ width: 100%;
115
+ z-index: 2;
116
+ }
117
+
118
  #jp-header {
119
  min-width: 741px;
120
  z-index: 0;
121
  margin: 30px 0 -30px 0;
122
  }
123
+
124
+ #jp-header.small {
125
+ margin: 20px 0 50px;
126
+ }
127
+
128
+ #jp-header #jp-clouds {
129
+ position: relative;
130
+ padding-top: 110px;
131
+ }
132
+
133
+ #jp-header.small #jp-clouds {
134
+ padding: 50px 0 0 0;
135
+ height: 70px;
136
+ }
137
+
138
+ #jp-header #jp-clouds #jp-disconnectors {
139
+ font-size: 12px;
140
+ color: #fff;
141
+ float: right;
142
+ margin-top: -35px;
143
+ text-align: left;
144
+ position: relative;
145
+ left: -45px;
146
+ }
147
+
148
+ #jp-header #jp-clouds .jp-disconnect a {
149
+ background: #8caa46 url(images/status-light.png) 3px 85% no-repeat;
150
+ display: inline-block;
151
+ position: relative;
152
+ width: 100%;
153
+ height: 1.7em;
154
+ overflow: hidden;
155
+ padding: 4px 0 3px 30px;
156
+ margin: 0 -20px 3px 0;
157
+ color: #fff;
158
+ text-decoration: none;
159
+ border: 1px solid #7a943d;
160
+ border-radius: 5px;
161
+ box-shadow: inset 0 0 2px rgba(255, 255, 255, 0.4);
162
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
163
+ }
164
+
165
+ #jp-header #jp-clouds .jp-disconnect a:hover {
166
+ background: #8caa46 url(images/status-light.png) 3px -2% no-repeat;
167
+ background-color: #839f40;
168
+ border-color: #6a8037;
169
+ }
170
+
171
+ #jp-header #jp-clouds .jp-disconnect div {
172
+ position: relative;
173
+ line-height: 1.7em;
174
+ height: 1.7em;
175
+ }
176
+
177
+ #jp-header #jp-clouds .jp-disconnect a:hover div,
178
+ #jp-header #jp-clouds .jp-disconnect a.clicked div {
179
+ top: -1.7em;
180
+ }
181
+
182
+ /* Retina Header Clouds & Status Light */
183
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
184
+ only screen and (-o-min-device-pixel-ratio: 3/2),
185
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
186
+ only screen and (min-device-pixel-ratio: 1.5) {
187
+
188
+ .toplevel_page_jetpack.jetpack-disconnected #wpwrap,
189
+ body[class*=" jetpack_page_jetpack_"].jetpack-disconnected #wpwrap {
190
+ background-image: url(images/header-clouds-2x.png);
191
+ background-size: 1600px 400px;
192
  }
193
 
194
+ .toplevel_page_jetpack.jetpack-connected #wpwrap,
195
+ body[class*=" jetpack_page_jetpack_"].jetpack-connected #wpwrap {
196
+ background-image: url(images/header-clouds-small-2x.png);
197
+ background-size: 980px 140px;
 
 
 
198
  }
199
+
200
+ #jp-header #jp-clouds .jp-disconnect a {
201
+ background-image: url(images/status-light-2x.png);
202
+ background-size: 25px 57px;
203
+ }
204
+
205
+ #jp-header #jp-clouds .jp-disconnect a:hover {
206
+ background-image: url(images/status-light-2x.png);
207
+ background-size: 25px 57px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  }
209
 
210
+ }
211
+
212
+ #jp-header h3 {
213
+ position: relative;
214
+ background: transparent url(images/logo.png) top left no-repeat;
215
+ width: 252px;
216
+ height: 200px;
217
+ overflow: hidden;
218
+ text-indent: -999em;
219
+ top: -95px;
220
+ left: 25px;
221
+ margin: 0;
222
+ padding: 0;
223
+ }
224
+
225
+ #jp-header.small h3 {
226
+ background: transparent url(images/logo-small.png) top left no-repeat;
227
+ width: 149px;
228
+ height: 120px;
229
+ top: -35px;
230
+ }
231
+
232
+ /* Retina Logo */
233
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
234
+ only screen and (-o-min-device-pixel-ratio: 3/2),
235
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
236
+ only screen and (min-device-pixel-ratio: 1.5) {
237
 
238
  #jp-header h3 {
239
+ background-image: url(images/logo-2x.png);
240
+ background-size: 250px 200px;
 
 
 
 
 
 
 
 
241
  }
242
+
243
+ #jp-header.small h3 {
244
+ background-image: url(images/logo-small-2x.png);
245
+ background-size: 150px 120px;
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  }
247
 
248
+ }
249
 
250
+ #jp-header p {
251
+ position: absolute;
252
+ left: 390px;
253
+ text-align: left;
254
+ top: 30px;
255
+ width: 48%;
256
+ color: #fff;
257
+ font-size: 25px;
258
+ line-height: 130%;
259
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
260
+ -webkit-font-smoothing: antialiased;
261
+ }
262
 
263
+ #jp-info {
264
+ position: relative;
265
+ overflow: visible;
266
+ z-index: 50;
267
+ margin: 0 12px 0 28px;
268
+ min-width: 780px;
269
+ }
 
 
 
 
 
 
270
 
271
+ #jp-info p {
272
+ font-size: 17px;
273
+ line-height: 150%;
274
+ text-shadow: 0 1px 0 #fff;
275
+ color: #666;
276
+ margin: 0 0 40px;
277
+ float: left;
278
+ width: 58%;
279
+ }
280
 
281
+ #jp-info p.small {
282
+ font-size: 14px;
283
+ }
284
+
285
+ #jp-info a.jp-button {
286
+ float: right;
287
+ margin: 8px 0 0 20px;
288
+ display: inline-block;
289
+ background: #69acce;
290
+ box-shadow: inset 0 0 2px #fff,
291
+ 0 1px 5px rgba(0, 0, 0, 0.3);
292
+ padding: 12px 20px;
293
+ border: 1px solid #2a8cba;
294
+ border-radius: 5px;
295
+ line-height: 100%;
296
+ color: #fff;
297
+ text-align: center;
298
+ font-size: 20px;
299
+ font-weight: bold;
300
+ text-decoration: none;
301
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
302
+ -webkit-transition-duration: 0.3s;
303
+ transition-duration: 0.3s;
304
+ cursor: pointer;
305
+ }
306
+
307
+ #jp-info a.jp-button:hover,
308
+ #jp-info a.jp-button:active {
309
+ background-color: #f0a000;
310
+ border-color: #c87800;
311
+ outline: none;
312
+ box-shadow: inset 0 0 2px #fff,
313
+ 0 1px 7px rgba(240, 160, 0, 0.5);
314
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
 
316
  .jetpack-message {
317
  position: relative;
318
  z-index: 100;
319
  border: 1px solid #2a8cba !important;
 
 
320
  border-radius: 3px;
321
+ background: url(images/alertbox-clouds.png) 100% 100% no-repeat;
322
  background-color: #6aafcf !important;
323
+ box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.04);
 
 
324
  padding: 18px 90px 8px 15px !important;
325
  overflow: hidden;
326
  line-height: 180%;
327
  }
328
 
329
  /* Retina alertbox clouds */
330
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
331
+ only screen and (-o-min-device-pixel-ratio: 3/2),
332
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
333
+ only screen and (min-device-pixel-ratio: 1.5) {
334
+
335
+ .jetpack-message {
336
+ background-image: url(images/alertbox-clouds-2x.png);
337
+ background-size: 95px 55px;
338
+ }
339
+
340
  }
341
 
342
+ .jp-connect {
343
+ padding: 10px 0 5px !important;
344
+ }
345
 
346
+ #jetpack-settings > .jetpack-message {
347
+ margin: 10px 13px 10px 15px;
348
+ }
349
 
350
+ .jetpack-message .squeezer {
351
+ max-width: 940px;
352
+ margin: 0 0 2px;
353
+ padding: 0 10px;
354
+ text-align: left;
355
+ overflow: hidden;
356
+ }
 
 
 
 
 
 
 
 
 
 
 
 
357
 
358
+ .jetpack-message h4 {
359
+ margin: 0 10px 10px 0;
360
+ font-size: 18px;
361
+ font-weight: normal;
362
+ color: #fff;
363
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
364
+ border-radius: 5px;
365
+ display: inline-block;
366
+ }
367
 
368
+ .jetpack-message h5 {
369
+ margin: 0;
370
+ }
 
371
 
372
+ .jetpack-message .squeezer a,
373
+ .jetpack-message .squeezer a:visited {
374
+ color: #fff;
375
+ text-decoration: underline;
376
+ }
377
 
378
+ .jetpack-message .squeezer a:hover {
379
+ color: #f0a000;
380
+ }
 
 
 
 
381
 
382
+ .jetpack-message code, .jetpack-err p {
383
+ background: rgba(0, 0, 0, 0.2);
384
+ font-size: 14px;
385
+ padding: 3px 5px !important;
386
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
387
+ color: #fff;
388
+ }
389
+
390
+ .jetpack-message p {
391
+ margin: -1px 0 0 0 !important;
392
+ padding: 0;
393
+ display: inline-block;
394
+ }
395
+
396
+ .jetpack-err p {
397
+ overflow: hidden;
398
+ margin-bottom: 10px !important;
399
+ }
400
+
401
+ .jetpack-message p a.button-primary {
402
+ font-size: 16px !important;
403
+ display: inline-block;
404
+ padding: 8px 15px;
405
+ color: #fff;
406
+ text-align: center;
407
+ font-size: 20px;
408
+ text-decoration: none;
409
+ border-radius: 5px;
410
+ border: 1px solid #8caa46;
411
+ background: #b4d278;
412
+ box-shadow: inset 0 0 2px #fff,
413
+ 0 1px 1px rgba(0, 0, 0, 0.1);
414
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3);
415
+ -webkit-transition-duration: 0.3s;
416
+ transition-duration: 0.3s;
417
+ cursor: pointer;
418
+ }
419
+
420
+ .jetpack-message p a.button-primary:hover,
421
+ .jetpack-message p a.button-primary:active {
422
+ background-color: #f0a000;
423
+ border-color: #c87800;
424
+ outline: none;
425
+ }
426
+
427
+ .inline-message p strong {
428
+ display: block;
429
+ }
430
+
431
+ .more-info {
432
+ position: relative;
433
+ top: -5px;
434
+ margin: 0 15px 5px 15px;
435
+ height: 230px; /* Have to set height otherwise slideDown() doesn't work. */
436
+ padding-right: 15px !important;
437
+ padding-bottom: 15px;
438
+ clear: both;
439
+ overflow: visible !important;
440
+ color: #666 !important;
441
+ background: transparent url(images/module-clouds.png) bottom left repeat-x;
442
+ background-color: #f0f0f0 !important;
443
+ border-color: #dcdcdc !important;
444
+ text-shadow: 0 1px 0 #fff;
445
+ box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.05),
446
+ 0 1px 2px rgba(0, 0, 0, 0.1);
447
+ }
448
+
449
+ /* Retina moreinfo bg clouds */
450
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
451
+ only screen and (-o-min-device-pixel-ratio: 3/2),
452
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
453
+ only screen and (min-device-pixel-ratio: 1.5) {
454
 
455
  .more-info {
456
+ background-image: url(images/module-clouds-2x.png);
457
+ background-size: 980px 140px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
  }
459
 
460
+ }
461
+
462
+ .more-info h4 {
463
+ padding: 0;
464
+ background: none;
465
+ font-weight: normal;
466
+ color: #000;
467
+ font-size: 19px;
468
+ text-shadow: 0 1px 0 #fff;
469
+ }
470
+
471
+ .more-info h5 {
472
+ margin-left: 0;
473
+ font-size: 12px !important;
474
+ }
475
+
476
+ .more-info .arrow {
477
+ position: absolute;
478
+ width: 29px;
479
+ height: 18px;
480
+ top: -16px;
481
+ left: 0;
482
+ background: url(images/arrow.png) top left no-repeat;
483
+ }
484
+
485
+ .more-info .arrow:after {
486
+ display: none;
487
+ }
488
+
489
+ /* Retina module more info arrow */
490
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
491
+ only screen and (-o-min-device-pixel-ratio: 3/2),
492
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
493
+ only screen and (min-device-pixel-ratio: 1.5) {
494
+
495
+ .more-info .arrow {
496
+ background-image: url(images/arrow-2x.png);
497
+ background-size: 29px 16px;
498
  }
499
 
500
+ }
501
+
502
+ .more-info p {
503
+ margin: 0 0 10px 0 !important;
504
+ font-size: 14px;
505
+ line-height: 150%;
506
+ display: block;
507
+ }
508
+
509
+ .more-info ul {
510
+ font-size: 14px;
511
+ line-height: 150%;
512
+ }
513
+
514
+ .more-info li {
515
+ list-style-type: disc;
516
+ list-style-position: inside;
517
+ }
518
+
519
+ .more-info code {
520
+ background: rgba(0, 0, 0, 0.05);
521
+ font-size: 12px;
522
+ padding: 1px;
523
+ text-shadow: none;
524
+ color: #555;
525
+ }
526
+
527
+ .more-info .jp-close {
528
+ position: absolute;
529
+ top: 18px;
530
+ right: 0;
531
+ background: #888;
532
+ background: rgba(0, 0, 0, 0.4);
533
+ color: #fff;
534
+ font-size: 14px !important;
535
+ height: 22px;
536
+ line-height: 20px;
537
+ padding: 0 6px 0 6px;
538
+ font-weight: bold !important;
539
+ border-radius: 3px;
540
+ border-top-right-radius: 0;
541
+ border-bottom-right-radius: 0;
542
+ cursor: pointer;
543
+ text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
544
+ }
545
+
546
+ .more-info .jp-close:hover {
547
+ background: #69acce;
548
+ }
549
+
550
+ .more-info div.jp-info-img {
551
+ float: right;
552
+ width: 320px;
553
+ margin: 0 30px 0 20px;
554
+ }
555
 
556
+ .more-info img.jp-info-img {
557
+ padding: 3px;
558
+ background: rgba(255, 255, 255, 0.65);
559
+ border: 5px solid #ddd;
560
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
 
562
  .jetpack-activated {
563
+ background: #fffff5 url(images/jp-enabled-bg.jpg) top left repeat-x !important;
564
  height: 154px;
565
  padding: 60px 0 0 200px !important;
566
  position: relative;
569
  z-index: 5;
570
  position: relative;
571
  }
572
+
573
+ .jetpack-activated h3 {
574
+ position: relative;
575
+ z-index: 5;
576
+ color: #444;
577
+ font-size: 42px;
578
+ font-weight: bold;
579
+ margin: 0;
580
+ padding: 0;
581
+ background: none;
582
+ display: block;
583
+ text-transform: uppercase;
584
+ }
585
+
586
+ .jetpack-activated p {
587
+ position: relative;
588
+ z-index: 3;
589
+ top: 3px;
590
+ left: 10px;
591
+ font-size: 16px;
592
+ font-weight: normal;
593
+ color: #666;
594
+ background: rgba(255, 255, 255, 0.75);
595
+ padding: 7px 10px 6px;
596
+ border-radius: 5px;
597
+ display: inline-block;
598
+ }
599
+
600
+ .jetpack-activated .jetpack {
601
+ position: absolute;
602
+ top: 0;
603
+ left: 0;
604
+ width: 238px;
605
+ height: 214px;
606
+ background: url(images/jp-enabled-jetpack.jpg) top left no-repeat;
607
+ z-index: 2;
608
+ }
609
+
610
+ .jetpack-activated .clouds {
611
+ position: absolute;
612
+ right: 0;
613
+ bottom: 0;
614
+ width: 566px;
615
+ height: 214px;
616
+ background: url(images/jp-enabled-clouds.png) bottom left no-repeat;
617
+ z-index: 0;
618
+ border-bottom-right-radius: 5px;
619
+ box-shadow: inset -7px -7px 10px rgba(0, 0, 0, 0.05);
620
+ }
 
 
 
 
621
 
622
  p.jp-help {
623
  padding: 10px 0 15px;
638
  max-height: 220px;
639
  margin: 0 0 15px 15px;
640
  border: 1px solid #dedede;
 
 
641
  border-radius: 3px;
642
  background: #fff;
643
  padding: 15px 0 35px 15px;
644
+ box-shadow: inset 0 1px 0 #fff,
645
+ inset 0 0 20px rgba(0, 0, 0, 0.05),
646
+ 0 1px 2px rgba(0, 0, 0, 0.1);
647
+ -webkit-transition-duration: 0.4s;
648
+ transition-duration: 0.4s;
649
  }
650
+
651
  /*
652
+ .jetpack-module:hover {
653
+ border-color: #bbb;
654
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
655
+ -webkit-transition-duration: 0.4s;
656
+ transition-duration: 0.4s;
657
+ }
 
 
658
  */
659
+
660
+ .jetpack-module div.module-image {
661
+ float: right;
662
+ margin: 0 0 5px 10px;
663
+ padding: 60px 0 0;
664
+ background: #cbe0a1;
665
+ width: 80px;
666
+ border-top-left-radius: 3px;
667
+ border-bottom-left-radius: 3px;
668
+ background-repeat: no-repeat;
669
+ background-image: url(images/module-icons-sprite.png);
670
+ background-size: 2705px 50px; /* remember to update this every time a new module is added! */
671
+ }
672
+
673
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
674
+ only screen and (-o-min-device-pixel-ratio: 3/2),
675
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
676
+ only screen and (min-device-pixel-ratio: 1.5) {
677
+
678
  .jetpack-module div.module-image {
679
+ background-image: url(images/module-icons-sprite-2x.png);
 
 
 
 
 
 
 
 
 
 
 
 
 
680
  }
681
 
682
+ }
683
 
684
+ #stats.jetpack-module div.module-image {
685
+ background-position: -510px 5px;
686
+ }
 
 
687
 
688
+ #comments.jetpack-module div.module-image {
689
+ background-position: -1210px 5px;
690
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
691
 
692
+ #subscriptions.jetpack-module div.module-image {
693
+ background-position: -1009px 5px;
694
+ }
 
 
 
 
695
 
696
+ #sharedaddy.jetpack-module div.module-image {
697
+ background-position: -710px 5px;
698
+ }
 
 
 
 
699
 
700
+ #after-the-deadline.jetpack-module div.module-image {
701
+ background-position: -308px 5px;
702
+ }
 
 
 
703
 
704
+ #vaultpress.jetpack-module div.module-image {
705
+ background-position: -910px 5px;
706
+ }
707
+
708
+ #gravatar-hovercards.jetpack-module div.module-image {
709
+ background-position: -410px 5px;
710
+ }
711
+
712
+ #contact-form.jetpack-module div.module-image {
713
+ background-position: -1107px 5px;
714
+ }
715
+
716
+ #shortlinks.jetpack-module div.module-image {
717
+ background-position: -108px 5px;
718
+ }
719
+
720
+ #shortcodes.jetpack-module div.module-image {
721
+ background-position: -608px 5px;
722
+ }
723
+
724
+ #latex.jetpack-module div.module-image {
725
+ background-position: -208px 5px;
726
+ }
727
+
728
+ #widgets.jetpack-module div.module-image {
729
+ background-position: -5px 5px;
730
+ }
731
+
732
+ #enhanced-distribution.jetpack-module div.module-image {
733
+ background-position: -808px 5px;
734
+ }
735
+
736
+ #carousel.jetpack-module div.module-image {
737
+ background-position: -1325px 5px;
738
+ }
739
+
740
+ #custom-css.jetpack-module div.module-image {
741
+ background-position: -1459px 5px;
742
+ }
743
+
744
+ #minileven.jetpack-module div.module-image {
745
+ background-position: -1570px 5px;
746
+ }
747
+
748
+ #notes.jetpack-module div.module-image {
749
+ background-position: -1806px 5px;
750
+ }
751
+
752
+ #json-api.jetpack-module div.module-image {
753
+ background-position: -1689px 5px;
754
+ }
755
+
756
+ #mobile-push.jetpack-module div.module-image {
757
+ background-position: -1925px 5px;
758
+ }
759
+
760
+ #publicize.jetpack-module div.module-image {
761
+ background-position: -2136px 5px;
762
+ }
763
+
764
+ #post-by-email.jetpack-module div.module-image {
765
+ background-position: -2025px 5px;
766
+ }
767
+
768
+ #infinite-scroll.jetpack-module div.module-image {
769
+ background-position: -2230px 5px;
770
+ }
771
+
772
+ #photon.jetpack-module div.module-image {
773
+ background-position: -2320px 5px;
774
+ }
775
+
776
+ #tiled-gallery.jetpack-module div.module-image {
777
+ background-position: -2400px 5px;
778
+ }
779
+
780
+ #likes.jetpack-module div.module-image {
781
+ background-position: -2471px 5px;
782
+ }
783
+
784
+ #debug.jetpack-module div.module-image {
785
+ background-position: -2550px 5px;
786
+ }
787
+
788
+ #omnisearch.jetpack-module div.module-image {
789
+ background-position: -2625px 5px;
790
+ }
791
+
792
+ .jetpack-module div.module-image p {
793
+ background-color: #b4d278;
794
+ color: #fff;
795
+ text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
796
+ text-align: center;
797
+ margin: 0;
798
+ padding: 0;
799
+ clear: both;
800
+ font-weight: bold;
801
+ -webkit-font-smoothing: antialiased;
802
+ border-bottom-left-radius: 2px;
803
+ }
804
 
805
+ .jetpack-new-module div.module-image p {
806
+ background-color: #f5bd4d;
807
+ }
808
 
809
+ .jetpack-updated-module div.module-image p {
810
+ background-color: #6aafcf;
811
+ }
 
812
 
813
+ .jetpack-new-module:hover div.module-image p {
814
+ background-color: #b4d278;
815
+ }
 
 
 
816
 
817
+ .jetpack-updated-module:hover div.module-image p {
818
+ background-color: #b4d278;
819
+ }
820
 
821
+ .jetpack-new-module:hover div.module-image span.module-image-free,
822
+ .jetpack-updated-module:hover div.module-image span.module-image-free {
823
+ display: inline !important;
824
+ }
825
 
826
+ .jetpack-new-module:hover div.module-image span.module-image-badge,
827
+ .jetpack-updated-module:hover div.module-image span.module-image-badge {
828
+ display: none;
829
+ }
830
 
831
+ .jetpack-toggle {
832
+ float: right;
833
+ padding: 2px 4px 4px;
834
+ }
835
 
836
+ .jetpack-toggle a {
837
+ text-decoration: none;
838
+ font-weight: bold;
839
+ font-size: 180%;
840
+ color: #bbb;
841
+ }
842
+
843
+ .jetpack-active .jetpack-toggle-button:hover {
844
+ color: #b90000;
845
+ }
846
+
847
+ .jetpack-module h3 {
848
+ line-height: 1.1;
849
+ margin: 0;
850
+ padding: 0;
851
+ font-size: 17px;
852
+ font-weight: normal;
853
+ font-style: normal;
854
+ color: #000;
855
+ }
856
+
857
+ .jetpack-module-description p {
858
+ line-height: 150%;
859
+ font-size: 12px;
860
+ margin-bottom: 20px;
861
+ color: #666;
862
+ }
863
+
864
+ .jetpack-module .jetpack-module-actions {
865
+ position: absolute;
866
+ bottom: 20px;
867
+ left: 15px;
868
+ background: #fff;
869
+ display: block;
870
+ }
871
+
872
+ .jetpack-module .jetpack-module-actions a {
873
+ position: relative;
874
+ font-weight: bold;
875
+ color: #888;
876
+ }
877
+
878
+ .jetpack-inactive {
879
+ border-color: #eee;
880
+ cursor: pointer;
881
+ }
882
+
883
+ .jetpack-inactive *,
884
+ jetpack-inactive:hover * {
885
+ -webkit-transition-duration: 0.4s;
886
+ transition-duration: 0.4s;
887
+ }
888
+
889
+ .jetpack-inactive h3, .jetpack-inactive p, .jetpack-inactive span {
890
+ color: #ccc;
891
+ }
892
+
893
+ .jetpack-inactive .jetpack-configure-button {
894
+ display: none;
895
+ }
896
+
897
+ .jetpack-inactive div.module-image {
898
+ opacity: 0.6;
899
+ }
900
+
901
+ .jetpack-inactive .jetpack-module-description p a {
902
+ color: #92b8d0;
903
+ }
904
+
905
+ .jetpack-inactive:hover .jetpack-module-description p a {
906
+ color: #5590b7;
907
+ }
908
+
909
+ .jetpack-inactive:hover {
910
+ border-color: #ddd;
911
+ }
912
+
913
+ .jetpack-inactive:hover h3,
914
+ .jetpack-inactive:hover p,
915
+ .jetpack-inactive:hover span {
916
+ color: #aaa;
917
+ }
918
+
919
+ .jetpack-inactive:hover div.module-image {
920
+ opacity: 0.75;
921
+ }
922
+
923
+ .placeholder {
924
+ border-color: #eee !important;
925
+ cursor: default !important;
926
+ }
927
+
928
+ .placeholder h3 {
929
+ color: #dadada;
930
+ margin-top: 55px;
931
+ text-align: center;
932
+ background: transparent url(images/icon-comingsoon.png) top center no-repeat;
933
+ padding: 40px 0 0 0;
934
+ margin-right: 15px;
935
+ box-shadow: none;
936
+ }
937
+
938
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
939
+ only screen and (-o-min-device-pixel-ratio: 3/2),
940
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
941
+ only screen and (min-device-pixel-ratio: 1.5) {
942
+
943
+ .placeholder h3 {
944
+ background-image: url(images/icon-comingsoon-2x.png);
945
+ background-size: 32px 32px;
946
  }
947
 
948
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
949
 
950
  #jp-settings-screen {
951
  margin: 0 25px;
952
  }
953
+
954
+ #jp-settings-screen h3 {
955
+ font-size: 18px;
956
+ color: #555;
957
+ padding-bottom: 20px;
958
+ border-bottom: 1px solid #eee;
959
+ }
960
 
961
  p#news-sub {
962
  text-align: center;
963
  }
964
 
965
  #jp-footer {
966
+ background: url(images/footer-clouds.png) top center no-repeat;
967
  margin: 30px 0;
968
  padding-top: 60px;
969
  text-align: center;
970
  }
971
 
972
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
973
+ only screen and (-o-min-device-pixel-ratio: 3/2),
974
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
975
+ only screen and (min-device-pixel-ratio: 1.5) {
976
+
977
+ #jp-footer {
978
+ background-image: url(images/footer-clouds-2x.png);
979
+ background-size: 700px 150px;
980
+ }
981
+
982
  }
983
 
984
+ #jp-footer .automattic {
985
+ color: #999;
986
+ font-size: 10px;
987
+ line-height: 15px;
988
+ text-transform: uppercase;
989
+ letter-spacing: 3px;
990
+ padding-left: 3px;
991
+ }
992
 
993
+ #jp-footer .automattic span {
994
+ text-indent: -999em;
995
+ overflow: hidden;
996
+ background: url(images/automattic.png) center top no-repeat;
997
+ display: inline-block;
998
+ width: 165px;
999
+ vertical-align: top;
1000
+ margin: 0 5px 0 1px;
1001
+ line-height: 14px;
1002
+ height: 14px;
1003
+ filter: alpha(opacity=40);
1004
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
1005
+ opacity: 0.5;
1006
+ }
1007
 
1008
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
1009
+ only screen and (-o-min-device-pixel-ratio: 3/2),
1010
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
1011
+ only screen and (min-device-pixel-ratio: 1.5) {
1012
+
1013
+ #jp-footer .automattic span {
1014
+ background-image: url(images/automattic-2x.png);
1015
+ background-size: 165px 14px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1016
  }
1017
 
1018
+ }
 
 
1019
 
1020
+ #jp-footer p.small {
1021
+ font-size: 11px;
1022
+ color: #ccc;
1023
+ }
1024
+
1025
+ #jp-footer .small a {
1026
+ text-decoration: none;
1027
+ }
1028
+
1029
+ #jp-footer .small a:hover {
1030
+ text-decoration: underline;
1031
+ }
1032
 
1033
  #jetpack-configuration code {
1034
  font-size: 14px;
1038
  clear: both;
1039
  }
1040
 
1041
+ .error,
1042
+ .updated {
1043
+ position: relative;
1044
+ z-index: 100;
1045
+ }
1046
 
1047
  .toplevel_page_jetpack .wrap {
1048
  max-width: 983px;
1058
  position: relative;
1059
  z-index: 100;
1060
  border: 1px solid #ccc !important;
 
 
1061
  border-radius: 3px;
1062
  background-color: #efefef !important;
1063
+ box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.04);
 
 
1064
  padding: 18px 90px 8px 15px !important;
1065
  overflow: hidden;
1066
  line-height: 180%;
1067
  }
1068
 
1069
+ #jetpack-settings > .jp-survey {
1070
+ margin: 10px 13px 40px 15px;
1071
+ }
1072
 
1073
  .jp-survey h4 {
1074
  margin: 0;
1075
  font-size: 18px;
 
1076
  font-weight: normal;
1077
  color: #333;
1078
  text-shadow: 0 1px 0 #fff;
 
 
1079
  border-radius: 5px;
1080
  display: block;
1081
  float: left;
1115
  width: 16px;
1116
  height: 16px;
1117
  text-indent: -9999px;
1118
+ background: transparent url(images/alertbox-closeicon.png) center center no-repeat;
1119
  border: 0 none;
 
 
 
 
1120
  border-radius: 0 0 0 5px;
 
 
1121
  box-shadow: none;
1122
+ -webkit-transition-duration: 0.3s;
1123
+ transition-duration: 0.3s;
 
 
 
1124
  cursor: pointer;
1125
  }
1126
 
1127
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
1128
+ only screen and (-o-min-device-pixel-ratio: 3/2),
1129
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
1130
+ only screen and (min-device-pixel-ratio: 1.5) {
1131
+
1132
+ .jetpack-close-button {
1133
+ background-image: url(images/alertbox-closeicon-2x.png);
1134
+ background-size: 16px 16px;
1135
+ }
1136
+
1137
  }
1138
 
1139
  .jetpack-close-button:hover {
1140
  background-color: #fff;
1141
  border: 0 none;
1142
  outline: none;
1143
+ -webkit-transition-duration: 0.3s;
1144
+ transition-duration: 0.3s;
 
 
 
1145
  }
1146
 
1147
  .jetpack-close-button:active {
1148
  background-color: #efefef;
1149
  border: 0 none;
1150
+ -webkit-transition-duration: 0.3s;
1151
+ transition-duration: 0.3s;
 
 
 
1152
  }
1153
 
1154
  .jetpack-wrap-container {
1165
  position: absolute;
1166
  bottom: 5px;
1167
  right: 15px;
 
1168
  float: right;
1169
  display: inline-block;
1170
  background: #b4d278;
1171
+ box-shadow: inset 0 0 2px #fff,
1172
+ 0 1px 5px rgba(0, 0, 0, 0.3);
 
1173
  padding: 8px 15px;
1174
  border: 1px solid #2a8cba;
 
 
1175
  border-radius: 5px;
1176
  line-height: 1.3;
1177
  color: #fff;
1179
  font-size: 16px;
1180
  font-weight: bold;
1181
  text-decoration: none;
1182
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
1183
+ -webkit-transition-duration: 0.3s;
1184
+ transition-duration: 0.3s;
1185
  cursor: pointer;
1186
  }
1187
 
1188
+ .jetpack-install-container p a.button-connector:hover,
1189
+ .jetpack-install-container p a.button-connector:active {
1190
  background-color: #f0a000;
1191
  border-color: #c87800;
 
1192
  outline: none;
1193
+ box-shadow: inset 0 0 2px #fff,
1194
+ 0 1px 7px rgba(240, 160, 0, 0.5);
 
1195
  }
1196
 
1197
  .jetpack-inline-error, .jetpack-inline-message {
1198
+ padding: 0.5em 1em 0.5em 1em;
 
 
1199
  border-radius: 3px;
1200
  border-width: 1px;
1201
  border-style: solid;
_inc/jetpack.js CHANGED
@@ -80,6 +80,7 @@ jetpack = {
80
  }
81
  } );
82
 
 
83
  },
84
 
85
  level_modules: function() {
80
  }
81
  } );
82
 
83
+ jQuery( '#screen-meta, #screen-meta-links' ).wrapAll( '<div class="screen-meta-wrap" />' );
84
  },
85
 
86
  level_modules: function() {
_inc/jquery.spin.js CHANGED
@@ -1,86 +1,104 @@
1
- /*
2
- * Matt Husby https://github.com/matthusby/spin.js
3
- * Based on the jquery plugin by Bradley Smith
4
- * https://gist.github.com/1290439
5
  */
6
 
7
  /*
8
- Add spin to the jQuery object
9
- If color is not passed the spinner will be black
10
- You can now create a spinner using any of the variants below:
11
- $("#el").spin(); // Produces default Spinner
12
- $("#el").spin("small"); // Produces a 'small' Spinner
13
- $("#el").spin("large", "white"); // Produces a 'large' Spinner in white (or any valid CSS color).
14
- $("#el").spin({ ... }); // Produces a Spinner using your custom settings.
15
- $("#el").spin("small-right"); // Pin the small spinner to the right edge
16
- $("#el").spin("{small, medium, large}-{left, right, top, bottom}"); // All options for where to pin
17
- $("#el").spin(false); // Kills the spinner.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  */
19
 
20
- ( function( $ ) {
21
- $.fn.spin = function( opts, color ) {
22
- var presets = {
23
- "small": { lines: 8, length: 2, width: 2, radius: 3, trail: 60, speed: 1.3 },
24
- "medium": { lines: 8, length: 4, width: 3, radius: 5, trail: 60, speed: 1.3 },
25
- "large": { lines: 10, length: 6, width: 4, radius: 7, trail: 60, speed: 1.3 }
26
- };
27
- if ( Spinner ) {
28
- return this.each( function() {
29
- var $this = $( this ),
30
- data = $this.data();
31
-
32
- if ( data.spinner ) {
33
- data.spinner.stop();
34
- delete data.spinner;
35
- }
36
- if ( opts !== false ) {
37
- var spinner_options;
38
- if ( typeof opts === "string" ) {
39
- var spinner_base = opts.indexOf( '-' );
40
- if( spinner_base == -1 ) {
41
- spinner_base = opts;
42
- } else {
43
- spinner_base = opts.substring( 0, spinner_base );
44
- }
45
- if ( spinner_base in presets ) {
46
- spinner_options = presets[spinner_base];
47
- } else {
48
- spinner_options = {};
49
- }
50
- var padding;
51
- if ( opts.indexOf( "-right" ) != -1 ) {
52
- padding = jQuery( this ).css( 'padding-left' );
53
- if( typeof padding === "undefined" ) {
54
- padding = 0;
55
- } else {
56
- padding = padding.replace( 'px', '' );
57
- }
58
- spinner_options.left = jQuery( this ).outerWidth() - ( 2 * ( spinner_options.length + spinner_options.width + spinner_options.radius ) ) - padding - 5;
59
- }
60
- if ( opts.indexOf( '-left' ) != -1 ) {
61
- spinner_options.left = 5;
62
- }
63
- if ( opts.indexOf( '-top' ) != -1 ) {
64
- spinner_options.top = 5;
65
- }
66
- if ( opts.indexOf( '-bottom' ) != -1 ) {
67
- padding = jQuery( this ).css( 'padding-top' );
68
- if( typeof padding === "undefined" ) {
69
- padding = 0;
70
- } else {
71
- padding = padding.replace( 'px', '' );
72
- }
73
- spinner_options.top = jQuery( this ).outerHeight() - ( 2 * ( spinner_options.length + spinner_options.width + spinner_options.radius ) ) - padding - 5;
74
- }
75
- }
76
- if( color ){
77
- spinner_options.color = color;
78
- }
79
- data.spinner = new Spinner( spinner_options ).spin( this );
80
- }
81
- });
82
- } else {
83
- throw "Spinner class not available.";
84
- }
85
- };
86
- })( jQuery );
 
 
1
+ /**
2
+ * Copyright (c) 2011-2013 Felix Gnass
3
+ * Licensed under the MIT license
 
4
  */
5
 
6
  /*
7
+
8
+ Basic Usage:
9
+ ============
10
+
11
+ $('#el').spin(); // Creates a default Spinner using the text color of #el.
12
+ $('#el').spin({ ... }); // Creates a Spinner using the provided options.
13
+
14
+ $('#el').spin(false); // Stops and removes the spinner.
15
+
16
+ Using Presets:
17
+ ==============
18
+
19
+ $('#el').spin('small'); // Creates a 'small' Spinner using the text color of #el.
20
+ $('#el').spin('large', '#fff'); // Creates a 'large' white Spinner.
21
+
22
+ Adding a custom preset:
23
+ =======================
24
+
25
+ $.fn.spin.presets.flower = {
26
+ lines: 9
27
+ length: 10
28
+ width: 20
29
+ radius: 0
30
+ }
31
+
32
+ $('#el').spin('flower', 'red');
33
+
34
  */
35
 
36
+ (function(factory) {
37
+
38
+ if (typeof exports == 'object') {
39
+ // CommonJS
40
+ factory(require('jquery'), require('spin'))
41
+ }
42
+ else if (typeof define == 'function' && define.amd) {
43
+ // AMD, register as anonymous module
44
+ define(['jquery', 'spin'], factory)
45
+ }
46
+ else {
47
+ // Browser globals
48
+ if (!window.Spinner) throw new Error('Spin.js not present')
49
+ factory(window.jQuery, window.Spinner)
50
+ }
51
+
52
+ }(function($, Spinner) {
53
+
54
+ $.fn.spin = function(opts, color) {
55
+
56
+ return this.each(function() {
57
+ var $this = $(this),
58
+ data = $this.data();
59
+
60
+ if (data.spinner) {
61
+ data.spinner.stop();
62
+ delete data.spinner;
63
+ }
64
+ if (opts !== false) {
65
+ opts = $.extend(
66
+ { color: color || $this.css('color') },
67
+ $.fn.spin.presets[opts] || opts
68
+ )
69
+ // Begin WordPress Additions
70
+ // To use opts.right, you need to have specified a length, width, and radius.
71
+ if ( typeof opts.right !== 'undefined' && typeof opts.length !== 'undefined'
72
+ && typeof opts.width !== 'undefined' && typeof opts.radius !== 'undefined' ) {
73
+ var pad = $this.css( 'padding-left' );
74
+ pad = ( typeof pad === 'undefined' ) ? 0 : parseInt( pad, 10 );
75
+ opts.left = $this.outerWidth() - ( 2 * ( opts.length + opts.width + opts.radius ) ) - pad - opts.right;
76
+ delete opts.right;
77
+ }
78
+ // End WordPress Additions
79
+ data.spinner = new Spinner(opts).spin(this)
80
+ }
81
+ })
82
+ }
83
+
84
+ $.fn.spin.presets = {
85
+ tiny: { lines: 8, length: 2, width: 2, radius: 3 },
86
+ small: { lines: 8, length: 4, width: 3, radius: 5 },
87
+ large: { lines: 10, length: 8, width: 4, radius: 8 }
88
+ }
89
+
90
+ }));
91
+
92
+ // Jetpack Presets Overrides:
93
+ (function($){
94
+ $.fn.spin.presets.wp = { trail: 60, speed: 1.3 };
95
+ $.fn.spin.presets.small = $.extend( { lines: 8, length: 2, width: 2, radius: 3 }, $.fn.spin.presets.wp );
96
+ $.fn.spin.presets.medium = $.extend( { lines: 8, length: 4, width: 3, radius: 5 }, $.fn.spin.presets.wp );
97
+ $.fn.spin.presets.large = $.extend( { lines: 10, length: 6, width: 4, radius: 7 }, $.fn.spin.presets.wp );
98
+ $.fn.spin.presets['small-left'] = $.extend( { left: 5 }, $.fn.spin.presets.small );
99
+ $.fn.spin.presets['small-right'] = $.extend( { right: 5 }, $.fn.spin.presets.small );
100
+ $.fn.spin.presets['medium-left'] = $.extend( { left: 5 }, $.fn.spin.presets.medium );
101
+ $.fn.spin.presets['medium-right'] = $.extend( { right: 5 }, $.fn.spin.presets.medium );
102
+ $.fn.spin.presets['large-left'] = $.extend( { left: 5 }, $.fn.spin.presets.large );
103
+ $.fn.spin.presets['large-right'] = $.extend( { right: 5 }, $.fn.spin.presets.large );
104
+ })(jQuery);
_inc/spin.js CHANGED
@@ -1,301 +1,349 @@
1
- //fgnass.github.com/spin.js#v1.2.4
2
- (function(window, document, undefined) {
3
 
4
  /**
5
- * Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de]
6
  * Licensed under the MIT license
7
  */
8
-
9
- var prefixes = ['webkit', 'Moz', 'ms', 'O']; /* Vendor prefixes */
10
- var animations = {}; /* Animation rules keyed by their name */
11
- var useCssAnimations;
12
-
13
- /**
14
- * Utility function to create elements. If no tag name is given,
15
- * a DIV is created. Optionally properties can be passed.
16
- */
17
- function createEl(tag, prop) {
18
- var el = document.createElement(tag || 'div');
19
- var n;
20
-
21
- for(n in prop) {
22
- el[n] = prop[n];
23
- }
24
- return el;
25
- }
26
-
27
- /**
28
- * Appends children and returns the parent.
29
- */
30
- function ins(parent /* child1, child2, ...*/) {
31
- for (var i=1, n=arguments.length; i<n; i++) {
32
- parent.appendChild(arguments[i]);
33
- }
34
- return parent;
35
- }
36
-
37
- /**
38
- * Insert a new stylesheet to hold the @keyframe or VML rules.
39
- */
40
- var sheet = function() {
41
- var el = createEl('style');
42
- ins(document.getElementsByTagName('head')[0], el);
43
- return el.sheet || el.styleSheet;
44
- }();
45
-
46
- /**
47
- * Creates an opacity keyframe animation rule and returns its name.
48
- * Since most mobile Webkits have timing issues with animation-delay,
49
- * we create separate rules for each line/segment.
50
- */
51
- function addAnimation(alpha, trail, i, lines) {
52
- var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-');
53
- var start = 0.01 + i/lines*100;
54
- var z = Math.max(1-(1-alpha)/trail*(100-start) , alpha);
55
- var prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase();
56
- var pre = prefix && '-'+prefix+'-' || '';
57
-
58
- if (!animations[name]) {
59
- sheet.insertRule(
60
- '@' + pre + 'keyframes ' + name + '{' +
61
- '0%{opacity:'+z+'}' +
62
- start + '%{opacity:'+ alpha + '}' +
63
- (start+0.01) + '%{opacity:1}' +
64
- (start+trail)%100 + '%{opacity:'+ alpha + '}' +
65
- '100%{opacity:'+ z + '}' +
66
- '}', 0);
67
- animations[name] = 1;
68
- }
69
- return name;
70
- }
71
-
72
- /**
73
- * Tries various vendor prefixes and returns the first supported property.
74
- **/
75
- function vendor(el, prop) {
76
- var s = el.style;
77
- var pp;
78
- var i;
79
-
80
- if(s[prop] !== undefined) return prop;
81
- prop = prop.charAt(0).toUpperCase() + prop.slice(1);
82
- for(i=0; i<prefixes.length; i++) {
83
- pp = prefixes[i]+prop;
84
- if(s[pp] !== undefined) return pp;
85
- }
86
- }
87
-
88
- /**
89
- * Sets multiple style properties at once.
90
- */
91
- function css(el, prop) {
92
- for (var n in prop) {
93
- el.style[vendor(el, n)||n] = prop[n];
94
- }
95
- return el;
96
- }
97
-
98
- /**
99
- * Fills in default values.
100
- */
101
- function merge(obj) {
102
- for (var i=1; i < arguments.length; i++) {
103
- var def = arguments[i];
104
- for (var n in def) {
105
- if (obj[n] === undefined) obj[n] = def[n];
106
- }
107
- }
108
- return obj;
109
- }
110
-
111
- /**
112
- * Returns the absolute page-offset of the given element.
113
- */
114
- function pos(el) {
115
- var o = {x:el.offsetLeft, y:el.offsetTop};
116
- while((el = el.offsetParent)) {
117
- o.x+=el.offsetLeft;
118
- o.y+=el.offsetTop;
119
- }
120
- return o;
121
- }
122
-
123
- var defaults = {
124
- lines: 12, // The number of lines to draw
125
- length: 7, // The length of each line
126
- width: 5, // The line thickness
127
- radius: 10, // The radius of the inner circle
128
- color: '#000', // #rgb or #rrggbb
129
- speed: 1, // Rounds per second
130
- trail: 100, // Afterglow percentage
131
- opacity: 1/4, // Opacity of the lines
132
- fps: 20, // Frames per second when using setTimeout()
133
- zIndex: 2e9, // Use a high z-index by default
134
- className: 'spinner', // CSS class to assign to the element
135
- top: 'auto', // center vertically
136
- left: 'auto' // center horizontally
137
- };
138
-
139
- /** The constructor */
140
- var Spinner = function Spinner(o) {
141
- if (!this.spin) return new Spinner(o);
142
- this.opts = merge(o || {}, Spinner.defaults, defaults);
143
- };
144
-
145
- Spinner.defaults = {};
146
- Spinner.prototype = {
147
- spin: function(target) {
148
- this.stop();
149
- var self = this;
150
- var o = self.opts;
151
- var el = self.el = css(createEl(0, {className: o.className}), {position: 'relative', zIndex: o.zIndex});
152
- var mid = o.radius+o.length+o.width;
153
- var ep; // element position
154
- var tp; // target position
155
-
156
- if (target) {
157
- target.insertBefore(el, target.firstChild||null);
158
- tp = pos(target);
159
- ep = pos(el);
160
- css(el, {
161
- left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : o.left+mid) + 'px',
162
- top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : o.top+mid) + 'px'
163
- });
164
- }
165
-
166
- el.setAttribute('aria-role', 'progressbar');
167
- self.lines(el, self.opts);
168
-
169
- if (!useCssAnimations) {
170
- // No CSS animation support, use setTimeout() instead
171
- var i = 0;
172
- var fps = o.fps;
173
- var f = fps/o.speed;
174
- var ostep = (1-o.opacity)/(f*o.trail / 100);
175
- var astep = f/o.lines;
176
-
177
- !function anim() {
178
- i++;
179
- for (var s=o.lines; s; s--) {
180
- var alpha = Math.max(1-(i+s*astep)%f * ostep, o.opacity);
181
- self.opacity(el, o.lines-s, alpha, o);
182
- }
183
- self.timeout = self.el && setTimeout(anim, ~~(1000/fps));
184
- }();
185
- }
186
- return self;
187
- },
188
- stop: function() {
189
- var el = this.el;
190
- if (el) {
191
- clearTimeout(this.timeout);
192
- if (el.parentNode) el.parentNode.removeChild(el);
193
- this.el = undefined;
194
- }
195
- return this;
196
- },
197
- lines: function(el, o) {
198
- var i = 0;
199
- var seg;
200
-
201
- function fill(color, shadow) {
202
- return css(createEl(), {
203
- position: 'absolute',
204
- width: (o.length+o.width) + 'px',
205
- height: o.width + 'px',
206
- background: color,
207
- boxShadow: shadow,
208
- transformOrigin: 'left',
209
- transform: 'rotate(' + ~~(360/o.lines*i) + 'deg) translate(' + o.radius+'px' +',0)',
210
- borderRadius: (o.width>>1) + 'px'
211
- });
212
- }
213
- for (; i < o.lines; i++) {
214
- seg = css(createEl(), {
215
- position: 'absolute',
216
- top: 1+~(o.width/2) + 'px',
217
- transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
218
- opacity: o.opacity,
219
- animation: useCssAnimations && addAnimation(o.opacity, o.trail, i, o.lines) + ' ' + 1/o.speed + 's linear infinite'
220
- });
221
- if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}));
222
- ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)')));
223
- }
224
- return el;
225
- },
226
- opacity: function(el, i, val) {
227
- if (i < el.childNodes.length) el.childNodes[i].style.opacity = val;
228
- }
229
- };
230
-
231
- /////////////////////////////////////////////////////////////////////////
232
- // VML rendering for IE
233
- /////////////////////////////////////////////////////////////////////////
234
-
235
- /**
236
- * Check and init VML support
237
- */
238
- !function() {
239
- var s = css(createEl('group'), {behavior: 'url(#default#VML)'});
240
- var i;
241
-
242
- if (!vendor(s, 'transform') && s.adj) {
243
-
244
- // VML support detected. Insert CSS rules ...
245
- for (i=4; i--;) sheet.addRule(['group', 'roundrect', 'fill', 'stroke'][i], 'behavior:url(#default#VML)');
246
-
247
- Spinner.prototype.lines = function(el, o) {
248
- var r = o.length+o.width;
249
- var s = 2*r;
250
-
251
- function grp() {
252
- return css(createEl('group', {coordsize: s +' '+s, coordorigin: -r +' '+-r}), {width: s, height: s});
253
- }
254
-
255
- var margin = -(o.width+o.length)*2+'px';
256
- var g = css(grp(), {position: 'absolute', top: margin, left: margin});
257
-
258
- var i;
259
-
260
- function seg(i, dx, filter) {
261
- ins(g,
262
- ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
263
- ins(css(createEl('roundrect', {arcsize: 1}), {
264
- width: r,
265
- height: o.width,
266
- left: o.radius,
267
- top: -o.width>>1,
268
- filter: filter
269
- }),
270
- createEl('fill', {color: o.color, opacity: o.opacity}),
271
- createEl('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
272
- )
273
- )
274
- );
275
- }
276
-
277
- if (o.shadow) {
278
- for (i = 1; i <= o.lines; i++) {
279
- seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)');
280
- }
281
- }
282
- for (i = 1; i <= o.lines; i++) seg(i);
283
- return ins(el, g);
284
- };
285
- Spinner.prototype.opacity = function(el, i, val, o) {
286
- var c = el.firstChild;
287
- o = o.shadow && o.lines || 0;
288
- if (c && i+o < c.childNodes.length) {
289
- c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild;
290
- if (c) c.opacity = val;
291
- }
292
- };
293
- }
294
- else {
295
- useCssAnimations = vendor(s, 'animation');
296
- }
297
- }();
298
-
299
- window.Spinner = Spinner;
300
-
301
- })(window, document);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //fgnass.github.com/spin.js#v1.3
 
2
 
3
  /**
4
+ * Copyright (c) 2011-2013 Felix Gnass
5
  * Licensed under the MIT license
6
  */
7
+ (function(root, factory) {
8
+
9
+ /* CommonJS */
10
+ if (typeof exports == 'object') module.exports = factory()
11
+
12
+ /* AMD module */
13
+ else if (typeof define == 'function' && define.amd) define(factory)
14
+
15
+ /* Browser global */
16
+ else root.Spinner = factory()
17
+ }
18
+ (this, function() {
19
+ "use strict";
20
+
21
+ var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */
22
+ , animations = {} /* Animation rules keyed by their name */
23
+ , useCssAnimations /* Whether to use CSS animations or setTimeout */
24
+
25
+ /**
26
+ * Utility function to create elements. If no tag name is given,
27
+ * a DIV is created. Optionally properties can be passed.
28
+ */
29
+ function createEl(tag, prop) {
30
+ var el = document.createElement(tag || 'div')
31
+ , n
32
+
33
+ for(n in prop) el[n] = prop[n]
34
+ return el
35
+ }
36
+
37
+ /**
38
+ * Appends children and returns the parent.
39
+ */
40
+ function ins(parent /* child1, child2, ...*/) {
41
+ for (var i=1, n=arguments.length; i<n; i++)
42
+ parent.appendChild(arguments[i])
43
+
44
+ return parent
45
+ }
46
+
47
+ /**
48
+ * Insert a new stylesheet to hold the @keyframe or VML rules.
49
+ */
50
+ var sheet = (function() {
51
+ var el = createEl('style', {type : 'text/css'})
52
+ ins(document.getElementsByTagName('head')[0], el)
53
+ return el.sheet || el.styleSheet
54
+ }())
55
+
56
+ /**
57
+ * Creates an opacity keyframe animation rule and returns its name.
58
+ * Since most mobile Webkits have timing issues with animation-delay,
59
+ * we create separate rules for each line/segment.
60
+ */
61
+ function addAnimation(alpha, trail, i, lines) {
62
+ var name = ['opacity', trail, ~~(alpha*100), i, lines].join('-')
63
+ , start = 0.01 + i/lines * 100
64
+ , z = Math.max(1 - (1-alpha) / trail * (100-start), alpha)
65
+ , prefix = useCssAnimations.substring(0, useCssAnimations.indexOf('Animation')).toLowerCase()
66
+ , pre = prefix && '-' + prefix + '-' || ''
67
+
68
+ if (!animations[name]) {
69
+ sheet.insertRule(
70
+ '@' + pre + 'keyframes ' + name + '{' +
71
+ '0%{opacity:' + z + '}' +
72
+ start + '%{opacity:' + alpha + '}' +
73
+ (start+0.01) + '%{opacity:1}' +
74
+ (start+trail) % 100 + '%{opacity:' + alpha + '}' +
75
+ '100%{opacity:' + z + '}' +
76
+ '}', sheet.cssRules.length)
77
+
78
+ animations[name] = 1
79
+ }
80
+
81
+ return name
82
+ }
83
+
84
+ /**
85
+ * Tries various vendor prefixes and returns the first supported property.
86
+ */
87
+ function vendor(el, prop) {
88
+ var s = el.style
89
+ , pp
90
+ , i
91
+
92
+ if(s[prop] !== undefined) return prop
93
+ prop = prop.charAt(0).toUpperCase() + prop.slice(1)
94
+ for(i=0; i<prefixes.length; i++) {
95
+ pp = prefixes[i]+prop
96
+ if(s[pp] !== undefined) return pp
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Sets multiple style properties at once.
102
+ */
103
+ function css(el, prop) {
104
+ for (var n in prop)
105
+ el.style[vendor(el, n)||n] = prop[n]
106
+
107
+ return el
108
+ }
109
+
110
+ /**
111
+ * Fills in default values.
112
+ */
113
+ function merge(obj) {
114
+ for (var i=1; i < arguments.length; i++) {
115
+ var def = arguments[i]
116
+ for (var n in def)
117
+ if (obj[n] === undefined) obj[n] = def[n]
118
+ }
119
+ return obj
120
+ }
121
+
122
+ /**
123
+ * Returns the absolute page-offset of the given element.
124
+ */
125
+ function pos(el) {
126
+ var o = { x:el.offsetLeft, y:el.offsetTop }
127
+ while((el = el.offsetParent))
128
+ o.x+=el.offsetLeft, o.y+=el.offsetTop
129
+
130
+ return o
131
+ }
132
+
133
+ // Built-in defaults
134
+
135
+ var defaults = {
136
+ lines: 12, // The number of lines to draw
137
+ length: 7, // The length of each line
138
+ width: 5, // The line thickness
139
+ radius: 10, // The radius of the inner circle
140
+ rotate: 0, // Rotation offset
141
+ corners: 1, // Roundness (0..1)
142
+ color: '#000', // #rgb or #rrggbb
143
+ direction: 1, // 1: clockwise, -1: counterclockwise
144
+ speed: 1, // Rounds per second
145
+ trail: 100, // Afterglow percentage
146
+ opacity: 1/4, // Opacity of the lines
147
+ fps: 20, // Frames per second when using setTimeout()
148
+ zIndex: 2e9, // Use a high z-index by default
149
+ className: 'spinner', // CSS class to assign to the element
150
+ top: 'auto', // center vertically
151
+ left: 'auto', // center horizontally
152
+ position: 'relative' // element position
153
+ }
154
+
155
+ /** The constructor */
156
+ function Spinner(o) {
157
+ if (typeof this == 'undefined') return new Spinner(o)
158
+ this.opts = merge(o || {}, Spinner.defaults, defaults)
159
+ }
160
+
161
+ // Global defaults that override the built-ins:
162
+ Spinner.defaults = {}
163
+
164
+ merge(Spinner.prototype, {
165
+
166
+ /**
167
+ * Adds the spinner to the given target element. If this instance is already
168
+ * spinning, it is automatically removed from its previous target b calling
169
+ * stop() internally.
170
+ */
171
+ spin: function(target) {
172
+ this.stop()
173
+
174
+ var self = this
175
+ , o = self.opts
176
+ , el = self.el = css(createEl(0, {className: o.className}), {position: o.position, width: 0, zIndex: o.zIndex})
177
+ , mid = o.radius+o.length+o.width
178
+ , ep // element position
179
+ , tp // target position
180
+
181
+ if (target) {
182
+ target.insertBefore(el, target.firstChild||null)
183
+ tp = pos(target)
184
+ ep = pos(el)
185
+ css(el, {
186
+ left: (o.left == 'auto' ? tp.x-ep.x + (target.offsetWidth >> 1) : parseInt(o.left, 10) + mid) + 'px',
187
+ top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid) + 'px'
188
+ })
189
+ }
190
+
191
+ el.setAttribute('role', 'progressbar')
192
+ self.lines(el, self.opts)
193
+
194
+ if (!useCssAnimations) {
195
+ // No CSS animation support, use setTimeout() instead
196
+ var i = 0
197
+ , start = (o.lines - 1) * (1 - o.direction) / 2
198
+ , alpha
199
+ , fps = o.fps
200
+ , f = fps/o.speed
201
+ , ostep = (1-o.opacity) / (f*o.trail / 100)
202
+ , astep = f/o.lines
203
+
204
+ ;(function anim() {
205
+ i++;
206
+ for (var j = 0; j < o.lines; j++) {
207
+ alpha = Math.max(1 - (i + (o.lines - j) * astep) % f * ostep, o.opacity)
208
+
209
+ self.opacity(el, j * o.direction + start, alpha, o)
210
+ }
211
+ self.timeout = self.el && setTimeout(anim, ~~(1000/fps))
212
+ })()
213
+ }
214
+ return self
215
+ },
216
+
217
+ /**
218
+ * Stops and removes the Spinner.
219
+ */
220
+ stop: function() {
221
+ var el = this.el
222
+ if (el) {
223
+ clearTimeout(this.timeout)
224
+ if (el.parentNode) el.parentNode.removeChild(el)
225
+ this.el = undefined
226
+ }
227
+ return this
228
+ },
229
+
230
+ /**
231
+ * Internal method that draws the individual lines. Will be overwritten
232
+ * in VML fallback mode below.
233
+ */
234
+ lines: function(el, o) {
235
+ var i = 0
236
+ , start = (o.lines - 1) * (1 - o.direction) / 2
237
+ , seg
238
+
239
+ function fill(color, shadow) {
240
+ return css(createEl(), {
241
+ position: 'absolute',
242
+ width: (o.length+o.width) + 'px',
243
+ height: o.width + 'px',
244
+ background: color,
245
+ boxShadow: shadow,
246
+ transformOrigin: 'left',
247
+ transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)',
248
+ borderRadius: (o.corners * o.width>>1) + 'px'
249
+ })
250
+ }
251
+
252
+ for (; i < o.lines; i++) {
253
+ seg = css(createEl(), {
254
+ position: 'absolute',
255
+ top: 1+~(o.width/2) + 'px',
256
+ transform: o.hwaccel ? 'translate3d(0,0,0)' : '',
257
+ opacity: o.opacity,
258
+ animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite'
259
+ })
260
+
261
+ if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'}))
262
+
263
+ ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)')))
264
+ }
265
+ return el
266
+ },
267
+
268
+ /**
269
+ * Internal method that adjusts the opacity of a single line.
270
+ * Will be overwritten in VML fallback mode below.
271
+ */
272
+ opacity: function(el, i, val) {
273
+ if (i < el.childNodes.length) el.childNodes[i].style.opacity = val
274
+ }
275
+
276
+ })
277
+
278
+
279
+ function initVML() {
280
+
281
+ /* Utility function to create a VML tag */
282
+ function vml(tag, attr) {
283
+ return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr)
284
+ }
285
+
286
+ // No CSS transforms but VML support, add a CSS rule for VML elements:
287
+ sheet.addRule('.spin-vml', 'behavior:url(#default#VML)')
288
+
289
+ Spinner.prototype.lines = function(el, o) {
290
+ var r = o.length+o.width
291
+ , s = 2*r
292
+
293
+ function grp() {
294
+ return css(
295
+ vml('group', {
296
+ coordsize: s + ' ' + s,
297
+ coordorigin: -r + ' ' + -r
298
+ }),
299
+ { width: s, height: s }
300
+ )
301
+ }
302
+
303
+ var margin = -(o.width+o.length)*2 + 'px'
304
+ , g = css(grp(), {position: 'absolute', top: margin, left: margin})
305
+ , i
306
+
307
+ function seg(i, dx, filter) {
308
+ ins(g,
309
+ ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}),
310
+ ins(css(vml('roundrect', {arcsize: o.corners}), {
311
+ width: r,
312
+ height: o.width,
313
+ left: o.radius,
314
+ top: -o.width>>1,
315
+ filter: filter
316
+ }),
317
+ vml('fill', {color: o.color, opacity: o.opacity}),
318
+ vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change
319
+ )
320
+ )
321
+ )
322
+ }
323
+
324
+ if (o.shadow)
325
+ for (i = 1; i <= o.lines; i++)
326
+ seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)')
327
+
328
+ for (i = 1; i <= o.lines; i++) seg(i)
329
+ return ins(el, g)
330
+ }
331
+
332
+ Spinner.prototype.opacity = function(el, i, val, o) {
333
+ var c = el.firstChild
334
+ o = o.shadow && o.lines || 0
335
+ if (c && i+o < c.childNodes.length) {
336
+ c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild
337
+ if (c) c.opacity = val
338
+ }
339
+ }
340
+ }
341
+
342
+ var probe = css(createEl('group'), {behavior: 'url(#default#VML)'})
343
+
344
+ if (!vendor(probe, 'transform') && probe.adj) initVML()
345
+ else useCssAnimations = vendor(probe, 'animation')
346
+
347
+ return Spinner
348
+
349
+ }));
class.jetpack-client-server.php ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Client = Plugin
5
+ * Client Server = API Methods the Plugin must respond to
6
+ *
7
+ * @todo Roll this into Jetpack? There's only one 'public' method now: ::authorize().
8
+ */
9
+ class Jetpack_Client_Server {
10
+ function authorize() {
11
+ $data = stripslashes_deep( $_GET );
12
+
13
+ $args = array();
14
+
15
+ $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
16
+
17
+ do {
18
+ $jetpack = Jetpack::init();
19
+ $role = $jetpack->translate_current_user_to_role();
20
+ if ( !$role ) {
21
+ Jetpack::state( 'error', 'no_role' );
22
+ break;
23
+ }
24
+
25
+ $cap = $jetpack->translate_role_to_cap( $role );
26
+ if ( !$cap ) {
27
+ Jetpack::state( 'error', 'no_cap' );
28
+ break;
29
+ }
30
+
31
+ check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
32
+
33
+ if ( !empty( $data['error'] ) ) {
34
+ Jetpack::state( 'error', $data['error'] );
35
+ break;
36
+ }
37
+
38
+ if ( empty( $data['state'] ) ) {
39
+ Jetpack::state( 'error', 'no_state' );
40
+ break;
41
+ }
42
+
43
+ if ( !ctype_digit( $data['state'] ) ) {
44
+ Jetpack::state( 'error', 'invalid_state' );
45
+ break;
46
+ }
47
+
48
+ $current_user_id = get_current_user_id();
49
+ if ( $current_user_id != $data['state'] ) {
50
+ Jetpack::state( 'error', 'wrong_state' );
51
+ break;
52
+ }
53
+
54
+ if ( empty( $data['code'] ) ) {
55
+ Jetpack::state( 'error', 'no_code' );
56
+ break;
57
+ }
58
+
59
+ $token = $this->get_token( $data );
60
+
61
+ if ( is_wp_error( $token ) ) {
62
+ if ( $error = $token->get_error_code() )
63
+ Jetpack::state( 'error', $error );
64
+ else
65
+ Jetpack::state( 'error', 'invalid_token' );
66
+
67
+ Jetpack::state( 'error_description', $token->get_error_message() );
68
+
69
+ break;
70
+ }
71
+
72
+ if ( !$token ) {
73
+ Jetpack::state( 'error', 'no_token' );
74
+ break;
75
+ }
76
+
77
+ $is_master_user = ! Jetpack::is_active();
78
+
79
+ Jetpack::update_user_token( $current_user_id, sprintf( '%s.%d', $token, $current_user_id ), $is_master_user );
80
+
81
+
82
+ if ( $is_master_user ) {
83
+ Jetpack::state( 'message', 'authorized' );
84
+ } else {
85
+ Jetpack::state( 'message', 'linked' );
86
+ // Don't activate anything since we are just connecting a user.
87
+ break;
88
+ }
89
+
90
+ if ( $active_modules = Jetpack::get_option( 'active_modules' ) ) {
91
+ Jetpack::delete_option( 'active_modules' );
92
+
93
+ Jetpack::activate_default_modules( 999, 1, $active_modules );
94
+ } else {
95
+ Jetpack::activate_default_modules();
96
+ }
97
+
98
+ $jetpack->sync->register( 'noop' ); // Spawn a sync to make sure the Jetpack Servers know what modules are active.
99
+
100
+ // Start nonce cleaner
101
+ wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
102
+ wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
103
+ } while ( false );
104
+
105
+ if ( wp_validate_redirect( $redirect ) ) {
106
+ wp_safe_redirect( $redirect );
107
+ } else {
108
+ wp_safe_redirect( Jetpack::admin_url() );
109
+ }
110
+
111
+ exit;
112
+ }
113
+
114
+ public static function deactivate_plugin( $probable_file, $probable_title ) {
115
+ if ( is_plugin_active( $probable_file ) ) {
116
+ deactivate_plugins( $probable_file );
117
+ return 1;
118
+ } else {
119
+ // If the plugin is not in the usual place, try looking through all active plugins.
120
+ $active_plugins = get_option( 'active_plugins', array() );
121
+ foreach ( $active_plugins as $plugin ) {
122
+ $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
123
+ if ( $data['Name'] == $probable_title ) {
124
+ deactivate_plugins( $plugin );
125
+ return 1;
126
+ }
127
+ }
128
+ }
129
+
130
+ return 0;
131
+ }
132
+
133
+ /**
134
+ * @return object|WP_Error
135
+ */
136
+ function get_token( $data ) {
137
+ $jetpack = Jetpack::init();
138
+ $role = $jetpack->translate_current_user_to_role();
139
+
140
+ if ( !$role ) {
141
+ return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
142
+ }
143
+
144
+ $client_secret = Jetpack_Data::get_access_token();
145
+ if ( !$client_secret ) {
146
+ return new Jetpack_Error( 'client_secret', __( 'You need to register your Jetpack before connecting it.', 'jetpack' ) );
147
+ }
148
+
149
+ $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
150
+
151
+ $body = array(
152
+ 'client_id' => Jetpack::get_option( 'id' ),
153
+ 'client_secret' => $client_secret->secret,
154
+ 'grant_type' => 'authorization_code',
155
+ 'code' => $data['code'],
156
+ 'redirect_uri' => add_query_arg( array(
157
+ 'action' => 'authorize',
158
+ '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
159
+ 'redirect' => $redirect ? urlencode( $redirect ) : false,
160
+ ), menu_page_url( 'jetpack', false ) ),
161
+ );
162
+
163
+ $args = array(
164
+ 'method' => 'POST',
165
+ 'body' => $body,
166
+ 'headers' => array(
167
+ 'Accept' => 'application/json',
168
+ ),
169
+ );
170
+ $response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'token' ), $args ), $args );
171
+
172
+ if ( is_wp_error( $response ) ) {
173
+ return new Jetpack_Error( 'token_http_request_failed', $response->get_error_message() );
174
+ }
175
+
176
+ $code = wp_remote_retrieve_response_code( $response );
177
+ $entity = wp_remote_retrieve_body( $response );
178
+
179
+ if ( $entity )
180
+ $json = json_decode( $entity );
181
+ else
182
+ $json = false;
183
+
184
+ if ( 200 != $code || !empty( $json->error ) ) {
185
+ if ( empty( $json->error ) )
186
+ return new Jetpack_Error( 'unknown', '', $code );
187
+
188
+ $error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
189
+
190
+ return new Jetpack_Error( (string) $json->error, $error_description, $code );
191
+ }
192
+
193
+ if ( empty( $json->access_token ) || !is_scalar( $json->access_token ) ) {
194
+ return new Jetpack_Error( 'access_token', '', $code );
195
+ }
196
+
197
+ if ( empty( $json->token_type ) || 'X_JETPACK' != strtoupper( $json->token_type ) ) {
198
+ return new Jetpack_Error( 'token_type', '', $code );
199
+ }
200
+
201
+ if ( empty( $json->scope ) ) {
202
+ return new Jetpack_Error( 'scope', 'No Scope', $code );
203
+ }
204
+ @list( $role, $hmac ) = explode( ':', $json->scope );
205
+ if ( empty( $role ) || empty( $hmac ) ) {
206
+ return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
207
+ }
208
+ if ( $jetpack->sign_role( $role ) !== $json->scope ) {
209
+ return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
210
+ }
211
+
212
+ if ( !$cap = $jetpack->translate_role_to_cap( $role ) )
213
+ return new Jetpack_Error( 'scope', 'No Cap', $code );
214
+ if ( !current_user_can( $cap ) )
215
+ return new Jetpack_Error( 'scope', 'current_user_cannot', $code );
216
+
217
+ return (string) $json->access_token;
218
+ }
219
+ }
class.jetpack-client.php ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Jetpack_Client {
4
+ /**
5
+ * Makes an authorized remote request using Jetpack_Signature
6
+ *
7
+ * @return array|WP_Error WP HTTP response on success
8
+ */
9
+ public static function remote_request( $args, $body = null ) {
10
+ $defaults = array(
11
+ 'url' => '',
12
+ 'user_id' => 0,
13
+ 'blog_id' => 0,
14
+ 'auth_location' => JETPACK_CLIENT__AUTH_LOCATION,
15
+ 'method' => 'POST',
16
+ 'timeout' => 10,
17
+ 'redirection' => 0,
18
+ );
19
+
20
+ $args = wp_parse_args( $args, $defaults );
21
+
22
+ $args['blog_id'] = (int) $args['blog_id'];
23
+
24
+ if ( 'header' != $args['auth_location'] ) {
25
+ $args['auth_location'] = 'query_string';
26
+ }
27
+
28
+ $token = Jetpack_Data::get_access_token( $args['user_id'] );
29
+ if ( !$token ) {
30
+ return new Jetpack_Error( 'missing_token' );
31
+ }
32
+
33
+ $method = strtoupper( $args['method'] );
34
+
35
+ $timeout = intval( $args['timeout'] );
36
+
37
+ $redirection = $args['redirection'];
38
+
39
+ $request = compact( 'method', 'body', 'timeout', 'redirection' );
40
+
41
+ @list( $token_key, $secret ) = explode( '.', $token->secret );
42
+ if ( empty( $token ) || empty( $secret ) ) {
43
+ return new Jetpack_Error( 'malformed_token' );
44
+ }
45
+
46
+ $token_key = sprintf( '%s:%d:%d', $token_key, JETPACK__API_VERSION, $token->external_user_id );
47
+
48
+ require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
49
+
50
+ $time_diff = (int) Jetpack::get_option( 'time_diff' );
51
+ $jetpack_signature = new Jetpack_Signature( $token->secret, $time_diff );
52
+
53
+ $timestamp = time() + $time_diff;
54
+ $nonce = wp_generate_password( 10, false );
55
+
56
+ // Kind of annoying. Maybe refactor Jetpack_Signature to handle body-hashing
57
+ if ( is_null( $body ) ) {
58
+ $body_hash = '';
59
+ } else {
60
+ if ( !is_string( $body ) ) {
61
+ return new Jetpack_Error( 'invalid_body', 'Body is malformed.' );
62
+ }
63
+ $body_hash = jetpack_sha1_base64( $body );
64
+ }
65
+
66
+ $auth = array(
67
+ 'token' => $token_key,
68
+ 'timestamp' => $timestamp,
69
+ 'nonce' => $nonce,
70
+ 'body-hash' => $body_hash,
71
+ );
72
+
73
+ if ( false !== strpos( $args['url'], 'xmlrpc.php' ) ) {
74
+ $url_args = array(
75
+ 'for' => 'jetpack',
76
+ 'blog_id' => $args['blog_id'],
77
+ );
78
+ } else {
79
+ $url_args = array();
80
+ }
81
+
82
+ if ( 'header' != $args['auth_location'] ) {
83
+ $url_args += $auth;
84
+ }
85
+
86
+ $url = add_query_arg( urlencode_deep( $url_args ), $args['url'] );
87
+ $url = Jetpack::fix_url_for_bad_hosts( $url, $request );
88
+
89
+ $signature = $jetpack_signature->sign_request( $token_key, $timestamp, $nonce, $body_hash, $method, $url, $body, false );
90
+
91
+ if ( !$signature || is_wp_error( $signature ) ) {
92
+ return $signature;
93
+ }
94
+
95
+ // Send an Authorization header so various caches/proxies do the right thing
96
+ $auth['signature'] = $signature;
97
+ $auth['version'] = JETPACK__VERSION;
98
+ $header_pieces = array();
99
+ foreach ( $auth as $key => $value ) {
100
+ $header_pieces[] = sprintf( '%s="%s"', $key, $value );
101
+ }
102
+ $request['headers'] = array(
103
+ 'Authorization' => "X_JETPACK " . join( ' ', $header_pieces ),
104
+ );
105
+
106
+ if ( 'header' != $args['auth_location'] ) {
107
+ $url = add_query_arg( 'signature', urlencode( $signature ), $url );
108
+ }
109
+
110
+ return Jetpack_Client::_wp_remote_request( $url, $request );
111
+ }
112
+
113
+ /**
114
+ * Wrapper for wp_remote_request(). Turns off SSL verification for certain SSL errors.
115
+ * This is lame, but many, many, many hosts have misconfigured SSL.
116
+ *
117
+ * When Jetpack is registered, the jetpack_fallback_no_verify_ssl_certs option is set to the current time if:
118
+ * 1. a certificate error is found AND
119
+ * 2. not verifying the certificate works around the problem.
120
+ *
121
+ * The option is checked on each request.
122
+ *
123
+ * @internal
124
+ * @todo: Better fallbacks (bundled certs?), feedback, UI, ....
125
+ * @see Jetpack::fix_url_for_bad_hosts()
126
+ *
127
+ * @return array|WP_Error WP HTTP response on success
128
+ */
129
+ public static function _wp_remote_request( $url, $args, $set_fallback = false ) {
130
+ $fallback = Jetpack::get_option( 'fallback_no_verify_ssl_certs' );
131
+ if ( false === $fallback ) {
132
+ Jetpack::update_option( 'fallback_no_verify_ssl_certs', 0 );
133
+ }
134
+
135
+ if ( (int) $fallback ) {
136
+ // We're flagged to fallback
137
+ $args['sslverify'] = false;
138
+ }
139
+
140
+ $response = wp_remote_request( $url, $args );
141
+
142
+ if (
143
+ !$set_fallback // We're not allowed to set the flag on this request, so whatever happens happens
144
+ ||
145
+ isset( $args['sslverify'] ) && !$args['sslverify'] // No verification - no point in doing it again
146
+ ||
147
+ !is_wp_error( $response ) // Let it ride
148
+ ) {
149
+ Jetpack_Client::set_time_diff( $response, $set_fallback );
150
+ return $response;
151
+ }
152
+
153
+ // At this point, we're not flagged to fallback and we are allowed to set the flag on this request.
154
+
155
+ $message = $response->get_error_message();
156
+
157
+ // Is it an SSL Certificate verification error?
158
+ if (
159
+ false === strpos( $message, '14090086' ) // OpenSSL SSL3 certificate error
160
+ &&
161
+ false === strpos( $message, '1407E086' ) // OpenSSL SSL2 certificate error
162
+ &&
163
+ false === strpos( $message, 'error setting certificate verify locations' ) // cURL CA bundle not found
164
+ &&
165
+ false === strpos( $message, 'Peer certificate cannot be authenticated with' ) // cURL CURLE_SSL_CACERT: CA bundle found, but not helpful
166
+ // different versions of curl have different error messages
167
+ // this string should catch them all
168
+ &&
169
+ false === strpos( $message, 'Problem with the SSL CA cert' ) // cURL CURLE_SSL_CACERT_BADFILE: probably access rights
170
+ ) {
171
+ // No, it is not.
172
+ return $response;
173
+ }
174
+
175
+ // Redo the request without SSL certificate verification.
176
+ $args['sslverify'] = false;
177
+ $response = wp_remote_request( $url, $args );
178
+
179
+ if ( !is_wp_error( $response ) ) {
180
+ // The request went through this time, flag for future fallbacks
181
+ Jetpack::update_option( 'fallback_no_verify_ssl_certs', time() );
182
+ Jetpack_Client::set_time_diff( $response, $set_fallback );
183
+ }
184
+
185
+ return $response;
186
+ }
187
+
188
+ public static function set_time_diff( &$response, $force_set = false ) {
189
+ $code = wp_remote_retrieve_response_code( $response );
190
+
191
+ // Only trust the Date header on some responses
192
+ if ( 200 != $code && 304 != $code && 400 != $code && 401 != $code ) {
193
+ return;
194
+ }
195
+
196
+ if ( !$date = wp_remote_retrieve_header( $response, 'date' ) ) {
197
+ return;
198
+ }
199
+
200
+ if ( 0 >= $time = (int) strtotime( $date ) ) {
201
+ return;
202
+ }
203
+
204
+ $time_diff = $time - time();
205
+
206
+ if ( $force_set ) { // during register
207
+ Jetpack::update_option( 'time_diff', $time_diff );
208
+ } else { // otherwise
209
+ $old_diff = Jetpack::get_option( 'time_diff' );
210
+ if ( false === $old_diff || abs( $time_diff - (int) $old_diff ) > 10 ) {
211
+ Jetpack::update_option( 'time_diff', $time_diff );
212
+ }
213
+ }
214
+ }
215
+ }
class.jetpack-data.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Jetpack_Data {
4
+ /**
5
+ * Gets locally stored token
6
+ *
7
+ * @return object|false
8
+ */
9
+ public static function get_access_token( $user_id = false ) {
10
+ if ( $user_id ) {
11
+ if ( !$tokens = Jetpack::get_option( 'user_tokens' ) ) {
12
+ return false;
13
+ }
14
+ if ( $user_id === JETPACK_MASTER_USER ) {
15
+ if ( !$user_id = Jetpack::get_option( 'master_user' ) ) {
16
+ return false;
17
+ }
18
+ }
19
+ if ( !isset( $tokens[$user_id] ) || !$token = $tokens[$user_id] ) {
20
+ return false;
21
+ }
22
+ $token_chunks = explode( '.', $token );
23
+ if ( empty( $token_chunks[1] ) || empty( $token_chunks[2] ) ) {
24
+ return false;
25
+ }
26
+ if ( $user_id != $token_chunks[2] ) {
27
+ return false;
28
+ }
29
+ $token = "{$token_chunks[0]}.{$token_chunks[1]}";
30
+ } else {
31
+ $token = Jetpack::get_option( 'blog_token' );
32
+ if ( empty( $token ) ) {
33
+ return false;
34
+ }
35
+ }
36
+
37
+ return (object) array(
38
+ 'secret' => $token,
39
+ 'external_user_id' => (int) $user_id,
40
+ );
41
+ }
42
+ }
class.jetpack-debugger.php ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function is_jetpack_support_open() {
4
+ try {
5
+ $response = wp_remote_request( "http://jetpack.me/is-support-open" );
6
+ $body = wp_remote_retrieve_body( $response );
7
+ $json = json_decode( $body );
8
+ return ( ( bool )$json->is_support_open );
9
+ }
10
+ catch ( Exception $e ) {
11
+ return true;
12
+ }
13
+ }
14
+
15
+ function jetpack_increase_timeout($time) {
16
+ $time = 20; //seconds
17
+ return $time;
18
+ }
19
+
20
+
21
+ function jetpack_debug_display_handler() {
22
+ if ( ! current_user_can( 'manage_options' ) )
23
+ wp_die( esc_html__('You do not have sufficient permissions to access this page.', 'jetpack' ) );
24
+
25
+ global $current_user;
26
+ get_currentuserinfo();
27
+
28
+ $user_id = get_current_user_id();
29
+ $user_tokens = Jetpack::get_option( 'user_tokens' );
30
+ if ( is_array( $user_tokens ) && array_key_exists( $user_id, $user_tokens ) ) {
31
+ $user_token = $user_tokens[$user_id];
32
+ } else {
33
+ $user_token = '[this user has no token]';
34
+ }
35
+ unset( $user_tokens );
36
+
37
+ $debug_info = "\r\n";
38
+ foreach ( array(
39
+ 'CLIENT_ID' => 'id',
40
+ 'BLOG_TOKEN' => 'blog_token',
41
+ 'MASTER_USER' => 'master_user',
42
+ 'CERT' => 'fallback_no_verify_ssl_certs',
43
+ 'TIME_DIFF' => 'time_diff',
44
+ 'VERSION' => 'version',
45
+ 'OLD_VERSION' => 'old_version',
46
+ 'PUBLIC' => 'public',
47
+ ) as $label => $option_name ) {
48
+ $debug_info .= "\r\n" . esc_html( $label . ": " . Jetpack::get_option( $option_name ) );
49
+ }
50
+
51
+ $debug_info .= "\r\n" . esc_html( "USER_ID: " . $user_id );
52
+ $debug_info .= "\r\n" . esc_html( "USER_TOKEN: " . $user_token );
53
+ $debug_info .= "\r\n" . esc_html( "PHP_VERSION: " . PHP_VERSION );
54
+ $debug_info .= "\r\n" . esc_html( "WORDPRESS_VERSION: " . $GLOBALS['wp_version'] );
55
+ $debug_info .= "\r\n" . esc_html( "JETPACK__VERSION: " . JETPACK__VERSION );
56
+ $debug_info .= "\r\n" . esc_html( "JETPACK__PLUGIN_DIR: " . JETPACK__PLUGIN_DIR );
57
+ $debug_info .= "\r\n" . esc_html( "SITE_URL: " . site_url() );
58
+ $debug_info .= "\r\n" . esc_html( "HOME_URL: " . home_url() );
59
+
60
+ $debug_info .= "\r\n\r\nTEST RESULTS:\r\n\r\n";
61
+ $debug_raw_info = '';
62
+
63
+
64
+ $tests = array();
65
+
66
+ $tests['HTTP']['result'] = wp_remote_get( preg_replace( '/^https:/', 'http:', JETPACK__API_BASE ) . 'test/1/' );
67
+ $tests['HTTP']['fail_message'] = esc_html__( 'Your site isn’t reaching the Jetpack servers.', 'jetpack' );
68
+
69
+ $tests['HTTPS']['result'] = wp_remote_get( preg_replace( '/^http:/', 'https:', JETPACK__API_BASE ) . 'test/1/' );
70
+ $tests['HTTPS']['fail_message'] = esc_html__( 'Your site isn’t securely reaching the Jetpack servers.', 'jetpack' );
71
+
72
+
73
+ $self_xml_rpc_url = site_url( 'xmlrpc.php' );
74
+
75
+ $args = array();
76
+ $testsite_url = Jetpack::fix_url_for_bad_hosts( JETPACK__API_BASE . 'testsite/1/?url=', $args );
77
+
78
+ add_filter( 'http_request_timeout', 'jetpack_increase_timeout' );
79
+
80
+ $tests['SELF']['result'] = wp_remote_get( $testsite_url . $self_xml_rpc_url );
81
+ $tests['SELF']['fail_message'] = esc_html__( 'It looks like your site can not communicate properly with Jetpack.', 'jetpack' );
82
+
83
+ remove_filter( 'http_request_timeout', 'jetpack_increase_timeout' );
84
+
85
+ ?>
86
+ <div class="wrap">
87
+ <h2><?php esc_html_e( 'Jetpack Debugging Center', 'jetpack' ); ?></h2>
88
+ <h3><?php _e( "Testing your site's compatibily with Jetpack...", 'jetpack' ); ?></h3>
89
+ <div class="jetpack-debug-test-container">
90
+ <?php
91
+ ob_start();
92
+ foreach ( $tests as $test_name => $test_info ) :
93
+ if ( is_wp_error( $test_info['result'] ) ||
94
+ false == ( $response_code = wp_remote_retrieve_response_code( $test_info['result'] ) ) ||
95
+ '200' != $response_code ) {
96
+ $debug_info .= $test_name . ": FAIL\r\n";
97
+ ?>
98
+ <div class="jetpack-test-error">
99
+ <p>
100
+ <a class="jetpack-test-heading" href="#"><?php echo $test_info['fail_message']; ?>
101
+ <span class="noticon noticon-collapse"></span>
102
+ </a>
103
+ </p>
104
+ <pre class="jetpack-test-details"><?php esc_html_e( $test_name , 'jetpack'); ?>:
105
+ <?php esc_html_e( is_wp_error( $test_info['result'] ) ? $test_info['result']->get_error_message() : print_r( $test_info['result'], 1 ) ); ?></pre>
106
+ </div><?php
107
+ } else {
108
+ $debug_info .= $test_name . ": PASS\r\n";
109
+ }
110
+ $debug_raw_info .= "\r\n\r\n" . $test_name . "\r\n" . esc_html( print_r( $test_info['result'], 1 ) );
111
+ ?>
112
+ <?php endforeach;
113
+ $html = ob_get_clean();
114
+
115
+ if ( '' == trim( $html ) ) {
116
+ echo '<div class="jetpack-tests-succed">' . esc_html__( 'Your Jetpack setup looks a-okay!', 'jetpack' ) . '</div>';
117
+ }
118
+ else {
119
+ echo '<h3>' . esc_html__( 'There seems to be a problem with your site’s ability to communicate with Jetpack!', 'jetpack' ) . '</h3>';
120
+ echo $html;
121
+ }
122
+ $debug_info .= "\r\n\r\nRAW TEST RESULTS:" . $debug_raw_info ."\r\n";
123
+ ?>
124
+ </div>
125
+ <div class="entry-content">
126
+ <h3><?php esc_html_e( 'Trouble with Jetpack?', 'jetpack' ); ?></h3>
127
+ <h4><?php esc_html_e( 'It may be caused by one of these issues, which you can diagnose yourself:', 'jetpack' ); ?></h4>
128
+ <ol>
129
+ <li><b><em><?php esc_html_e( 'A known issue.', 'jetpack' ); ?></em></b> <?php echo sprintf( __( 'Some themes and plugins have <a href="%1$s" target="_blank">known conflicts</a> with Jetpack – check the <a href="%2$s" target="_blank">list</a>. (You can also browse the <a href="%3$s">Jetpack support pages</a> or <a href="%4$s">Jetpack support forum</a> to see if others have experienced and solved the problem.)', 'jetpack' ), 'http://jetpack.me/known-issues/', 'http://jetpack.me/known-issues/', 'http://jetpack.me/support/', 'http://wordpress.org/support/plugin/jetpack' ); ?></li>
130
+ <li><b><em><?php esc_html_e( 'An incompatible plugin.', 'jetpack' ); ?></em></b> <?php esc_html_e( "Find out by disabling all plugins except Jetpack. If the problem persists, it's not a plugin issue. If the problem is solved, turn your plugins on one by one until the problem pops up again – there's the culprit! Let us know, and we'll try to help.", 'jetpack' ); ?></li>
131
+ <li><b><em><?php esc_html_e( 'A theme conflict.', 'jetpack' ); ?></em></b> <?php esc_html_e( "If your problem isn't known or caused by a plugin, try activating Twenty Twelve (the default WordPress theme). If this solves the problem, something in your theme is probably broken – let the theme's author know.", 'jetpack' ); ?></li>
132
+ <li><b><em><?php esc_html_e( 'A problem with your XMLRPC file.', 'jetpack' ); ?></em></b> <?php echo sprintf( __( 'Load your <a href="%s">XMLRPC file</a>. It should say “XML-RPC server accepts POST requests only.” on a line by itself.', 'jetpack' ), site_url( 'xmlrpc.php' ) ); ?>
133
+ <ul>
134
+ <li>- <?php esc_html_e( "If it's not by itself, a theme or plugin is displaying extra characters. Try steps 2 and 3.", 'jetpack' ); ?></li>
135
+ <li>- <?php esc_html_e( "If you get a 404 message, contact your web host. Their security may block XMLRPC.", 'jetpack' ); ?></li>
136
+ </ul>
137
+ </li>
138
+ </ol>
139
+ <p class="jetpack-show-contact-form"><?php _e( 'If none of these help you find a solution, <a href="#">click here to contact Jetpack support</a>. Tell us as much as you can about the issue and what steps you\'ve tried to resolve it, and one of our Happiness Engineers will be in touch to help.', 'jetpack' ); ?>
140
+ </p>
141
+ </div>
142
+ <div id="contact-message" style="display:none">
143
+ <?php if ( is_jetpack_support_open() ): ?>
144
+ <form id="contactme" method="post" action="http://jetpack.me/contact-support/">
145
+ <input type="hidden" name="action" value="submit">
146
+ <input type="hidden" name="jetpack" value="needs-service">
147
+
148
+ <input type="hidden" name="contact_form" id="contact_form" value="1">
149
+ <input type="hidden" name="blog_url" id="blog_url" value="<?php echo esc_attr( site_url() ); ?>">
150
+ <input type="hidden" name="subject" id="subject" value="from: <?php echo esc_attr( site_url() ); ?> Jetpack contact form">
151
+ <div class="formbox">
152
+ <label for="message" class="h"><?php esc_html_e( 'Please describe the problem you are having.', 'jetpack' ); ?></label>
153
+ <textarea name="message" cols="40" rows="7" id="did"></textarea>
154
+ </div>
155
+
156
+ <div id="name_div" class="formbox">
157
+ <label class="h" for="your_name"><?php esc_html_e( 'Name', 'jetpack' ); ?></label>
158
+ <span class="errormsg"><?php esc_html_e( 'Let us know your name.', 'jetpack' ); ?></span>
159
+ <input name="your_name" type="text" id="your_name" value="<?php esc_html_e( $current_user->display_name , 'jetpack'); ?>" size="40">
160
+ </div>
161
+
162
+ <div id="email_div" class="formbox">
163
+ <label class="h" for="your_email"><?php esc_html_e( 'E-mail', 'jetpack' ); ?></label>
164
+ <span class="errormsg"><?php esc_html_e( 'Use a valid email address.', 'jetpack' ); ?></span>
165
+ <input name="your_email" type="text" id="your_email" value="<?php esc_html_e( $current_user->user_email , 'jetpack'); ?>" size="40">
166
+ </div>
167
+
168
+ <div id="toggle_debug_info" class="formbox">
169
+ <p><?php _e( 'The test results and some other useful debug information will be sent to the support team. Please feel free to <a href="#">review/modify</a> this information.', 'jetpack' ); ?></p>
170
+ </div>
171
+
172
+ <div id="debug_info_div" class="formbox" style="display:none">
173
+ <label class="h" for="debug_info"><?php esc_html_e( 'Debug Info', 'jetpack' ); ?></label>
174
+ <textarea name="debug_info" cols="40" rows="7" id="debug_info"><?php echo esc_attr( $debug_info ); ?></textarea>
175
+ </div>
176
+
177
+ <div style="clear: both;"></div>
178
+
179
+ <div id="blog_div" class="formbox">
180
+ <div id="submit_div" class="contact-support">
181
+ <input type="submit" name="submit" value="Contact Support">
182
+ </div>
183
+ </div>
184
+ <div style="clear: both;"></div>
185
+ </form>
186
+ <?php endif; ?>
187
+ </div>
188
+ </div>
189
+ <?php
190
+ }
191
+
192
+ function jetpack_debug_admin_head() {
193
+ ?>
194
+ <style type="text/css">
195
+
196
+ .jetpack-debug-test-container {
197
+ margin-top: 20px;
198
+ margin-bottom: 30px;
199
+ }
200
+
201
+ .jetpack-tests-succed {
202
+ font-size: large;
203
+ color: #8BAB3E;
204
+ }
205
+
206
+ .jetpack-test-details {
207
+ margin: 4px 6px;
208
+ padding: 10px;
209
+ overflow: auto;
210
+ display: none;
211
+ }
212
+
213
+ .jetpack-test-error {
214
+ margin-bottom: 10px;
215
+ background: #FFEBE8;
216
+ border: solid 1px #C00;
217
+ border-radius: 3px;
218
+ }
219
+
220
+ .jetpack-test-error p {
221
+ margin: 0;
222
+ padding: 0;
223
+ }
224
+
225
+ .jetpack-test-error a.jetpack-test-heading {
226
+ padding: 4px 6px;
227
+ display: block;
228
+ text-decoration: none;
229
+ color: inherit;
230
+ }
231
+
232
+ .jetpack-test-error .noticon {
233
+ float: right;
234
+ }
235
+
236
+ form#contactme {
237
+ border: 1px solid #dfdfdf;
238
+ background: #eaf3fa;
239
+ padding: 20px;
240
+ margin: 10px;
241
+ background-color: #eaf3fa;
242
+ border-radius: 5px;
243
+ font-size: 15px;
244
+ font-family: "Open Sans", "Helvetica Neue", sans-serif;
245
+ }
246
+
247
+ form#contactme label.h {
248
+ color: #444;
249
+ display: block;
250
+ font-weight: bold;
251
+ margin: 0 0 7px 10px;
252
+ text-shadow: 1px 1px 0 #fff;
253
+ }
254
+
255
+ .formbox {
256
+ margin: 0 0 25px 0;
257
+ }
258
+
259
+ .formbox input[type="text"], .formbox input[type="email"], .formbox input[type="url"], .formbox textarea {
260
+ border: 1px solid #e5e5e5;
261
+ border-radius: 11px;
262
+ box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);
263
+ color: #666;
264
+ font-size: 14px;
265
+ padding: 10px;
266
+ width: 97%;
267
+ }
268
+ .formbox .contact-support input[type="submit"] {
269
+ float: right;
270
+ margin: 0 !important;
271
+ border-radius: 20px !important;
272
+ cursor: pointer;
273
+ font-size: 13pt !important;
274
+ height: auto !important;
275
+ margin: 0 0 2em 10px !important;
276
+ padding: 8px 16px !important;
277
+ background-color: #ddd;
278
+ border: 1px solid rgba(0,0,0,0.05);
279
+ border-top-color: rgba(255,255,255,0.1);
280
+ border-bottom-color: rgba(0,0,0,0.15);
281
+ color: #333;
282
+ font-weight: 400;
283
+ display: inline-block;
284
+ text-align: center;
285
+ text-decoration: none;
286
+ }
287
+
288
+ .formbox span.errormsg {
289
+ margin: 0 0 10px 10px;
290
+ color: #d00;
291
+ display: none;
292
+ }
293
+
294
+ .formbox.error span.errormsg {
295
+ display: block;
296
+ }
297
+
298
+ #contact-message ul {
299
+ margin: 0 0 20px 10px;
300
+ }
301
+
302
+ #contact-message li {
303
+ margin: 0 0 10px 10px;
304
+ list-style: disc;
305
+ display: list-item;
306
+ }
307
+
308
+ </style>
309
+ <script type="text/javascript">
310
+ jQuery( document ).ready( function($) {
311
+
312
+ $('#debug_info').prepend('jQuery version: ' + jQuery.fn.jquery + "\r\n");
313
+
314
+ $( '.jetpack-test-error .jetpack-test-heading' ).on( 'click', function() {
315
+ $( this ).parents( '.jetpack-test-error' ).find( '.jetpack-test-details' ).slideToggle();
316
+ return false;
317
+ } );
318
+
319
+ $( '.jetpack-show-contact-form a' ).on( 'click', function() {
320
+ $('#contact-message').slideToggle();
321
+ return false;
322
+ } );
323
+
324
+ $( '#toggle_debug_info a' ).on( 'click', function() {
325
+ $('#debug_info_div').slideToggle();
326
+ return false;
327
+ } );
328
+
329
+ $('form#contactme').on("submit", function(e){
330
+ var form = $(this);
331
+ var message = form.find('#did');
332
+ var name = form.find('#your_name');
333
+ var email = form.find('#your_email')
334
+ var validation_error = false;
335
+ if( !name.val() ) {
336
+ name.parents('.formbox').addClass('error');
337
+ validation_error = true;
338
+ }
339
+ if( !email.val() ) {
340
+ email.parents('.formbox').addClass('error');
341
+ validation_error = true;
342
+ }
343
+ if ( validation_error ) {
344
+ return false;
345
+ }
346
+ message.val(message.val() + "\r\n\r\n----------------------------------------------\r\n\r\nDEBUG INFO:\r\n" + $('#debug_info').val() );
347
+ return true;
348
+ });
349
+
350
+ } );
351
+ </script>
352
+ <?php
353
+ }
class.jetpack-error.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+
3
+ class Jetpack_Error extends WP_Error {}
class.jetpack-heartbeat.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Jetpack_Heartbeat {
4
+
5
+ /**
6
+ * Holds the singleton instance of this class
7
+ *
8
+ * @since 2.3.3
9
+ * @var Jetpack_Heartbeat
10
+ */
11
+ static $instance = false;
12
+
13
+ private $cron_name = 'jetpack_heartbeat';
14
+
15
+ /**
16
+ * Singleton
17
+ *
18
+ * @since 2.3.3
19
+ * @static
20
+ * @return Jetpack_Heartbeat
21
+ */
22
+ public static function init() {
23
+ if ( ! self::$instance ) {
24
+ self::$instance = new Jetpack_Heartbeat;
25
+ }
26
+
27
+ return self::$instance;
28
+ }
29
+
30
+ /**
31
+ * Constructor for singleton
32
+ *
33
+ * @since 2.3.3
34
+ * @return Jetpack_Heartbeat
35
+ */
36
+ private function __construct() {
37
+ // Add weekly interval for wp-cron
38
+ add_filter('cron_schedules', array( $this, 'add_cron_intervals' ) );
39
+
40
+ // Schedule the task
41
+ add_action( $this->cron_name, array( $this, 'cron_exec' ) );
42
+
43
+ if (!wp_next_scheduled( $this->cron_name ) ) {
44
+ wp_schedule_event( time(), 'jetpack_weekly', $this->cron_name );
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Method that gets executed on the wp-cron call
50
+ *
51
+ * @since 2.3.3
52
+ * @global string $wp_version
53
+ */
54
+ public function cron_exec() {
55
+
56
+ /*
57
+ * Check for an identity crisis
58
+ *
59
+ * If one exists:
60
+ * - Bump stat for ID crisis
61
+ * - Email site admin about potential ID crisis
62
+ */
63
+
64
+
65
+
66
+ /**
67
+ * Setup an array of items that will eventually be stringified
68
+ * and sent off to the Jetpack API
69
+ *
70
+ * Associative array with format group => values
71
+ * - values should be an array that will be imploded to a string
72
+ */
73
+
74
+ $jetpack = Jetpack::init();
75
+
76
+ $jetpack->stat( 'active-modules', implode( ',', $this->jetpack->get_active_modules() ) );
77
+ $jetpack->stat( 'active', JETPACK__VERSION );
78
+ $jetpack->stat( 'wp-version', get_bloginfo( 'version' ) );
79
+ $jetpack->stat( 'php-version', PHP_VERSION );
80
+ $jetpack->stat( 'ssl', $jetpack->permit_ssl() );
81
+ $jetpack->stat( 'language', get_bloginfo( 'language' ) );
82
+ $jetpack->stat( 'charset', get_bloginfo( 'charset' ) );
83
+ $jetpack->stat( 'qty-posts', wp_count_posts()->publish );
84
+ $jetpack->stat( 'qty-pages', wp_count_posts( 'page' )->publish );
85
+ $jetpack->stat( 'qty-comments', wp_count_comments()->approved );
86
+ $jetpack->stat( 'is-multisite', is_multisite() ? 'multisite' : 'singlesite' );
87
+
88
+ // Only check a few plugins, to see if they're currently active.
89
+ $plugins_to_check = array(
90
+ 'vaultpress/vaultpress.php',
91
+ 'akismet/akismet.php',
92
+ 'wp-super-cache/wp-cache.php',
93
+ );
94
+ $plugins = array_intersect( $plugins_to_check, get_option( 'active_plugins', array() ) );
95
+ foreach( $plugins as $plugin ) {
96
+ $jetpack->stat( 'plugins', $plugin );
97
+ }
98
+
99
+ $jetpack->do_stats( 'server_side' );
100
+ }
101
+
102
+ /**
103
+ * Adds additional Jetpack specific intervals to wp-cron
104
+ *
105
+ * @since 2.3.3
106
+ * @return array
107
+ */
108
+ public function add_cron_intervals( $schedules ) {
109
+ $schedules['jetpack_weekly'] = array(
110
+ 'interval' => WEEK_IN_SECONDS,
111
+ 'display' => __('Jetpack weekly')
112
+ );
113
+ return $schedules;
114
+ }
115
+
116
+ public function deactivate() {
117
+ $timestamp = wp_next_scheduled( $this->cron_name );
118
+ wp_unschedule_event($timestamp, $this->cron_name );
119
+ }
120
+
121
+ }
class.jetpack-options.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Jetpack_Options {
4
+
5
+ public static function get_option_names( $type = 'compact' ) {
6
+ switch ( $type ) {
7
+ case 'non-compact' :
8
+ case 'non_compact' :
9
+ return array(
10
+ 'register',
11
+ 'activated',
12
+ 'active_modules',
13
+ 'do_activate',
14
+ 'publicize',
15
+ 'widget_twitter',
16
+ );
17
+ }
18
+
19
+ return array(
20
+ 'id', // (int) The Client ID/WP.com Blog ID of this site.
21
+ 'blog_token', // (string) The Client Secret/Blog Token of this site.
22
+ 'user_token', // (string) The User Token of this site. (deprecated)
23
+ 'publicize_connections', // (array) An array of Publicize connections from WordPress.com
24
+ 'master_user', // (int) The local User ID of the user who connected this site to jetpack.wordpress.com.
25
+ 'user_tokens', // (array) User Tokens for each user of this site who has connected to jetpack.wordpress.com.
26
+ 'version', // (string) Used during upgrade procedure to auto-activate new modules. version:time
27
+ 'old_version', // (string) Used to determine which modules are the most recently added. previous_version:time
28
+ 'fallback_no_verify_ssl_certs', // (int) Flag for determining if this host must skip SSL Certificate verification due to misconfigured SSL.
29
+ 'time_diff', // (int) Offset between Jetpack server's clocks and this server's clocks. Jetpack Server Time = time() + (int) Jetpack_Options::get_option( 'time_diff' )
30
+ 'public', // (int|bool) If we think this site is public or not (1, 0), false if we haven't yet tried to figure it out.
31
+ 'is_network_site', // (int|bool) If we think this site is a network or a single blog (1, 0), false if we haven't yet tried to figue it out.
32
+ 'social_links', // (array) The specified links for each social networking site.
33
+ );
34
+ }
35
+
36
+ /**
37
+ * Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate.
38
+ *
39
+ * @param string $name Option name
40
+ * @param mixed $default (optional)
41
+ */
42
+ public static function get_option( $name, $default = false ) {
43
+ if ( in_array( $name, self::get_option_names( 'non_compact' ) ) ) {
44
+ return get_option( "jetpack_$name" );
45
+ } else if ( !in_array( $name, self::get_option_names() ) ) {
46
+ trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
47
+ return false;
48
+ }
49
+
50
+ $options = get_option( 'jetpack_options' );
51
+ if ( is_array( $options ) && isset( $options[$name] ) ) {
52
+ return $options[$name];
53
+ }
54
+
55
+ return $default;
56
+ }
57
+
58
+ /**
59
+ * Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate.
60
+ *
61
+ * @param string $name Option name
62
+ * @param mixed $value Option value
63
+ */
64
+ public static function update_option( $name, $value ) {
65
+ if ( in_array( $name, self::get_option_names( 'non_compact' ) ) ) {
66
+ return update_option( "jetpack_$name", $value );
67
+ } else if ( !in_array( $name, self::get_option_names() ) ) {
68
+ trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
69
+ return false;
70
+ }
71
+
72
+ $options = get_option( 'jetpack_options' );
73
+ if ( !is_array( $options ) ) {
74
+ $options = array();
75
+ }
76
+
77
+ $options[$name] = $value;
78
+
79
+ return update_option( 'jetpack_options', $options );
80
+ }
81
+
82
+ /**
83
+ * Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate.
84
+ *
85
+ * @param array $array array( option name => option value, ... )
86
+ */
87
+ public static function update_options( $array ) {
88
+ $names = array_keys( $array );
89
+
90
+ foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ) ) as $unknown_name ) {
91
+ trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
92
+ unset( $array[$unknown_name] );
93
+ }
94
+
95
+ foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
96
+ update_option( "jetpack_$name", $array[$name] );
97
+ unset( $array[$name] );
98
+ }
99
+
100
+ $options = get_option( 'jetpack_options' );
101
+ if ( !is_array( $options ) ) {
102
+ $options = array();
103
+ }
104
+
105
+ return update_option( 'jetpack_options', array_merge( $options, $array ) );
106
+ }
107
+
108
+ /**
109
+ * Deletes the given option. May be passed multiple option names as an array.
110
+ * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
111
+ *
112
+ * @param string|array $names
113
+ */
114
+ public static function delete_option( $names ) {
115
+ $names = (array) $names;
116
+
117
+ foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ) ) as $unknown_name ) {
118
+ trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
119
+ }
120
+
121
+ foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
122
+ delete_option( "jetpack_$name" );
123
+ }
124
+
125
+ $options = get_option( 'jetpack_options' );
126
+ if ( !is_array( $options ) ) {
127
+ $options = array();
128
+ }
129
+
130
+ $to_delete = array_intersect( $names, self::get_option_names(), array_keys( $options ) );
131
+ if ( $to_delete ) {
132
+ foreach ( $to_delete as $name ) {
133
+ unset( $options[$name] );
134
+ }
135
+
136
+ return update_option( 'jetpack_options', $options );
137
+ }
138
+
139
+ return true;
140
+ }
141
+
142
+ }
143
+
class.jetpack-post-images.php CHANGED
@@ -265,6 +265,8 @@ class Jetpack_PostImages {
265
  return $images;
266
 
267
  $html = $post->post_content; // DO NOT apply the_content filters here, it will cause loops
 
 
268
  }
269
 
270
  if ( !$html )
265
  return $images;
266
 
267
  $html = $post->post_content; // DO NOT apply the_content filters here, it will cause loops
268
+ } else {
269
+ $html = $html_or_id;
270
  }
271
 
272
  if ( !$html )
class.jetpack-sync.php ADDED
@@ -0,0 +1,713 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Request that a piece of data on this WordPress install be synced back to the
5
+ * Jetpack server for remote processing/notifications/etc
6
+ */
7
+ class Jetpack_Sync {
8
+ // What modules want to sync what content
9
+ var $sync_conditions = array( 'posts' => array(), 'comments' => array() );
10
+
11
+ // We keep track of all the options registered for sync so that we can sync them all if needed
12
+ var $sync_options = array();
13
+
14
+ // Keep trac of status transitions, which we wouldn't always know about on the Jetpack Servers but are important when deciding what to do with the sync.
15
+ var $post_transitions = array();
16
+ var $comment_transitions = array();
17
+
18
+ // Objects to sync
19
+ var $sync = array();
20
+
21
+ function __construct() {
22
+ // WP Cron action. Only used on upgrade
23
+ add_action( 'jetpack_sync_all_registered_options', array( $this, 'sync_all_registered_options' ) );
24
+ }
25
+
26
+ /* Static Methods for Modules */
27
+
28
+ /**
29
+ * @param string $file __FILE__
30
+ * @param array settings:
31
+ * post_types => array( post_type slugs ): The post types to sync. Default: post, page
32
+ * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
33
+ */
34
+ static function sync_posts( $file, array $settings = null ) {
35
+ $jetpack = Jetpack::init();
36
+ $args = func_get_args();
37
+ return call_user_func_array( array( $jetpack->sync, 'posts' ), $args );
38
+ }
39
+
40
+ /**
41
+ * @param string $file __FILE__
42
+ * @param array settings:
43
+ * post_types => array( post_type slugs ): The post types to sync. Default: post, page
44
+ * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
45
+ * comment_types => array( comment_type slugs ): The comment types to sync. Default: '', comment, trackback, pingback
46
+ * comment_stati => array( comment_status slugs ): The comment stati to sync. Default: approved
47
+ */
48
+ static function sync_comments( $file, array $settings = null ) {
49
+ $jetpack = Jetpack::init();
50
+ $args = func_get_args();
51
+ return call_user_func_array( array( $jetpack->sync, 'comments' ), $args );
52
+ }
53
+
54
+ /**
55
+ * @param string $file __FILE__
56
+ * @param string $option, Option name to sync
57
+ * @param string $option ...
58
+ */
59
+ static function sync_options( $file, $option /*, $option, ... */ ) {
60
+ $jetpack = Jetpack::init();
61
+ $args = func_get_args();
62
+ return call_user_func_array( array( $jetpack->sync, 'options' ), $args );
63
+ }
64
+
65
+ /* Internal Methods */
66
+
67
+ /**
68
+ * Create a sync object/request
69
+ *
70
+ * @param string $object Type of object to sync -- [ post | comment | option ]
71
+ * @param int $id Unique identifier
72
+ * @param array $settings
73
+ */
74
+ function register( $object, $id = false, array $settings = null ) {
75
+ // Since we've registered something for sync, hook it up to execute on shutdown if we haven't already
76
+ if ( !$this->sync ) {
77
+ ignore_user_abort( true );
78
+ add_action( 'shutdown', array( $this, 'sync' ), 9 ); // Right before async XML-RPC
79
+ }
80
+
81
+ $defaults = array(
82
+ 'on_behalf_of' => array(), // What modules want this data
83
+ );
84
+ $settings = wp_parse_args( $settings, $defaults );
85
+
86
+ if ( !isset( $this->sync[$object] ) ) {
87
+ $this->sync[$object] = array();
88
+ }
89
+
90
+ // Store the settings for this object
91
+ if (
92
+ // First time for this object
93
+ !isset( $this->sync[$object][$id] )
94
+ ) {
95
+ // Easy: store the current settings
96
+ $this->sync[$object][$id] = $settings;
97
+ } else {
98
+ // Not as easy: we have to manually merge the settings from previous runs for this object with the settings for this run
99
+
100
+ $this->sync[$object][$id]['on_behalf_of'] = array_unique( array_merge( $this->sync[$object][$id]['on_behalf_of'], $settings['on_behalf_of'] ) );
101
+ }
102
+
103
+ $delete_prefix = 'delete_';
104
+ if ( 0 === strpos( $object, $delete_prefix ) ) {
105
+ $unset_object = substr( $object, strlen( $delete_prefix ) );
106
+ } else {
107
+ $unset_object = "{$delete_prefix}{$object}";
108
+ }
109
+
110
+ // Ensure post ... delete_post yields a delete operation
111
+ // Ensure delete_post ... post yields a sync post operation
112
+ // Ensure update_option() ... delete_option() ends up as a delete
113
+ // Ensure delete_option() ... update_option() ends up as an update
114
+ // Etc.
115
+ unset( $this->sync[$unset_object][$id] );
116
+
117
+ return true;
118
+ }
119
+
120
+ function get_common_sync_data() {
121
+ $available_modules = Jetpack::get_available_modules();
122
+ $active_modules = Jetpack::get_active_modules();
123
+ $modules = array();
124
+ foreach ( $available_modules as $available_module ) {
125
+ $modules[$available_module] = in_array( $available_module, $active_modules );
126
+ }
127
+ $modules['vaultpress'] = class_exists( 'VaultPress' ) || function_exists( 'vaultpress_contact_service' );
128
+
129
+ $sync_data = array(
130
+ 'modules' => $modules,
131
+ 'version' => JETPACK__VERSION,
132
+ );
133
+
134
+ return $sync_data;
135
+ }
136
+
137
+ /**
138
+ * Set up all the data and queue it for the outgoing XML-RPC request
139
+ */
140
+ function sync() {
141
+ if ( !$this->sync ) {
142
+ return false;
143
+ }
144
+
145
+ $sync_data = $this->get_common_sync_data();
146
+
147
+ $wp_importing = defined( 'WP_IMPORTING' ) && WP_IMPORTING;
148
+
149
+ foreach ( $this->sync as $sync_operation_type => $sync_operations ) {
150
+ switch ( $sync_operation_type ) {
151
+ case 'post':
152
+ if ( $wp_importing ) {
153
+ break;
154
+ }
155
+
156
+ $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
157
+ $GLOBALS['post'] = null;
158
+ foreach ( $sync_operations as $post_id => $settings ) {
159
+ $sync_data['post'][$post_id] = $this->get_post( $post_id );
160
+ if ( isset( $this->post_transitions[$post_id] ) ) {
161
+ $sync_data['post'][$post_id]['transitions'] = $this->post_transitions[$post_id];
162
+ } else {
163
+ $sync_data['post'][$post_id]['transitions'] = array( false, false );
164
+ }
165
+ $sync_data['post'][$post_id]['on_behalf_of'] = $settings['on_behalf_of'];
166
+ }
167
+ $GLOBALS['post'] = $global_post;
168
+ unset( $global_post );
169
+ break;
170
+ case 'comment':
171
+ if ( $wp_importing ) {
172
+ break;
173
+ }
174
+
175
+ $global_comment = isset( $GLOBALS['comment'] ) ? $GLOBALS['comment'] : null;
176
+ unset( $GLOBALS['comment'] );
177
+ foreach ( $sync_operations as $comment_id => $settings ) {
178
+ $sync_data['comment'][$comment_id] = $this->get_comment( $comment_id );
179
+ if ( isset( $this->comment_transitions[$comment_id] ) ) {
180
+ $sync_data['comment'][$comment_id]['transitions'] = $this->comment_transitions[$comment_id];
181
+ } else {
182
+ $sync_data['comment'][$comment_id]['transitions'] = array( false, false );
183
+ }
184
+ $sync_data['comment'][$comment_id]['on_behalf_of'] = $settings['on_behalf_of'];
185
+ }
186
+ $GLOBALS['comment'] = $global_comment;
187
+ unset( $global_comment );
188
+ break;
189
+ case 'option' :
190
+ foreach ( $sync_operations as $option => $settings ) {
191
+ $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
192
+ }
193
+ break;
194
+
195
+ case 'delete_post':
196
+ case 'delete_comment':
197
+ foreach ( $sync_operations as $object_id => $settings ) {
198
+ $sync_data[$sync_operation_type][$object_id] = array( 'on_behalf_of' => $settings['on_behalf_of'] );
199
+ }
200
+ break;
201
+ case 'delete_option' :
202
+ foreach ( $sync_operations as $object_id => $settings ) {
203
+ $sync_data[$sync_operation_type][$object_id] = true;
204
+ }
205
+ break;
206
+ }
207
+ }
208
+
209
+ Jetpack::xmlrpc_async_call( 'jetpack.syncContent', $sync_data );
210
+ }
211
+
212
+ /**
213
+ * Format and return content data from a direct xmlrpc request for it.
214
+ *
215
+ * @param array $content_ids: array( 'posts' => array of ids, 'comments' => array of ids, 'options' => array of options )
216
+ */
217
+ function get_content( $content_ids ) {
218
+ $sync_data = $this->get_common_sync_data();
219
+
220
+ if ( isset( $content_ids['posts'] ) ) {
221
+ foreach ( $content_ids['posts'] as $id ) {
222
+ $sync_data['post'][$id] = $this->get_post( $id );
223
+ }
224
+ }
225
+
226
+ if ( isset( $content_ids['comments'] ) ) {
227
+ foreach ( $content_ids['comments'] as $id ) {
228
+ $sync_data['comment'][$id] = $this->get_post( $id );
229
+ }
230
+ }
231
+
232
+ if ( isset( $content_ids['options'] ) ) {
233
+ foreach ( $content_ids['options'] as $option ) {
234
+ $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
235
+ }
236
+ }
237
+
238
+ return $sync_data;
239
+ }
240
+
241
+ /**
242
+ * Helper method for registering a post for sync
243
+ *
244
+ * @param int $id wp_posts.ID
245
+ * @param array $settings Sync data
246
+ */
247
+ function register_post( $id, array $settings = null ) {
248
+ $id = (int) $id;
249
+ if ( !$id ) {
250
+ return false;
251
+ }
252
+
253
+ $post = get_post( $id );
254
+ if ( !$post ) {
255
+ return false;
256
+ }
257
+
258
+ $settings = wp_parse_args( $settings, array(
259
+ 'on_behalf_of' => array(),
260
+ ) );
261
+
262
+ return $this->register( 'post', $id, $settings );
263
+ }
264
+
265
+ /**
266
+ * Helper method for registering a comment for sync
267
+ *
268
+ * @param int $id wp_comments.comment_ID
269
+ * @param array $settings Sync data
270
+ */
271
+ function register_comment( $id, array $settings = null ) {
272
+ $id = (int) $id;
273
+ if ( !$id ) {
274
+ return false;
275
+ }
276
+
277
+ $comment = get_comment( $id );
278
+ if ( !$comment || empty( $comment->comment_post_ID ) ) {
279
+ return false;
280
+ }
281
+
282
+ $post = get_post( $comment->comment_post_ID );
283
+ if ( !$post ) {
284
+ return false;
285
+ }
286
+
287
+ $settings = wp_parse_args( $settings, array(
288
+ 'on_behalf_of' => array(),
289
+ ) );
290
+
291
+ return $this->register( 'comment', $id, $settings );
292
+ }
293
+
294
+ /* Posts Sync */
295
+
296
+ function posts( $file, array $settings = null ) {
297
+ $module_slug = Jetpack::get_module_slug( $file );
298
+
299
+ $defaults = array(
300
+ 'post_types' => array( 'post', 'page' ),
301
+ 'post_stati' => array( 'publish' ),
302
+ );
303
+
304
+ $this->sync_conditions['posts'][$module_slug] = wp_parse_args( $settings, $defaults );
305
+
306
+ add_action( 'transition_post_status', array( $this, 'transition_post_status_action' ), 10, 3 );
307
+ add_action( 'delete_post', array( $this, 'delete_post_action' ) );
308
+ }
309
+
310
+ function delete_post_action( $post_id ) {
311
+ $post = get_post( $post_id );
312
+ if ( !$post ) {
313
+ return $this->register( 'delete_post', (int) $post_id );
314
+ }
315
+
316
+ $this->transition_post_status_action( 'delete', $post->post_status, $post );
317
+ }
318
+
319
+ function transition_post_status_action( $new_status, $old_status, $post ) {
320
+ $sync = $this->get_post_sync_operation( $new_status, $old_status, $post, $this->sync_conditions['posts'] );
321
+ if ( !$sync ) {
322
+ // No module wants to sync this post
323
+ return false;
324
+ }
325
+
326
+ // Track post transitions
327
+ if ( isset( $this->post_transitions[$post->ID] ) ) {
328
+ // status changed more than once - keep tha most recent $new_status
329
+ $this->post_transitions[$post->ID][0] = $new_status;
330
+ } else {
331
+ $this->post_transitions[$post->ID] = array( $new_status, $old_status );
332
+ }
333
+
334
+ $operation = $sync['operation'];
335
+ unset( $sync['operation'] );
336
+
337
+ switch ( $operation ) {
338
+ case 'delete' :
339
+ return $this->register( 'delete_post', (int) $post->ID, $sync );
340
+ case 'submit' :
341
+ return $this->register_post( (int) $post->ID, $sync );
342
+ }
343
+ }
344
+
345
+ function get_post_sync_operation( $new_status, $old_status, $post, $module_conditions ) {
346
+ $delete_on_behalf_of = array();
347
+ $submit_on_behalf_of = array();
348
+ $delete_stati = array( 'delete' );
349
+
350
+ foreach ( $module_conditions as $module => $conditions ) {
351
+ if ( !in_array( $post->post_type, $conditions['post_types'] ) ) {
352
+ continue;
353
+ }
354
+
355
+ $deleted_post = in_array( $new_status, $delete_stati );
356
+
357
+ if ( $deleted_post ) {
358
+ $delete_on_behalf_of[] = $module;
359
+ } else {
360
+ clean_post_cache( $post->ID );
361
+ $new_status = get_post_status( $post->ID ); // Inherited status is resolved here
362
+ }
363
+
364
+ $old_status_in_stati = in_array( $old_status, $conditions['post_stati'] );
365
+ $new_status_in_stati = in_array( $new_status, $conditions['post_stati'] );
366
+
367
+ if ( $old_status_in_stati && !$new_status_in_stati ) {
368
+ // Jetpack no longer needs the post
369
+ if ( !$deleted_post ) {
370
+ $delete_on_behalf_of[] = $module;
371
+ } // else, we've already flagged it above
372
+ continue;
373
+ }
374
+
375
+ if ( !$new_status_in_stati ) {
376
+ continue;
377
+ }
378
+
379
+ // At this point, we know we want to sync the post, not delete it
380
+ $submit_on_behalf_of[] = $module;
381
+ }
382
+
383
+ if ( !empty( $submit_on_behalf_of ) ) {
384
+ return array( 'operation' => 'submit', 'on_behalf_of' => $submit_on_behalf_of );
385
+ }
386
+
387
+ if ( !empty( $delete_on_behalf_of ) ) {
388
+ return array( 'operation' => 'delete', 'on_behalf_of' => $delete_on_behalf_of );
389
+ }
390
+
391
+ return false;
392
+ }
393
+
394
+ /**
395
+ * Get a post and associated data in the standard JP format.
396
+ * Cannot be called statically
397
+ *
398
+ * @param int $id Post ID
399
+ * @return Array containing full post details
400
+ */
401
+ function get_post( $id ) {
402
+ $post_obj = get_post( $id );
403
+ if ( !$post_obj )
404
+ return false;
405
+
406
+ if ( is_callable( $post_obj, 'to_array' ) ) {
407
+ // WP >= 3.5
408
+ $post = $post_obj->to_array();
409
+ } else {
410
+ // WP < 3.5
411
+ $post = get_object_vars( $post_obj );
412
+ }
413
+
414
+ if ( 0 < strlen( $post['post_password'] ) ) {
415
+ $post['post_password'] = 'auto-' . wp_generate_password( 10, false ); // We don't want the real password. Just pass something random.
416
+ }
417
+
418
+ // local optimizations
419
+ unset(
420
+ $post['filter'],
421
+ $post['ancestors'],
422
+ $post['post_content_filtered'],
423
+ $post['to_ping'],
424
+ $post['pinged']
425
+ );
426
+
427
+ if ( $this->is_post_public( $post ) ) {
428
+ $post['post_is_public'] = Jetpack::get_option( 'public' );
429
+ } else {
430
+ //obscure content
431
+ $post['post_content'] = '';
432
+ $post['post_excerpt'] = '';
433
+ $post['post_is_public'] = false;
434
+ }
435
+ $post_type_obj = get_post_type_object( $post['post_type'] );
436
+ $post['post_is_excluded_from_search'] = $post_type_obj->exclude_from_search;
437
+
438
+ $post['tax'] = array();
439
+ $taxonomies = get_object_taxonomies( $post_obj );
440
+ foreach ( $taxonomies as $taxonomy ) {
441
+ $terms = get_object_term_cache( $post_obj->ID, $taxonomy );
442
+ if ( empty( $terms ) )
443
+ $terms = wp_get_object_terms( $post_obj->ID, $taxonomy );
444
+ $term_names = array();
445
+ foreach ( $terms as $term ) {
446
+ $term_names[] = $term->name;
447
+ }
448
+ $post['tax'][$taxonomy] = $term_names;
449
+ }
450
+
451
+ $meta = get_post_meta( $post_obj->ID, false );
452
+ $post['meta'] = array();
453
+ foreach ( $meta as $key => $value ) {
454
+ $post['meta'][$key] = array_map( 'maybe_unserialize', $value );
455
+ }
456
+
457
+ $post['extra'] = array(
458
+ 'author' => get_the_author_meta( 'display_name', $post_obj->post_author ),
459
+ 'author_email' => get_the_author_meta( 'email', $post_obj->post_author ),
460
+ );
461
+
462
+ if ( $fid = get_post_thumbnail_id( $id ) ) {
463
+ $feature = wp_get_attachment_image_src( $fid, 'large' );
464
+ if ( !empty( $feature[0] ) )
465
+ $post['extra']['featured_image'] = $feature[0];
466
+ }
467
+
468
+ $post['permalink'] = get_permalink( $post_obj->ID );
469
+ $post['shortlink'] = wp_get_shortlink( $post_obj->ID );
470
+ return $post;
471
+ }
472
+
473
+ /**
474
+ * Decide whether a post/page/attachment is visible to the public.
475
+ *
476
+ * @param array $post
477
+ * @return bool
478
+ */
479
+ function is_post_public( $post ) {
480
+ if ( !is_array( $post ) ) {
481
+ $post = (array) $post;
482
+ }
483
+
484
+ if ( 0 < strlen( $post['post_password'] ) )
485
+ return false;
486
+ if ( ! in_array( $post['post_type'], get_post_types( array( 'public' => true ) ) ) )
487
+ return false;
488
+ $post_status = get_post_status( $post['ID'] ); // Inherited status is resolved here.
489
+ if ( ! in_array( $post_status, get_post_stati( array( 'public' => true ) ) ) )
490
+ return false;
491
+ return true;
492
+ }
493
+
494
+ /* Comments Sync */
495
+
496
+ function comments( $file, array $settings = null ) {
497
+ $module_slug = Jetpack::get_module_slug( $file );
498
+
499
+ $defaults = array(
500
+ 'post_types' => array( 'post', 'page' ), // For what post types will we sync comments?
501
+ 'post_stati' => array( 'publish' ), // For what post stati will we sync comments?
502
+ 'comment_types' => array( '', 'comment', 'trackback', 'pingback' ), // What comment types will we sync?
503
+ 'comment_stati' => array( 'approved' ), // What comment stati will we sync?
504
+ );
505
+
506
+ $settings = wp_parse_args( $settings, $defaults );
507
+
508
+ $this->sync_conditions['comments'][$module_slug] = $settings;
509
+
510
+ add_action( 'wp_insert_comment', array( $this, 'wp_insert_comment_action' ), 10, 2 );
511
+ add_action( 'transition_comment_status', array( $this, 'transition_comment_status_action' ), 10, 3 );
512
+ add_action( 'edit_comment', array( $this, 'edit_comment_action' ) );
513
+ }
514
+
515
+ /*
516
+ * This is really annoying. If you edit a comment, but don't change the status, WordPress doesn't fire the transition_comment_status hook.
517
+ * That means we have to catch these comments on the edit_comment hook, but ignore comments on that hook when the transition_comment_status does fire.
518
+ */
519
+ function edit_comment_action( $comment_id ) {
520
+ $comment = get_comment( $comment_id );
521
+ $new_status = $this->translate_comment_status( $comment->comment_approved );
522
+ add_action( "comment_{$new_status}_{$comment->comment_type}", array( $this, 'transition_comment_status_for_comments_whose_status_does_not_change' ), 10, 2 );
523
+ }
524
+
525
+ function wp_insert_comment_action( $comment_id, $comment ) {
526
+ $this->transition_comment_status_action( $comment->comment_approved, 'new', $comment );
527
+ }
528
+
529
+ function transition_comment_status_for_comments_whose_status_does_not_change( $comment_id, $comment ) {
530
+ if ( isset( $this->comment_transitions[$comment_id] ) ) {
531
+ return $this->transition_comment_status_action( $comment->comment_approved, $this->comment_transitions[$comment_id][1], $comment );
532
+ }
533
+
534
+ return $this->transition_comment_status_action( $comment->comment_approved, $comment->comment_approved, $comment );
535
+ }
536
+
537
+ function translate_comment_status( $status ) {
538
+ switch ( (string) $status ) {
539
+ case '0' :
540
+ case 'hold' :
541
+ return 'unapproved';
542
+ case '1' :
543
+ case 'approve' :
544
+ return 'approved';
545
+ }
546
+
547
+ return $status;
548
+ }
549
+
550
+ function transition_comment_status_action( $new_status, $old_status, $comment ) {
551
+ $post = get_post( $comment->comment_post_ID );
552
+ if ( !$post ) {
553
+ return false;
554
+ }
555
+
556
+ foreach ( array( 'new_status', 'old_status' ) as $_status ) {
557
+ $$_status = $this->translate_comment_status( $$_status );
558
+ }
559
+
560
+ // Track comment transitions
561
+ if ( isset( $this->comment_transitions[$comment->comment_ID] ) ) {
562
+ // status changed more than once - keep tha most recent $new_status
563
+ $this->comment_transitions[$comment->comment_ID][0] = $new_status;
564
+ } else {
565
+ $this->comment_transitions[$comment->comment_ID] = array( $new_status, $old_status );
566
+ }
567
+
568
+ $post_sync = $this->get_post_sync_operation( $post->post_status, '_jetpack_test_sync', $post, $this->sync_conditions['comments'] );
569
+
570
+ if ( !$post_sync ) {
571
+ // No module wants to sync this comment because its post doesn't match any sync conditions
572
+ return false;
573
+ }
574
+
575
+ if ( 'delete' == $post_sync['operation'] ) {
576
+ // Had we been looking at post sync operations (instead of comment sync operations),
577
+ // this comment's post would have been deleted. Don't sync the comment.
578
+ return false;
579
+ }
580
+
581
+ $delete_on_behalf_of = array();
582
+ $submit_on_behalf_of = array();
583
+ $delete_stati = array( 'delete' );
584
+
585
+ foreach ( $this->sync_conditions['comments'] as $module => $conditions ) {
586
+ if ( !in_array( $comment->comment_type, $conditions['comment_types'] ) ) {
587
+ continue;
588
+ }
589
+
590
+ $deleted_comment = in_array( $new_status, $delete_stati );
591
+
592
+ if ( $deleted_comment ) {
593
+ $delete_on_behalf_of[] = $module;
594
+ }
595
+
596
+ $old_status_in_stati = in_array( $old_status, $conditions['comment_stati'] );
597
+ $new_status_in_stati = in_array( $new_status, $conditions['comment_stati'] );
598
+
599
+ if ( $old_status_in_stati && !$new_status_in_stati ) {
600
+ // Jetpack no longer needs the comment
601
+ if ( !$deleted_comment ) {
602
+ $delete_on_behalf_of[] = $module;
603
+ } // else, we've already flagged it above
604
+ continue;
605
+ }
606
+
607
+ if ( !$new_status_in_stati ) {
608
+ continue;
609
+ }
610
+
611
+ // At this point, we know we want to sync the comment, not delete it
612
+ $submit_on_behalf_of[] = $module;
613
+ }
614
+
615
+ if ( ! empty( $submit_on_behalf_of ) ) {
616
+ $this->register_post( $comment->comment_post_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
617
+ return $this->register_comment( $comment->comment_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
618
+ }
619
+
620
+ if ( !empty( $delete_on_behalf_of ) ) {
621
+ return $this->register( 'delete_comment', $comment->comment_ID, array( 'on_behalf_of' => $delete_on_behalf_of ) );
622
+ }
623
+
624
+ return false;
625
+ }
626
+
627
+ /**
628
+ * Get a comment and associated data in the standard JP format.
629
+ * Cannot be called statically
630
+ *
631
+ * @param int $id Comment ID
632
+ * @return Array containing full comment details
633
+ */
634
+ function get_comment( $id ) {
635
+ $comment_obj = get_comment( $id );
636
+ if ( !$comment_obj )
637
+ return false;
638
+ $comment = get_object_vars( $comment_obj );
639
+
640
+ $meta = get_comment_meta( $id, false );
641
+ $comment['meta'] = array();
642
+ foreach ( $meta as $key => $value ) {
643
+ $comment['meta'][$key] = array_map( 'maybe_unserialize', $value );
644
+ }
645
+
646
+ return $comment;
647
+ }
648
+
649
+ /* Options Sync */
650
+
651
+ /* Ah... so much simpler than Posts and Comments :) */
652
+ function options( $file, $option /*, $option, ... */ ) {
653
+ $options = func_get_args();
654
+ $file = array_shift( $options );
655
+
656
+ $module_slug = Jetpack::get_module_slug( $file );
657
+
658
+ if ( !isset( $this->sync_options[$module_slug] ) ) {
659
+ $this->sync_options[$module_slug] = array();
660
+ }
661
+
662
+ foreach ( $options as $option ) {
663
+ $this->sync_options[$module_slug][] = $option;
664
+ add_action( "delete_option_{$option}", array( $this, 'deleted_option_action' ) );
665
+ add_action( "update_option_{$option}", array( $this, 'updated_option_action' ) );
666
+ add_action( "add_option_{$option}", array( $this, 'added_option_action' ) );
667
+ }
668
+
669
+ $this->sync_options[$module_slug] = array_unique( $this->sync_options[$module_slug] );
670
+ }
671
+
672
+ function deleted_option_action( $option ) {
673
+ $this->register( 'delete_option', $option );
674
+ }
675
+
676
+ function updated_option_action( $old_value ) {
677
+ // The value of $option isn't passed to the filter
678
+ // Calculate it
679
+ $option = current_filter();
680
+ $prefix = 'update_option_';
681
+ if ( 0 !== strpos( $option, $prefix ) ) {
682
+ return;
683
+ }
684
+ $option = substr( $option, strlen( $prefix ) );
685
+
686
+ $this->added_option_action( $option );
687
+ }
688
+
689
+ function added_option_action( $option ) {
690
+ $this->register( 'option', $option );
691
+ }
692
+
693
+ function sync_all_module_options( $module_slug ) {
694
+ if ( empty( $this->sync_options[$module_slug] ) ) {
695
+ return;
696
+ }
697
+
698
+ foreach ( $this->sync_options[$module_slug] as $option ) {
699
+ $this->added_option_action( $option );
700
+ }
701
+ }
702
+
703
+ function sync_all_registered_options( $options = array() ) {
704
+ if ( 'jetpack_sync_all_registered_options' == current_filter() ) {
705
+ $all_registered_options = array_unique( call_user_func_array( 'array_merge', $this->sync_options ) );
706
+ foreach ( $all_registered_options as $option ) {
707
+ $this->added_option_action( $option );
708
+ }
709
+ } else {
710
+ wp_schedule_single_event( time(), 'jetpack_sync_all_registered_options', array( $this->sync_options ) );
711
+ }
712
+ }
713
+ }
class.jetpack-user-agent.php CHANGED
@@ -78,6 +78,7 @@ class Jetpack_User_Agent_Info {
78
  const PLATFORM_J2ME_MIDP = 'j2me_midp';
79
  const PLATFORM_ANDROID = 'android';
80
  const PLATFORM_ANDROID_TABLET = 'android_tablet';
 
81
 
82
  var $dumb_agents = array(
83
  'nokia', 'blackberry', 'philips', 'samsung', 'sanyo', 'sony', 'panasonic', 'webos',
@@ -139,6 +140,8 @@ class Jetpack_User_Agent_Info {
139
  return 'webos';
140
  elseif ( $this->is_S60_OSSBrowser() )
141
  return 'series60';
 
 
142
  elseif ( $this->is_firefox_mobile() )
143
  return 'firefox_mobile';
144
  elseif ( $this->is_MaemoTablet() )
@@ -228,6 +231,9 @@ class Jetpack_User_Agent_Info {
228
  elseif ( $this->is_J2ME_platform() ) {
229
  $this->_platform = self::PLATFORM_J2ME_MIDP;
230
  }
 
 
 
231
  else
232
  $this->_platform = false;
233
 
@@ -297,6 +303,12 @@ class Jetpack_User_Agent_Info {
297
  $this->isTierRichCss = false;
298
  $this->isTierGenericMobile = false;
299
  }
 
 
 
 
 
 
300
  elseif ( $this->is_firefox_mobile() ) {
301
  $this->matched_agent = 'fennec';
302
  $this->isTierIphone = true;
@@ -377,7 +389,7 @@ class Jetpack_User_Agent_Info {
377
 
378
  // Detects if the user is using a tablet.
379
  // props Corey Gilmore, BGR.com
380
- function is_tablet() {
381
  return ( 0 // never true, but makes it easier to manage our list of tablet conditions
382
  || self::is_ipad()
383
  || self::is_android_tablet()
@@ -387,14 +399,14 @@ class Jetpack_User_Agent_Info {
387
  || self::is_TouchPad()
388
  );
389
  }
390
-
391
  /*
392
  * Detects if the current UA is the default iPhone or iPod Touch Browser.
393
  *
394
  * DEPRECATED: use is_iphone_or_ipod
395
  *
396
  */
397
- function is_iphoneOrIpod(){
398
 
399
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
400
  return false;
@@ -421,7 +433,7 @@ class Jetpack_User_Agent_Info {
421
  * Otherwise those browsers will be 'catched' by the iphone string.
422
  *
423
  */
424
- function is_iphone_or_ipod( $type = 'iphone-any' ) {
425
 
426
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
427
  return false;
@@ -438,61 +450,61 @@ class Jetpack_User_Agent_Info {
438
  return $is_iphone;
439
  }
440
 
441
-
442
  /*
443
  * Detects if the current UA is Chrome for iOS
444
  *
445
  * The User-Agent string in Chrome for iOS is the same as the Mobile Safari User-Agent, with CriOS/<ChromeRevision> instead of Version/<VersionNum>.
446
  * - Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3
447
  */
448
- function is_chrome_for_iOS( ) {
449
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
450
  return false;
451
-
452
  if ( self::is_iphone_or_ipod( 'iphone-safari' ) === false ) return false;
453
-
454
  $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
455
-
456
  if ( strpos( $ua, 'crios/' ) !== false )
457
  return true;
458
  else
459
  return false;
460
  }
461
-
462
-
463
  /*
464
  * Detects if the current UA is Twitter for iPhone
465
- *
466
  * Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; nb-no) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8L1 Twitter for iPhone
467
  * Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 Twitter for iPhone
468
- *
469
  */
470
- function is_twitter_for_iphone( ) {
471
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
472
  return false;
473
-
474
  $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
475
 
476
  if ( strpos( $ua, 'ipad' ) !== false )
477
  return false;
478
-
479
  if ( strpos( $ua, 'twitter for iphone' ) !== false )
480
  return true;
481
  else
482
  return false;
483
  }
484
-
485
  /*
486
  * Detects if the current UA is Twitter for iPad
487
- *
488
  * Old version 4.X - Mozilla/5.0 (iPad; U; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8L1 Twitter for iPad
489
  * Ver 5.0 or Higher - Mozilla/5.0 (iPad; CPU OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 Twitter for iPhone
490
- *
491
  */
492
- function is_twitter_for_ipad( ) {
493
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
494
  return false;
495
-
496
  $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
497
 
498
  if ( strpos( $ua, 'twitter for ipad' ) !== false )
@@ -502,7 +514,7 @@ class Jetpack_User_Agent_Info {
502
  else
503
  return false;
504
  }
505
-
506
 
507
  /*
508
  * Detects if the current UA is Facebook for iPhone
@@ -510,7 +522,7 @@ class Jetpack_User_Agent_Info {
510
  * - Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/O2;FBID/phone;FBLC/en_US;FBSF/2.0]
511
  * - Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 [FBAN/FBIOS;FBAV/5.0;FBBV/47423;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.1.1;FBSS/2; FBCR/3ITA;FBID/phone;FBLC/en_US]
512
  */
513
- function is_facebook_for_iphone( ) {
514
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
515
  return false;
516
 
@@ -535,7 +547,7 @@ class Jetpack_User_Agent_Info {
535
  * - Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]
536
  * - Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10A403 [FBAN/FBIOS;FBAV/5.0;FBBV/47423;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/6.0;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US]
537
  */
538
- function is_facebook_for_ipad( ) {
539
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
540
  return false;
541
 
@@ -553,7 +565,7 @@ class Jetpack_User_Agent_Info {
553
  /*
554
  * Detects if the current UA is WordPress for iOS
555
  */
556
- function is_wordpress_for_ios( ) {
557
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
558
  return false;
559
 
@@ -573,7 +585,7 @@ class Jetpack_User_Agent_Info {
573
  * Otherwise those browsers will be 'catched' by the ipad string.
574
  *
575
  */
576
- function is_ipad( $type = 'ipad-any' ) {
577
 
578
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
579
  return false;
@@ -598,7 +610,7 @@ class Jetpack_User_Agent_Info {
598
  * Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.1.1) Gecko/20110415 Firefox/4.0.2pre Fennec/4.0.1
599
  * Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1
600
  */
601
- function is_firefox_mobile( ) {
602
 
603
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
604
  return false;
@@ -612,6 +624,26 @@ class Jetpack_User_Agent_Info {
612
  }
613
 
614
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
  /*
616
  * Detects if the current browser is Opera Mobile
617
  *
@@ -623,7 +655,7 @@ class Jetpack_User_Agent_Info {
623
  *
624
  * Opera/9.80 (Windows NT 6.1; Opera Mobi/14316; U; en) Presto/2.7.81 Version/11.00"
625
  */
626
- function is_opera_mobile( ) {
627
 
628
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
629
  return false;
@@ -649,7 +681,7 @@ class Jetpack_User_Agent_Info {
649
  * Opera/9.80 (BlackBerry; Opera Mini/5.1.22303/22.387; U; en) Presto/2.5.25 Version/10.54
650
  *
651
  */
652
- function is_opera_mini( ) {
653
 
654
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
655
  return false;
@@ -666,7 +698,7 @@ class Jetpack_User_Agent_Info {
666
  * Detects if the current browser is Opera Mini, but not on a smart device OS(Android, iOS, etc)
667
  * Used to send users on dumb devices to m.wor
668
  */
669
- function is_opera_mini_dumb( ) {
670
 
671
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
672
  return false;
@@ -690,7 +722,7 @@ class Jetpack_User_Agent_Info {
690
  * Opera Mini 5 Beta: Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.15650/756; U; en) Presto/2.2.0
691
  * Opera Mini 8: Opera/8.01 (J2ME/MIDP; Opera Mini/3.0.6306/1528; en; U; ssr)
692
  */
693
- function is_OperaMobile() {
694
  _deprecated_function( __FUNCTION__, 'always', 'is_opera_mini() or is_opera_mobile()' );
695
 
696
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
@@ -712,7 +744,7 @@ class Jetpack_User_Agent_Info {
712
  * Detects if the current browser is a Windows Phone 7 device.
713
  * ex: Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; LG; GW910)
714
  */
715
- function is_WindowsPhone7() {
716
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
717
  return false;
718
 
@@ -732,10 +764,10 @@ class Jetpack_User_Agent_Info {
732
  * Detects if the current browser is a Windows Phone 8 device.
733
  * ex: Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; ARM; Touch; IEMobile/10.0; <Manufacturer>; <Device> [;<Operator>])
734
  */
735
- function is_windows_phone_8() {
736
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
737
  return false;
738
-
739
  $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
740
  if ( strpos( $ua, 'windows phone 8' ) === false ) {
741
  return false;
@@ -743,8 +775,8 @@ class Jetpack_User_Agent_Info {
743
  return true;
744
  }
745
  }
746
-
747
-
748
  /*
749
  * Detects if the current browser is on a Palm device running the new WebOS. This EXCLUDES TouchPad.
750
  *
@@ -752,7 +784,7 @@ class Jetpack_User_Agent_Info {
752
  * ex2: Mozilla/5.0 (webOS/1.4.0; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pixi/1.1
753
  *
754
  */
755
- function is_PalmWebOS() {
756
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
757
  return false;
758
 
@@ -775,7 +807,7 @@ class Jetpack_User_Agent_Info {
775
  * TouchPad: Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0
776
  *
777
  */
778
- function is_TouchPad() {
779
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
780
  return false;
781
 
@@ -801,7 +833,7 @@ class Jetpack_User_Agent_Info {
801
  * Browser 7.1 (Nokia N97 (v12.0.024)) : Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/12.0.024; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.12344
802
  *
803
  */
804
- function is_S60_OSSBrowser() {
805
 
806
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
807
  return false;
@@ -831,7 +863,7 @@ class Jetpack_User_Agent_Info {
831
  * Detects if the device platform is the Symbian Series 60.
832
  *
833
  */
834
- function is_symbian_platform() {
835
 
836
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
837
  return false;
@@ -864,7 +896,7 @@ class Jetpack_User_Agent_Info {
864
  * This browser will report 'NokiaBrowser' in the header, however some older version will also report 'OviBrowser'.
865
  *
866
  */
867
- function is_symbian_s40_platform() {
868
 
869
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
870
  return false;
@@ -879,7 +911,7 @@ class Jetpack_User_Agent_Info {
879
  return false;
880
  }
881
 
882
- function is_J2ME_platform() {
883
 
884
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
885
  return false;
@@ -899,7 +931,7 @@ class Jetpack_User_Agent_Info {
899
  /*
900
  * Detects if the current UA is on one of the Maemo-based Nokia Internet Tablets.
901
  */
902
- function is_MaemoTablet() {
903
 
904
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
905
  return false;
@@ -922,7 +954,7 @@ class Jetpack_User_Agent_Info {
922
  /*
923
  * Detects if the current UA is a MeeGo device (Nokia Smartphone).
924
  */
925
- function is_MeeGo() {
926
 
927
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
928
  return false;
@@ -943,7 +975,7 @@ class Jetpack_User_Agent_Info {
943
  /*
944
  is_webkit() can be used to check the User Agent for an webkit generic browser
945
  */
946
- function is_webkit() {
947
 
948
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
949
  return false;
@@ -962,7 +994,7 @@ class Jetpack_User_Agent_Info {
962
  * Detects if the current browser is the Native Android browser.
963
  * @return boolean true if the browser is Android otherwise false
964
  */
965
- function is_android() {
966
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
967
  return false;
968
 
@@ -985,7 +1017,7 @@ class Jetpack_User_Agent_Info {
985
  *
986
  * @return boolean true if the browser is Android and not 'mobile' otherwise false
987
  */
988
- function is_android_tablet( ) {
989
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
990
  return false;
991
 
@@ -1012,7 +1044,7 @@ class Jetpack_User_Agent_Info {
1012
  *
1013
  * @return boolean true if the browser is Kindle Fire Native browser otherwise false
1014
  */
1015
- function is_kindle_fire( ) {
1016
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1017
  return false;
1018
 
@@ -1033,7 +1065,7 @@ class Jetpack_User_Agent_Info {
1033
  *
1034
  * @return boolean true if the browser is Kindle monochrome Native browser otherwise false
1035
  */
1036
- function is_kindle_touch( ) {
1037
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1038
  return false;
1039
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
@@ -1046,7 +1078,7 @@ class Jetpack_User_Agent_Info {
1046
 
1047
 
1048
  // Detect if user agent is the WordPress.com Windows 8 app (used ONLY on the custom oauth stylesheet)
1049
- function is_windows8_auth( ) {
1050
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1051
  return false;
1052
 
@@ -1059,10 +1091,10 @@ class Jetpack_User_Agent_Info {
1059
  }
1060
 
1061
  // Detect if user agent is the WordPress.com Windows 8 app.
1062
- function is_wordpress_for_win8( ) {
1063
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1064
  return false;
1065
-
1066
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1067
  $pos = strpos( $agent, 'wp-windows8' );
1068
  if ( $pos !== false )
@@ -1070,15 +1102,15 @@ class Jetpack_User_Agent_Info {
1070
  else
1071
  return false;
1072
  }
1073
-
1074
-
1075
  /*
1076
  * is_blackberry_tablet() can be used to check the User Agent for a RIM blackberry tablet
1077
  * The user agent of the BlackBerry® Tablet OS follows a format similar to the following:
1078
  * Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/0.0.1 Safari/534.8+
1079
  *
1080
  */
1081
- function is_blackberry_tablet() {
1082
 
1083
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1084
  return false;
@@ -1099,13 +1131,13 @@ class Jetpack_User_Agent_Info {
1099
  is_blackbeberry() can be used to check the User Agent for a blackberry device
1100
  Note that opera mini on BB matches this rule.
1101
  */
1102
- function is_blackbeberry() {
1103
 
1104
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1105
  return false;
1106
 
1107
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1108
-
1109
  $pos_blackberry = strpos( $agent, 'blackberry' );
1110
  if ( $pos_blackberry !== false ) {
1111
  if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
@@ -1120,7 +1152,7 @@ class Jetpack_User_Agent_Info {
1120
  /*
1121
  is_blackberry_10() can be used to check the User Agent for a BlackBerry 10 device.
1122
  */
1123
- function is_blackberry_10() {
1124
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1125
  return ( strpos( $agent, 'bb10' ) !== false ) && ( strpos( $agent, 'mobile' ) !== false );
1126
  }
@@ -1141,14 +1173,14 @@ class Jetpack_User_Agent_Info {
1141
  * @return string Version of the BB OS.
1142
  * If version is not found, get_blackbeberry_OS_version will return boolean false.
1143
  */
1144
- function get_blackbeberry_OS_version() {
1145
 
1146
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1147
  return false;
1148
 
1149
  if ( self::is_blackberry_10() )
1150
  return 'blackberry-10';
1151
-
1152
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1153
 
1154
  $pos_blackberry = stripos( $agent, 'blackberry' );
@@ -1223,7 +1255,7 @@ class Jetpack_User_Agent_Info {
1223
  * @return string Type of the BB browser.
1224
  * If browser's version is not found, detect_blackbeberry_browser_version will return boolean false.
1225
  */
1226
- function detect_blackberry_browser_version() {
1227
 
1228
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1229
  return false;
@@ -1232,7 +1264,7 @@ class Jetpack_User_Agent_Info {
1232
 
1233
  if ( self::is_blackberry_10() )
1234
  return 'blackberry-10';
1235
-
1236
  $pos_blackberry = strpos( $agent, 'blackberry' );
1237
  if ( $pos_blackberry === false ) {
1238
  //not a blackberry device
@@ -1270,7 +1302,7 @@ class Jetpack_User_Agent_Info {
1270
  }
1271
 
1272
  //Checks if a visitor is coming from one of the WordPress mobile apps
1273
- function is_mobile_app() {
1274
 
1275
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1276
  return false;
@@ -1294,38 +1326,51 @@ class Jetpack_User_Agent_Info {
1294
  return false;
1295
  }
1296
 
 
 
 
 
 
1297
  static function is_bot() {
1298
- static $is_bot = false;
1299
- static $first_run = true;
1300
 
1301
- if ( $first_run ) {
1302
- $first_run = false;
 
1303
 
1304
- /*
1305
- $bot_ips = array( );
1306
 
1307
- foreach ( $bot_ips as $bot_ip ) {
1308
- if ( $_SERVER['REMOTE_ADDR'] == $bot_ip )
1309
- $is_bot = true;
1310
- }
1311
- */
 
 
 
1312
 
1313
- $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
 
1314
 
1315
- $bot_agents = array(
1316
- 'alexa', 'altavista', 'ask jeeves', 'attentio', 'baiduspider', 'bingbot', 'chtml generic', 'crawler', 'fastmobilecrawl',
1317
- 'feedfetcher-google', 'firefly', 'froogle', 'gigabot', 'googlebot', 'googlebot-mobile', 'heritrix', 'ia_archiver', 'irlbot',
1318
- 'infoseek', 'jumpbot', 'lycos', 'mediapartners', 'mediobot', 'motionbot', 'msnbot', 'mshots', 'openbot',
1319
- 'pythumbnail', 'scooter', 'slurp', 'snapbot', 'spider', 'surphace scout', 'taptubot', 'technoratisnoop',
1320
- 'teoma', 'twiceler', 'yahooseeker', 'yahooysmcm', 'yammybot',
1321
- );
1322
-
1323
- foreach ( $bot_agents as $bot_agent ) {
1324
- if ( false !== strpos( $agent, $bot_agent ) )
1325
- $is_bot = true;
 
1326
  }
1327
  }
1328
 
1329
- return $is_bot;
1330
  }
 
 
 
1331
  }
78
  const PLATFORM_J2ME_MIDP = 'j2me_midp';
79
  const PLATFORM_ANDROID = 'android';
80
  const PLATFORM_ANDROID_TABLET = 'android_tablet';
81
+ const PLATFORM_FIREFOX_OS = 'firefoxOS';
82
 
83
  var $dumb_agents = array(
84
  'nokia', 'blackberry', 'philips', 'samsung', 'sanyo', 'sony', 'panasonic', 'webos',
140
  return 'webos';
141
  elseif ( $this->is_S60_OSSBrowser() )
142
  return 'series60';
143
+ elseif ( $this->is_firefox_os() )
144
+ return 'firefoxOS';
145
  elseif ( $this->is_firefox_mobile() )
146
  return 'firefox_mobile';
147
  elseif ( $this->is_MaemoTablet() )
231
  elseif ( $this->is_J2ME_platform() ) {
232
  $this->_platform = self::PLATFORM_J2ME_MIDP;
233
  }
234
+ elseif ( $this->is_firefox_os() ) {
235
+ $this->_platform = self::PLATFORM_FIREFOX_OS;
236
+ }
237
  else
238
  $this->_platform = false;
239
 
303
  $this->isTierRichCss = false;
304
  $this->isTierGenericMobile = false;
305
  }
306
+ elseif ( $this->is_firefox_os() ) {
307
+ $this->matched_agent = 'firefoxOS';
308
+ $this->isTierIphone = true;
309
+ $this->isTierRichCss = false;
310
+ $this->isTierGenericMobile = false;
311
+ }
312
  elseif ( $this->is_firefox_mobile() ) {
313
  $this->matched_agent = 'fennec';
314
  $this->isTierIphone = true;
389
 
390
  // Detects if the user is using a tablet.
391
  // props Corey Gilmore, BGR.com
392
+ static function is_tablet() {
393
  return ( 0 // never true, but makes it easier to manage our list of tablet conditions
394
  || self::is_ipad()
395
  || self::is_android_tablet()
399
  || self::is_TouchPad()
400
  );
401
  }
402
+
403
  /*
404
  * Detects if the current UA is the default iPhone or iPod Touch Browser.
405
  *
406
  * DEPRECATED: use is_iphone_or_ipod
407
  *
408
  */
409
+ static function is_iphoneOrIpod(){
410
 
411
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
412
  return false;
433
  * Otherwise those browsers will be 'catched' by the iphone string.
434
  *
435
  */
436
+ static function is_iphone_or_ipod( $type = 'iphone-any' ) {
437
 
438
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
439
  return false;
450
  return $is_iphone;
451
  }
452
 
453
+
454
  /*
455
  * Detects if the current UA is Chrome for iOS
456
  *
457
  * The User-Agent string in Chrome for iOS is the same as the Mobile Safari User-Agent, with CriOS/<ChromeRevision> instead of Version/<VersionNum>.
458
  * - Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3
459
  */
460
+ static function is_chrome_for_iOS( ) {
461
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
462
  return false;
463
+
464
  if ( self::is_iphone_or_ipod( 'iphone-safari' ) === false ) return false;
465
+
466
  $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
467
+
468
  if ( strpos( $ua, 'crios/' ) !== false )
469
  return true;
470
  else
471
  return false;
472
  }
473
+
474
+
475
  /*
476
  * Detects if the current UA is Twitter for iPhone
477
+ *
478
  * Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; nb-no) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8L1 Twitter for iPhone
479
  * Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 Twitter for iPhone
480
+ *
481
  */
482
+ static function is_twitter_for_iphone( ) {
483
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
484
  return false;
485
+
486
  $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
487
 
488
  if ( strpos( $ua, 'ipad' ) !== false )
489
  return false;
490
+
491
  if ( strpos( $ua, 'twitter for iphone' ) !== false )
492
  return true;
493
  else
494
  return false;
495
  }
496
+
497
  /*
498
  * Detects if the current UA is Twitter for iPad
499
+ *
500
  * Old version 4.X - Mozilla/5.0 (iPad; U; CPU OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8L1 Twitter for iPad
501
  * Ver 5.0 or Higher - Mozilla/5.0 (iPad; CPU OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 Twitter for iPhone
502
+ *
503
  */
504
+ static function is_twitter_for_ipad( ) {
505
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
506
  return false;
507
+
508
  $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
509
 
510
  if ( strpos( $ua, 'twitter for ipad' ) !== false )
514
  else
515
  return false;
516
  }
517
+
518
 
519
  /*
520
  * Detects if the current UA is Facebook for iPhone
522
  * - Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/O2;FBID/phone;FBLC/en_US;FBSF/2.0]
523
  * - Mozilla/5.0 (iPhone; CPU iPhone OS 5_1_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B206 [FBAN/FBIOS;FBAV/5.0;FBBV/47423;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.1.1;FBSS/2; FBCR/3ITA;FBID/phone;FBLC/en_US]
524
  */
525
+ static function is_facebook_for_iphone( ) {
526
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
527
  return false;
528
 
547
  * - Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]
548
  * - Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10A403 [FBAN/FBIOS;FBAV/5.0;FBBV/47423;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/6.0;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US]
549
  */
550
+ static function is_facebook_for_ipad( ) {
551
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
552
  return false;
553
 
565
  /*
566
  * Detects if the current UA is WordPress for iOS
567
  */
568
+ static function is_wordpress_for_ios( ) {
569
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
570
  return false;
571
 
585
  * Otherwise those browsers will be 'catched' by the ipad string.
586
  *
587
  */
588
+ static function is_ipad( $type = 'ipad-any' ) {
589
 
590
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
591
  return false;
610
  * Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.1.1) Gecko/20110415 Firefox/4.0.2pre Fennec/4.0.1
611
  * Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b2pre) Gecko/20081015 Fennec/1.0a1
612
  */
613
+ static function is_firefox_mobile( ) {
614
 
615
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
616
  return false;
624
  }
625
 
626
 
627
+ /*
628
+ * Detects if the current browser is FirefoxOS Native browser
629
+ *
630
+ * Mozilla/5.0 (Mobile; rv:14.0) Gecko/14.0 Firefox/14.0
631
+ *
632
+ */
633
+ static function is_firefox_os( ) {
634
+
635
+ if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
636
+ return false;
637
+
638
+ $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
639
+
640
+ if ( strpos( $ua, 'mozilla' ) !== false && strpos( $ua, 'mobile' ) !== false && strpos( $ua, 'gecko' ) !== false && strpos( $ua, 'firefox' ) !== false)
641
+ return true;
642
+ else
643
+ return false;
644
+ }
645
+
646
+
647
  /*
648
  * Detects if the current browser is Opera Mobile
649
  *
655
  *
656
  * Opera/9.80 (Windows NT 6.1; Opera Mobi/14316; U; en) Presto/2.7.81 Version/11.00"
657
  */
658
+ static function is_opera_mobile( ) {
659
 
660
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
661
  return false;
681
  * Opera/9.80 (BlackBerry; Opera Mini/5.1.22303/22.387; U; en) Presto/2.5.25 Version/10.54
682
  *
683
  */
684
+ static function is_opera_mini( ) {
685
 
686
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
687
  return false;
698
  * Detects if the current browser is Opera Mini, but not on a smart device OS(Android, iOS, etc)
699
  * Used to send users on dumb devices to m.wor
700
  */
701
+ static function is_opera_mini_dumb( ) {
702
 
703
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
704
  return false;
722
  * Opera Mini 5 Beta: Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.15650/756; U; en) Presto/2.2.0
723
  * Opera Mini 8: Opera/8.01 (J2ME/MIDP; Opera Mini/3.0.6306/1528; en; U; ssr)
724
  */
725
+ static function is_OperaMobile() {
726
  _deprecated_function( __FUNCTION__, 'always', 'is_opera_mini() or is_opera_mobile()' );
727
 
728
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
744
  * Detects if the current browser is a Windows Phone 7 device.
745
  * ex: Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; LG; GW910)
746
  */
747
+ static function is_WindowsPhone7() {
748
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
749
  return false;
750
 
764
  * Detects if the current browser is a Windows Phone 8 device.
765
  * ex: Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; ARM; Touch; IEMobile/10.0; <Manufacturer>; <Device> [;<Operator>])
766
  */
767
+ static function is_windows_phone_8() {
768
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
769
  return false;
770
+
771
  $ua = strtolower( $_SERVER['HTTP_USER_AGENT'] );
772
  if ( strpos( $ua, 'windows phone 8' ) === false ) {
773
  return false;
775
  return true;
776
  }
777
  }
778
+
779
+
780
  /*
781
  * Detects if the current browser is on a Palm device running the new WebOS. This EXCLUDES TouchPad.
782
  *
784
  * ex2: Mozilla/5.0 (webOS/1.4.0; U; en-US) AppleWebKit/532.2 (KHTML, like Gecko) Version/1.0 Safari/532.2 Pixi/1.1
785
  *
786
  */
787
+ static function is_PalmWebOS() {
788
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
789
  return false;
790
 
807
  * TouchPad: Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0
808
  *
809
  */
810
+ static function is_TouchPad() {
811
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
812
  return false;
813
 
833
  * Browser 7.1 (Nokia N97 (v12.0.024)) : Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/12.0.024; Profile/MIDP-2.1 Configuration/CLDC-1.1; en-us) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.12344
834
  *
835
  */
836
+ static function is_S60_OSSBrowser() {
837
 
838
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
839
  return false;
863
  * Detects if the device platform is the Symbian Series 60.
864
  *
865
  */
866
+ static function is_symbian_platform() {
867
 
868
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
869
  return false;
896
  * This browser will report 'NokiaBrowser' in the header, however some older version will also report 'OviBrowser'.
897
  *
898
  */
899
+ static function is_symbian_s40_platform() {
900
 
901
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
902
  return false;
911
  return false;
912
  }
913
 
914
+ static function is_J2ME_platform() {
915
 
916
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
917
  return false;
931
  /*
932
  * Detects if the current UA is on one of the Maemo-based Nokia Internet Tablets.
933
  */
934
+ static function is_MaemoTablet() {
935
 
936
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
937
  return false;
954
  /*
955
  * Detects if the current UA is a MeeGo device (Nokia Smartphone).
956
  */
957
+ static function is_MeeGo() {
958
 
959
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
960
  return false;
975
  /*
976
  is_webkit() can be used to check the User Agent for an webkit generic browser
977
  */
978
+ static function is_webkit() {
979
 
980
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
981
  return false;
994
  * Detects if the current browser is the Native Android browser.
995
  * @return boolean true if the browser is Android otherwise false
996
  */
997
+ static function is_android() {
998
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
999
  return false;
1000
 
1017
  *
1018
  * @return boolean true if the browser is Android and not 'mobile' otherwise false
1019
  */
1020
+ static function is_android_tablet( ) {
1021
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1022
  return false;
1023
 
1044
  *
1045
  * @return boolean true if the browser is Kindle Fire Native browser otherwise false
1046
  */
1047
+ static function is_kindle_fire( ) {
1048
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1049
  return false;
1050
 
1065
  *
1066
  * @return boolean true if the browser is Kindle monochrome Native browser otherwise false
1067
  */
1068
+ static function is_kindle_touch( ) {
1069
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1070
  return false;
1071
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1078
 
1079
 
1080
  // Detect if user agent is the WordPress.com Windows 8 app (used ONLY on the custom oauth stylesheet)
1081
+ static function is_windows8_auth( ) {
1082
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1083
  return false;
1084
 
1091
  }
1092
 
1093
  // Detect if user agent is the WordPress.com Windows 8 app.
1094
+ static function is_wordpress_for_win8( ) {
1095
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1096
  return false;
1097
+
1098
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1099
  $pos = strpos( $agent, 'wp-windows8' );
1100
  if ( $pos !== false )
1102
  else
1103
  return false;
1104
  }
1105
+
1106
+
1107
  /*
1108
  * is_blackberry_tablet() can be used to check the User Agent for a RIM blackberry tablet
1109
  * The user agent of the BlackBerry® Tablet OS follows a format similar to the following:
1110
  * Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/0.0.1 Safari/534.8+
1111
  *
1112
  */
1113
+ static function is_blackberry_tablet() {
1114
 
1115
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1116
  return false;
1131
  is_blackbeberry() can be used to check the User Agent for a blackberry device
1132
  Note that opera mini on BB matches this rule.
1133
  */
1134
+ static function is_blackbeberry() {
1135
 
1136
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1137
  return false;
1138
 
1139
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1140
+
1141
  $pos_blackberry = strpos( $agent, 'blackberry' );
1142
  if ( $pos_blackberry !== false ) {
1143
  if ( self::is_opera_mini() || self::is_opera_mobile() || self::is_firefox_mobile() )
1152
  /*
1153
  is_blackberry_10() can be used to check the User Agent for a BlackBerry 10 device.
1154
  */
1155
+ static function is_blackberry_10() {
1156
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1157
  return ( strpos( $agent, 'bb10' ) !== false ) && ( strpos( $agent, 'mobile' ) !== false );
1158
  }
1173
  * @return string Version of the BB OS.
1174
  * If version is not found, get_blackbeberry_OS_version will return boolean false.
1175
  */
1176
+ static function get_blackbeberry_OS_version() {
1177
 
1178
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1179
  return false;
1180
 
1181
  if ( self::is_blackberry_10() )
1182
  return 'blackberry-10';
1183
+
1184
  $agent = strtolower( $_SERVER['HTTP_USER_AGENT'] );
1185
 
1186
  $pos_blackberry = stripos( $agent, 'blackberry' );
1255
  * @return string Type of the BB browser.
1256
  * If browser's version is not found, detect_blackbeberry_browser_version will return boolean false.
1257
  */
1258
+ static function detect_blackberry_browser_version() {
1259
 
1260
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1261
  return false;
1264
 
1265
  if ( self::is_blackberry_10() )
1266
  return 'blackberry-10';
1267
+
1268
  $pos_blackberry = strpos( $agent, 'blackberry' );
1269
  if ( $pos_blackberry === false ) {
1270
  //not a blackberry device
1302
  }
1303
 
1304
  //Checks if a visitor is coming from one of the WordPress mobile apps
1305
+ static function is_mobile_app() {
1306
 
1307
  if ( empty( $_SERVER['HTTP_USER_AGENT'] ) )
1308
  return false;
1326
  return false;
1327
  }
1328
 
1329
+ /**
1330
+ * Was the current request made by a known bot?
1331
+ *
1332
+ * @return boolean
1333
+ */
1334
  static function is_bot() {
1335
+ static $is_bot = null;
 
1336
 
1337
+ if ( is_null( $is_bot ) ) {
1338
+ $is_bot = Jetpack_User_Agent_Info::is_bot_user_agent( $_SERVER['HTTP_USER_AGENT'] );
1339
+ }
1340
 
1341
+ return $is_bot;
1342
+ }
1343
 
1344
+ /**
1345
+ * Is the given user-agent a known bot?
1346
+ * If you want an is_bot check for the current request's UA, use is_bot() instead of passing a user-agent to this method.
1347
+ *
1348
+ * @param $ua (string) A user-agent string
1349
+ * @return boolean
1350
+ */
1351
+ static function is_bot_user_agent( $ua = null ) {
1352
 
1353
+ if ( empty( $ua ) )
1354
+ return false;
1355
 
1356
+ $bot_agents = array(
1357
+ 'alexa', 'altavista', 'ask jeeves', 'attentio', 'baiduspider', 'bingbot', 'chtml generic', 'crawler', 'fastmobilecrawl',
1358
+ 'feedfetcher-google', 'firefly', 'froogle', 'gigabot', 'googlebot', 'googlebot-mobile', 'heritrix', 'ia_archiver', 'irlbot',
1359
+ 'infoseek', 'jumpbot', 'lycos', 'mediapartners', 'mediobot', 'motionbot', 'msnbot', 'mshots', 'openbot',
1360
+ 'pss-webkit-request', // See http://systemsrequests.wordpress.com/2013/07/30/log-request-to-help-us-with-this-issue
1361
+ 'pythumbnail', 'scooter', 'slurp', 'snapbot', 'spider', 'taptubot', 'technoratisnoop',
1362
+ 'teoma', 'twiceler', 'yahooseeker', 'yahooysmcm', 'yammybot',
1363
+ );
1364
+
1365
+ foreach ( $bot_agents as $bot_agent ) {
1366
+ if ( false !== stripos( $ua, $bot_agent ) ) {
1367
+ return true;
1368
  }
1369
  }
1370
 
1371
+ return false;
1372
  }
1373
+
1374
+
1375
+
1376
  }
class.jetpack.php ADDED
@@ -0,0 +1,3723 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ Options:
5
+ jetpack_options (array)
6
+ An array of options.
7
+ @see Jetpack::get_option_names()
8
+
9
+ jetpack_register (string)
10
+ Temporary verification secrets.
11
+
12
+ jetpack_activated (int)
13
+ 1: the plugin was activated normally
14
+ 2: the plugin was activated on this site because of a network-wide activation
15
+ 3: the plugin was auto-installed
16
+ 4: the plugin was manually disconnected (but is still installed)
17
+
18
+ jetpack_active_modules (array)
19
+ Array of active module slugs.
20
+
21
+ jetpack_do_activate (bool)
22
+ Flag for "activating" the plugin on sites where the activation hook never fired (auto-installs)
23
+ */
24
+
25
+ class Jetpack {
26
+ var $xmlrpc_server = null;
27
+
28
+ private $xmlrpc_verification = null;
29
+
30
+ var $HTTP_RAW_POST_DATA = null; // copy of $GLOBALS['HTTP_RAW_POST_DATA']
31
+
32
+ var $plugins_to_deactivate = array(
33
+ 'stats' => array( 'stats/stats.php', 'WordPress.com Stats' ),
34
+ 'shortlinks' => array( 'stats/stats.php', 'WordPress.com Stats' ),
35
+ 'sharedaddy' => array( 'sharedaddy/sharedaddy.php', 'Sharedaddy' ),
36
+ 'twitter-widget' => array( 'wickett-twitter-widget/wickett-twitter-widget.php', 'Wickett Twitter Widget' ),
37
+ 'after-the-deadline' => array( 'after-the-deadline/after-the-deadline.php', 'After The Deadline' ),
38
+ 'contact-form' => array( 'grunion-contact-form/grunion-contact-form.php', 'Grunion Contact Form' ),
39
+ 'custom-css' => array( 'safecss/safecss.php', 'WordPress.com Custom CSS' ),
40
+ );
41
+
42
+ var $capability_translations = array(
43
+ 'administrator' => 'manage_options',
44
+ 'editor' => 'edit_others_posts',
45
+ 'author' => 'publish_posts',
46
+ 'contributor' => 'edit_posts',
47
+ 'subscriber' => 'read',
48
+ );
49
+
50
+ /**
51
+ * Message to display in admin_notice
52
+ * @var string
53
+ */
54
+ var $message = '';
55
+
56
+ /**
57
+ * Error to display in admin_notice
58
+ * @var string
59
+ */
60
+ var $error = '';
61
+
62
+ /**
63
+ * Modules that need more privacy description.
64
+ * @var string
65
+ */
66
+ var $privacy_checks = '';
67
+
68
+ /**
69
+ * Stats to record once the page loads
70
+ *
71
+ * @var array
72
+ */
73
+ var $stats = array();
74
+
75
+ /**
76
+ * Jetpack_Sync object
77
+ */
78
+ var $sync;
79
+
80
+ /**
81
+ * Verified data for JSON authorization request
82
+ */
83
+ var $json_api_authorization_request = array();
84
+
85
+ /**
86
+ * Holds the singleton instance of this class
87
+ * @since 2.3.3
88
+ * @var Jetpack
89
+ */
90
+ static $instance = false;
91
+
92
+ /**
93
+ * Singleton
94
+ * @static
95
+ */
96
+ public static function init() {
97
+ if ( ! self::$instance ) {
98
+ if ( did_action( 'plugins_loaded' ) )
99
+ self::plugin_textdomain();
100
+ else
101
+ add_action( 'plugins_loaded', array( __CLASS__, 'plugin_textdomain' ) );
102
+
103
+ self::$instance = new Jetpack;
104
+
105
+ self::$instance->plugin_upgrade();
106
+ }
107
+
108
+ return self::$instance;
109
+ }
110
+
111
+ /**
112
+ * Must never be called statically
113
+ */
114
+ function plugin_upgrade() {
115
+ // Upgrade: 1.1 -> 1.2
116
+ if ( get_option( 'jetpack_id' ) ) {
117
+ // Move individual jetpack options to single array of options
118
+ $options = array();
119
+ foreach ( Jetpack::get_option_names() as $option ) {
120
+ if ( false !== $value = get_option( "jetpack_$option" ) ) {
121
+ $options[$option] = $value;
122
+ }
123
+ }
124
+
125
+ if ( $options ) {
126
+ Jetpack::update_options( $options );
127
+
128
+ foreach ( array_keys( $options ) as $option ) {
129
+ delete_option( "jetpack_$option" );
130
+ }
131
+ }
132
+
133
+ // Add missing version and old_version options
134
+ if ( !$version = Jetpack::get_option( 'version' ) ) {
135
+ $version = $old_version = '1.1:' . time();
136
+ Jetpack::update_options( compact( 'version', 'old_version' ) );
137
+ }
138
+ }
139
+
140
+ // Upgrade from a single user token to a user_id-indexed array and a master_user ID
141
+ if ( !Jetpack::get_option( 'user_tokens' ) ) {
142
+ if ( $user_token = Jetpack::get_option( 'user_token' ) ) {
143
+ $token_parts = explode( '.', $user_token );
144
+ if ( isset( $token_parts[2] ) ) {
145
+ $master_user = $token_parts[2];
146
+ $user_tokens = array( $master_user => $user_token );
147
+ Jetpack::update_options( compact( 'master_user', 'user_tokens' ) );
148
+ Jetpack::delete_option( 'user_token' );
149
+ } else {
150
+ // @todo: is this even possible?
151
+ trigger_error( sprintf( 'Jetpack::plugin_upgrade found no user_id in user_token "%s"', $user_token ), E_USER_WARNING );
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Constructor. Initializes WordPress hooks
159
+ */
160
+ private function Jetpack() {
161
+ $this->sync = new Jetpack_Sync;
162
+
163
+ // Modules should do Jetpack_Sync::sync_options( __FILE__, $option, ... ); instead
164
+ // We access the "internal" method here only because the Jetpack object isn't instantiated yet
165
+ $this->sync->options( __FILE__,
166
+ 'home',
167
+ 'siteurl',
168
+ 'blogname',
169
+ 'gmt_offset',
170
+ 'timezone_string'
171
+ );
172
+
173
+ if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && isset( $_GET['for'] ) && 'jetpack' == $_GET['for'] ) {
174
+ @ini_set( 'display_errors', false ); // Display errors can cause the XML to be not well formed.
175
+
176
+ require_once dirname( __FILE__ ) . '/class.jetpack-xmlrpc-server.php';
177
+ $this->xmlrpc_server = new Jetpack_XMLRPC_Server();
178
+
179
+ $this->require_jetpack_authentication();
180
+
181
+ if ( Jetpack::is_active() ) {
182
+ // Hack to preserve $HTTP_RAW_POST_DATA
183
+ add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
184
+
185
+ $signed = $this->verify_xml_rpc_signature();
186
+ if ( $signed && ! is_wp_error( $signed ) ) {
187
+ // The actual API methods.
188
+ add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'xmlrpc_methods' ) );
189
+ } else {
190
+ add_filter( 'xmlrpc_methods', '__return_empty_array' );
191
+ }
192
+ } else {
193
+ // The bootstrap API methods.
194
+ add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'bootstrap_xmlrpc_methods' ) );
195
+ }
196
+
197
+ // Now that no one can authenticate, and we're whitelisting all XML-RPC methods, force enable_xmlrpc on.
198
+ add_filter( 'pre_option_enable_xmlrpc', '__return_true' );
199
+ } elseif ( is_admin() && isset( $_POST['action'] ) && 'jetpack_upload_file' == $_POST['action'] ) {
200
+ $this->require_jetpack_authentication();
201
+ $this->add_remote_request_handlers();
202
+ } else {
203
+ if ( Jetpack::is_active() ) {
204
+ add_action( 'login_form_jetpack_json_api_authorization', array( &$this, 'login_form_json_api_authorization' ) );
205
+ }
206
+ }
207
+
208
+ if ( Jetpack::is_active() ) {
209
+ Jetpack_Heartbeat::init();
210
+ }
211
+
212
+ add_action( 'jetpack_clean_nonces', array( 'Jetpack', 'clean_nonces' ) );
213
+ if ( !wp_next_scheduled( 'jetpack_clean_nonces' ) ) {
214
+ wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
215
+ }
216
+
217
+ add_filter( 'xmlrpc_blog_options', array( $this, 'xmlrpc_options' ) );
218
+
219
+ add_action( 'admin_menu', array( $this, 'admin_menu' ), 999 ); // run late so that other plugins hooking into this menu don't get left out
220
+ add_action( 'admin_init', array( $this, 'admin_init' ) );
221
+ add_action( 'admin_init', array( $this, 'dismiss_jetpack_notice' ) );
222
+
223
+ add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
224
+
225
+ add_action( 'wp_ajax_jetpack-check-news-subscription', array( $this, 'check_news_subscription' ) );
226
+ add_action( 'wp_ajax_jetpack-subscribe-to-news', array( $this, 'subscribe_to_news' ) );
227
+
228
+ add_action( 'wp_loaded', array( $this, 'register_assets' ) );
229
+ add_action( 'wp_enqueue_scripts', array( $this, 'devicepx' ) );
230
+ add_action( 'customize_controls_enqueue_scripts', array( $this, 'devicepx' ) );
231
+ add_action( 'admin_enqueue_scripts', array( $this, 'devicepx' ) );
232
+
233
+ // add_action( 'jetpack_admin_menu', array( $this, 'admin_menu_modules' ) );
234
+
235
+ add_action( 'jetpack_activate_module', array( $this, 'activate_module_actions' ) );
236
+
237
+ /**
238
+ * These actions run checks to load additional files.
239
+ * They check for external files or plugins, so thef need to run as late as possible.
240
+ */
241
+ add_action( 'plugins_loaded', array( $this, 'check_open_graph' ), 999 );
242
+ add_action( 'plugins_loaded', array( $this, 'check_rest_api_compat' ), 1000 );
243
+ }
244
+
245
+ /**
246
+ * If there are any stats that need to be pushed, but haven't been, push them now.
247
+ */
248
+ function __destruct() {
249
+ if ( ! empty( $this->stats ) ) {
250
+ $this->do_stats( 'server_side' );
251
+ }
252
+ }
253
+
254
+ function require_jetpack_authentication() {
255
+ // Don't let anyone authenticate
256
+ $_COOKIE = array();
257
+ remove_all_filters( 'authenticate' );
258
+
259
+ if ( Jetpack::is_active() ) {
260
+ // Allow Jetpack authentication
261
+ add_filter( 'authenticate', array( $this, 'authenticate_jetpack' ), 10, 3 );
262
+ }
263
+ }
264
+
265
+ /**
266
+ * Load language files
267
+ */
268
+ public static function plugin_textdomain() {
269
+ load_plugin_textdomain( 'jetpack', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
270
+ }
271
+
272
+ /**
273
+ * Register assets for use in various modules and the Jetpack admin page.
274
+ *
275
+ * @uses wp_script_is, wp_register_script, plugins_url
276
+ * @action wp_loaded
277
+ * @return null
278
+ */
279
+ public function register_assets() {
280
+ if ( ! wp_script_is( 'spin', 'registered' ) )
281
+ wp_register_script( 'spin', plugins_url( '_inc/spin.js', __FILE__ ), false, '1.3' );
282
+
283
+ if ( ! wp_script_is( 'jquery.spin', 'registered' ) )
284
+ wp_register_script( 'jquery.spin', plugins_url( '_inc/jquery.spin.js', __FILE__ ) , array( 'jquery', 'spin' ), '1.3' );
285
+
286
+ if ( ! wp_script_is( 'jetpack-gallery-settings', 'registered' ) )
287
+ wp_register_script( 'jetpack-gallery-settings', plugins_url( '_inc/gallery-settings.js', __FILE__ ), array( 'media-views' ), '20121225' );
288
+
289
+ if ( ! wp_style_is( 'genericons', 'registered' ) )
290
+ wp_register_style( 'genericons', plugins_url( '_inc/genericons.css', __FILE__ ), false, '2.09' );
291
+ }
292
+
293
+ /**
294
+ * Device Pixels support
295
+ * This improves the resolution of gravatars and wordpress.com uploads on hi-res and zoomed browsers.
296
+ */
297
+ function devicepx() {
298
+ wp_enqueue_script( 'devicepx', ( is_ssl() ? 'https' : 'http' ) . '://s0.wp.com/wp-content/js/devicepx-jetpack.js', array(), gmdate('oW'), true );
299
+ }
300
+
301
+ /**
302
+ * Is Jetpack active?
303
+ */
304
+ public static function is_active() {
305
+ return (bool) Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
306
+ }
307
+
308
+ /**
309
+ * Is Jetpack in development (offline) mode?
310
+ */
311
+ public static function is_development_mode() {
312
+ $development_mode = false;
313
+
314
+ if ( defined( 'JETPACK_DEV_DEBUG' ) ) {
315
+ $development_mode = JETPACK_DEV_DEBUG;
316
+ }
317
+
318
+ elseif ( site_url() && false === strpos( site_url(), '.' ) ) {
319
+ $development_mode = true;
320
+ }
321
+
322
+ return apply_filters( 'jetpack_development_mode', $development_mode );
323
+ }
324
+
325
+ /**
326
+ * Is a given user (or the current user if none is specified) linked to a WordPress.com user?
327
+ */
328
+ public static function is_user_connected( $user_id = false ) {
329
+ $user_id = false === $user_id ? get_current_user_id() : absint( $user_id );
330
+ if ( !$user_id ) {
331
+ return false;
332
+ }
333
+ return (bool) Jetpack_Data::get_access_token( $user_id );
334
+ }
335
+
336
+ function current_user_is_connection_owner() {
337
+ $user_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
338
+ return $user_token && is_object( $user_token ) && isset( $user_token->external_user_id ) && get_current_user_id() === $user_token->external_user_id;
339
+ }
340
+
341
+ /**
342
+ * Synchronize connected user role changes
343
+ */
344
+ function user_role_change( $user_id ) {
345
+ if ( Jetpack::is_active() && Jetpack::is_user_connected( $user_id ) ) {
346
+
347
+ $current_user_id = get_current_user_id();
348
+ wp_set_current_user( $user_id );
349
+ $role = $this->translate_current_user_to_role();
350
+ $signed_role = $this->sign_role( $role );
351
+ wp_set_current_user( $current_user_id );
352
+
353
+ $master_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
354
+ $master_user_id = absint( $master_token->external_user_id );
355
+
356
+ if ( !$master_user_id )
357
+ return; // this shouldn't happen
358
+
359
+ Jetpack::xmlrpc_async_call( 'jetpack.updateRole', $user_id, $signed_role );
360
+ //@todo retry on failure
361
+
362
+ //try to choose a new master if we're demoting the current one
363
+ if ( $user_id == $master_user_id && 'administrator' != $role ) {
364
+ $query = new WP_User_Query( array(
365
+ 'fields' => array( 'id' ),
366
+ 'role' => 'administrator',
367
+ 'orderby' => 'id',
368
+ 'exclude' => array( $master_user_id ),
369
+ )
370
+ );
371
+ $new_master = false;
372
+ foreach ( $query->results as $result ) {
373
+ $uid = absint( $result->id );
374
+ if ( $uid && Jetpack::is_user_connected( $uid ) ) {
375
+ $new_master = $uid;
376
+ break;
377
+ }
378
+ }
379
+
380
+ if ( $new_master ) {
381
+ Jetpack::update_option( 'master_user', $new_master );
382
+ }
383
+ // else disconnect..?
384
+ }
385
+ }
386
+ }
387
+
388
+ /**
389
+ * Loads the currently active modules.
390
+ */
391
+ public static function load_modules() {
392
+
393
+ /*
394
+ if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
395
+ return;
396
+ }
397
+ */
398
+
399
+ $version = Jetpack::get_option( 'version' );
400
+ if ( !$version ) {
401
+ $version = $old_version = JETPACK__VERSION . ':' . time();
402
+ Jetpack::update_options( compact( 'version', 'old_version' ) );
403
+ }
404
+ list( $version ) = explode( ':', $version );
405
+
406
+ $modules = array_filter( Jetpack::get_active_modules(), array( 'Jetpack', 'is_module' ) );
407
+
408
+ $modules_data = array();
409
+
410
+ // Don't load modules that have had "Major" changes since the stored version until they have been deactivated/reactivated through the lint check.
411
+ if ( version_compare( $version, JETPACK__VERSION, '<' ) ) {
412
+ $updated_modules = array();
413
+ foreach ( $modules as $module ) {
414
+ $modules_data[ $module ] = Jetpack::get_module( $module );
415
+ if ( ! isset( $modules_data[ $module ]['changed'] ) ) {
416
+ continue;
417
+ }
418
+
419
+ if ( version_compare( $modules_data[ $module ]['changed'], $version, '<=' ) ) {
420
+ continue;
421
+ }
422
+
423
+ $updated_modules[] = $module;
424
+ }
425
+
426
+ $modules = array_diff( $modules, $updated_modules );
427
+ }
428
+
429
+ foreach ( $modules as $module ) {
430
+ // If not connected and we're in dev mode, disable modules requiring a connection
431
+ if ( ! Jetpack::is_active() ) {
432
+ if ( empty( $modules_data[ $module ] ) ) {
433
+ $modules_data[ $module ] = Jetpack::get_module( $module );
434
+ }
435
+ if ( $modules_data[ $module ]['requires_connection'] || ! Jetpack::is_development_mode() ) {
436
+ continue;
437
+ }
438
+ }
439
+
440
+ if ( did_action( 'jetpack_module_loaded_' . $module ) ) {
441
+ continue;
442
+ }
443
+
444
+ require Jetpack::get_module_path( $module );
445
+ do_action( 'jetpack_module_loaded_' . $module );
446
+ }
447
+
448
+ do_action( 'jetpack_modules_loaded' );
449
+
450
+ // Load module-specific code that is needed even when a module isn't active. Loaded here because code contained therein may need actions such as setup_theme.
451
+ require_once( dirname( __FILE__ ) . '/modules/module-extras.php' );
452
+ }
453
+
454
+ /**
455
+ * Check if Jetpack's REST API compat file should be included
456
+ * @action plugins_loaded
457
+ * @return null
458
+ */
459
+ public function check_rest_api_compat() {
460
+ $_jetpack_rest_api_compat_includes = apply_filters( 'jetpack_rest_api_compat', array() );
461
+
462
+ if ( function_exists( 'bbpress' ) )
463
+ $_jetpack_rest_api_compat_includes[] = dirname( __FILE__ ) . '/class.jetpack-bbpress-json-api-compat.php';
464
+
465
+ foreach ( $_jetpack_rest_api_compat_includes as $_jetpack_rest_api_compat_include )
466
+ require_once $_jetpack_rest_api_compat_include;
467
+ }
468
+
469
+ /**
470
+ * Check if Jetpack's Open Graph tags should be used.
471
+ * If certain plugins are active, Jetpack's og tags are suppressed.
472
+ *
473
+ * @uses Jetpack::get_active_modules, add_filter, get_option, apply_filters
474
+ * @action plugins_loaded
475
+ * @return null
476
+ */
477
+ public function check_open_graph() {
478
+ if ( in_array( 'publicize', Jetpack::get_active_modules() ) || in_array( 'sharedaddy', Jetpack::get_active_modules() ) )
479
+ add_filter( 'jetpack_enable_open_graph', '__return_true', 0 );
480
+
481
+ $active_plugins = get_option( 'active_plugins', array() );
482
+
483
+ if ( is_multisite() ) {
484
+ // Due to legacy code, active_sitewide_plugins stores them in the keys,
485
+ // whereas active_plugins stores them in the values.
486
+ $network_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
487
+ if ( $network_plugins ) {
488
+ $active_plugins = array_merge( $active_plugins, $network_plugins );
489
+ }
490
+ }
491
+
492
+ $conflicting_plugins = array(
493
+ 'facebook/facebook.php', // Official Facebook plugin
494
+ 'wordpress-seo/wp-seo.php', // WordPress SEO by Yoast
495
+ 'add-link-to-facebook/add-link-to-facebook.php', // Add Link to Facebook
496
+ 'facebook-awd/AWD_facebook.php', // Facebook AWD All in one
497
+ 'header-footer/plugin.php', // Header and Footer
498
+ 'nextgen-facebook/nextgen-facebook.php', // NextGEN Facebook OG
499
+ 'seo-facebook-comments/seofacebook.php', // SEO Facebook Comments
500
+ 'seo-ultimate/seo-ultimate.php', // SEO Ultimate
501
+ 'sexybookmarks/sexy-bookmarks.php', // Shareaholic
502
+ 'shareaholic/sexy-bookmarks.php', // Shareaholic
503
+ 'social-discussions/social-discussions.php', // Social Discussions
504
+ 'social-networks-auto-poster-facebook-twitter-g/NextScripts_SNAP.php', // NextScripts SNAP
505
+ 'wordbooker/wordbooker.php', // Wordbooker
506
+ 'socialize/socialize.php', // Socialize
507
+ 'simple-facebook-connect/sfc.php', // Simple Facebook Connect
508
+ 'social-sharing-toolkit/social_sharing_toolkit.php', // Social Sharing Toolkit
509
+ 'wp-facebook-open-graph-protocol/wp-facebook-ogp.php', // WP Facebook Open Graph protocol
510
+ 'opengraph/opengraph.php', // Open Graph
511
+ 'sharepress/sharepress.php', // SharePress
512
+ 'wp-facebook-like-send-open-graph-meta/wp-facebook-like-send-open-graph-meta.php', // WP Facebook Like Send & Open Graph Meta
513
+ 'network-publisher/networkpub.php', // Network Publisher
514
+ 'wp-ogp/wp-ogp.php', // WP-OGP
515
+ );
516
+
517
+ foreach ( $conflicting_plugins as $plugin ) {
518
+ if ( in_array( $plugin, $active_plugins ) ) {
519
+ add_filter( 'jetpack_enable_open_graph', '__return_false', 99 );
520
+ break;
521
+ }
522
+ }
523
+
524
+ if ( apply_filters( 'jetpack_enable_open_graph', false ) )
525
+ require_once dirname( __FILE__ ) . '/functions.opengraph.php';
526
+ }
527
+
528
+ /* Jetpack Options API */
529
+
530
+ public static function get_option_names( $type = 'compact' ) {
531
+ return Jetpack_Options::get_option_names( $type );
532
+ }
533
+
534
+ /**
535
+ * Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate.
536
+ *
537
+ * @param string $name Option name
538
+ * @param mixed $default (optional)
539
+ */
540
+ public static function get_option( $name, $default = false ) {
541
+ return Jetpack_Options::get_option( $name, $default );
542
+ }
543
+
544
+ /**
545
+ * Stores two secrets and a timestamp so WordPress.com can make a request back and verify an action
546
+ * Does some extra verification so urls (such as those to public-api, register, etc) cant just be crafted
547
+ * $name must be a registered option name.
548
+ */
549
+ public static function create_nonce( $name ) {
550
+ $secret = wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 );
551
+
552
+ Jetpack::update_option( $name, $secret );
553
+ @list( $secret_1, $secret_2, $eol ) = explode( ':', Jetpack::get_option( $name ) );
554
+ if ( empty( $secret_1 ) || empty( $secret_2 ) || $eol < time() )
555
+ return new Jetpack_Error( 'missing_secrets' );
556
+
557
+ return array(
558
+ 'secret_1' => $secret_1,
559
+ 'secret_2' => $secret_2,
560
+ 'eol' => $eol,
561
+ );
562
+ }
563
+
564
+ /**
565
+ * Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate.
566
+ *
567
+ * @param string $name Option name
568
+ * @param mixed $value Option value
569
+ */
570
+ public static function update_option( $name, $value ) {
571
+ return Jetpack_Options::update_option( $name, $value );
572
+ }
573
+
574
+ /**
575
+ * Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate.
576
+ *
577
+ * @param array $array array( option name => option value, ... )
578
+ */
579
+ public static function update_options( $array ) {
580
+ return Jetpack_Options::update_options( $array );
581
+ }
582
+
583
+ /**
584
+ * Deletes the given option. May be passed multiple option names as an array.
585
+ * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
586
+ *
587
+ * @param string|array $names
588
+ */
589
+ public static function delete_option( $names ) {
590
+ return Jetpack_Options::delete_option( $names );
591
+ }
592
+
593
+ /**
594
+ * Enters a user token into the user_tokens option
595
+ *
596
+ * @param int $user_id
597
+ * @param string $token
598
+ * return bool
599
+ */
600
+ public static function update_user_token( $user_id, $token, $is_master_user ) {
601
+ // not designed for concurrent updates
602
+ $user_tokens = Jetpack::get_option( 'user_tokens' );
603
+ if ( ! is_array( $user_tokens ) )
604
+ $user_tokens = array();
605
+ $user_tokens[$user_id] = $token;
606
+ if ( $is_master_user ) {
607
+ $master_user = $user_id;
608
+ $options = compact('user_tokens', 'master_user');
609
+ } else {
610
+ $options = compact('user_tokens');
611
+ }
612
+ return Jetpack::update_options( $options );
613
+ }
614
+
615
+ /**
616
+ * Returns an array of all PHP files in the specified absolute path.
617
+ * Equivalent to glob( "$absolute_path/*.php" ).
618
+ *
619
+ * @param string $absolute_path The absolute path of the directory to search.
620
+ * @return array Array of absolute paths to the PHP files.
621
+ */
622
+ public static function glob_php( $absolute_path ) {
623
+ $absolute_path = untrailingslashit( $absolute_path );
624
+ $files = array();
625
+ if ( !$dir = @opendir( $absolute_path ) ) {
626
+ return $files;
627
+ }
628
+
629
+ while ( false !== $file = readdir( $dir ) ) {
630
+ if ( '.' == substr( $file, 0, 1 ) || '.php' != substr( $file, -4 ) ) {
631
+ continue;
632
+ }
633
+
634
+ $file = "$absolute_path/$file";
635
+
636
+ if ( !is_file( $file ) ) {
637
+ continue;
638
+ }
639
+
640
+ $files[] = $file;
641
+ }
642
+
643
+ closedir( $dir );
644
+
645
+ return $files;
646
+ }
647
+
648
+ public function activate_new_modules() {
649
+ if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
650
+ return;
651
+ }
652
+
653
+ $jetpack_old_version = Jetpack::get_option( 'version' ); // [sic]
654
+ if ( !$jetpack_old_version ) {
655
+ $jetpack_old_version = $version = $old_version = '1.1:' . time();
656
+ Jetpack::update_options( compact( 'version', 'old_version' ) );
657
+ }
658
+
659
+ list( $jetpack_version ) = explode( ':', $jetpack_old_version ); // [sic]
660
+
661
+ if ( version_compare( JETPACK__VERSION, $jetpack_version, '<=' ) ) {
662
+ return;
663
+ }
664
+
665
+ $active_modules = Jetpack::get_active_modules();
666
+ $reactivate_modules = array();
667
+ foreach ( $active_modules as $active_module ) {
668
+ $module = Jetpack::get_module( $active_module );
669
+ if ( !isset( $module['changed'] ) ) {
670
+ continue;
671
+ }
672
+
673
+ if ( version_compare( $module['changed'], $jetpack_version, '<=' ) ) {
674
+ continue;
675
+ }
676
+
677
+ $reactivate_modules[] = $active_module;
678
+ Jetpack::deactivate_module( $active_module );
679
+ }
680
+
681
+ if ( version_compare( $jetpack_version, '1.9.2', '<' ) && version_compare( '1.9-something', JETPACK__VERSION, '<' ) ) {
682
+ add_action( 'jetpack_activate_default_modules', array( $this->sync, 'sync_all_registered_options' ), 1000 );
683
+ }
684
+
685
+ Jetpack::update_options( array(
686
+ 'version' => JETPACK__VERSION . ':' . time(),
687
+ 'old_version' => $jetpack_old_version,
688
+ ) );
689
+
690
+ Jetpack::state( 'message', 'modules_activated' );
691
+ Jetpack::activate_default_modules( $jetpack_version, JETPACK__VERSION, $reactivate_modules );
692
+ wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
693
+ exit;
694
+ }
695
+
696
+ /**
697
+ * List available Jetpack modules. Simply lists .php files in /modules/.
698
+ * Make sure to tuck away module "library" files in a sub-directory.
699
+ */
700
+ public static function get_available_modules( $min_version = false, $max_version = false ) {
701
+ static $modules = null;
702
+
703
+ if ( !isset( $modules ) ) {
704
+ $files = Jetpack::glob_php( dirname( __FILE__ ) . '/modules' );
705
+
706
+ $modules = array();
707
+
708
+ foreach ( $files as $file ) {
709
+ if ( !$headers = Jetpack::get_module( $file ) ) {
710
+ continue;
711
+ }
712
+
713
+ $modules[ Jetpack::get_module_slug( $file ) ] = $headers['introduced'];
714
+ }
715
+ }
716
+
717
+ if ( !$min_version && !$max_version ) {
718
+ return array_keys( $modules );
719
+ }
720
+
721
+ $r = array();
722
+ foreach ( $modules as $slug => $introduced ) {
723
+ if ( $min_version && version_compare( $min_version, $introduced, '>=' ) ) {
724
+ continue;
725
+ }
726
+
727
+ if ( $max_version && version_compare( $max_version, $introduced, '<' ) ) {
728
+ continue;
729
+ }
730
+
731
+ $r[] = $slug;
732
+ }
733
+
734
+ return $r;
735
+ }
736
+
737
+ /**
738
+ * Default modules loaded on activation.
739
+ */
740
+ public static function get_default_modules( $min_version = false, $max_version = false ) {
741
+ $return = array();
742
+
743
+ foreach ( Jetpack::get_available_modules( $min_version, $max_version ) as $module ) {
744
+ // Add special cases here for modules to avoid auto-activation
745
+ switch ( $module ) {
746
+
747
+ // These modules are default off: they change things blog-side
748
+ case 'comments' :
749
+ case 'carousel' :
750
+ case 'minileven':
751
+ case 'infinite-scroll' :
752
+ case 'photon' :
753
+ case 'tiled-gallery' :
754
+ case 'likes' :
755
+ break;
756
+
757
+ // These modules are default off if we think the site is a private one
758
+ case 'enhanced-distribution' :
759
+ case 'json-api' :
760
+ if ( !Jetpack::get_option( 'public' ) ) {
761
+ break;
762
+ }
763
+ // else no break
764
+ // The rest are default on
765
+ default :
766
+ $return[] = $module;
767
+ }
768
+ }
769
+
770
+ return $return;
771
+ }
772
+
773
+ /**
774
+ * Extract a module's slug from its full path.
775
+ */
776
+ public static function get_module_slug( $file ) {
777
+ return str_replace( '.php', '', basename( $file ) );
778
+ }
779
+
780
+ /**
781
+ * Generate a module's path from its slug.
782
+ */
783
+ public static function get_module_path( $slug ) {
784
+ return dirname( __FILE__ ) . "/modules/$slug.php";
785
+ }
786
+
787
+ /**
788
+ * Load module data from module file. Headers differ from WordPress
789
+ * plugin headers to avoid them being identified as standalone
790
+ * plugins on the WordPress plugins page.
791
+ */
792
+ public static function get_module( $module ) {
793
+ $headers = array(
794
+ 'name' => 'Module Name',
795
+ 'description' => 'Module Description',
796
+ 'sort' => 'Sort Order',
797
+ 'introduced' => 'First Introduced',
798
+ 'changed' => 'Major Changes In',
799
+ 'deactivate' => 'Deactivate',
800
+ 'free' => 'Free',
801
+ 'requires_connection' => 'Requires Connection',
802
+ );
803
+
804
+ $file = Jetpack::get_module_path( Jetpack::get_module_slug( $module ) );
805
+ if ( !file_exists( $file ) )
806
+ return false;
807
+
808
+ $mod = get_file_data( $file, $headers );
809
+ if ( empty( $mod['name'] ) )
810
+ return false;
811
+
812
+ $mod['name'] = translate( $mod['name'], 'jetpack' );
813
+ $mod['description'] = translate( $mod['description'], 'jetpack' );
814
+ if ( empty( $mod['sort'] ) )
815
+ $mod['sort'] = 10;
816
+ $mod['deactivate'] = empty( $mod['deactivate'] );
817
+ $mod['free'] = empty( $mod['free'] );
818
+ $mod['requires_connection'] = ( ! empty( $mod['requires_connection'] ) && 'No' == $mod['requires_connection'] ) ? false : true;
819
+ return $mod;
820
+ }
821
+
822
+ /**
823
+ * Get a list of activated modules as an array of module slugs.
824
+ */
825
+ public static function get_active_modules() {
826
+ $active = Jetpack::get_option( 'active_modules' );
827
+ if ( !is_array( $active ) )
828
+ $active = array();
829
+ if ( is_admin() ) {
830
+ $active[] = 'vaultpress';
831
+ } else {
832
+ $active = array_diff( $active, array( 'vaultpress' ) );
833
+ }
834
+ return array_unique( $active );
835
+ }
836
+
837
+ /**
838
+ * Check whether or not a Jetpack module is active.
839
+ *
840
+ * @param string $module The slug of a Jetpack module.
841
+ * @return bool
842
+ *
843
+ * @static
844
+ */
845
+ public static function is_module_active( $module ) {
846
+ return in_array( $module, self::get_active_modules() );
847
+ }
848
+
849
+ public static function is_module( $module ) {
850
+ return !empty( $module ) && !validate_file( $module, Jetpack::get_available_modules() );
851
+ }
852
+
853
+ /**
854
+ * Catches PHP errors. Must be used in conjunction with output buffering.
855
+ *
856
+ * @param bool $catch True to start catching, False to stop.
857
+ *
858
+ * @static
859
+ */
860
+ public static function catch_errors( $catch ) {
861
+ static $display_errors, $error_reporting;
862
+
863
+ if ( $catch ) {
864
+ $display_errors = @ini_set( 'display_errors', 1 );
865
+ $error_reporting = @error_reporting( E_ALL );
866
+ add_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 0 );
867
+ } else {
868
+ @ini_set( 'display_errors', $display_errors );
869
+ @error_reporting( $error_reporting );
870
+ remove_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 1 );
871
+ }
872
+ }
873
+
874
+ /**
875
+ * Saves any generated PHP errors in ::state( 'php_errors', {errors} )
876
+ */
877
+ public static function catch_errors_on_shutdown() {
878
+ Jetpack::state( 'php_errors', ob_get_clean() );
879
+ }
880
+
881
+ public static function activate_default_modules( $min_version = false, $max_version = false, $other_modules = array() ) {
882
+ $jetpack = Jetpack::init();
883
+
884
+ $modules = Jetpack::get_default_modules( $min_version, $max_version );
885
+ $modules = array_merge( $other_modules, $modules );
886
+
887
+ // Look for standalone plugins and disable if active.
888
+
889
+ $to_deactivate = array();
890
+ foreach ( $modules as $module ) {
891
+ if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) {
892
+ $to_deactivate[$module] = $jetpack->plugins_to_deactivate[$module];
893
+ }
894
+ }
895
+
896
+ $deactivated = array();
897
+ foreach ( $to_deactivate as $module => $deactivate_me ) {
898
+ list( $probable_file, $probable_title ) = $deactivate_me;
899
+ if ( Jetpack_Client_Server::deactivate_plugin( $probable_file, $probable_title ) ) {
900
+ $deactivated[] = $module;
901
+ }
902
+ }
903
+
904
+ if ( $deactivated ) {
905
+ Jetpack::state( 'deactivated_plugins', join( ',', $deactivated ) );
906
+
907
+ $url = add_query_arg( array(
908
+ 'action' => 'activate_default_modules',
909
+ '_wpnonce' => wp_create_nonce( 'activate_default_modules' ),
910
+ ), add_query_arg( compact( 'min_version', 'max_version', 'other_modules' ), Jetpack::admin_url( 'page=jetpack' ) ) );
911
+ wp_safe_redirect( $url );
912
+ exit;
913
+ }
914
+
915
+ do_action( 'jetpack_before_activate_default_modules', $min_version, $max_version, $other_modules );
916
+
917
+ // Check each module for fatal errors, a la wp-admin/plugins.php::activate before activating
918
+ $redirect = menu_page_url( 'jetpack', false );
919
+ Jetpack::restate();
920
+ Jetpack::catch_errors( true );
921
+ foreach ( $modules as $module ) {
922
+ if ( did_action( "jetpack_module_loaded_$module" ) ) {
923
+ $active[] = $module;
924
+ Jetpack::update_option( 'active_modules', array_unique( $active ) );
925
+ continue;
926
+ }
927
+ $active = Jetpack::get_active_modules();
928
+ if ( in_array( $module, $active ) ) {
929
+ $module_info = Jetpack::get_module( $module );
930
+ if ( !$module_info['deactivate'] ) {
931
+ $state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules';
932
+ if ( $active_state = Jetpack::state( $state ) ) {
933
+ $active_state = explode( ',', $active_state );
934
+ } else {
935
+ $active_state = array();
936
+ }
937
+ $active_state[] = $module;
938
+ Jetpack::state( $state, implode( ',', $active_state ) );
939
+ }
940
+ continue;
941
+ }
942
+
943
+ $file = Jetpack::get_module_path( $module );
944
+ if ( !file_exists( $file ) ) {
945
+ continue;
946
+ }
947
+
948
+ // we'll override this later if the plugin can be included without fatal error
949
+ wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
950
+ Jetpack::state( 'error', 'module_activation_failed' );
951
+ Jetpack::state( 'module', $module );
952
+ ob_start();
953
+ require $file;
954
+ do_action( 'jetpack_activate_module', $module );
955
+ $active[] = $module;
956
+ $state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules';
957
+ if ( $active_state = Jetpack::state( $state ) ) {
958
+ $active_state = explode( ',', $active_state );
959
+ } else {
960
+ $active_state = array();
961
+ }
962
+ $active_state[] = $module;
963
+ Jetpack::state( $state, implode( ',', $active_state ) );
964
+ Jetpack::update_option( 'active_modules', array_unique( $active ) );
965
+ ob_end_clean();
966
+ }
967
+ Jetpack::state( 'error', false );
968
+ Jetpack::state( 'module', false );
969
+ Jetpack::catch_errors( false );
970
+ do_action( 'jetpack_activate_default_modules', $min_version, $max_version, $other_modules );
971
+ }
972
+
973
+ public static function activate_module( $module, $exit = true ) {
974
+ $jetpack = Jetpack::init();
975
+
976
+ if ( ! strlen( $module ) )
977
+ return false;
978
+
979
+ if ( ! Jetpack::is_module( $module ) )
980
+ return false;
981
+
982
+ // If it's already active, then don't do it again
983
+ $active = Jetpack::get_active_modules();
984
+ foreach ( $active as $act ) {
985
+ if ( $act == $module )
986
+ return true;
987
+ }
988
+
989
+ $module_data = Jetpack::get_module( $module );
990
+
991
+ if ( ! Jetpack::is_active() ) {
992
+ if ( ! Jetpack::is_development_mode() )
993
+ return false;
994
+
995
+ // If we're not connected but in development mode, make sure the module doesn't require a connection
996
+ if ( Jetpack::is_development_mode() && $module_data['requires_connection'] )
997
+ return false;
998
+ }
999
+
1000
+ // Check and see if the old plugin is active
1001
+ if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) {
1002
+ // Deactivate the old plugin
1003
+ if ( Jetpack_Client_Server::deactivate_plugin( $jetpack->plugins_to_deactivate[$module][0], $jetpack->plugins_to_deactivate[$module][1] ) ) {
1004
+ // If we deactivated the old plugin, remembere that with ::state() and redirect back to this page to activate the module
1005
+ // We can't activate the module on this page load since the newly deactivated old plugin is still loaded on this page load.
1006
+ Jetpack::state( 'deactivated_plugins', $module );
1007
+ wp_safe_redirect( add_query_arg( 'jetpack_restate', 1 ) );
1008
+ exit;
1009
+ }
1010
+ }
1011
+
1012
+ // Check the file for fatal errors, a la wp-admin/plugins.php::activate
1013
+ Jetpack::state( 'module', $module );
1014
+ Jetpack::state( 'error', 'module_activation_failed' ); // we'll override this later if the plugin can be included without fatal error
1015
+ wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
1016
+
1017
+ Jetpack::catch_errors( true );
1018
+ ob_start();
1019
+ require Jetpack::get_module_path( $module );
1020
+ do_action( 'jetpack_activate_module', $module );
1021
+ $active[] = $module;
1022
+ Jetpack::update_option( 'active_modules', array_unique( $active ) );
1023
+ Jetpack::state( 'error', false ); // the override
1024
+ Jetpack::state( 'message', 'module_activated' );
1025
+ Jetpack::state( 'module', $module );
1026
+ ob_end_clean();
1027
+ Jetpack::catch_errors( false );
1028
+
1029
+ if ( $exit ) {
1030
+ exit;
1031
+ }
1032
+ }
1033
+
1034
+ function activate_module_actions( $module ) {
1035
+ do_action( "jetpack_activate_module_$module" );
1036
+
1037
+ $this->sync->sync_all_module_options( $module );
1038
+ }
1039
+
1040
+ public static function deactivate_module( $module ) {
1041
+ $active = Jetpack::get_active_modules();
1042
+ $new = array();
1043
+ foreach ( $active as $check ) {
1044
+ if ( !empty( $check ) && $module != $check )
1045
+ $new[] = $check;
1046
+ }
1047
+
1048
+ do_action( "jetpack_deactivate_module_$module" );
1049
+ return Jetpack::update_option( 'active_modules', array_unique( $new ) );
1050
+ }
1051
+
1052
+ public static function enable_module_configurable( $module ) {
1053
+ $module = Jetpack::get_module_slug( $module );
1054
+ add_filter( 'jetpack_module_configurable_' . $module, '__return_true' );
1055
+ }
1056
+
1057
+ public static function module_configuration_url( $module ) {
1058
+ $module = Jetpack::get_module_slug( $module );
1059
+ return Jetpack::admin_url( array( 'page' => 'jetpack', 'configure' => $module ) );
1060
+ }
1061
+
1062
+ public static function module_configuration_load( $module, $method ) {
1063
+ $module = Jetpack::get_module_slug( $module );
1064
+ add_action( 'jetpack_module_configuration_load_' . $module, $method );
1065
+ }
1066
+
1067
+ public static function module_configuration_head( $module, $method ) {
1068
+ $module = Jetpack::get_module_slug( $module );
1069
+ add_action( 'jetpack_module_configuration_head_' . $module, $method );
1070
+ }
1071
+
1072
+ public static function module_configuration_screen( $module, $method ) {
1073
+ $module = Jetpack::get_module_slug( $module );
1074
+ add_action( 'jetpack_module_configuration_screen_' . $module, $method );
1075
+ }
1076
+
1077
+ /* Installation */
1078
+
1079
+ public static function bail_on_activation( $message, $deactivate = true ) {
1080
+ ?>
1081
+ <!doctype html>
1082
+ <html>
1083
+ <head>
1084
+ <meta charset="<?php bloginfo( 'charset' ); ?>">
1085
+ <style>
1086
+ * {
1087
+ text-align: center;
1088
+ margin: 0;
1089
+ padding: 0;
1090
+ font-family: "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif;
1091
+ }
1092
+ p {
1093
+ margin-top: 1em;
1094
+ font-size: 18px;
1095
+ }
1096
+ </style>
1097
+ <body>
1098
+ <p><?php echo esc_html( $message ); ?></p>
1099
+ </body>
1100
+ </html>
1101
+ <?php
1102
+ if ( $deactivate ) {
1103
+ $plugins = get_option( 'active_plugins' );
1104
+ $jetpack = plugin_basename( __FILE__ );
1105
+ $update = false;
1106
+ foreach ( $plugins as $i => $plugin ) {
1107
+ if ( $plugin === $jetpack ) {
1108
+ $plugins[$i] = false;
1109
+ $update = true;
1110
+ }
1111
+ }
1112
+
1113
+ if ( $update ) {
1114
+ update_option( 'active_plugins', array_filter( $plugins ) );
1115
+ }
1116
+ }
1117
+ exit;
1118
+ }
1119
+
1120
+ /**
1121
+ * Attached to activate_{ plugin_basename( __FILES__ ) } by register_activation_hook()
1122
+ * @static
1123
+ */
1124
+ public static function plugin_activation( $network_wide ) {
1125
+ Jetpack::update_option( 'activated', 1 );
1126
+
1127
+ if ( version_compare( $GLOBALS['wp_version'], JETPACK__MINIMUM_WP_VERSION, '<' ) ) {
1128
+ Jetpack::bail_on_activation( sprintf( __( 'Jetpack requires WordPress version %s or later.', 'jetpack' ), JETPACK__MINIMUM_WP_VERSION ) );
1129
+ }
1130
+
1131
+ if ( $network_wide )
1132
+ Jetpack::state( 'network_nag', true );
1133
+
1134
+ Jetpack::plugin_initialize();
1135
+ }
1136
+
1137
+ /**
1138
+ * Sets the internal version number and activation state.
1139
+ * @static
1140
+ */
1141
+ public static function plugin_initialize() {
1142
+ if ( !Jetpack::get_option( 'activated' ) ) {
1143
+ Jetpack::update_option( 'activated', 2 );
1144
+ }
1145
+
1146
+ if ( !Jetpack::get_option( 'version' ) ) {
1147
+ $version = $old_version = JETPACK__VERSION . ':' . time();
1148
+ Jetpack::update_options( compact( 'version', 'old_version' ) );
1149
+ }
1150
+
1151
+ Jetpack::load_modules();
1152
+
1153
+ Jetpack::delete_option( 'do_activate' );
1154
+ }
1155
+
1156
+ /**
1157
+ * Removes all connection options
1158
+ * @static
1159
+ */
1160
+ public static function plugin_deactivation( ) {
1161
+ Jetpack::disconnect( false );
1162
+
1163
+ Jetpack_Heartbeat::init()->deactivate();
1164
+ }
1165
+
1166
+ /**
1167
+ * Disconnects from the Jetpack servers.
1168
+ * Forgets all connection details and tells the Jetpack servers to do the same.
1169
+ * @static
1170
+ */
1171
+ public static function disconnect( $update_activated_state = true ) {
1172
+ wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
1173
+ Jetpack::clean_nonces( true );
1174
+
1175
+ Jetpack::load_xml_rpc_client();
1176
+ $xml = new Jetpack_IXR_Client();
1177
+ $xml->query( 'jetpack.deregister' );
1178
+
1179
+ Jetpack::delete_option( array(
1180
+ 'register',
1181
+ 'blog_token',
1182
+ 'user_token',
1183
+ 'user_tokens',
1184
+ 'master_user',
1185
+ 'time_diff',
1186
+ 'fallback_no_verify_ssl_certs',
1187
+ ) );
1188
+
1189
+ if ( $update_activated_state ) {
1190
+ Jetpack::update_option( 'activated', 4 );
1191
+ }
1192
+ }
1193
+
1194
+ /**
1195
+ * Unlinks the current user from the linked WordPress.com user
1196
+ */
1197
+ function unlink_user() {
1198
+ if ( !$tokens = Jetpack::get_option( 'user_tokens' ) )
1199
+ return false;
1200
+
1201
+ $user_id = get_current_user_id();
1202
+
1203
+ if ( Jetpack::get_option( 'master_user' ) == $user_id )
1204
+ return false;
1205
+
1206
+ if ( !isset( $tokens[$user_id] ) )
1207
+ return false;
1208
+
1209
+ Jetpack::load_xml_rpc_client();
1210
+ $xml = new Jetpack_IXR_Client( compact( 'user_id' ) );
1211
+ $xml->query( 'jetpack.unlink_user', $user_id );
1212
+
1213
+ unset( $tokens[$user_id] );
1214
+
1215
+ Jetpack::update_option( 'user_tokens', $tokens );
1216
+
1217
+ return true;
1218
+ }
1219
+
1220
+ /**
1221
+ * Attempts Jetpack registration. If it fail, a state flag is set: @see ::admin_page_load()
1222
+ */
1223
+ public static function try_registration() {
1224
+ $result = Jetpack::register();
1225
+
1226
+ // If there was an error with registration and the site was not registered, record this so we can show a message.
1227
+ if ( !$result || is_wp_error( $result ) ) {
1228
+ return $result;
1229
+ } else {
1230
+ return true;
1231
+ }
1232
+ }
1233
+
1234
+ /* Admin Pages */
1235
+
1236
+ function admin_init() {
1237
+ // If the plugin is not connected, display a connect message.
1238
+ if (
1239
+ // the plugin was auto-activated and needs its candy
1240
+ Jetpack::get_option( 'do_activate' )
1241
+ ||
1242
+ // the plugin is active, but was never activated. Probably came from a site-wide network activation
1243
+ !Jetpack::get_option( 'activated' )
1244
+ ) {
1245
+ Jetpack::plugin_initialize();
1246
+ }
1247
+
1248
+ if ( !Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
1249
+ if ( 4 != Jetpack::get_option( 'activated' ) ) {
1250
+ // Show connect notice on dashboard and plugins pages
1251
+ add_action( 'load-index.php', array( $this, 'prepare_connect_notice' ) );
1252
+ add_action( 'load-plugins.php', array( $this, 'prepare_connect_notice' ) );
1253
+ }
1254
+ } elseif ( false === Jetpack::get_option( 'fallback_no_verify_ssl_certs' ) ) {
1255
+ // Upgrade: 1.1 -> 1.1.1
1256
+ // Check and see if host can verify the Jetpack servers' SSL certificate
1257
+ $args = array();
1258
+ Jetpack_Client::_wp_remote_request(
1259
+ Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'test' ), $args ),
1260
+ $args,
1261
+ true
1262
+ );
1263
+ }
1264
+ /* Toggle this off as it's not ready for prime time just yet.
1265
+ if( current_user_can( 'manage_options' ) && self::check_identity_crisis() ) {
1266
+ add_action( 'admin_notices', array( $this, 'alert_identity_crisis' ) );
1267
+ }
1268
+ /**/
1269
+
1270
+ if ( current_user_can( 'manage_options' ) && 'ALWAYS' == JETPACK_CLIENT__HTTPS && ! self::permit_ssl() ) {
1271
+ add_action( 'admin_notices', array( $this, 'alert_required_ssl_fail' ) );
1272
+ }
1273
+
1274
+ add_action( 'load-plugins.php', array( $this, 'intercept_plugin_error_scrape_init' ) );
1275
+ add_action( 'admin_head', array( $this, 'admin_menu_css' ) );
1276
+ add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
1277
+
1278
+ if ( Jetpack::is_active() || Jetpack::is_development_mode() ) {
1279
+ // Artificially throw errors in certain whitelisted cases during plugin activation
1280
+ add_action( 'activate_plugin', array( $this, 'throw_error_on_activate_plugin' ) );
1281
+
1282
+ // Kick off synchronization of user role when it changes
1283
+ add_action( 'set_user_role', array( $this, 'user_role_change' ) );
1284
+ }
1285
+ }
1286
+
1287
+ function admin_body_class( $admin_body_class = '' ) {
1288
+ if ( self::is_active() ) {
1289
+ $admin_body_class .= ' jetpack-connected';
1290
+ } else {
1291
+ $admin_body_class .= ' jetpack-disconnected';
1292
+ }
1293
+ return $admin_body_class;
1294
+ }
1295
+
1296
+ function prepare_connect_notice() {
1297
+ add_action( 'admin_print_styles', array( $this, 'admin_styles' ) );
1298
+
1299
+ add_action( 'admin_notices', array( $this, 'admin_connect_notice' ) );
1300
+
1301
+ if ( Jetpack::state( 'network_nag' ) )
1302
+ add_action( 'network_admin_notices', array( $this, 'network_connect_notice' ) );
1303
+ }
1304
+
1305
+ /**
1306
+ * Sometimes a plugin can activate without causing errors, but it will cause errors on the next page load.
1307
+ * This function artificially throws errors for such cases (whitelisted).
1308
+ *
1309
+ * @param string $plugin The activated plugin.
1310
+ */
1311
+ function throw_error_on_activate_plugin( $plugin ) {
1312
+ $active_modules = Jetpack::get_active_modules();
1313
+
1314
+ // The Shortlinks module and the Stats plugin conflict, but won't cause errors on activation because of some function_exists() checks.
1315
+ if ( function_exists( 'stats_get_api_key' ) && in_array( 'shortlinks', $active_modules ) ) {
1316
+ $throw = false;
1317
+
1318
+ // Try and make sure it really was the stats plugin
1319
+ if ( !class_exists( 'ReflectionFunction' ) ) {
1320
+ if ( 'stats.php' == basename( $plugin ) ) {
1321
+ $throw = true;
1322
+ }
1323
+ } else {
1324
+ $reflection = new ReflectionFunction( 'stats_get_api_key' );
1325
+ if ( basename( $plugin ) == basename( $reflection->getFileName() ) ) {
1326
+ $throw = true;
1327
+ }
1328
+ }
1329
+
1330
+ if ( $throw ) {
1331
+ trigger_error( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), 'WordPress.com Stats' ), E_USER_ERROR );
1332
+ }
1333
+ }
1334
+ }
1335
+
1336
+ function intercept_plugin_error_scrape_init() {
1337
+ add_action( 'check_admin_referer', array( $this, 'intercept_plugin_error_scrape' ), 10, 2 );
1338
+ }
1339
+
1340
+ function intercept_plugin_error_scrape( $action, $result ) {
1341
+ if ( !$result ) {
1342
+ return;
1343
+ }
1344
+
1345
+ foreach ( $this->plugins_to_deactivate as $module => $deactivate_me ) {
1346
+ if ( "plugin-activation-error_{$deactivate_me[0]}" == $action ) {
1347
+ Jetpack::bail_on_activation( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), $deactivate_me[1] ), false );
1348
+ }
1349
+ }
1350
+ }
1351
+
1352
+ function admin_menu() {
1353
+ list( $jetpack_version ) = explode( ':', Jetpack::get_option( 'version' ) );
1354
+ if (
1355
+ $jetpack_version
1356
+ &&
1357
+ $jetpack_version != JETPACK__VERSION
1358
+ &&
1359
+ ( $new_modules = Jetpack::get_default_modules( $jetpack_version, JETPACK__VERSION ) )
1360
+ &&
1361
+ is_array( $new_modules )
1362
+ &&
1363
+ ( $new_modules_count = count( $new_modules ) )
1364
+ &&
1365
+ ( Jetpack::is_active() || Jetpack::is_development_mode() )
1366
+ ) {
1367
+ $new_modules_count_i18n = number_format_i18n( $new_modules_count );
1368
+ $span_title = esc_attr( sprintf( _n( 'One New Jetpack Module', '%s New Jetpack Modules', $new_modules_count, 'jetpack' ), $new_modules_count_i18n ) );
1369
+ $title = sprintf( 'Jetpack %s', "<span class='update-plugins count-{$new_modules_count}' title='$span_title'><span class='update-count'>$new_modules_count_i18n</span></span>" );
1370
+ } else {
1371
+ $title = __( 'Jetpack', 'jetpack' );
1372
+ }
1373
+
1374
+ $hook = add_menu_page( 'Jetpack', $title, 'read', 'jetpack', array( $this, 'admin_page' ), 'div' );
1375
+
1376
+ $debugger_hook = add_submenu_page( 'jetpack', 'Jetpack Debugging Center', '', 'manage_options', 'jetpack-debugger', array( $this, 'debugger_page' ) );
1377
+ add_action( "admin_head-$debugger_hook", 'jetpack_debug_admin_head' );
1378
+
1379
+
1380
+ add_action( "load-$hook", array( $this, 'admin_page_load' ) );
1381
+
1382
+ if ( version_compare( $GLOBALS['wp_version'], '3.3', '<' ) ) {
1383
+ if ( isset( $_GET['page'] ) && 'jetpack' == $_GET['page'] ) {
1384
+ add_contextual_help( $hook, $this->jetpack_help() );
1385
+ }
1386
+ } else {
1387
+ add_action( "load-$hook", array( $this, 'admin_help' ) );
1388
+ }
1389
+ add_action( "admin_head-$hook", array( $this, 'admin_head' ) );
1390
+ add_filter( 'custom_menu_order', array( $this, 'admin_menu_order' ) );
1391
+ add_filter( 'menu_order', array( $this, 'jetpack_menu_order' ) );
1392
+
1393
+ add_action( "admin_print_styles-$hook", array( $this, 'admin_styles' ) );
1394
+
1395
+ add_action( "admin_print_scripts-$hook", array( $this, 'admin_scripts' ) );
1396
+
1397
+ do_action( 'jetpack_admin_menu' );
1398
+ }
1399
+ /*
1400
+ function admin_menu_modules() {
1401
+ $hook = add_submenu_page( 'jetpack', __( 'Jetpack Modules', 'jetpack' ), __( 'Modules', 'jetpack' ), 'edit_posts', 'jetpack_modules', array( $this, 'admin_page_modules' ) );
1402
+
1403
+ add_action( "load-$hook", array( $this, 'admin_page_load' ) );
1404
+ add_action( "load-$hook", array( $this, 'admin_help' ) );
1405
+ add_action( "admin_head-$hook", array( $this, 'admin_head' ) );
1406
+ add_action( "admin_print_styles-$hook", array( $this, 'admin_styles' ) );
1407
+ add_action( "admin_print_scripts-$hook", array( $this, 'admin_scripts' ) );
1408
+ }
1409
+ /**/
1410
+ function add_remote_request_handlers() {
1411
+ add_action( 'wp_ajax_nopriv_jetpack_upload_file', array( $this, 'remote_request_handlers' ) );
1412
+ }
1413
+
1414
+ function remote_request_handlers() {
1415
+ switch ( current_filter() ) {
1416
+ case 'wp_ajax_nopriv_jetpack_upload_file' :
1417
+ $response = $this->upload_handler();
1418
+ break;
1419
+ default :
1420
+ $response = new Jetpack_Error( 'unknown_handler', 'Unknown Handler', 400 );
1421
+ break;
1422
+ }
1423
+
1424
+ if ( !$response ) {
1425
+ $response = new Jetpack_Error( 'unknown_error', 'Unknown Error', 400 );
1426
+ }
1427
+
1428
+ if ( is_wp_error( $response ) ) {
1429
+ $status_code = $response->get_error_data();
1430
+ $error = $response->get_error_code();
1431
+ $error_description = $response->get_error_message();
1432
+
1433
+ if ( !is_int( $status_code ) ) {
1434
+ $status_code = 400;
1435
+ }
1436
+
1437
+ status_header( $status_code );
1438
+ die( json_encode( (object) compact( 'error', 'error_description' ) ) );
1439
+ }
1440
+
1441
+ status_header( 200 );
1442
+ if ( true === $response ) {
1443
+ exit;
1444
+ }
1445
+
1446
+ die( json_encode( (object) $response ) );
1447
+ }
1448
+
1449
+ function upload_handler() {
1450
+ if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
1451
+ return new Jetpack_Error( 405, get_status_header_desc( 405 ), 405 );
1452
+ }
1453
+
1454
+ $user = wp_authenticate( '', '' );
1455
+ if ( !$user || is_wp_error( $user ) ) {
1456
+ return new Jetpack_Error( 403, get_status_header_desc( 403 ), 403 );
1457
+ }
1458
+
1459
+ wp_set_current_user( $user->ID );
1460
+
1461
+ if ( !current_user_can( 'upload_files' ) ) {
1462
+ return new Jetpack_Error( 'cannot_upload_files', 'User does not have permission to upload files', 403 );
1463
+ }
1464
+
1465
+ if ( empty( $_FILES ) ) {
1466
+ return new Jetpack_Error( 'no_files_uploaded', 'No files were uploaded: nothing to process', 400 );
1467
+ }
1468
+
1469
+ foreach ( array_keys( $_FILES ) as $files_key ) {
1470
+ if ( !isset( $_POST["_jetpack_file_hmac_{$files_key}"] ) ) {
1471
+ return new Jetpack_Error( 'missing_hmac', 'An HMAC for one or more files is missing', 400 );
1472
+ }
1473
+ }
1474
+
1475
+ $media_keys = array_keys( $_FILES['media'] );
1476
+
1477
+ $token = Jetpack_Data::get_access_token( get_current_user_id() );
1478
+ if ( !$token || is_wp_error( $token ) ) {
1479
+ return new Jetpack_Error( 'unknown_token', 'Unknown Jetpack token', 403 );
1480
+ }
1481
+
1482
+ $uploaded_files = array();
1483
+ $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
1484
+ unset( $GLOBALS['post'] );
1485
+ foreach ( $_FILES['media']['name'] as $index => $name ) {
1486
+ $file = array();
1487
+ foreach ( $media_keys as $media_key ) {
1488
+ $file[$media_key] = $_FILES['media'][$media_key][$index];
1489
+ }
1490
+
1491
+ list( $hmac_provided, $salt ) = explode( ':', $_POST['_jetpack_file_hmac_media'][$index] );
1492
+
1493
+ $hmac_file = hash_hmac_file( 'sha1', $file['tmp_name'], $salt . $token->secret );
1494
+ if ( $hmac_provided !== $hmac_file ) {
1495
+ $uploaded_files[$index] = (object) array( 'error' => 'invalid_hmac', 'error_description' => 'The corresponding HMAC for this file does not match' );
1496
+ continue;
1497
+ }
1498
+
1499
+ $_FILES['.jetpack.upload.'] = $file;
1500
+ $post_id = isset( $_POST['post_id'][$index] ) ? absint( $_POST['post_id'][$index] ) : 0;
1501
+ if ( !current_user_can( 'edit_post', $post_id ) ) {
1502
+ $post_id = 0;
1503
+ }
1504
+ $attachment_id = media_handle_upload( '.jetpack.upload.', $post_id, array(), array(
1505
+ 'action' => 'jetpack_upload_file',
1506
+ ) );
1507
+
1508
+ if ( !$attachment_id ) {
1509
+ $uploaded_files[$index] = (object) array( 'error' => 'unknown', 'error_description' => 'An unknown problem occurred processing the upload on the Jetpack site' );
1510
+ } elseif ( is_wp_error( $attachment_id ) ) {
1511
+ $uploaded_files[$index] = (object) array( 'error' => 'attachment_' . $attachment_id->get_error_code(), 'error_description' => $attachment_id->get_error_message() );
1512
+ } else {
1513
+ $attachment = get_post( $attachment_id );
1514
+ $uploaded_files[$index] = (object) array(
1515
+ 'id' => (string) $attachment_id,
1516
+ 'file' => $attachment->post_title,
1517
+ 'url' => wp_get_attachment_url( $attachment_id ),
1518
+ 'type' => $attachment->post_mime_type,
1519
+ 'meta' => wp_get_attachment_metadata( $attachment_id ),
1520
+ );
1521
+ }
1522
+ }
1523
+ if ( !is_null( $global_post ) ) {
1524
+ $GLOBALS['post'] = $global_post;
1525
+ }
1526
+
1527
+ return $uploaded_files;
1528
+ }
1529
+
1530
+ /**
1531
+ * Add help to the Jetpack page
1532
+ *
1533
+ * Deprecated. Remove when Jetpack requires WP 3.3+
1534
+ */
1535
+ function jetpack_help() {
1536
+ return
1537
+ '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
1538
+ '<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' .
1539
+ '<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>' .
1540
+ '<p><strong>' . __( 'Jetpack Module Options', 'jetpack' ) . '</strong></p>' .
1541
+ '<p>' . __( '<strong>To Activate/Deactivate a Module</strong> - Click on Learn More. An Activate or Deactivate button will now appear next to the Learn More button. Click the Activate/Deactivate button.', 'jetpack' ) . '</p>' .
1542
+ '<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' .
1543
+ '<p><a href="http://jetpack.me/faq/" target="_blank">' . __( 'Jetpack FAQ', 'jetpack' ) . '</a></p>' .
1544
+ '<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></p>';
1545
+ }
1546
+
1547
+ /**
1548
+ * Add help to the Jetpack page
1549
+ *
1550
+ * @since Jetpack (1.2.3)
1551
+ * @return false if not the Jetpack page
1552
+ */
1553
+ function admin_help() {
1554
+ $current_screen = get_current_screen();
1555
+
1556
+ // Overview
1557
+ $current_screen->add_help_tab( array(
1558
+ 'id' => 'overview',
1559
+ 'title' => __( 'Overview', 'jetpack' ),
1560
+ 'content' =>
1561
+ '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
1562
+ '<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' .
1563
+ '<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>'
1564
+ ) );
1565
+
1566
+ // Screen Content
1567
+ if ( current_user_can( 'manage_options' ) ) {
1568
+ $current_screen->add_help_tab( array(
1569
+ 'id' => 'modules',
1570
+ 'title' => __( 'Modules', 'jetpack' ),
1571
+ 'content' =>
1572
+ '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
1573
+ '<p>' . __( 'You can activate or deactivate individual Jetpack modules to suit your needs.', 'jetpack' ) . '</p>' .
1574
+ '<ol>' .
1575
+ '<li>' . __( 'Find the component you want to manage', 'jetpack' ) . '</li>' .
1576
+ '<li>' . __( 'Click on Learn More', 'jetpack' ) . '</li>' .
1577
+ '<li>' . __( 'An Activate or Deactivate button will appear', 'jetpack' ) . '</li>' .
1578
+ '<li>' . __( 'If additional settings are available, a link to them will appear', 'jetpack' ) . '</li>' .
1579
+ '</ol>'
1580
+ ) );
1581
+ }
1582
+
1583
+ // Help Sidebar
1584
+ $current_screen->set_help_sidebar(
1585
+ '<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' .
1586
+ '<p><a href="http://jetpack.me/faq/" target="_blank">' . __( 'Jetpack FAQ', 'jetpack' ) . '</a></p>' .
1587
+ '<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></p>' .
1588
+ '<p><a href="' . Jetpack::admin_url( array( 'page' => 'jetpack-debugger' ) ) .'">' . __( 'Jetpack Debugging Center', 'jetpack' ) . '</a></p>'
1589
+
1590
+ );
1591
+ }
1592
+
1593
+ function admin_menu_css() { ?>
1594
+ <style type="text/css" id="jetpack-menu-css">
1595
+ #toplevel_page_jetpack .wp-menu-image {
1596
+ background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite.png' ) ?> ) 0 90% no-repeat;
1597
+ }
1598
+ /* Retina Jetpack Menu Icon */
1599
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
1600
+ #toplevel_page_jetpack .wp-menu-image {
1601
+ background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite-2x.png' ) ?> ) 0 90% no-repeat;
1602
+ background-size:30px 64px;
1603
+ }
1604
+ }
1605
+ #toplevel_page_jetpack.current .wp-menu-image,
1606
+ #toplevel_page_jetpack.wp-has-current-submenu .wp-menu-image,
1607
+ #toplevel_page_jetpack:hover .wp-menu-image {
1608
+ background-position: top left;
1609
+ }
1610
+ </style><?php
1611
+ }
1612
+
1613
+ function admin_menu_order() {
1614
+ return true;
1615
+ }
1616
+
1617
+ function jetpack_menu_order( $menu_order ) {
1618
+ $jp_menu_order = array();
1619
+
1620
+ foreach ( $menu_order as $index => $item ) {
1621
+ if ( $item != 'jetpack' )
1622
+ $jp_menu_order[] = $item;
1623
+
1624
+ if ( $index == 0 )
1625
+ $jp_menu_order[] = 'jetpack';
1626
+ }
1627
+
1628
+ return $jp_menu_order;
1629
+ }
1630
+
1631
+ function admin_head() {
1632
+ if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) )
1633
+ do_action( 'jetpack_module_configuration_head_' . $_GET['configure'] );
1634
+ }
1635
+
1636
+ function admin_styles() {
1637
+ global $wp_styles;
1638
+ wp_enqueue_style( 'jetpack', plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/jetpack.css' ), false, JETPACK__VERSION . '-20121016' );
1639
+ $wp_styles->add_data( 'jetpack', 'rtl', true );
1640
+ }
1641
+
1642
+ function admin_scripts() {
1643
+ wp_enqueue_script( 'jetpack-js', plugins_url( basename( dirname( __FILE__ ) ) ) . '/_inc/jetpack.js', array( 'jquery' ), JETPACK__VERSION . '-20121111' );
1644
+ wp_localize_script( 'jetpack-js', 'jetpackL10n', array(
1645
+ 'ays_disconnect' => "This will deactivate all Jetpack modules.\nAre you sure you want to disconnect?",
1646
+ 'ays_unlink' => "This will prevent user-specific modules such as Publicize, Notifications and Post By Email from working.\nAre you sure you want to unlink?",
1647
+ 'ays_dismiss' => "This will deactivate Jetpack.\nAre you sure you want to deactivate Jetpack?",
1648
+ ) );
1649
+ add_action( 'admin_footer', array( $this, 'do_stats' ) );
1650
+ }
1651
+
1652
+ function plugin_action_links( $actions ) {
1653
+ return array_merge(
1654
+ array( 'settings' => sprintf( '<a href="%s">%s</a>', Jetpack::admin_url(), __( 'Settings', 'jetpack' ) ) ),
1655
+ $actions
1656
+ );
1657
+ return $actions;
1658
+ }
1659
+
1660
+ function admin_connect_notice() {
1661
+ // Don't show the connect notice on the jetpack settings page. @todo: must be a better way?
1662
+ if ( false !== strpos( $_SERVER['QUERY_STRING'], 'page=jetpack' ) )
1663
+ return;
1664
+
1665
+ if ( !current_user_can( 'manage_options' ) )
1666
+ return;
1667
+ ?>
1668
+
1669
+ <div id="message" class="updated jetpack-message jp-connect">
1670
+ <div id="jp-dismiss" class="jetpack-close-button-container">
1671
+ <a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?></a>
1672
+ </div>
1673
+ <div class="jetpack-wrap-container">
1674
+ <div class="jetpack-text-container">
1675
+ <h4>
1676
+ <?php if ( 1 == Jetpack::get_option( 'activated' ) ) : ?>
1677
+ <p><?php _e( '<strong>Your Jetpack is almost ready</strong> &#8211; A connection to WordPress.com is needed to enable features like Stats, Contact Forms, and Subscriptions. Connect now to get fueled up!', 'jetpack' ); ?></p>
1678
+ <?php else : ?>
1679
+ <p><?php _e( '<strong>Jetpack is installed</strong> and ready to bring awesome, WordPress.com cloud-powered features to your site.', 'jetpack' ) ?></p>
1680
+ <?php endif; ?>
1681
+ </h4>
1682
+ </div>
1683
+ <div class="jetpack-install-container">
1684
+ <?php if ( 1 == Jetpack::get_option( 'activated' ) ) : ?>
1685
+ <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
1686
+ <?php else : ?>
1687
+ <p class="submit"><a href="<?php echo Jetpack::admin_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Learn More', 'jetpack' ); ?></a></p>
1688
+ <?php endif; ?>
1689
+ </div>
1690
+ </div>
1691
+ </div>
1692
+
1693
+ <?php
1694
+ }
1695
+
1696
+ function network_connect_notice() {
1697
+ ?>
1698
+ <div id="message" class="updated jetpack-message">
1699
+ <div class="squeezer">
1700
+ <h4><?php _e( '<strong>Jetpack is activated!</strong> Each site on your network must be connected individually by an admin on that site.', 'jetpack' ) ?></h4>
1701
+ </div>
1702
+ </div>
1703
+ <?php
1704
+ }
1705
+
1706
+ public static function jetpack_comment_notice() {
1707
+ if ( in_array( 'comments', Jetpack::get_active_modules() ) ) {
1708
+ return '';
1709
+ }
1710
+
1711
+ $jetpack_old_version = explode( ':', Jetpack::get_option( 'old_version' ) );
1712
+ $jetpack_new_version = explode( ':', Jetpack::get_option( 'version' ) );
1713
+
1714
+ if ( $jetpack_old_version ) {
1715
+ if ( version_compare( $jetpack_old_version[0], '1.4', '>=' ) ) {
1716
+ return '';
1717
+ }
1718
+ }
1719
+
1720
+ if ( $jetpack_new_version ) {
1721
+ if ( version_compare( $jetpack_new_version[0], '1.4-something', '<' ) ) {
1722
+ return '';
1723
+ }
1724
+ }
1725
+
1726
+ return '<br /><br />' . sprintf(
1727
+ __( 'Jetpack now includes Jetpack Comments, which enables your visitors to use their WordPress.com, Twitter, or Facebook accounts when commenting on your site. To activate Jetpack Comments, <a href="%s">%s</a>.', 'jetpack' ),
1728
+ wp_nonce_url(
1729
+ Jetpack::admin_url( array(
1730
+ 'page' => 'jetpack',
1731
+ 'action' => 'activate',
1732
+ 'module' => 'comments',
1733
+ ) ),
1734
+ "jetpack_activate-comments"
1735
+ ),
1736
+ __( 'click here', 'jetpack' )
1737
+ );
1738
+ }
1739
+
1740
+ /*
1741
+ * Registration flow:
1742
+ * 1 - ::admin_page_load() action=register
1743
+ * 2 - ::try_registration()
1744
+ * 3 - ::register()
1745
+ * - Creates jetpack_register option containing two secrets and a timestamp
1746
+ * - Calls https://jetpack.wordpress.com/jetpack.register/1/ with
1747
+ * siteurl, home, gmt_offset, timezone_string, site_name, secret_1, secret_2, site_lang, timeout, stats_id
1748
+ * - That request to jetpack.wordpress.com does not immediately respond. It first makes a request BACK to this site's
1749
+ * xmlrpc.php?for=jetpack: RPC method: jetpack.verifyRegistration, Parameters: secret_1
1750
+ * - The XML-RPC request verifies secret_1, deletes both secrets and responds with: secret_2
1751
+ * - https://jetpack.wordpress.com/jetpack.register/1/ verifies that XML-RPC response (secret_2) then finally responds itself with
1752
+ * jetpack_id, jetpack_secret, jetpack_public
1753
+ * - ::register() then stores jetpack_options: id => jetpack_id, blog_token => jetpack_secret
1754
+ * 4 - redirect to https://jetpack.wordpress.com/jetpack.authorize/1/
1755
+ * 5 - user logs in with WP.com account
1756
+ * 6 - redirect to this site's wp-admin/index.php?page=jetpack&action=authorize with
1757
+ * code <-- OAuth2 style authorization code
1758
+ * 7 - ::admin_page_load() action=authorize
1759
+ * 8 - Jetpack_Client_Server::authorize()
1760
+ * 9 - Jetpack_Client_Server::get_token()
1761
+ * 10- GET https://jetpack.wordpress.com/jetpack.token/1/ with
1762
+ * client_id, client_secret, grant_type, code, redirect_uri:action=authorize, state, scope, user_email, user_login
1763
+ * 11- which responds with
1764
+ * access_token, token_type, scope
1765
+ * 12- Jetpack_Client_Server::authorize() stores jetpack_options: user_token => access_token.$user_id
1766
+ * 13- Jetpack::activate_default_modules()
1767
+ * Deactivates deprecated plugins
1768
+ * Activates all default modules
1769
+ * Catches errors: redirects to wp-admin/index.php?page=jetpack state:error=something
1770
+ * 14- redirect to this site's wp-admin/index.php?page=jetpack with state:message=authorized
1771
+ * Done!
1772
+ */
1773
+
1774
+ /**
1775
+ * Handles the page load events for the Jetpack admin page
1776
+ */
1777
+ function admin_page_load() {
1778
+ $error = false;
1779
+
1780
+ if ( !empty( $_GET['jetpack_restate'] ) ) {
1781
+ // Should only be used in intermediate redirects to preserve state across redirects
1782
+ Jetpack::restate();
1783
+ }
1784
+
1785
+ if ( isset( $_GET['connect_url_redirect'] ) ) {
1786
+ // User clicked in the iframe to link their accounts
1787
+ if ( ! Jetpack::is_user_connected() ) {
1788
+ $connect_url = $this->build_connect_url( true );
1789
+ if ( isset( $_GET['notes_iframe'] ) )
1790
+ $connect_url .= '&notes_iframe';
1791
+ wp_redirect( $connect_url );
1792
+ exit;
1793
+ } else {
1794
+ Jetpack::state( 'message', 'already_authorized' );
1795
+ wp_safe_redirect( Jetpack::admin_url() );
1796
+ exit;
1797
+ }
1798
+ }
1799
+
1800
+ if ( isset( $_GET['action'] ) ) {
1801
+ switch ( $_GET['action'] ) {
1802
+ case 'authorize' :
1803
+ if ( Jetpack::is_active() && Jetpack::is_user_connected() ) {
1804
+ Jetpack::state( 'message', 'already_authorized' );
1805
+ wp_safe_redirect( Jetpack::admin_url() );
1806
+ exit;
1807
+ }
1808
+ $client_server = new Jetpack_Client_Server;
1809
+ $client_server->authorize();
1810
+ exit;
1811
+ case 'register' :
1812
+ check_admin_referer( 'jetpack-register' );
1813
+ $registered = Jetpack::try_registration();
1814
+ if ( is_wp_error( $registered ) ) {
1815
+ $error = $registered->get_error_code();
1816
+ Jetpack::state( 'error_description', $registered->get_error_message() );
1817
+ break;
1818
+ }
1819
+
1820
+ wp_redirect( $this->build_connect_url( true ) );
1821
+ exit;
1822
+ case 'activate' :
1823
+ if ( ! current_user_can( 'manage_options' ) ) {
1824
+ $error = 'cheatin';
1825
+ break;
1826
+ }
1827
+
1828
+ $module = stripslashes( $_GET['module'] );
1829
+ check_admin_referer( "jetpack_activate-$module" );
1830
+ Jetpack::activate_module( $module );
1831
+ // The following two lines will rarely happen, as Jetpack::activate_module normally exits at the end.
1832
+ wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
1833
+ exit;
1834
+ case 'activate_default_modules' :
1835
+ check_admin_referer( 'activate_default_modules' );
1836
+ Jetpack::restate();
1837
+ $min_version = isset( $_GET['min_version'] ) ? $_GET['min_version'] : false;
1838
+ $max_version = isset( $_GET['max_version'] ) ? $_GET['max_version'] : false;
1839
+ $other_modules = isset( $_GET['other_modules'] ) && is_array( $_GET['other_modules'] ) ? $_GET['other_modules'] : array();
1840
+ Jetpack::activate_default_modules( $min_version, $max_version, $other_modules );
1841
+ wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
1842
+ exit;
1843
+ case 'disconnect' :
1844
+ check_admin_referer( 'jetpack-disconnect' );
1845
+ Jetpack::disconnect();
1846
+ wp_safe_redirect( Jetpack::admin_url() );
1847
+ exit;
1848
+ case 'reconnect' :
1849
+ if ( ! current_user_can( 'manage_options' ) ) {
1850
+ $error = 'cheatin';
1851
+ break;
1852
+ }
1853
+
1854
+ check_admin_referer( 'jetpack-reconnect' );
1855
+ $this->disconnect();
1856
+ wp_redirect( $this->build_connect_url( true ) );
1857
+ exit;
1858
+ case 'deactivate' :
1859
+ if ( ! current_user_can( 'manage_options' ) ) {
1860
+ $error = 'cheatin';
1861
+ break;
1862
+ }
1863
+
1864
+ $modules = stripslashes( $_GET['module'] );
1865
+ check_admin_referer( "jetpack_deactivate-$modules" );
1866
+ foreach ( explode( ',', $modules ) as $module ) {
1867
+ Jetpack::deactivate_module( $module );
1868
+ Jetpack::state( 'message', 'module_deactivated' );
1869
+ }
1870
+ Jetpack::state( 'module', $modules );
1871
+ wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
1872
+ exit;
1873
+ case 'unlink' :
1874
+ check_admin_referer( 'jetpack-unlink' );
1875
+ $this->unlink_user();
1876
+ Jetpack::state( 'message', 'unlinked' );
1877
+ wp_safe_redirect( Jetpack::admin_url() );
1878
+ exit;
1879
+ }
1880
+ }
1881
+
1882
+ if ( !$error = $error ? $error : Jetpack::state( 'error' ) ) {
1883
+ $this->activate_new_modules();
1884
+ }
1885
+
1886
+ switch ( $error ) {
1887
+ case 'cheatin' :
1888
+ $this->error = __( 'Cheatin&#8217; uh?', 'jetpack' );
1889
+ break;
1890
+ case 'access_denied' :
1891
+ $this->error = __( 'You need to authorize the Jetpack connection between your site and WordPress.com to enable the awesome features.', 'jetpack' );
1892
+ break;
1893
+ case 'wrong_state' :
1894
+ $this->error = __( "Don&#8217;t cross the streams! You need to stay logged in to your WordPress blog while you authorize Jetpack.", 'jetpack' );
1895
+ break;
1896
+ case 'invalid_client' :
1897
+ // @todo re-register instead of deactivate/reactivate
1898
+ $this->error = __( 'Return to sender. Whoops! It looks like you got the wrong Jetpack in the mail; deactivate then reactivate the Jetpack plugin to get a new one.', 'jetpack' );
1899
+ break;
1900
+ case 'invalid_grant' :
1901
+ $this->error = __( "Wrong size. Hm&#8230; it seems your Jetpack doesn&#8217;t quite fit. Have you lost weight? Click &#8220;Connect to WordPress.com&#8221; again to get your Jetpack adjusted.", 'jetpack' );
1902
+ break;
1903
+ case 'site_inaccessible' :
1904
+ case 'site_requires_authorization' :
1905
+ $this->error = sprintf( __( 'Your website needs to be publicly accessible to use Jetpack: %s', 'jetpack' ), "<code>$error</code>" );
1906
+ break;
1907
+ case 'module_activation_failed' :
1908
+ $module = Jetpack::state( 'module' );
1909
+ if ( !empty( $module ) && $mod = Jetpack::get_module( $module ) ) {
1910
+ $this->error = sprintf( __( '%s could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' ), $mod['name'] );
1911
+ if ( isset( $this->plugins_to_deactivate[$module] ) ) {
1912
+ $this->error .= ' ' . sprintf( __( 'Do you still have the %s plugin installed?', 'jetpack' ), $this->plugins_to_deactivate[$module][1] );
1913
+ }
1914
+ } else {
1915
+ $this->error = __( 'Module could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' );
1916
+ }
1917
+ if ( $php_errors = Jetpack::state( 'php_errors' ) ) {
1918
+ $this->error .= "<br />\n";
1919
+ $this->error .= $php_errors;
1920
+ }
1921
+ break;
1922
+ case 'not_public' :
1923
+ $this->error = __( "<strong>Your Jetpack has a glitch.</strong> Connecting this site with WordPress.com is not possible. This usually means your site is not publicly accessible (localhost).", 'jetpack' );
1924
+ break;
1925
+ case 'wpcom_408' :
1926
+ case 'wpcom_5??' :
1927
+ case 'wpcom_bad_response' :
1928
+ case 'wpcom_outage' :
1929
+ $this->error = __( 'WordPress.com is currently having problems and is unable to fuel up your Jetpack. Please try again later.', 'jetpack' );
1930
+ break;
1931
+ case 'register_http_request_failed' :
1932
+ case 'token_http_request_failed' :
1933
+ $this->error = sprintf( __( 'Jetpack could not contact WordPress.com: %s. This usually means something is incorrectly configured on your web host.', 'jetpack' ), "<code>$error</code>" );
1934
+ break;
1935
+ default :
1936
+ if ( empty( $error ) ) {
1937
+ break;
1938
+ }
1939
+ $error = trim( substr( strip_tags( $error ), 0, 20 ) );
1940
+ // no break: fall through
1941
+ case 'no_role' :
1942
+ case 'no_cap' :
1943
+ case 'no_code' :
1944
+ case 'no_state' :
1945
+ case 'invalid_state' :
1946
+ case 'invalid_request' :
1947
+ case 'invalid_scope' :
1948
+ case 'unsupported_response_type' :
1949
+ case 'invalid_token' :
1950
+ case 'no_token' :
1951
+ case 'missing_secrets' :
1952
+ case 'home_missing' :
1953
+ case 'siteurl_missing' :
1954
+ case 'gmt_offset_missing' :
1955
+ case 'site_name_missing' :
1956
+ case 'secret_1_missing' :
1957
+ case 'secret_2_missing' :
1958
+ case 'site_lang_missing' :
1959
+ case 'home_malformed' :
1960
+ case 'siteurl_malformed' :
1961
+ case 'gmt_offset_malformed' :
1962
+ case 'timezone_string_malformed' :
1963
+ case 'site_name_malformed' :
1964
+ case 'secret_1_malformed' :
1965
+ case 'secret_2_malformed' :
1966
+ case 'site_lang_malformed' :
1967
+ case 'secrets_mismatch' :
1968
+ case 'verify_secret_1_missing' :
1969
+ case 'verify_secret_1_malformed' :
1970
+ case 'verify_secrets_missing' :
1971
+ case 'verify_secrets_mismatch' :
1972
+ $error = esc_html( $error );
1973
+ $this->error = sprintf( __( "<strong>Your Jetpack has a glitch.</strong> Something went wrong that&#8217;s never supposed to happen. Guess you&#8217;re just lucky: %s", 'jetpack' ), "<code>$error</code>" );
1974
+ if ( !Jetpack::is_active() ) {
1975
+ $this->error .= '<br />';
1976
+ $this->error .= sprintf( __( 'Try connecting again.', 'jetpack' ) );
1977
+ }
1978
+ break;
1979
+ }
1980
+
1981
+ $message_code = Jetpack::state( 'message' );
1982
+
1983
+ $active_state = Jetpack::state( 'activated_modules' );
1984
+ if ( !empty( $active_state ) ) {
1985
+ $available = Jetpack::get_available_modules();
1986
+ $active_state = explode( ',', $active_state );
1987
+ $active_state = array_intersect( $active_state, $available );
1988
+ if ( count( $active_state ) ) {
1989
+ foreach ( $active_state as $mod ) {
1990
+ $this->stat( 'module-activated', $mod );
1991
+ }
1992
+ } else {
1993
+ $active_state = false;
1994
+ }
1995
+ }
1996
+
1997
+ switch ( $message_code ) {
1998
+ case 'modules_activated' :
1999
+ $this->message = sprintf(
2000
+ __( 'Welcome to <strong>Jetpack %s</strong>!', 'jetpack' ),
2001
+ JETPACK__VERSION
2002
+ );
2003
+
2004
+ if ( $active_state ) {
2005
+ $titles = array();
2006
+ foreach ( $active_state as $mod ) {
2007
+ if ( $mod_headers = Jetpack::get_module( $mod ) ) {
2008
+ $titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', '&nbsp;', $mod_headers['name'] ) . '</strong>';
2009
+ }
2010
+ }
2011
+ if ( $titles ) {
2012
+ $this->message .= '<br /><br />' . wp_sprintf( __( 'The following new modules have been activated: %l.', 'jetpack' ), $titles );
2013
+ }
2014
+ }
2015
+
2016
+ if ( $reactive_state = Jetpack::state( 'reactivated_modules' ) ) {
2017
+ $titles = array();
2018
+ foreach ( explode( ',', $reactive_state ) as $mod ) {
2019
+ if ( $mod_headers = Jetpack::get_module( $mod ) ) {
2020
+ $titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', '&nbsp;', $mod_headers['name'] ) . '</strong>';
2021
+ }
2022
+ }
2023
+ if ( $titles ) {
2024
+ $this->message .= '<br /><br />' . wp_sprintf( __( 'The following modules have been updated: %l.', 'jetpack' ), $titles );
2025
+ }
2026
+ }
2027
+
2028
+ $this->message .= Jetpack::jetpack_comment_notice();
2029
+ break;
2030
+
2031
+ case 'module_activated' :
2032
+ if ( $module = Jetpack::get_module( Jetpack::state( 'module' ) ) ) {
2033
+ $this->message = sprintf( __( '<strong>%s Activated!</strong> You can deactivate at any time by clicking Learn More and then Deactivate on the module card.', 'jetpack' ), $module['name'] );
2034
+ $this->stat( 'module-activated', Jetpack::state( 'module' ) );
2035
+ }
2036
+ break;
2037
+
2038
+ case 'module_deactivated' :
2039
+ $modules = Jetpack::state( 'module' );
2040
+ if ( !$modules ) {
2041
+ break;
2042
+ }
2043
+
2044
+ $module_names = array();
2045
+ foreach ( explode( ',', $modules ) as $module_slug ) {
2046
+ $module = Jetpack::get_module( $module_slug );
2047
+ if ( $module ) {
2048
+ $module_names[] = $module['name'];
2049
+ }
2050
+
2051
+ $this->stat( 'module-deactivated', $module_slug );
2052
+ }
2053
+
2054
+ if ( !$module_names ) {
2055
+ break;
2056
+ }
2057
+
2058
+ $this->message = wp_sprintf(
2059
+ _nx(
2060
+ '<strong>%l Deactivated!</strong> You can activate it again at any time using the activate button on the module card.',
2061
+ '<strong>%l Deactivated!</strong> You can activate them again at any time using the activate buttons on their module cards.',
2062
+ count( $module_names ),
2063
+ '%l = list of Jetpack module/feature names',
2064
+ 'jetpack'
2065
+ ),
2066
+ $module_names
2067
+ );
2068
+ break;
2069
+
2070
+ case 'module_configured' :
2071
+ $this->message = __( '<strong>Module settings were saved.</strong> ', 'jetpack' );
2072
+ break;
2073
+
2074
+ case 'already_authorized' :
2075
+ $this->message = __( '<strong>Your Jetpack is already connected.</strong> ', 'jetpack' );
2076
+ break;
2077
+
2078
+ case 'authorized' :
2079
+ $this->message = __( "<strong>You&#8217;re fueled up and ready to go.</strong> ", 'jetpack' );
2080
+ $this->message .= "<br />\n";
2081
+ $this->message .= __( 'The features below are now active. Click the learn more buttons to explore each feature.', 'jetpack' );
2082
+ $this->message .= Jetpack::jetpack_comment_notice();
2083
+ break;
2084
+
2085
+ case 'linked' :
2086
+ $this->message = __( "<strong>You&#8217;re fueled up and ready to go.</strong> ", 'jetpack' );
2087
+ $this->message .= Jetpack::jetpack_comment_notice();
2088
+ break;
2089
+
2090
+ case 'unlinked' :
2091
+ $user = wp_get_current_user();
2092
+ $this->message = sprintf( __( '<strong>You have unlinked your account (%s) from WordPress.com.</strong>', 'jetpack' ), $user->user_login );
2093
+ break;
2094
+ }
2095
+
2096
+ $deactivated_plugins = Jetpack::state( 'deactivated_plugins' );
2097
+
2098
+ if ( !empty( $deactivated_plugins ) ) {
2099
+ $deactivated_plugins = explode( ',', $deactivated_plugins );
2100
+ $deactivated_titles = array();
2101
+ foreach ( $deactivated_plugins as $deactivated_plugin ) {
2102
+ if ( !isset( $this->plugins_to_deactivate[$deactivated_plugin] ) ) {
2103
+ continue;
2104
+ }
2105
+
2106
+ $deactivated_titles[] = '<strong>' . str_replace( ' ', '&nbsp;', $this->plugins_to_deactivate[$deactivated_plugin][1] ) . '</strong>';
2107
+ }
2108
+
2109
+ if ( $deactivated_titles ) {
2110
+ if ( $this->message ) {
2111
+ $this->message .= "<br /><br />\n";
2112
+ }
2113
+
2114
+ $this->message .= wp_sprintf( _n(
2115
+ 'Jetpack contains the most recent version of the old %l plugin.',
2116
+ 'Jetpack contains the most recent versions of the old %l plugins.',
2117
+ count( $deactivated_titles ),
2118
+ 'jetpack'
2119
+ ), $deactivated_titles );
2120
+
2121
+ $this->message .= "<br />\n";
2122
+
2123
+ $this->message .= _n(
2124
+ 'The old version has been deactivated and can be removed from your site.',
2125
+ 'The old versions have been deactivated and can be removed from your site.',
2126
+ count( $deactivated_titles ),
2127
+ 'jetpack'
2128
+ );
2129
+ }
2130
+ }
2131
+
2132
+ $this->privacy_checks = Jetpack::state( 'privacy_checks' );
2133
+
2134
+ if ( $this->message || $this->error || $this->privacy_checks ) {
2135
+ add_action( 'jetpack_notices', array( $this, 'admin_notices' ) );
2136
+ }
2137
+
2138
+ if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
2139
+ do_action( 'jetpack_module_configuration_load_' . $_GET['configure'] );
2140
+ }
2141
+
2142
+ add_filter( 'jetpack_short_module_description', 'wptexturize' );
2143
+ }
2144
+
2145
+ function admin_notices() {
2146
+
2147
+ if ( $this->error ) {
2148
+ ?>
2149
+ <div id="message" class="jetpack-message jetpack-err">
2150
+ <div class="squeezer">
2151
+ <h4><?php echo wp_kses( $this->error, array( 'code' => true, 'strong' => true, 'br' => true, 'b' => true ) ); ?></h4>
2152
+ <?php if ( $desc = Jetpack::state( 'error_description' ) ) : ?>
2153
+ <p><?php echo esc_html( stripslashes( $desc ) ); ?></p>
2154
+ <?php endif; ?>
2155
+ </div>
2156
+ </div>
2157
+ <?php
2158
+ }
2159
+
2160
+ if ( $this->message ) {
2161
+ ?>
2162
+ <div id="message" class="jetpack-message">
2163
+ <div class="squeezer">
2164
+ <h4><?php echo wp_kses( $this->message, array( 'strong' => array(), 'a' => array( 'href' => true ), 'br' => true ) ); ?></h4>
2165
+ </div>
2166
+ </div>
2167
+ <?php
2168
+
2169
+ }
2170
+
2171
+ if ( $this->privacy_checks ) :
2172
+ $module_names = $module_slugs = array();
2173
+
2174
+ $privacy_checks = explode( ',', $this->privacy_checks );
2175
+ foreach ( $privacy_checks as $module_slug ) {
2176
+ $module = Jetpack::get_module( $module_slug );
2177
+ if ( !$module ) {
2178
+ continue;
2179
+ }
2180
+
2181
+ $module_slugs[] = $module_slug;
2182
+ $module_names[] = "<strong>{$module['name']}</strong>";
2183
+ }
2184
+
2185
+ $module_slugs = join( ',', $module_slugs );
2186
+ ?>
2187
+ <div id="message" class="jetpack-message jetpack-err">
2188
+ <div class="squeezer">
2189
+ <h4><strong><?php esc_html_e( 'Is this site private?', 'jetpack' ); ?></strong></h4><br />
2190
+ <p><?php
2191
+ echo wp_kses( wptexturize( wp_sprintf(
2192
+ _nx(
2193
+ "Like your site's RSS feeds, %l allows access to your posts and other content to third parties.",
2194
+ "Like your site's RSS feeds, %l allow access to your posts and other content to third parties.",
2195
+ count( $privacy_checks ),
2196
+ '%l = list of Jetpack module/feature names',
2197
+ 'jetpack'
2198
+ ),
2199
+ $module_names
2200
+ ) ), array( 'strong' => true ) );
2201
+
2202
+ echo "\n<br />\n";
2203
+
2204
+ echo wp_kses( sprintf(
2205
+ _nx(
2206
+ 'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating this feature</a>.',
2207
+ 'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating these features</a>.',
2208
+ count( $privacy_checks ),
2209
+ '%1$s = deactivation URL, %2$s = "Deactivate {list of Jetpack module/feature names}',
2210
+ 'jetpack'
2211
+ ),
2212
+ wp_nonce_url(
2213
+ Jetpack::admin_url( array(
2214
+ 'page' => 'jetpack',
2215
+ 'action' => 'deactivate',
2216
+ 'module' => urlencode( $module_slugs ),
2217
+ ) ),
2218
+ "jetpack_deactivate-$module_slugs"
2219
+ ),
2220
+ esc_attr( wp_kses( wp_sprintf( _x( 'Deactivate %l', '%l = list of Jetpack module/feature names', 'jetpack' ), $module_names ), array() ) )
2221
+ ), array( 'a' => array( 'href' => true, 'title' => true ) ) );
2222
+ ?></p>
2223
+ </div>
2224
+ </div>
2225
+ <?php
2226
+ endif;
2227
+ }
2228
+
2229
+ /**
2230
+ * Record a stat for later output. This will only currently output in the admin_footer.
2231
+ */
2232
+ function stat( $group, $detail ) {
2233
+ if ( !isset( $this->stats[ $group ] ) )
2234
+ $this->stats[ $group ] = array();
2235
+ $this->stats[ $group ][] = $detail;
2236
+ }
2237
+
2238
+ /**
2239
+ * Load stats pixels. $group is auto-prefixed with "x_jetpack-"
2240
+ */
2241
+ function do_stats( $method = '' ) {
2242
+ if ( is_array( $this->stats ) && count( $this->stats ) ) {
2243
+ foreach ( $this->stats as $group => $stats ) {
2244
+ if ( is_array( $stats ) && count( $stats ) ) {
2245
+ $args = array( "x_jetpack-{$group}" => implode( ',', $stats ) );
2246
+ if ( 'server_side' === $method ) {
2247
+ self::do_server_side_stat( $args );
2248
+ } else {
2249
+ echo '<img src="' . esc_url( self::build_stats_url( $args ) ) . '" width="1" height="1" style="display:none;" />';
2250
+ }
2251
+ }
2252
+ unset( $this->stats[ $group ] );
2253
+ }
2254
+ }
2255
+ }
2256
+
2257
+ /**
2258
+ * Runs stats code for a one-off, server-side.
2259
+ *
2260
+ * @param $args array|string The arguments to append to the URL. Should include `x_jetpack-{$group}={$stats}` or whatever we want to store.
2261
+ *
2262
+ * @return bool If it worked.
2263
+ */
2264
+ static function do_server_side_stat( $args ) {
2265
+ $response = wp_remote_get( self::build_stats_url( $args ) );
2266
+ if ( is_wp_error( $response ) )
2267
+ return false;
2268
+
2269
+ if ( 200 !== wp_remote_retrieve_response_code( $response ) )
2270
+ return false;
2271
+
2272
+ return true;
2273
+ }
2274
+
2275
+ /**
2276
+ * Builds the stats url.
2277
+ *
2278
+ * @param $args array|string The arguments to append to the URL.
2279
+ *
2280
+ * @return string The URL to be pinged.
2281
+ */
2282
+ static function build_stats_url( $args ) {
2283
+ $defaults = array(
2284
+ 'v' => 'wpcom2',
2285
+ 'rand' => md5( mt_rand( 0, 999 ) . time() ),
2286
+ );
2287
+ $args = wp_parse_args( $args, $defaults );
2288
+ $base_url = apply_filters( 'jetpack_stats_base_url', ( is_ssl() ? 'https' : 'http' ) . '://stats.wordpress.com/g.gif' );
2289
+ $url = add_query_arg( $args, $base_url );
2290
+ return $url;
2291
+ }
2292
+
2293
+ function translate_current_user_to_role() {
2294
+ foreach ( $this->capability_translations as $role => $cap ) {
2295
+ if ( current_user_can( $role ) || current_user_can( $cap ) ) {
2296
+ return $role;
2297
+ }
2298
+ }
2299
+
2300
+ return false;
2301
+ }
2302
+
2303
+ function translate_role_to_cap( $role ) {
2304
+ if ( !isset( $this->capability_translations[$role] ) ) {
2305
+ return false;
2306
+ }
2307
+
2308
+ return $this->capability_translations[$role];
2309
+ }
2310
+
2311
+ function sign_role( $role ) {
2312
+ if ( !$user_id = (int) get_current_user_id() ) {
2313
+ return false;
2314
+ }
2315
+
2316
+ $token = Jetpack_Data::get_access_token();
2317
+ if ( !$token || is_wp_error( $token ) ) {
2318
+ return false;
2319
+ }
2320
+
2321
+ return $role . ':' . hash_hmac( 'md5', "{$role}|{$user_id}", $token->secret );
2322
+ }
2323
+
2324
+ function build_connect_url( $raw = false, $redirect = false ) {
2325
+ if ( !Jetpack::get_option( 'blog_token' ) ) {
2326
+ $url = $this->nonce_url_no_esc( $this->admin_url( 'action=register' ), 'jetpack-register' );
2327
+ } else {
2328
+ $role = $this->translate_current_user_to_role();
2329
+ $signed_role = $this->sign_role( $role );
2330
+
2331
+ $user = wp_get_current_user();
2332
+
2333
+ $redirect = $redirect ? esc_url_raw( $redirect ) : '';
2334
+
2335
+ $args = urlencode_deep( array(
2336
+ 'response_type' => 'code',
2337
+ 'client_id' => Jetpack::get_option( 'id' ),
2338
+ 'redirect_uri' => add_query_arg( array(
2339
+ 'action' => 'authorize',
2340
+ '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
2341
+ 'redirect' => $redirect ? urlencode( $redirect ) : false,
2342
+ ), menu_page_url( 'jetpack', false ) ),
2343
+ 'state' => $user->ID,
2344
+ 'scope' => $signed_role,
2345
+ 'user_email' => $user->user_email,
2346
+ 'user_login' => $user->user_login,
2347
+ 'is_active' => Jetpack::is_active(),
2348
+ 'jp_version' => JETPACK__VERSION,
2349
+ ) );
2350
+
2351
+ $url = add_query_arg( $args, Jetpack::api_url( 'authorize' ) );
2352
+ }
2353
+
2354
+ return $raw ? $url : esc_url( $url );
2355
+ }
2356
+
2357
+ function build_reconnect_url( $raw = false ) {
2358
+ $url = wp_nonce_url( $this->admin_url( 'action=reconnect' ), 'jetpack-reconnect' );
2359
+ return $raw ? $url : esc_url( $url );
2360
+ }
2361
+
2362
+ public static function admin_url( $args = null ) {
2363
+ $args = wp_parse_args( $args, array( 'page' => 'jetpack' ) );
2364
+ $url = add_query_arg( $args, admin_url( 'admin.php' ) );
2365
+ return $url;
2366
+ }
2367
+
2368
+ public static function nonce_url_no_esc( $actionurl, $action = -1, $name = '_wpnonce' ) {
2369
+ $actionurl = str_replace( '&amp;', '&', $actionurl );
2370
+ return add_query_arg( $name, wp_create_nonce( $action ), $actionurl );
2371
+ }
2372
+
2373
+ function dismiss_jetpack_notice() {
2374
+ if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] && ! is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
2375
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
2376
+
2377
+ deactivate_plugins( plugin_basename( __FILE__ ), false, false );
2378
+
2379
+ wp_safe_redirect( admin_url() . 'plugins.php?deactivate=true&plugin_status=all&paged=1&s=' );
2380
+ exit;
2381
+ }
2382
+ }
2383
+
2384
+ function admin_page() {
2385
+ global $current_user;
2386
+
2387
+ $role = $this->translate_current_user_to_role();
2388
+ $is_connected = Jetpack::is_active();
2389
+ $user_token = Jetpack_Data::get_access_token($current_user->ID);
2390
+ $is_user_connected = $user_token && !is_wp_error($user_token);
2391
+ $is_master_user = $current_user->ID == Jetpack::get_option( 'master_user' );
2392
+ $module = false;
2393
+ ?>
2394
+ <div class="wrap" id="jetpack-settings">
2395
+
2396
+ <h2 style="display: none"></h2> <!-- For WP JS message relocation -->
2397
+
2398
+ <div id="jp-header"<?php if ( $is_connected ) : ?> class="small"<?php endif; ?>>
2399
+ <div id="jp-clouds">
2400
+ <?php if ( $is_connected ) : ?>
2401
+ <div id="jp-disconnectors">
2402
+ <?php if ( current_user_can( 'manage_options' ) ) : ?>
2403
+ <div id="jp-disconnect" class="jp-disconnect">
2404
+ <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=disconnect' ), 'jetpack-disconnect' ); ?>"><div class="deftext"><?php _e( 'Connected to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Disconnect from WordPress.com', 'jetpack' ) ?></div></a>
2405
+ </div>
2406
+ <?php endif; ?>
2407
+ <?php if ( $is_user_connected && !$is_master_user ) : ?>
2408
+ <div id="jp-unlink" class="jp-disconnect">
2409
+ <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=unlink' ), 'jetpack-unlink' ); ?>"><div class="deftext"><?php _e( 'User linked to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Unlink user from WordPress.com', 'jetpack' ) ?></div></a>
2410
+ </div>
2411
+ <?php endif; ?>
2412
+ </div>
2413
+ <?php endif; ?>
2414
+ <h3><?php _e( 'Jetpack by WordPress.com', 'jetpack' ) ?></h3>
2415
+ <?php if ( !$is_connected ) : ?>
2416
+ <div id="jp-notice">
2417
+ <p><?php _e( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ); ?></p>
2418
+ </div>
2419
+ <?php endif; ?>
2420
+ </div>
2421
+ </div>
2422
+
2423
+ <?php if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] ) : ?>
2424
+ <div id="message" class="error">
2425
+ <p><?php _e( 'Jetpack is network activated and notices can not be dismissed.', 'jetpack' ); ?></p>
2426
+ </div>
2427
+ <?php endif; ?>
2428
+
2429
+ <?php do_action( 'jetpack_notices' ) ?>
2430
+
2431
+ <?php
2432
+ // If the connection has not been made then show the marketing text.
2433
+ if ( ! Jetpack::is_development_mode() ) :
2434
+ ?>
2435
+ <?php if ( ! $is_connected ) : ?>
2436
+
2437
+ <div id="message" class="updated jetpack-message jp-connect">
2438
+ <div id="jp-dismiss" class="jetpack-close-button-container">
2439
+ <a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice.', 'jetpack' ); ?></a>
2440
+ </div>
2441
+ <div class="jetpack-wrap-container">
2442
+ <div class="jetpack-text-container">
2443
+ <h4>
2444
+ <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to connect your website to WordPress.com using the button to the right. Once you&#8217;ve made the connection you&#8217;ll activate all the delightful features below.", 'jetpack' ) ?></p>
2445
+ </h4>
2446
+ </div>
2447
+ <div class="jetpack-install-container">
2448
+ <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
2449
+ </div>
2450
+ </div>
2451
+ </div>
2452
+
2453
+ <?php elseif ( ! $is_user_connected ) : ?>
2454
+
2455
+ <div id="message" class="updated jetpack-message jp-connect">
2456
+ <div class="jetpack-wrap-container">
2457
+ <div class="jetpack-text-container">
2458
+ <h4>
2459
+ <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to link your account here to your WordPress.com account using the button to the right.", 'jetpack' ) ?></p>
2460
+ </h4>
2461
+ </div>
2462
+ <div class="jetpack-install-container">
2463
+ <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Link account with WordPress.com', 'jetpack' ); ?></a></p>
2464
+ </div>
2465
+ </div>
2466
+ </div>
2467
+
2468
+ <?php else /* blog and user are connected */ : ?>
2469
+ <?php /* TODO: if not master user, show user disconnect button? */ ?>
2470
+ <?php endif; ?>
2471
+ <?php endif; // ! Jetpack::is_development_mode() ?>
2472
+
2473
+ <?php
2474
+ if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
2475
+ $this->admin_screen_configure_module( $_GET['configure'] );
2476
+ } else {
2477
+ $this->admin_screen_list_modules();
2478
+ }
2479
+ ?>
2480
+
2481
+ <div id="survey" class="jp-survey">
2482
+ <div class="jp-survey-container">
2483
+ <div class="jp-survey-text">
2484
+ <h4><?php _e( 'Have feedback on Jetpack?', 'jetpack' ); ?></h4>
2485
+ <br />
2486
+ <?php _e( 'Answer a short survey to let us know how we&#8217;re doing and what to add in the future.', 'jetpack' ); ?>
2487
+ </div>
2488
+ <div class="jp-survey-button-container">
2489
+ <p class="submit"><?php printf( '<a id="jp-survey-button" class="button-primary" target="_blank" href="%1$s">%2$s</a>', 'http://jetpack.me/survey/?rel=' . JETPACK__VERSION, __( 'Take Survey', 'jetpack' ) ); ?></p>
2490
+ </div>
2491
+ </div>
2492
+ </div>
2493
+
2494
+ <?php if ( $is_connected && $this->current_user_is_connection_owner() ) : ?>
2495
+ <p id="news-sub"><?php _e( 'Checking email updates status&hellip;', 'jetpack' ); ?></p>
2496
+ <script type="text/javascript">
2497
+ jQuery(document).ready(function($){
2498
+ $.get( ajaxurl, { action: 'jetpack-check-news-subscription', rand: jQuery.now().toString() + Math.random().toString() }, function( data ) {
2499
+ if ( 'subscribed' == data ) {
2500
+ $( '#news-sub' ).html( '<?php printf(
2501
+ esc_js( _x( 'You are currently subscribed to email updates. %s', '%s = Unsubscribe link', 'jetpack' ) ),
2502
+ '<a href="#" class="jp-news-link button">' . esc_js( __( 'Unsubscribe', 'jetpack' ) ) . '</a>'
2503
+ ); ?>' );
2504
+ } else {
2505
+ $( '#news-sub' ).html( '<?php printf(
2506
+ esc_js( _x( 'Want to receive updates about Jetpack by email? %s', '%s = Subscribe link', 'jetpack' ) ),
2507
+ '<a href="#" class="jp-news-link button-primary">' . esc_js( __( 'Subscribe', 'jetpack' ) ) . '</a>'
2508
+ ); ?>' );
2509
+ }
2510
+ $( '.jp-news-link' ).click( function() {
2511
+ $( '#news-sub' ).append( ' <img src="<?php echo esc_js( esc_url( admin_url( 'images/loading.gif' ) ) ); ?>" align="absmiddle" id="jp-news-loading" />' );
2512
+ $.get( ajaxurl, { action: 'jetpack-subscribe-to-news', rand: jQuery.now().toString() + Math.random().toString() }, function( data ) {
2513
+ if ( 'subscribed' == data ) {
2514
+ $( '#news-sub' ).text( '<?php echo esc_js( __( 'You have been subscribed to receive email updates.', 'jetpack' ) ); ?>' );
2515
+ } else {
2516
+ $( '#news-sub' ).text( '<?php echo esc_js( __( 'You will no longer receive email updates about Jetpack.', 'jetpack' ) ); ?>' );
2517
+ }
2518
+ $( '#jp-news-loading' ).remove();
2519
+ } );
2520
+ return false;
2521
+ } );
2522
+ } );
2523
+ } );
2524
+ </script>
2525
+ <?php endif; ?>
2526
+
2527
+ <div id="jp-footer">
2528
+ <p class="automattic"><?php _e( 'An <span>Automattic</span> Airline', 'jetpack' ) ?></p>
2529
+ <p class="small">
2530
+ <a href="http://jetpack.me/" target="_blank">Jetpack <?php echo esc_html( JETPACK__VERSION ); ?></a> |
2531
+ <a href="http://automattic.com/privacy/" target="_blank"><?php _e( 'Privacy Policy', 'jetpack' ); ?></a> |
2532
+ <a href="http://wordpress.com/tos/" target="_blank"><?php _e( 'Terms of Service', 'jetpack' ); ?></a> |
2533
+ <?php if ( current_user_can( 'manage_options' ) ) : ?>
2534
+ <a href="<?php echo Jetpack::admin_url( array( 'page' => 'jetpack-debugger' ) ); ?>"><?php _e( 'Debug', 'jetpack' ); ?></a> |
2535
+ <?php endif; ?>
2536
+ <a href="http://jetpack.me/support/" target="_blank"><?php _e( 'Support', 'jetpack' ); ?></a>
2537
+ </p>
2538
+ </div>
2539
+
2540
+ <div id="jetpack-configuration" style="display:none;">
2541
+ <p><img width="16" src="<?php echo esc_url( plugins_url( '_inc/images/wpspin_light-2x.gif', __FILE__ ) ); ?>" alt="Loading ..." /></p>
2542
+ </div>
2543
+ </div>
2544
+ <?php
2545
+ }
2546
+ /*
2547
+ function admin_page_modules() {
2548
+ global $current_user;
2549
+
2550
+ $role = $this->translate_current_user_to_role();
2551
+ $is_connected = Jetpack::is_active();
2552
+ $user_token = Jetpack_Data::get_access_token($current_user->ID);
2553
+ $is_user_connected = $user_token && !is_wp_error($user_token);
2554
+ $is_master_user = $current_user->ID == Jetpack::get_option( 'master_user' );
2555
+ $module = false;
2556
+ ?>
2557
+ <div class="wrap" id="jetpack-settings">
2558
+
2559
+ <h2 style="display: none"></h2> <!-- For WP JS message relocation -->
2560
+
2561
+ <div id="jp-header"<?php if ( $is_connected ) : ?> class="small"<?php endif; ?>>
2562
+ <div id="jp-clouds">
2563
+ <?php if ( $is_connected ) : ?>
2564
+ <div id="jp-disconnectors">
2565
+ <?php if ( current_user_can( 'manage_options' ) ) : ?>
2566
+ <div id="jp-disconnect" class="jp-disconnect">
2567
+ <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=disconnect' ), 'jetpack-disconnect' ); ?>"><div class="deftext"><?php _e( 'Connected to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Disconnect from WordPress.com', 'jetpack' ) ?></div></a>
2568
+ </div>
2569
+ <?php endif; ?>
2570
+ <?php if ( $is_user_connected && !$is_master_user ) : ?>
2571
+ <div id="jp-unlink" class="jp-disconnect">
2572
+ <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=unlink' ), 'jetpack-unlink' ); ?>"><div class="deftext"><?php _e( 'User linked to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Unlink user from WordPress.com', 'jetpack' ) ?></div></a>
2573
+ </div>
2574
+ <?php endif; ?>
2575
+ </div>
2576
+ <?php endif; ?>
2577
+ <h3><?php _e( 'Jetpack by WordPress.com', 'jetpack' ) ?></h3>
2578
+ <?php if ( !$is_connected ) : ?>
2579
+ <div id="jp-notice">
2580
+ <p><?php _e( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ); ?></p>
2581
+ </div>
2582
+ <?php endif; ?>
2583
+ </div>
2584
+ </div>
2585
+
2586
+ <?php if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] ) : ?>
2587
+ <div id="message" class="error">
2588
+ <p><?php _e( 'Jetpack is network activated and notices can not be dismissed.', 'jetpack' ); ?></p>
2589
+ </div>
2590
+ <?php endif; ?>
2591
+
2592
+ <?php do_action( 'jetpack_notices' ) ?>
2593
+
2594
+ <?php
2595
+ // If the connection has not been made then show the marketing text.
2596
+ if ( ! Jetpack::is_development_mode() ) :
2597
+ ?>
2598
+ <?php if ( ! $is_connected ) : ?>
2599
+
2600
+ <div id="message" class="updated jetpack-message jp-connect">
2601
+ <div id="jp-dismiss" class="jetpack-close-button-container">
2602
+ <a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice.', 'jetpack' ); ?></a>
2603
+ </div>
2604
+ <div class="jetpack-wrap-container">
2605
+ <div class="jetpack-text-container">
2606
+ <h4>
2607
+ <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to connect your website to WordPress.com using the button to the right. Once you&#8217;ve made the connection you&#8217;ll activate all the delightful features below.", 'jetpack' ) ?></p>
2608
+ </h4>
2609
+ </div>
2610
+ <div class="jetpack-install-container">
2611
+ <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
2612
+ </div>
2613
+ </div>
2614
+ </div>
2615
+
2616
+ <?php elseif ( ! $is_user_connected ) : ?>
2617
+
2618
+ <div id="message" class="updated jetpack-message jp-connect">
2619
+ <div class="jetpack-wrap-container">
2620
+ <div class="jetpack-text-container">
2621
+ <h4>
2622
+ <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to link your account here to your WordPress.com account using the button to the right.", 'jetpack' ) ?></p>
2623
+ </h4>
2624
+ </div>
2625
+ <div class="jetpack-install-container">
2626
+ <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Link account with WordPress.com', 'jetpack' ); ?></a></p>
2627
+ </div>
2628
+ </div>
2629
+ </div>
2630
+
2631
+ <?php else: // blog and user are connected ?>
2632
+ <?php // TODO: if not master user, show user disconnect button? ?>
2633
+ <?php endif; ?>
2634
+ <?php endif; // ! Jetpack::is_development_mode() ?>
2635
+
2636
+ <?php
2637
+ if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
2638
+ $this->admin_screen_configure_module( $_GET['configure'] );
2639
+ } else {
2640
+ $this->admin_screen_list_modules();
2641
+ }
2642
+ ?>
2643
+
2644
+ </div>
2645
+ <?php
2646
+ }
2647
+ /**/
2648
+ function debugger_page() {
2649
+ nocache_headers();
2650
+ if ( !current_user_can( 'manage_options' ) ) {
2651
+ die( '-1' );
2652
+ }
2653
+ jetpack_debug_display_handler();
2654
+ exit;
2655
+ }
2656
+
2657
+ function admin_screen_configure_module( $module_id ) {
2658
+ if ( !in_array( $module_id, Jetpack::get_active_modules() ) || !current_user_can( 'manage_options' ) )
2659
+ return false; ?>
2660
+
2661
+ <div id="jp-settings-screen" style="position: relative">
2662
+ <h3>
2663
+ <?php
2664
+ $module = Jetpack::get_module( $module_id );
2665
+ echo '<a href="' . menu_page_url( 'jetpack', false ) . '">' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</a> &rarr; ';
2666
+ printf( __( 'Configure %s', 'jetpack' ), $module['name'] );
2667
+ ?>
2668
+ </h3>
2669
+
2670
+ <?php do_action( 'jetpack_module_configuration_screen_' . $module_id ); ?>
2671
+ </div><?php
2672
+ }
2673
+
2674
+ public static function sort_modules( $a, $b ) {
2675
+ if ( $a['sort'] == $b['sort'] )
2676
+ return 0;
2677
+
2678
+ return ( $a['sort'] < $b['sort'] ) ? -1 : 1;
2679
+ }
2680
+
2681
+ function admin_screen_list_modules() {
2682
+ require_once dirname( __FILE__ ) . '/modules/module-info.php';
2683
+ $jetpack_connected = true;
2684
+ if ( !Jetpack::is_active() )
2685
+ $jetpack_connected = false;
2686
+
2687
+ ?>
2688
+ <div class="module-container">
2689
+ <?php
2690
+
2691
+ $avail_raw = Jetpack::get_available_modules();
2692
+ $available = array();
2693
+ $active = Jetpack::get_active_modules();
2694
+ $counter = 0;
2695
+
2696
+ foreach ( (array) $avail_raw as $module ) {
2697
+ if ( $plugin = Jetpack::get_module( $module ) ) {
2698
+ $plugin['module'] = $module;
2699
+ $available[] = $plugin;
2700
+ }
2701
+ }
2702
+ unset( $avail_raw );
2703
+ usort( $available, array( 'Jetpack', 'sort_modules' ) );
2704
+ $jetpack_version = Jetpack::get_option( 'version' );
2705
+ if ( $jetpack_version ) {
2706
+ list( $jetpack_version, $jetpack_version_time ) = explode( ':', $jetpack_version );
2707
+ } else {
2708
+ $jetpack_version = 0;
2709
+ $jetpack_version_time = 0;
2710
+ }
2711
+
2712
+ $jetpack_old_version = Jetpack::get_option( 'old_version' );
2713
+ if ( $jetpack_old_version ) {
2714
+ list( $jetpack_old_version ) = explode( ':', $jetpack_old_version );
2715
+ } else {
2716
+ $jetpack_old_version = 0;
2717
+ }
2718
+ $now = time();
2719
+
2720
+ foreach ( (array) $available as $module_data ) {
2721
+ $module = $module_data['module'];
2722
+ $activated = in_array( $module, $active );
2723
+ if ( $activated ) {
2724
+ $css = 'active';
2725
+ $toggle = __( 'Deactivate', 'jetpack' );
2726
+ $toggle_url = wp_nonce_url(
2727
+ Jetpack::admin_url( array(
2728
+ 'page' => 'jetpack',
2729
+ 'action' => 'deactivate',
2730
+ 'module' => $module
2731
+ ) ),
2732
+ "jetpack_deactivate-$module"
2733
+ );
2734
+ } else {
2735
+ $css = 'inactive';
2736
+ $toggle = __( 'Activate', 'jetpack' );
2737
+ $toggle_url = wp_nonce_url(
2738
+ Jetpack::admin_url( array(
2739
+ 'page' => 'jetpack',
2740
+ 'action' => 'activate',
2741
+ 'module' => $module
2742
+ ) ),
2743
+ "jetpack_activate-$module"
2744
+ );
2745
+ }
2746
+
2747
+ if ( $counter % 4 == 0 ) {
2748
+ $classes = $css . ' jetpack-newline';
2749
+ $counter = 0;
2750
+ } else {
2751
+ $classes = $css;
2752
+ }
2753
+
2754
+ $free_text = esc_html( $module_data['free'] ? __( 'Free', 'jetpack' ) : __( 'Purchase', 'jetpack' ) );
2755
+ $free_text = apply_filters( 'jetpack_module_free_text_' . $module, $free_text );
2756
+ $badge_text = $free_text;
2757
+
2758
+ if ( ( ! $jetpack_connected && ! Jetpack::is_development_mode() ) ) {
2759
+ $classes = 'x disabled';
2760
+ } else if ( $jetpack_version_time + 604800 > $now ) { // 1 week
2761
+ if ( version_compare( $module_data['introduced'], $jetpack_old_version, '>' ) ) {
2762
+ $badge_text = esc_html__( 'New', 'jetpack' );
2763
+ $classes .= ' jetpack-new-module';
2764
+ } elseif ( isset( $module_data['changed'] ) && version_compare( $module_data['changed'], $jetpack_old_version, '>' ) ) {
2765
+ $badge_text = esc_html__( 'Updated', 'jetpack' );
2766
+ $classes .= ' jetpack-updated-module';
2767
+ } else {
2768
+ $badge_text = $free_text;
2769
+ }
2770
+ }
2771
+
2772
+ ?>
2773
+ <div class="jetpack-module jetpack-<?php echo $classes; ?>" id="<?php echo $module ?>">
2774
+ <h3><?php echo $module_data['name']; ?></h3>
2775
+ <div class="jetpack-module-description">
2776
+ <div class="module-image">
2777
+ <p><span class="module-image-badge"><?php echo $badge_text; ?></span><span class="module-image-free" style="display: none"><?php echo $free_text; ?></span></p>
2778
+ </div>
2779
+
2780
+ <p><?php echo apply_filters( 'jetpack_short_module_description', $module_data['description'], $module ); ?></p>
2781
+ </div>
2782
+
2783
+ <div class="jetpack-module-actions">
2784
+ <?php if ( $jetpack_connected || ( Jetpack::is_development_mode() && ! $module_data['requires_connection'] ) ) : ?>
2785
+ <?php if ( !$activated && current_user_can( 'manage_options' ) && apply_filters( 'jetpack_can_activate_' . $module, true ) ) : ?>
2786
+ <a href="<?php echo esc_url( $toggle_url ); ?>" class="<?php echo ( 'inactive' == $css ? ' button-primary' : ' button-secondary' ); ?>"><?php echo $toggle; ?></a>&nbsp;
2787
+ <?php endif; ?>
2788
+
2789
+ <?php do_action( 'jetpack_learn_more_button_' . $module ) ?>
2790
+
2791
+ <?php
2792
+ if ( current_user_can( 'manage_options' ) && apply_filters( 'jetpack_module_configurable_' . $module, false ) ) {
2793
+ echo '<a href="' . esc_url( Jetpack::module_configuration_url( $module ) ) . '" class="jetpack-configure-button button-secondary">' . __( 'Configure', 'jetpack' ) . '</a>';
2794
+ }
2795
+ ?><?php if ( $activated && $module_data['deactivate'] && current_user_can( 'manage_options' ) ) : ?><a style="display: none;" href="<?php echo esc_url( $toggle_url ); ?>" class="jetpack-deactivate-button button-secondary"><?php echo $toggle; ?></a>&nbsp;<?php endif; ?>
2796
+
2797
+ <?php else : ?>
2798
+ <?php do_action( 'jetpack_learn_more_button_' . $module ) ?>
2799
+ <?php endif; ?>
2800
+ </div>
2801
+ </div>
2802
+ <?php if ( 'inactive' == $css && $jetpack_connected && current_user_can( 'manage_options' ) && apply_filters( 'jetpack_can_activate_' . $module, true ) ) : ?>
2803
+ <script type="text/javascript">
2804
+ jQuery( '#<?php echo esc_js( $module ); ?>' ).bind( 'click', function(e){
2805
+ if ( !jQuery(e.target).hasClass('more-info-link') )
2806
+ document.location.href = '<?php echo str_replace( '&amp;', '&', esc_js( esc_url( $toggle_url ) ) ); ?>';
2807
+ } );
2808
+ </script>
2809
+ <?php else: ?>
2810
+ <style>
2811
+ #<?php echo $module; ?> { cursor: default; }
2812
+ </style>
2813
+ <?php endif; ?>
2814
+
2815
+ <div id="jp-more-info-<?php echo esc_attr( $module ); ?>" style="display:none;">
2816
+ <?php
2817
+ if ( $jetpack_connected && has_action( 'jetpack_module_more_info_connected_' . $module ) )
2818
+ do_action( 'jetpack_module_more_info_connected_' . $module );
2819
+ else
2820
+ do_action( 'jetpack_module_more_info_' . $module );
2821
+ ?>
2822
+ </div>
2823
+
2824
+ <?php
2825
+ $counter++;
2826
+ }
2827
+
2828
+ // Add in some "Coming soon..." placeholders to fill up the current row and one more
2829
+ for ( $i = 0; $i < 4; $i++ ) { ?>
2830
+ <div class="jetpack-module placeholder"<?php if ( $i > 8 - $counter ) echo ' style="display: none;"'; ?>>
2831
+ <h3><?php _e( 'Coming soon&#8230;', 'jetpack' ) ?></h3>
2832
+ </div>
2833
+ <?php
2834
+ }
2835
+
2836
+ echo '</div><!-- .module-container -->';
2837
+ }
2838
+
2839
+ function check_news_subscription() {
2840
+ if ( !$this->current_user_is_connection_owner() ) {
2841
+ exit;
2842
+ }
2843
+
2844
+ Jetpack::load_xml_rpc_client();
2845
+ $xml = new Jetpack_IXR_Client( array(
2846
+ 'user_id' => JETPACK_MASTER_USER,
2847
+ ) );
2848
+ $xml->query( 'jetpack.checkNewsSubscription' );
2849
+ if ( $xml->isError() ) {
2850
+ printf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() );
2851
+ } else {
2852
+ print_r( $xml->getResponse() );
2853
+ }
2854
+ exit;
2855
+ }
2856
+
2857
+ function subscribe_to_news() {
2858
+ if ( !$this->current_user_is_connection_owner() ) {
2859
+ exit;
2860
+ }
2861
+
2862
+ Jetpack::load_xml_rpc_client();
2863
+ $xml = new Jetpack_IXR_Client( array(
2864
+ 'user_id' => JETPACK_MASTER_USER,
2865
+ ) );
2866
+ $xml->query( 'jetpack.subscribeToNews' );
2867
+ if ( $xml->isError() ) {
2868
+ printf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() );
2869
+ } else {
2870
+ print_r( $xml->getResponse() );
2871
+ }
2872
+ exit;
2873
+ }
2874
+
2875
+ /* Client API */
2876
+
2877
+ /**
2878
+ * Returns the requested Jetpack API URL
2879
+ *
2880
+ * @return string
2881
+ */
2882
+ public static function api_url( $relative_url ) {
2883
+ return trailingslashit( JETPACK__API_BASE . $relative_url ) . JETPACK__API_VERSION . '/';
2884
+ }
2885
+
2886
+ /**
2887
+ * Some hosts disable the OpenSSL extension and so cannot make outgoing HTTPS requsets
2888
+ */
2889
+ public static function fix_url_for_bad_hosts( $url, &$args ) {
2890
+ if ( 0 !== strpos( $url, 'https://' ) ) {
2891
+ return $url;
2892
+ }
2893
+
2894
+ switch ( JETPACK_CLIENT__HTTPS ) {
2895
+ case 'ALWAYS' :
2896
+ return $url;
2897
+ case 'NEVER' :
2898
+ return self::force_url_to_non_ssl( $url );
2899
+ // default : case 'AUTO' :
2900
+ }
2901
+
2902
+ $jetpack = Jetpack::init();
2903
+
2904
+ // Yay! Your host is good!
2905
+ if ( self::permit_ssl() && wp_http_supports( array( 'ssl' => true ) ) ) {
2906
+ return $url;
2907
+ }
2908
+
2909
+ // Boo! Your host is bad and makes Jetpack cry!
2910
+ return self::force_url_to_non_ssl( $url );
2911
+ }
2912
+
2913
+ /**
2914
+ * Checks to see if the URL is using SSL to connect with Jetpack
2915
+ *
2916
+ * @since 2.3.3
2917
+ * @return boolean
2918
+ */
2919
+ public static function permit_ssl( $force_recheck = false ) {
2920
+ // Do some fancy tests to see if ssl is being supported
2921
+ if ( $force_recheck || false === ( $ssl = get_transient( 'jetpack_https_test' ) ) ) {
2922
+
2923
+ if ( 'https' !== substr( JETPACK__API_BASE, 0, 5 ) ) {
2924
+ $ssl = 0;
2925
+ } else {
2926
+ switch ( JETPACK_CLIENT__HTTPS ) {
2927
+ case 'NEVER':
2928
+ $ssl = 0;
2929
+ break;
2930
+ case 'ALWAYS':
2931
+ case 'AUTO':
2932
+ default:
2933
+ $ssl = 1;
2934
+ break;
2935
+ }
2936
+
2937
+ // If it's not 'NEVER', test to see
2938
+ if ( $ssl ) {
2939
+ $response = wp_remote_get( JETPACK__API_BASE . 'test/1/' );
2940
+ if ( is_wp_error( $response ) || ( 'OK' !== wp_remote_retrieve_body( $response ) ) ) {
2941
+ $ssl = 0;
2942
+ }
2943
+ }
2944
+ }
2945
+ set_transient( 'jetpack_https_test', $ssl, DAY_IN_SECONDS );
2946
+ }
2947
+
2948
+ return (bool) $ssl;
2949
+ }
2950
+
2951
+ /**
2952
+ * Take any URL, and if it starts with https:// change it to http://
2953
+ */
2954
+ public static function force_url_to_non_ssl( $url ) {
2955
+ return preg_replace( '#^https://#i', 'http://', $url );
2956
+ }
2957
+
2958
+ /*
2959
+ * Displays an admin_notice, alerting the user to their JETPACK_CLIENT__HTTPS constant being 'ALWAYS' but SSL isn't working.
2960
+ */
2961
+ public function alert_required_ssl_fail() {
2962
+ if ( ! current_user_can( 'manage_options' ) )
2963
+ return;
2964
+ ?>
2965
+
2966
+ <div id="message" class="error jetpack-message jp-identity-crisis">
2967
+ <div class="jetpack-wrap-container">
2968
+ <div class="jetpack-text-container">
2969
+ <h3><?php _e( 'Something is being cranky!', 'jetpack' ); ?></h3>
2970
+ <p><?php _e( 'Your site is configured to only permit SSL connections to Jetpack, but SSL connections don\'t seem to be functional!', 'jetpack' ); ?></p>
2971
+ </div>
2972
+ </div>
2973
+ </div>
2974
+
2975
+ <?php
2976
+ }
2977
+
2978
+ /**
2979
+ * Returns the Jetpack XML-RPC API
2980
+ *
2981
+ * @return string
2982
+ */
2983
+ public static function xmlrpc_api_url() {
2984
+ $base = preg_replace( '#(https?://[^?/]+)(/?.*)?$#', '\\1', JETPACK__API_BASE );
2985
+ return untrailingslashit( $base ) . '/xmlrpc.php';
2986
+ }
2987
+
2988
+ /**
2989
+ * @return bool|WP_Error
2990
+ */
2991
+ public static function register() {
2992
+ Jetpack::update_option( 'register', wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 ) );
2993
+
2994
+ @list( $secret_1, $secret_2, $secret_eol ) = explode( ':', Jetpack::get_option( 'register' ) );
2995
+ if ( empty( $secret_1 ) || empty( $secret_2 ) || empty( $secret_eol ) || $secret_eol < time() )
2996
+ return new Jetpack_Error( 'missing_secrets' );
2997
+
2998
+ $timeout = (int) ini_get( 'max_execution_time' );
2999
+ if ( !$timeout )
3000
+ $timeout = 30;
3001
+ $timeout = intval( $timeout / 2 );
3002
+
3003
+ $gmt_offset = get_option( 'gmt_offset' );
3004
+ if ( !$gmt_offset ) {
3005
+ $gmt_offset = 0;
3006
+ }
3007
+
3008
+ $stats_options = get_option( 'stats_options' );
3009
+ $stats_id = isset($stats_options['blog_id']) ? $stats_options['blog_id'] : null;
3010
+
3011
+ $args = array(
3012
+ 'method' => 'POST',
3013
+ 'body' => array(
3014
+ 'siteurl' => site_url(),
3015
+ 'home' => home_url(),
3016
+ 'gmt_offset' => $gmt_offset,
3017
+ 'timezone_string' => (string) get_option( 'timezone_string' ),
3018
+ 'site_name' => (string) get_option( 'blogname' ),
3019
+ 'secret_1' => $secret_1,
3020
+ 'secret_2' => $secret_2,
3021
+ 'site_lang' => get_locale(),
3022
+ 'timeout' => $timeout,
3023
+ 'stats_id' => $stats_id,
3024
+ ),
3025
+ 'headers' => array(
3026
+ 'Accept' => 'application/json',
3027
+ ),
3028
+ 'timeout' => $timeout,
3029
+ );
3030
+ $response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'register' ), $args ), $args, true );
3031
+
3032
+ if ( is_wp_error( $response ) ) {
3033
+ return new Jetpack_Error( 'register_http_request_failed', $response->get_error_message() );
3034
+ }
3035
+
3036
+ $code = wp_remote_retrieve_response_code( $response );
3037
+ $entity = wp_remote_retrieve_body( $response );
3038
+
3039
+ if ( $entity )
3040
+ $json = json_decode( $entity );
3041
+ else
3042
+ $json = false;
3043
+
3044
+ $code_type = intval( $code / 100 );
3045
+ if ( 5 == $code_type ) {
3046
+ return new Jetpack_Error( 'wpcom_5??', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
3047
+ } elseif ( 408 == $code ) {
3048
+ return new Jetpack_Error( 'wpcom_408', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
3049
+ } elseif ( !empty( $json->error ) ) {
3050
+ $error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
3051
+ return new Jetpack_Error( (string) $json->error, $error_description, $code );
3052
+ } elseif ( 200 != $code ) {
3053
+ return new Jetpack_Error( 'wpcom_bad_response', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
3054
+ }
3055
+
3056
+ // Jetpack ID error block
3057
+ if ( empty( $json->jetpack_id ) ) {
3058
+ return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is empty. Do not publicly post this error message! %s', 'jetpack' ), $entity ), $entity );
3059
+ } elseif ( ! is_scalar( $json->jetpack_id ) ) {
3060
+ return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is not a scalar. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity );
3061
+ } elseif ( preg_match( '/[^0-9]/', $json->jetpack_id ) ) {
3062
+ return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID begins with a numeral. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity);
3063
+ }
3064
+
3065
+ if ( empty( $json->jetpack_secret ) || !is_string( $json->jetpack_secret ) )
3066
+ return new Jetpack_Error( 'jetpack_secret', '', $code );
3067
+
3068
+ if ( isset( $json->jetpack_public ) ) {
3069
+ $jetpack_public = (int) $json->jetpack_public;
3070
+ } else {
3071
+ $jetpack_public = false;
3072
+ }
3073
+
3074
+ Jetpack::update_options( array(
3075
+ 'id' => (int) $json->jetpack_id,
3076
+ 'blog_token' => (string) $json->jetpack_secret,
3077
+ 'public' => $jetpack_public,
3078
+ ) );
3079
+
3080
+ return true;
3081
+ }
3082
+
3083
+
3084
+ /* Client Server API */
3085
+
3086
+ /**
3087
+ * Loads the Jetpack XML-RPC client
3088
+ */
3089
+ public static function load_xml_rpc_client() {
3090
+ require_once ABSPATH . WPINC . '/class-IXR.php';
3091
+ require_once dirname( __FILE__ ) . '/class.jetpack-ixr-client.php';
3092
+ }
3093
+
3094
+ function verify_xml_rpc_signature() {
3095
+ if ( $this->xmlrpc_verification ) {
3096
+ return $this->xmlrpc_verification;
3097
+ }
3098
+
3099
+ // It's not for us
3100
+ if ( !isset( $_GET['token'] ) || empty( $_GET['signature'] ) ) {
3101
+ return false;
3102
+ }
3103
+
3104
+ @list( $token_key, $version, $user_id ) = explode( ':', $_GET['token'] );
3105
+ if (
3106
+ empty( $token_key )
3107
+ ||
3108
+ empty( $version ) || strval( JETPACK__API_VERSION ) !== $version
3109
+ ) {
3110
+ return false;
3111
+ }
3112
+
3113
+ if ( '0' === $user_id ) {
3114
+ $token_type = 'blog';
3115
+ $user_id = 0;
3116
+ } else {
3117
+ $token_type = 'user';
3118
+ if ( empty( $user_id ) || ! ctype_digit( $user_id ) ) {
3119
+ return false;
3120
+ }
3121
+ $user_id = (int) $user_id;
3122
+
3123
+ $user = new WP_User( $user_id );
3124
+ if ( ! $user || ! $user->exists() ) {
3125
+ return false;
3126
+ }
3127
+ }
3128
+
3129
+ $token = Jetpack_Data::get_access_token( $user_id );
3130
+ if ( !$token ) {
3131
+ return false;
3132
+ }
3133
+
3134
+ if ( 0 !== strpos( $token->secret, "$token_key." ) ) {
3135
+ return false;
3136
+ }
3137
+
3138
+ require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
3139
+
3140
+ $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
3141
+ if ( isset( $_POST['_jetpack_is_multipart'] ) ) {
3142
+ $post_data = $_POST;
3143
+ $file_hashes = array();
3144
+ foreach ( $post_data as $post_data_key => $post_data_value ) {
3145
+ if ( 0 !== strpos( $post_data_key, '_jetpack_file_hmac_' ) ) {
3146
+ continue;
3147
+ }
3148
+ $post_data_key = substr( $post_data_key, strlen( '_jetpack_file_hmac_' ) );
3149
+ $file_hashes[$post_data_key] = $post_data_value;
3150
+ }
3151
+
3152
+ foreach ( $file_hashes as $post_data_key => $post_data_value ) {
3153
+ unset( $post_data["_jetpack_file_hmac_{$post_data_key}"] );
3154
+ $post_data[$post_data_key] = $post_data_value;
3155
+ }
3156
+
3157
+ ksort( $post_data );
3158
+
3159
+ $body = http_build_query( stripslashes_deep( $post_data ) );
3160
+ } elseif ( is_null( $this->HTTP_RAW_POST_DATA ) ) {
3161
+ $body = file_get_contents( 'php://input' );
3162
+ } else {
3163
+ $body = null;
3164
+ }
3165
+ $signature = $jetpack_signature->sign_current_request( array(
3166
+ 'body' => is_null( $body ) ? $this->HTTP_RAW_POST_DATA : $body
3167
+ ) );
3168
+
3169
+ if ( !$signature ) {
3170
+ return false;
3171
+ } else if ( is_wp_error( $signature ) ) {
3172
+ return $signature;
3173
+ } else if ( $signature !== $_GET['signature'] ) {
3174
+ return false;
3175
+ }
3176
+
3177
+ $timestamp = (int) $_GET['timestamp'];
3178
+ $nonce = stripslashes( (string) $_GET['nonce'] );
3179
+
3180
+ if ( !$this->add_nonce( $timestamp, $nonce ) ) {
3181
+ return false;
3182
+ }
3183
+
3184
+ $this->xmlrpc_verification = array(
3185
+ 'type' => $token_type,
3186
+ 'user_id' => $token->external_user_id,
3187
+ );
3188
+
3189
+ return $this->xmlrpc_verification;
3190
+ }
3191
+
3192
+ /**
3193
+ * Authenticates XML-RPC and other requests from the Jetpack Server
3194
+ */
3195
+ function authenticate_jetpack( $user, $username, $password ) {
3196
+ if ( is_a( $user, 'WP_User' ) ) {
3197
+ return $user;
3198
+ }
3199
+
3200
+ $token_details = $this->verify_xml_rpc_signature();
3201
+
3202
+ if ( ! $token_details || is_wp_error( $token_details ) ) {
3203
+ return $user;
3204
+ }
3205
+
3206
+ if ( 'user' !== $token_details['type'] ) {
3207
+ return $user;
3208
+ }
3209
+
3210
+ if ( ! $token_details['user_id'] ) {
3211
+ return $user;
3212
+ }
3213
+
3214
+ nocache_headers();
3215
+
3216
+ return new WP_User( $token_details['user_id'] );
3217
+ }
3218
+
3219
+ function add_nonce( $timestamp, $nonce ) {
3220
+ global $wpdb;
3221
+ static $nonces_used_this_request = array();
3222
+
3223
+ if ( isset( $nonces_used_this_request["$timestamp:$nonce"] ) ) {
3224
+ return $nonces_used_this_request["$timestamp:$nonce"];
3225
+ }
3226
+
3227
+ // This should always have gone through Jetpack_Signature::sign_request() first to check $timestamp an $nonce
3228
+ $timestamp = (int) $timestamp;
3229
+ $nonce = $wpdb->escape( $nonce );
3230
+
3231
+ // Raw query so we can avoid races: add_option will also update
3232
+ $show_errors = $wpdb->show_errors( false );
3233
+ $return = $wpdb->query( $wpdb->prepare(
3234
+ "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s)",
3235
+ "jetpack_nonce_{$timestamp}_{$nonce}",
3236
+ time(),
3237
+ 'no'
3238
+ ) );
3239
+ $wpdb->show_errors( $show_errors );
3240
+
3241
+ $nonces_used_this_request["$timestamp:$nonce"] = $return;
3242
+
3243
+ return $return;
3244
+ }
3245
+
3246
+ /**
3247
+ * In some setups, $HTTP_RAW_POST_DATA can be emptied during some IXR_Server paths since it is passed by reference to various methods.
3248
+ * Capture it here so we can verify the signature later.
3249
+ */
3250
+ function xmlrpc_methods( $methods ) {
3251
+ $this->HTTP_RAW_POST_DATA = $GLOBALS['HTTP_RAW_POST_DATA'];
3252
+ return $methods;
3253
+ }
3254
+
3255
+ function xmlrpc_options( $options ) {
3256
+ $options['jetpack_version'] = array(
3257
+ 'desc' => __( 'Jetpack Plugin Version' , 'jetpack'),
3258
+ 'readonly' => true,
3259
+ 'value' => JETPACK__VERSION,
3260
+ );
3261
+
3262
+ $options['jetpack_client_id'] = array(
3263
+ 'desc' => __( 'The Client ID/WP.com Blog ID of this site' , 'jetpack'),
3264
+ 'readonly' => true,
3265
+ 'value' => Jetpack::get_option( 'id' ),
3266
+ );
3267
+ return $options;
3268
+ }
3269
+
3270
+ public static function clean_nonces( $all = false ) {
3271
+ global $wpdb;
3272
+
3273
+ $sql = "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE %s";
3274
+ $sql_args = array( like_escape( 'jetpack_nonce_' ) . '%' );
3275
+
3276
+ if ( true !== $all ) {
3277
+ $sql .= ' AND CAST( `option_value` AS UNSIGNED ) < %d';
3278
+ $sql_args[] = time() - 3600;
3279
+ }
3280
+
3281
+ $sql .= ' LIMIT 100';
3282
+
3283
+ $sql = $wpdb->prepare( $sql, $sql_args );
3284
+
3285
+ for ( $i = 0; $i < 1000; $i++ ) {
3286
+ if ( !$wpdb->query( $sql ) ) {
3287
+ break;
3288
+ }
3289
+ }
3290
+ }
3291
+
3292
+ /**
3293
+ * State is passed via cookies from one request to the next, but never to subsequent requests.
3294
+ * SET: state( $key, $value );
3295
+ * GET: $value = state( $key );
3296
+ *
3297
+ * @param string $key
3298
+ * @param string $value
3299
+ * @param bool $restate private
3300
+ */
3301
+ public static function state( $key = null, $value = null, $restate = false ) {
3302
+ static $state = array();
3303
+ static $path, $domain;
3304
+ if ( !isset( $path ) ) {
3305
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
3306
+ $admin_url = Jetpack::admin_url();
3307
+ $bits = parse_url( $admin_url );
3308
+
3309
+ if ( is_array( $bits ) ) {
3310
+ $path = ( isset( $bits['path'] ) ) ? dirname( $bits['path'] ) : null;
3311
+ $domain = ( isset( $bits['host'] ) ) ? $bits['host'] : null;
3312
+ } else {
3313
+ $path = $domain = null;
3314
+ }
3315
+ }
3316
+
3317
+ // Extract state from cookies and delete cookies
3318
+ if ( isset( $_COOKIE[ 'jetpackState' ] ) && is_array( $_COOKIE[ 'jetpackState' ] ) ) {
3319
+ $yum = $_COOKIE[ 'jetpackState' ];
3320
+ unset( $_COOKIE[ 'jetpackState' ] );
3321
+ foreach ( $yum as $k => $v ) {
3322
+ if ( strlen( $v ) )
3323
+ $state[ $k ] = $v;
3324
+ setcookie( "jetpackState[$k]", false, 0, $path, $domain );
3325
+ }
3326
+ }
3327
+
3328
+ if ( $restate ) {
3329
+ foreach ( $state as $k => $v ) {
3330
+ setcookie( "jetpackState[$k]", $v, 0, $path, $domain );
3331
+ }
3332
+ return;
3333
+ }
3334
+
3335
+ // Get a state variable
3336
+ if ( isset( $key ) && !isset( $value ) ) {
3337
+ if ( array_key_exists( $key, $state ) )
3338
+ return $state[ $key ];
3339
+ return null;
3340
+ }
3341
+
3342
+ // Set a state variable
3343
+ if ( isset ( $key ) && isset( $value ) ) {
3344
+ $state[ $key ] = $value;
3345
+ setcookie( "jetpackState[$key]", $value, 0, $path, $domain );
3346
+ }
3347
+ }
3348
+
3349
+ public static function restate() {
3350
+ Jetpack::state( null, null, true );
3351
+ }
3352
+
3353
+ public static function check_privacy( $file ) {
3354
+ static $is_site_publicly_accessible = null;
3355
+
3356
+ if ( is_null( $is_site_publicly_accessible ) ) {
3357
+ $is_site_publicly_accessible = false;
3358
+
3359
+ Jetpack::load_xml_rpc_client();
3360
+ $rpc = new Jetpack_IXR_Client();
3361
+
3362
+ $success = $rpc->query( 'jetpack.isSitePubliclyAccessible', home_url() );
3363
+ if ( $success ) {
3364
+ $response = $rpc->getResponse();
3365
+ if ( $response ) {
3366
+ $is_site_publicly_accessible = true;
3367
+ }
3368
+ }
3369
+
3370
+ Jetpack::update_option( 'public', (int) $is_site_publicly_accessible );
3371
+ }
3372
+
3373
+ if ( $is_site_publicly_accessible ) {
3374
+ return;
3375
+ }
3376
+
3377
+ $module_slug = self::get_module_slug( $file );
3378
+
3379
+ $privacy_checks = Jetpack::state( 'privacy_checks' );
3380
+ if ( !$privacy_checks ) {
3381
+ $privacy_checks = $module_slug;
3382
+ } else {
3383
+ $privacy_checks .= ",$module_slug";
3384
+ }
3385
+
3386
+ Jetpack::state( 'privacy_checks', $privacy_checks );
3387
+ }
3388
+
3389
+ /**
3390
+ * Helper method for multicall XMLRPC.
3391
+ */
3392
+ public static function xmlrpc_async_call() {
3393
+ global $blog_id;
3394
+ static $clients = array();
3395
+
3396
+ $client_blog_id = is_multisite() ? $blog_id : 0;
3397
+
3398
+ if ( !isset( $clients[$client_blog_id] ) ) {
3399
+ Jetpack::load_xml_rpc_client();
3400
+ $clients[$client_blog_id] = new Jetpack_IXR_ClientMulticall( array(
3401
+ 'user_id' => JETPACK_MASTER_USER,
3402
+ ) );
3403
+ ignore_user_abort( true );
3404
+ add_action( 'shutdown', array( 'Jetpack', 'xmlrpc_async_call' ) );
3405
+ }
3406
+
3407
+ $args = func_get_args();
3408
+
3409
+ if ( !empty( $args[0] ) ) {
3410
+ call_user_func_array( array( $clients[$client_blog_id], 'addCall' ), $args );
3411
+ } elseif ( is_multisite() ) {
3412
+ foreach ( $clients as $client_blog_id => $client ) {
3413
+ if ( !$client_blog_id || empty( $client->calls ) ) {
3414
+ continue;
3415
+ }
3416
+
3417
+ $switch_success = switch_to_blog( $client_blog_id, true );
3418
+ if ( !$switch_success ) {
3419
+ continue;
3420
+ }
3421
+
3422
+ flush();
3423
+ $client->query();
3424
+
3425
+ restore_current_blog();
3426
+ }
3427
+ } else {
3428
+ if ( isset( $clients[0] ) && !empty( $clients[0]->calls ) ) {
3429
+ flush();
3430
+ $clients[0]->query();
3431
+ }
3432
+ }
3433
+ }
3434
+
3435
+ public static function staticize_subdomain( $url ) {
3436
+ $host = parse_url( $url, PHP_URL_HOST );
3437
+ if ( !preg_match( '/.?(?:wordpress|wp)\.com$/', $host ) ) {
3438
+ return $url;
3439
+ }
3440
+
3441
+ if ( is_ssl() ) {
3442
+ return preg_replace( '|https?://[^/]++/|', 'https://s-ssl.wordpress.com/', $url );
3443
+ }
3444
+
3445
+ srand( crc32( basename( $url ) ) );
3446
+ $static_counter = rand( 0, 2 );
3447
+ srand(); // this resets everything that relies on this, like array_rand() and shuffle()
3448
+
3449
+ return preg_replace( '|://[^/]+?/|', "://s$static_counter.wp.com/", $url );
3450
+ }
3451
+
3452
+ /* JSON API Authorization */
3453
+
3454
+ /**
3455
+ * Handles the login action for Authorizing the JSON API
3456
+ */
3457
+ function login_form_json_api_authorization() {
3458
+ $this->verify_json_api_authorization_request();
3459
+
3460
+ add_action( 'wp_login', array( &$this, 'store_json_api_authorization_token' ), 10, 2 );
3461
+
3462
+ add_action( 'login_message', array( &$this, 'login_message_json_api_authorization' ) );
3463
+ add_action( 'login_form', array( &$this, 'preserve_action_in_login_form_for_json_api_authorization' ) );
3464
+ add_filter( 'site_url', array( &$this, 'post_login_form_to_signed_url' ), 10, 3 );
3465
+ }
3466
+
3467
+ // Make sure the login form is POSTed to the signed URL so we can reverify the request
3468
+ function post_login_form_to_signed_url( $url, $path, $scheme ) {
3469
+ if ( 'wp-login.php' !== $path || 'login_post' !== $scheme ) {
3470
+ return $url;
3471
+ }
3472
+
3473
+ return "$url?{$_SERVER['QUERY_STRING']}";
3474
+ }
3475
+
3476
+ // Make sure the POSTed request is handled by the same action
3477
+ function preserve_action_in_login_form_for_json_api_authorization() {
3478
+ echo "<input type='hidden' name='action' value='jetpack_json_api_authorization' />\n";
3479
+ }
3480
+
3481
+ // If someone logs in to approve API access, store the Access Code in usermeta
3482
+ function store_json_api_authorization_token( $user_login, $user ) {
3483
+ add_filter( 'login_redirect', array( &$this, 'add_token_to_login_redirect_json_api_authorization' ), 10, 3 );
3484
+ add_filter( 'allowed_redirect_hosts', array( &$this, 'allow_wpcom_public_api_domain' ) );
3485
+ $token = wp_generate_password( 32, false );
3486
+ update_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], $token );
3487
+ }
3488
+
3489
+ // Add public-api.wordpress.com to the safe redirect whitelist - only added when someone allows API access
3490
+ function allow_wpcom_public_api_domain( $domains ) {
3491
+ $domains[] = 'public-api.wordpress.com';
3492
+ return $domains;
3493
+ }
3494
+
3495
+ // Add the Access Code details to the public-api.wordpress.com redirect
3496
+ function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) {
3497
+ return add_query_arg( urlencode_deep( array(
3498
+ 'jetpack-code' => get_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], true ),
3499
+ 'jetpack-user-id' => (int) $user->ID,
3500
+ 'jetpack-state' => $this->json_api_authorization_request['state'],
3501
+ ) ), $redirect_to );
3502
+ }
3503
+
3504
+ // Verifies the request by checking the signature
3505
+ function verify_json_api_authorization_request() {
3506
+ require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
3507
+
3508
+ $token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
3509
+ if ( !$token || empty( $token->secret ) ) {
3510
+ wp_die( __( 'You must connect your Jetpack plugin to WordPress.com to use this feature.' , 'jetpack') );
3511
+ }
3512
+
3513
+ $die_error = __( 'Someone may be trying to trick you into giving them access to your site. Or it could be you just encountered a bug :). Either way, please close this window.', 'jetpack' );
3514
+
3515
+ $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
3516
+ $signature = $jetpack_signature->sign_current_request( array( 'body' => null, 'method' => 'GET' ) );
3517
+ if ( !$signature ) {
3518
+ wp_die( $die_error );
3519
+ } else if ( is_wp_error( $signature ) ) {
3520
+ wp_die( $die_error );
3521
+ } else if ( $signature !== $_GET['signature'] ) {
3522
+ if ( is_ssl() ) {
3523
+ // If we signed an HTTP request on the Jetpack Servers, but got redirected to HTTPS by the local blog, check the HTTP signature as well
3524
+ $signature = $jetpack_signature->sign_current_request( array( 'scheme' => 'http', 'body' => null, 'method' => 'GET' ) );
3525
+ if ( !$signature || is_wp_error( $signature ) || $signature !== $_GET['signature'] ) {
3526
+ wp_die( $die_error );
3527
+ }
3528
+ } else {
3529
+ wp_die( $die_error );
3530
+ }
3531
+ }
3532
+
3533
+ $timestamp = (int) $_GET['timestamp'];
3534
+ $nonce = stripslashes( (string) $_GET['nonce'] );
3535
+
3536
+ if ( !$this->add_nonce( $timestamp, $nonce ) ) {
3537
+ // De-nonce the nonce, at least for 5 minutes.
3538
+ // We have to reuse this nonce at least once (used the first time when the initial request is made, used a second time when the login form is POSTed)
3539
+ $old_nonce_time = get_option( "jetpack_nonce_{$timestamp}_{$nonce}" );
3540
+ if ( $old_nonce_time < time() - 300 ) {
3541
+ wp_die( __( 'The authorization process expired. Please go back and try again.' , 'jetpack') );
3542
+ }
3543
+ }
3544
+
3545
+ $data = json_decode( base64_decode( stripslashes( $_GET['data'] ) ) );
3546
+ $data_filters = array(
3547
+ 'state' => 'opaque',
3548
+ 'client_id' => 'int',
3549
+ 'client_title' => 'string',
3550
+ 'client_image' => 'url',
3551
+ );
3552
+
3553
+ foreach ( $data_filters as $key => $sanitation ) {
3554
+ if ( !isset( $data->$key ) ) {
3555
+ wp_die( $die_error );
3556
+ }
3557
+
3558
+ switch ( $sanitation ) {
3559
+ case 'int' :
3560
+ $this->json_api_authorization_request[$key] = (int) $data->$key;
3561
+ break;
3562
+ case 'opaque' :
3563
+ $this->json_api_authorization_request[$key] = (string) $data->$key;
3564
+ break;
3565
+ case 'string' :
3566
+ $this->json_api_authorization_request[$key] = wp_kses( (string) $data->$key, array() );
3567
+ break;
3568
+ case 'url' :
3569
+ $this->json_api_authorization_request[$key] = esc_url_raw( (string) $data->$key );
3570
+ break;
3571
+ }
3572
+ }
3573
+
3574
+ if ( empty( $this->json_api_authorization_request['client_id'] ) ) {
3575
+ wp_die( $die_error );
3576
+ }
3577
+ }
3578
+
3579
+ function login_message_json_api_authorization( $message ) {
3580
+ return '<p class="message">' . sprintf(
3581
+ esc_html__( '%s wants to access your site&#8217;s data. Log in to authorize that access.' , 'jetpack'),
3582
+ '<strong>' . esc_html( $this->json_api_authorization_request['client_title'] ) . '</strong>'
3583
+ ) . '<img src="' . esc_url( $this->json_api_authorization_request['client_image'] ) . '" /></p>';
3584
+ }
3585
+
3586
+ /**
3587
+ * Get $content_width, but with a <s>twist</s> filter.
3588
+ */
3589
+ public static function get_content_width() {
3590
+ return apply_filters( 'jetpack_content_width', $GLOBALS['content_width'] );
3591
+ }
3592
+
3593
+ /**
3594
+ * Centralize the function here until it gets added to core.
3595
+ *
3596
+ * @param int|string|object $id_or_email A user ID, email address, or comment object
3597
+ * @param int $size Size of the avatar image
3598
+ * @param string $default URL to a default image to use if no avatar is available
3599
+ * @param bool $force_display Whether to force it to return an avatar even if show_avatars is disabled
3600
+ *
3601
+ * @return array First element is the URL, second is the class.
3602
+ */
3603
+ public static function get_avatar_url( $id_or_email, $size = 96, $default = '', $force_display = false ) {
3604
+ // Don't bother adding the __return_true filter if it's already there.
3605
+ $has_filter = has_filter( 'pre_option_show_avatars', '__return_true' );
3606
+
3607
+ if ( $force_display && ! $has_filter )
3608
+ add_filter( 'pre_option_show_avatars', '__return_true' );
3609
+
3610
+ $avatar = get_avatar( $id_or_email, $size, $default );
3611
+
3612
+ if ( $force_display && ! $has_filter )
3613
+ remove_filter( 'pre_option_show_avatars', '__return_true' );
3614
+
3615
+ // If no data, fail out.
3616
+ if ( is_wp_error( $avatar ) || ! $avatar )
3617
+ return array( null, null );
3618
+
3619
+ // Pull out the URL. If it's not there, fail out.
3620
+ if ( ! preg_match( '/src=["\']([^"\']+)["\']/', $avatar, $url_matches ) )
3621
+ return array( null, null );
3622
+ $url = wp_specialchars_decode( $url_matches[1], ENT_QUOTES );
3623
+
3624
+ // Pull out the class, but it's not a big deal if it's missing.
3625
+ $class = '';
3626
+ if ( preg_match( '/class=["\']([^"\']+)["\']/', $avatar, $class_matches ) )
3627
+ $class = wp_specialchars_decode( $class_matches[1], ENT_QUOTES );
3628
+
3629
+ return array( $url, $class );
3630
+ }
3631
+
3632
+ /*
3633
+ * Pings the WordPress.com Mirror Site for the specified options.
3634
+ *
3635
+ * @param string|array $option_names The option names to request from the WordPress.com Mirror Site
3636
+ *
3637
+ * @return array An associative array of the option values as stored in the WordPress.com Mirror Site
3638
+ */
3639
+ public static function get_cloud_site_options( $option_names ) {
3640
+ $option_names = array_filter( (array) $option_names, 'is_string' );
3641
+
3642
+ Jetpack::load_xml_rpc_client();
3643
+ $xml = new Jetpack_IXR_Client( array(
3644
+ 'user_id' => get_current_user_id(),
3645
+ ) );
3646
+ $xml->query( 'jetpack.fetchSiteOptions', $option_names );
3647
+ if ( $xml->isError() ) {
3648
+ return array_flip( $option_names );
3649
+ }
3650
+ $cloud_site_options = $xml->getResponse();
3651
+
3652
+ // If we want to intentionally jumble the results to test it ...
3653
+ if( isset( $_GET['spoof_identity_crisis'] ) ) {
3654
+ foreach( $cloud_site_options as $key => $value ) {
3655
+ $cloud_site_options[ $key ] = wp_generate_password();
3656
+ }
3657
+ }
3658
+ return $cloud_site_options;
3659
+ }
3660
+
3661
+ /*
3662
+ * Checks to make sure that local options have the same values as remote options. Will cache the results for up to 24 hours.
3663
+ *
3664
+ * @param bool $force_recheck Whether to ignore any cached transient and manually re-check.
3665
+ *
3666
+ * @return array An array of options that do not match. If everything is good, it will evaluate to false.
3667
+ */
3668
+ public static function check_identity_crisis( $force_recheck = false ) {
3669
+ if ( ! current_user_can( 'manage_options' ) )
3670
+ return false;
3671
+
3672
+ if ( ! Jetpack::is_active() || Jetpack::is_development_mode() )
3673
+ return false;
3674
+
3675
+ if ( isset( $_GET['spoof_identity_crisis'] ) )
3676
+ $force_recheck = true;
3677
+
3678
+ if ( $force_recheck || false === ( $errors = get_transient( 'jetpack_has_identity_crisis' ) ) ) {
3679
+ $options_to_check = array(
3680
+ 'siteurl',
3681
+ 'home',
3682
+ );
3683
+ $cloud_options = self::get_cloud_site_options( $options_to_check );
3684
+ $errors = array();
3685
+ foreach ( $cloud_options as $cloud_key => $cloud_value ) {
3686
+ if ( $cloud_value !== get_option( $cloud_key ) ) {
3687
+ $errors[ $cloud_key ] = $cloud_value;
3688
+ }
3689
+ }
3690
+ // Make sure if we're spoofing it, that we don't let the spoof spill over.
3691
+ if ( ! isset( $_GET['spoof_identity_crisis'] ) ) {
3692
+ set_transient( 'jetpack_has_identity_crisis', $errors, DAY_IN_SECONDS );
3693
+ }
3694
+ }
3695
+ return apply_filters( 'jetpack_has_identity_crisis', $errors, $force_recheck );
3696
+ }
3697
+
3698
+ /*
3699
+ * Displays an admin_notice, alerting the user to an identity crisis.
3700
+ */
3701
+ public function alert_identity_crisis() {
3702
+ if ( ! current_user_can( 'manage_options' ) )
3703
+ return;
3704
+
3705
+ if ( ! $errors = self::check_identity_crisis() )
3706
+ return;
3707
+ ?>
3708
+
3709
+ <div id="message" class="updated jetpack-message jp-identity-crisis">
3710
+ <div class="jetpack-wrap-container">
3711
+ <div class="jetpack-text-container">
3712
+ <h3><?php _e( 'Something has gotten mixed up!', 'jetpack' ); ?></h3>
3713
+ <?php foreach ( $errors as $key => $value ) : ?>
3714
+ <p><?php printf( __( 'Your <code>%1$s</code> option is set up as <strong>%2$s</strong>, but your WordPress.com connection lists it as <strong>%3$s</strong>!', 'jetpack' ), $key, (string) get_option( $key ), $value ); ?></p>
3715
+ <?php endforeach; ?>
3716
+ <p><?php _e( 'This problem can often be resolved by disconnecting, then reconnecting to WordPress.com.', 'jetpack' ); ?> <a href="<?php echo $this->build_reconnect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Disconnect and Reconnect to WordPress.com', 'jetpack' ); ?></a></p>
3717
+ </div>
3718
+ </div>
3719
+ </div>
3720
+
3721
+ <?php
3722
+ }
3723
+ }
class.json-api-endpoints.php CHANGED
@@ -161,7 +161,6 @@ abstract class WPCOM_JSON_API_Endpoint {
161
  // Get POST body data
162
  function input( $return_default_values = true, $cast_and_filter = true ) {
163
  $input = trim( $this->api->post_body );
164
-
165
  switch ( $this->api->content_type ) {
166
  case 'application/json; charset=utf-8' :
167
  case 'application/json' :
@@ -170,7 +169,8 @@ abstract class WPCOM_JSON_API_Endpoint {
170
  case 'text/x-javascript' :
171
  case 'text/x-json' :
172
  case 'text/json' :
173
- $return = json_decode( $input );
 
174
  if ( function_exists( 'json_last_error' ) ) {
175
  if ( JSON_ERROR_NONE !== json_last_error() ) {
176
  return null;
@@ -181,9 +181,6 @@ abstract class WPCOM_JSON_API_Endpoint {
181
  }
182
  }
183
 
184
- if ( is_object( $return ) ) {
185
- $return = (array) $return;
186
- }
187
  break;
188
  case 'multipart/form-data' :
189
  $return = array_merge( stripslashes_deep( $_POST ), $_FILES );
@@ -203,6 +200,7 @@ abstract class WPCOM_JSON_API_Endpoint {
203
  function cast_and_filter( $data, $documentation, $return_default_values = false, $for_output = false ) {
204
  $return_as_object = false;
205
  if ( is_object( $data ) ) {
 
206
  $data = (array) $data;
207
  $return_as_object = true;
208
  } elseif ( !is_array( $data ) ) {
@@ -575,25 +573,22 @@ abstract class WPCOM_JSON_API_Endpoint {
575
 
576
  // Examples for endpoint documentation response
577
  $response_key = 'dev_response_' . $this->version . '_' . $this->method . '_' . sanitize_title( $this->path );
578
- $response = get_option( $response_key );
579
 
580
  // Response doesn't exist, so run the request
581
- if ( empty( $response ) ) {
582
 
583
  // Only trust GET request
584
  if ( 'GET' === $this->method ) {
585
- $response = wp_remote_get( $this->example_request );
586
- }
587
-
588
- // Set as false if it's an error
589
- if ( is_wp_error( $response ) ) {
590
- $response = false;
591
- }
592
 
593
- // Only update the option if there's a result
594
- if ( !empty( $response ) ) {
595
- $response = $response['body'];
596
- update_option( $response_key, $response );
 
 
597
  }
598
  }
599
 
@@ -887,6 +882,9 @@ EOPHP;
887
  $profile_URL = 'http://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
888
  } else {
889
  if ( isset( $author->post_author ) ) {
 
 
 
890
  $author = $author->post_author;
891
  } elseif ( isset( $author->user_id ) && $author->user_id ) {
892
  $author = $author->user_id;
@@ -1150,7 +1148,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
1150
  if ( empty( $key ) )
1151
  return false;
1152
 
1153
- // whitelist of post types that can be accessed
1154
  if ( in_array( $key, apply_filters( 'rest_api_allowed_public_metadata', array() ) ) )
1155
  return true;
1156
 
@@ -1439,7 +1437,7 @@ abstract class WPCOM_JSON_API_Post_Endpoint extends WPCOM_JSON_API_Endpoint {
1439
  $metadata[] = array(
1440
  'id' => $meta['meta_id'],
1441
  'key' => $meta['meta_key'],
1442
- 'value' => $meta['meta_value']
1443
  );
1444
  }
1445
 
@@ -2007,6 +2005,8 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
2007
  if ( ! empty( $metadata ) ) {
2008
  foreach ( (array) $metadata as $meta ) {
2009
 
 
 
2010
  $existing_meta_item = new stdClass;
2011
 
2012
  if ( empty( $meta->operation ) )
@@ -2068,6 +2068,8 @@ class WPCOM_JSON_API_Update_Post_Endpoint extends WPCOM_JSON_API_Post_Endpoint {
2068
  }
2069
  }
2070
 
 
 
2071
  $return = $this->get_post_by( 'ID', $post_id, $args['context'] );
2072
  if ( !$return || is_wp_error( $return ) ) {
2073
  return $return;
@@ -2735,7 +2737,10 @@ class WPCOM_JSON_API_Update_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endp
2735
  // /sites/%s/comments/%d -> $blog_id, $comment_id
2736
  // /sites/%s/comments/%d/delete -> $blog_id, $comment_id
2737
  function callback( $path = '', $blog_id = 0, $object_id = 0 ) {
2738
- $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
 
 
 
2739
  if ( is_wp_error( $blog_id ) ) {
2740
  return $blog_id;
2741
  }
@@ -2873,6 +2878,10 @@ class WPCOM_JSON_API_Update_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endp
2873
  }
2874
 
2875
  if ( isset( $update['comment_status'] ) ) {
 
 
 
 
2876
  switch ( $update['comment_status'] ) {
2877
  case 'approved' :
2878
  if ( 'approve' !== $comment_status ) {
@@ -2957,6 +2966,12 @@ class WPCOM_JSON_API_Update_Comment_Endpoint extends WPCOM_JSON_API_Comment_Endp
2957
 
2958
  return $this->get_comment( $comment->comment_ID, $args['context'] );
2959
  }
 
 
 
 
 
 
2960
  }
2961
 
2962
  class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint {
@@ -3025,10 +3040,14 @@ class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint {
3025
  }
3026
  }
3027
 
 
 
3028
  /*
3029
  * Set up endpoints
3030
  */
3031
 
 
 
3032
  /*
3033
  * Site endpoints
3034
  */
@@ -3108,7 +3127,7 @@ new WPCOM_JSON_API_List_Posts_Endpoint( array(
3108
  'author' => "(int) Author's user ID",
3109
  'search' => '(string) Search query',
3110
  'meta_key' => '(string) Metadata key that the post should contain',
3111
- 'meta_value' => '(int|string) Metadata value that the post should contain. Will only be applied if a `meta_key` is also given',
3112
  ),
3113
 
3114
  'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/posts/?number=5&pretty=1'
161
  // Get POST body data
162
  function input( $return_default_values = true, $cast_and_filter = true ) {
163
  $input = trim( $this->api->post_body );
 
164
  switch ( $this->api->content_type ) {
165
  case 'application/json; charset=utf-8' :
166
  case 'application/json' :
169
  case 'text/x-javascript' :
170
  case 'text/x-json' :
171
  case 'text/json' :
172
+ $return = json_decode( $input, true );
173
+
174
  if ( function_exists( 'json_last_error' ) ) {
175
  if ( JSON_ERROR_NONE !== json_last_error() ) {
176
  return null;
181
  }
182
  }
183
 
 
 
 
184
  break;
185
  case 'multipart/form-data' :
186
  $return = array_merge( stripslashes_deep( $_POST ), $_FILES );
200
  function cast_and_filter( $data, $documentation, $return_default_values = false, $for_output = false ) {
201
  $return_as_object = false;
202
  if ( is_object( $data ) ) {
203
+ // @todo this should probably be a deep copy if $data can ever have nested objects
204
  $data = (array) $data;
205
  $return_as_object = true;
206
  } elseif ( !is_array( $data ) ) {
573
 
574
  // Examples for endpoint documentation response
575
  $response_key = 'dev_response_' . $this->version . '_' . $this->method . '_' . sanitize_title( $this->path );
576
+ $response = wp_cache_get( $response_key );
577
 
578
  // Response doesn't exist, so run the request
579
+ if ( false === $response ) {
580
 
581
  // Only trust GET request
582
  if ( 'GET' === $this->method ) {
583
+ $response = wp_remote_get( $this->example_request );
584
+ $response_body = wp_remote_retrieve_body( $response );
 
 
 
 
 
585
 
586
+ // Only cache if there's a result
587
+ if ( strlen( $response_body ) ) {
588
+ wp_cache_set( $response_key, $response );
589
+ } else {
590
+ wp_cache_delete( $response_key );
591
+ }
592
  }
593
  }
594
 
882
  $profile_URL = 'http://en.gravatar.com/' . md5( strtolower( trim( $email ) ) );
883
  } else {
884
  if ( isset( $author->post_author ) ) {
885
+ if ( 0 == $author->post_author )
886
+ return null;
887
+
888
  $author = $author->post_author;
889
  } elseif ( isset( $author->user_id ) && $author->user_id ) {
890
  $author = $author->user_id;
1148
  if ( empty( $key ) )
1149
  return false;
1150
 
1151
+ // whitelist of metadata that can be accessed
1152
  if ( in_array( $key, apply_filters( 'rest_api_allowed_public_metadata', array() ) ) )
1153
  return true;
1154
 
1437
  $metadata[] = array(
1438
  'id' => $meta['meta_id'],
1439
  'key' => $meta['meta_key'],
1440
+ 'value' => maybe_unserialize( $meta['meta_value'] ),
1441
  );
1442
  }
1443
 
2005
  if ( ! empty( $metadata ) ) {
2006
  foreach ( (array) $metadata as $meta ) {
2007
 
2008
+ $meta = (object) $meta;
2009
+
2010
  $existing_meta_item = new stdClass;
2011
 
2012
  if ( empty( $meta->operation ) )
2068
  }
2069
  }
2070
 
2071
+ do_action( 'rest_api_inserted_post', $post_id, $insert, $new );
2072
+
2073
  $return = $this->get_post_by( 'ID', $post_id, $args['context'] );
2074
  if ( !$return || is_wp_error( $return ) ) {
2075
  return $return;
2737
  // /sites/%s/comments/%d -> $blog_id, $comment_id
2738
  // /sites/%s/comments/%d/delete -> $blog_id, $comment_id
2739
  function callback( $path = '', $blog_id = 0, $object_id = 0 ) {
2740
+ if ( $this->api->ends_with( $path, '/new' ) )
2741
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ), false );
2742
+ else
2743
+ $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
2744
  if ( is_wp_error( $blog_id ) ) {
2745
  return $blog_id;
2746
  }
2878
  }
2879
 
2880
  if ( isset( $update['comment_status'] ) ) {
2881
+ if ( count( $update ) === 1 ) {
2882
+ // We are only here to update the comment status so let's respond ASAP
2883
+ add_action( 'wp_set_comment_status', array( $this, 'output_comment' ), 0, 1 );
2884
+ }
2885
  switch ( $update['comment_status'] ) {
2886
  case 'approved' :
2887
  if ( 'approve' !== $comment_status ) {
2966
 
2967
  return $this->get_comment( $comment->comment_ID, $args['context'] );
2968
  }
2969
+
2970
+ function output_comment( $comment_id ) {
2971
+ $args = $this->query_args();
2972
+ $output = $this->get_comment( $comment_id, $args['context'] );
2973
+ $this->api->output_early( 200, $output );
2974
+ }
2975
  }
2976
 
2977
  class WPCOM_JSON_API_GET_Site_Endpoint extends WPCOM_JSON_API_Endpoint {
3040
  }
3041
  }
3042
 
3043
+
3044
+
3045
  /*
3046
  * Set up endpoints
3047
  */
3048
 
3049
+
3050
+
3051
  /*
3052
  * Site endpoints
3053
  */
3127
  'author' => "(int) Author's user ID",
3128
  'search' => '(string) Search query',
3129
  'meta_key' => '(string) Metadata key that the post should contain',
3130
+ 'meta_value' => '(string) Metadata value that the post should contain. Will only be applied if a `meta_key` is also given',
3131
  ),
3132
 
3133
  'example_request' => 'https://public-api.wordpress.com/rest/v1/sites/en.blog.wordpress.com/posts/?number=5&pretty=1'
class.json-api.php CHANGED
@@ -12,6 +12,7 @@ class WPCOM_JSON_API {
12
  var $method = '';
13
  var $url = '';
14
  var $path = '';
 
15
  var $query = array();
16
  var $post_body = null;
17
  var $files = null;
@@ -23,6 +24,7 @@ class WPCOM_JSON_API {
23
  var $public_api_scheme = 'https';
24
 
25
  var $trapped_error = null;
 
26
 
27
  static function init( $method = null, $url = null, $post_body = null ) {
28
  if ( !self::$self ) {
@@ -122,11 +124,17 @@ class WPCOM_JSON_API {
122
 
123
  add_filter( 'comment_edit_pre', array( $this, 'comment_edit_pre' ) );
124
 
125
- $this->initialize();
 
 
 
 
126
 
127
- // Normalize path
128
  $this->path = untrailingslashit( $this->path );
129
- $this->path = preg_replace( '#^/rest/v1#', '', $this->path );
 
 
130
 
131
  $allowed_methods = array( 'GET', 'POST' );
132
  $four_oh_five = false;
@@ -238,29 +246,37 @@ class WPCOM_JSON_API {
238
  if ( !$response ) {
239
  return $this->output( 500, '', 'text/plain' );
240
  } elseif ( is_wp_error( $response ) ) {
241
- $status_code = $response->get_error_data();
242
-
243
- if ( is_array( $status_code ) )
244
- $status_code = $status_code['status_code'];
245
-
246
- if ( !$status_code ) {
247
- $status_code = 400;
248
- }
249
- $response = array(
250
- 'error' => $response->get_error_code(),
251
- 'message' => $response->get_error_message(),
252
- );
253
- return $this->output( $status_code, $response );
254
  }
255
 
256
  return $this->output( 200, $response );
257
  }
258
 
259
  function process_request( WPCOM_JSON_API_Endpoint $endpoint, $path_pieces ) {
 
260
  return call_user_func_array( array( $endpoint, 'callback' ), $path_pieces );
261
  }
262
 
 
 
 
 
 
 
 
 
 
 
 
263
  function output( $status_code, $response = null, $content_type = 'application/json' ) {
 
 
 
 
 
 
 
 
264
  if ( is_null( $response ) ) {
265
  $response = new stdClass;
266
  }
@@ -314,6 +330,22 @@ class WPCOM_JSON_API {
314
  return $content_type;
315
  }
316
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  function ensure_http_scheme_of_home_url( $url, $path, $original_scheme ) {
318
  if ( $original_scheme ) {
319
  return $url;
@@ -456,4 +488,9 @@ class WPCOM_JSON_API {
456
  'message' => $this->trapped_error['message'],
457
  ) );
458
  }
 
 
 
 
 
459
  }
12
  var $method = '';
13
  var $url = '';
14
  var $path = '';
15
+ var $version = null;
16
  var $query = array();
17
  var $post_body = null;
18
  var $files = null;
24
  var $public_api_scheme = 'https';
25
 
26
  var $trapped_error = null;
27
+ var $did_output = false;
28
 
29
  static function init( $method = null, $url = null, $post_body = null ) {
30
  if ( !self::$self ) {
124
 
125
  add_filter( 'comment_edit_pre', array( $this, 'comment_edit_pre' ) );
126
 
127
+ $initialization = $this->initialize();
128
+ if ( is_wp_error( $initialization ) ) {
129
+ $this->output_error( $initialization );
130
+ return;
131
+ }
132
 
133
+ // Normalize path and extract API version
134
  $this->path = untrailingslashit( $this->path );
135
+ preg_match( '#^/rest/v1(\.\d+)*#', $this->path, $matches );
136
+ $this->path = substr( $this->path, strlen( $matches[0] ) );
137
+ $this->version = $matches[1];
138
 
139
  $allowed_methods = array( 'GET', 'POST' );
140
  $four_oh_five = false;
246
  if ( !$response ) {
247
  return $this->output( 500, '', 'text/plain' );
248
  } elseif ( is_wp_error( $response ) ) {
249
+ return $this->output_error( $response );
 
 
 
 
 
 
 
 
 
 
 
 
250
  }
251
 
252
  return $this->output( 200, $response );
253
  }
254
 
255
  function process_request( WPCOM_JSON_API_Endpoint $endpoint, $path_pieces ) {
256
+ $this->endpoint = $endpoint;
257
  return call_user_func_array( array( $endpoint, 'callback' ), $path_pieces );
258
  }
259
 
260
+ function output_early( $status_code, $response = null, $content_type = 'application/json' ) {
261
+ $exit = $this->exit;
262
+ $this->exit = false;
263
+ if ( is_wp_error( $response ) )
264
+ $this->output_error( $response );
265
+ else
266
+ $this->output( $status_code, $response, $content_type );
267
+ $this->exit = $exit;
268
+ $this->finish_request();
269
+ }
270
+
271
  function output( $status_code, $response = null, $content_type = 'application/json' ) {
272
+ // In case output() was called before the callback returned
273
+ if ( $this->did_output ) {
274
+ if ( $this->exit )
275
+ exit;
276
+ return $content_type;
277
+ }
278
+ $this->did_output = true;
279
+
280
  if ( is_null( $response ) ) {
281
  $response = new stdClass;
282
  }
330
  return $content_type;
331
  }
332
 
333
+ function output_error( $error ) {
334
+ $status_code = $error->get_error_data();
335
+
336
+ if ( is_array( $status_code ) )
337
+ $status_code = $status_code['status_code'];
338
+
339
+ if ( !$status_code ) {
340
+ $status_code = 400;
341
+ }
342
+ $response = array(
343
+ 'error' => $error->get_error_code(),
344
+ 'message' => $error->get_error_message(),
345
+ );
346
+ return $this->output( $status_code, $response );
347
+ }
348
+
349
  function ensure_http_scheme_of_home_url( $url, $path, $original_scheme ) {
350
  if ( $original_scheme ) {
351
  return $url;
488
  'message' => $this->trapped_error['message'],
489
  ) );
490
  }
491
+
492
+ function finish_request() {
493
+ if ( function_exists( 'fastcgi_finish_request' ) )
494
+ return fastcgi_finish_request();
495
+ }
496
  }
class.photon.php CHANGED
@@ -51,8 +51,9 @@ class Jetpack_Photon {
51
  if ( ! function_exists( 'jetpack_photon_url' ) )
52
  return;
53
 
54
- // Images in post content
55
  add_filter( 'the_content', array( __CLASS__, 'filter_the_content' ), 999999 );
 
56
 
57
  // Core image retrieval
58
  add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), 10, 3 );
51
  if ( ! function_exists( 'jetpack_photon_url' ) )
52
  return;
53
 
54
+ // Images in post content and galleries
55
  add_filter( 'the_content', array( __CLASS__, 'filter_the_content' ), 999999 );
56
+ add_filter( 'get_post_gallery', array( __CLASS__, 'filter_the_content' ), 999999 );
57
 
58
  // Core image retrieval
59
  add_filter( 'image_downsize', array( $this, 'filter_image_downsize' ), 10, 3 );
functions.opengraph.php CHANGED
@@ -103,7 +103,7 @@ function jetpack_og_tags() {
103
  echo $og_output;
104
  }
105
 
106
- function jetpack_og_get_image( $width = 50, $height = 50, $max_images = 4 ) { // Facebook requires thumbnails to be a minimum of 50x50
107
  $image = '';
108
 
109
  if ( is_singular() && !is_home() && !is_front_page() ) {
103
  echo $og_output;
104
  }
105
 
106
+ function jetpack_og_get_image( $width = 200, $height = 200, $max_images = 4 ) { // Facebook requires thumbnails to be a minimum of 200x200
107
  $image = '';
108
 
109
  if ( is_singular() && !is_home() && !is_front_page() ) {
functions.photon.php CHANGED
@@ -80,7 +80,7 @@ function jetpack_photon_url( $image_url, $args = array(), $scheme = null ) {
80
 
81
  return jetpack_photon_url_scheme( $photon_url, $scheme );
82
  }
83
-
84
 
85
  /**
86
  * WordPress.com
@@ -157,4 +157,4 @@ function jetpack_photon_allow_facebook_graph_domain( $allow = false, $domain ) {
157
  }
158
 
159
  return $allow;
160
- }
80
 
81
  return jetpack_photon_url_scheme( $photon_url, $scheme );
82
  }
83
+ add_filter( 'jetpack_photon_url', 'jetpack_photon_url', 10, 3 );
84
 
85
  /**
86
  * WordPress.com
157
  }
158
 
159
  return $allow;
160
+ }
jetpack.php CHANGED
@@ -5,7 +5,7 @@
5
  * Plugin URI: http://wordpress.org/extend/plugins/jetpack/
6
  * Description: Bring the power of the WordPress.com cloud to your self-hosted WordPress. Jetpack enables you to connect your blog to a WordPress.com account to use the powerful features normally only available to WordPress.com users.
7
  * Author: Automattic
8
- * Version: 2.2.8
9
  * Author URI: http://jetpack.me
10
  * License: GPL2+
11
  * Text Domain: jetpack
@@ -14,4588 +14,41 @@
14
 
15
  defined( 'JETPACK__API_BASE' ) or define( 'JETPACK__API_BASE', 'https://jetpack.wordpress.com/jetpack.' );
16
  define( 'JETPACK__API_VERSION', 1 );
17
- define( 'JETPACK__MINIMUM_WP_VERSION', '3.3' );
18
  defined( 'JETPACK_CLIENT__AUTH_LOCATION' ) or define( 'JETPACK_CLIENT__AUTH_LOCATION', 'header' );
19
  defined( 'JETPACK_CLIENT__HTTPS' ) or define( 'JETPACK_CLIENT__HTTPS', 'AUTO' );
20
- define( 'JETPACK__VERSION', '2.2.8' );
21
  define( 'JETPACK__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
22
  defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) or define( 'JETPACK__GLOTPRESS_LOCALES_PATH', JETPACK__PLUGIN_DIR . 'locales.php' );
23
 
24
  define( 'JETPACK_MASTER_USER', true );
25
 
26
- /*
27
- Options:
28
- jetpack_options (array)
29
- An array of options.
30
- @see Jetpack::get_option_names()
31
-
32
- jetpack_register (string)
33
- Temporary verification secrets.
34
-
35
- jetpack_activated (int)
36
- 1: the plugin was activated normally
37
- 2: the plugin was activated on this site because of a network-wide activation
38
- 3: the plugin was auto-installed
39
- 4: the plugin was manually disconnected (but is still installed)
40
-
41
- jetpack_active_modules (array)
42
- Array of active module slugs.
43
-
44
- jetpack_do_activate (bool)
45
- Flag for "activating" the plugin on sites where the activation hook never fired (auto-installs)
46
- */
47
-
48
- class Jetpack {
49
- var $xmlrpc_server = null;
50
-
51
- private $xmlrpc_verification = null;
52
-
53
- var $HTTP_RAW_POST_DATA = null; // copy of $GLOBALS['HTTP_RAW_POST_DATA']
54
-
55
- var $plugins_to_deactivate = array(
56
- 'stats' => array( 'stats/stats.php', 'WordPress.com Stats' ),
57
- 'shortlinks' => array( 'stats/stats.php', 'WordPress.com Stats' ),
58
- 'sharedaddy' => array( 'sharedaddy/sharedaddy.php', 'Sharedaddy' ),
59
- 'twitter-widget' => array( 'wickett-twitter-widget/wickett-twitter-widget.php', 'Wickett Twitter Widget' ),
60
- 'after-the-deadline' => array( 'after-the-deadline/after-the-deadline.php', 'After The Deadline' ),
61
- 'contact-form' => array( 'grunion-contact-form/grunion-contact-form.php', 'Grunion Contact Form' ),
62
- 'custom-css' => array( 'safecss/safecss.php', 'WordPress.com Custom CSS' ),
63
- );
64
-
65
- var $capability_translations = array(
66
- 'administrator' => 'manage_options',
67
- 'editor' => 'edit_others_posts',
68
- 'author' => 'publish_posts',
69
- 'contributor' => 'edit_posts',
70
- 'subscriber' => 'read',
71
- );
72
-
73
- /**
74
- * Message to display in admin_notice
75
- * @var string
76
- */
77
- var $message = '';
78
-
79
- /**
80
- * Error to display in admin_notice
81
- * @var string
82
- */
83
- var $error = '';
84
-
85
- /**
86
- * Modules that need more privacy description.
87
- * @var string
88
- */
89
- var $privacy_checks = '';
90
-
91
- /**
92
- * Stats to record once the page loads
93
- *
94
- * @var array
95
- */
96
- var $stats = array();
97
-
98
- /**
99
- * Jetpack_Sync object
100
- */
101
- var $sync;
102
-
103
- /**
104
- * Verified data for JSON authorization request
105
- */
106
- var $json_api_authorization_request = array();
107
-
108
- /**
109
- * Singleton
110
- * @static
111
- */
112
- public static function init() {
113
- static $instance = false;
114
-
115
- if ( !$instance ) {
116
- load_plugin_textdomain( 'jetpack', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
117
- $instance = new Jetpack;
118
-
119
- $instance->plugin_upgrade();
120
- }
121
-
122
- return $instance;
123
- }
124
-
125
- /**
126
- * Must never be called statically
127
- */
128
- function plugin_upgrade() {
129
- // Upgrade: 1.1 -> 1.2
130
- if ( get_option( 'jetpack_id' ) ) {
131
- // Move individual jetpack options to single array of options
132
- $options = array();
133
- foreach ( Jetpack::get_option_names() as $option ) {
134
- if ( false !== $value = get_option( "jetpack_$option" ) ) {
135
- $options[$option] = $value;
136
- }
137
- }
138
-
139
- if ( $options ) {
140
- Jetpack::update_options( $options );
141
-
142
- foreach ( array_keys( $options ) as $option ) {
143
- delete_option( "jetpack_$option" );
144
- }
145
- }
146
-
147
- // Add missing version and old_version options
148
- if ( !$version = Jetpack::get_option( 'version' ) ) {
149
- $version = $old_version = '1.1:' . time();
150
- Jetpack::update_options( compact( 'version', 'old_version' ) );
151
- }
152
- }
153
-
154
- // Upgrade from a single user token to a user_id-indexed array and a master_user ID
155
- if ( !Jetpack::get_option( 'user_tokens' ) ) {
156
- if ( $user_token = Jetpack::get_option( 'user_token' ) ) {
157
- $token_parts = explode( '.', $user_token );
158
- if ( isset( $token_parts[2] ) ) {
159
- $master_user = $token_parts[2];
160
- $user_tokens = array( $master_user => $user_token );
161
- Jetpack::update_options( compact( 'master_user', 'user_tokens' ) );
162
- Jetpack::delete_option( 'user_token' );
163
- } else {
164
- // @todo: is this even possible?
165
- trigger_error( sprintf( 'Jetpack::plugin_upgrade found no user_id in user_token "%s"', $user_token ), E_USER_WARNING );
166
- }
167
- }
168
- }
169
- }
170
-
171
- /**
172
- * Constructor. Initializes WordPress hooks
173
- */
174
- function Jetpack() {
175
- $this->sync = new Jetpack_Sync;
176
-
177
- // Modules should do Jetpack_Sync::sync_options( __FILE__, $option, ... ); instead
178
- // We access the "internal" method here only because the Jetpack object isn't instantiated yet
179
- $this->sync->options( __FILE__,
180
- 'home',
181
- 'siteurl',
182
- 'blogname',
183
- 'gmt_offset',
184
- 'timezone_string'
185
- );
186
-
187
- if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && isset( $_GET['for'] ) && 'jetpack' == $_GET['for'] ) {
188
- @ini_set( 'display_errors', false ); // Display errors can cause the XML to be not well formed.
189
-
190
- require_once dirname( __FILE__ ) . '/class.jetpack-xmlrpc-server.php';
191
- $this->xmlrpc_server = new Jetpack_XMLRPC_Server();
192
-
193
- $this->require_jetpack_authentication();
194
-
195
- if ( Jetpack::is_active() ) {
196
- // Hack to preserve $HTTP_RAW_POST_DATA
197
- add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
198
-
199
- $signed = $this->verify_xml_rpc_signature();
200
- if ( $signed && ! is_wp_error( $signed ) ) {
201
- // The actual API methods.
202
- add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'xmlrpc_methods' ) );
203
- } else {
204
- add_filter( 'xmlrpc_methods', '__return_empty_array' );
205
- }
206
- } else {
207
- // The bootstrap API methods.
208
- add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'bootstrap_xmlrpc_methods' ) );
209
- }
210
-
211
- // Now that no one can authenticate, and we're whitelisting all XML-RPC methods, force enable_xmlrpc on.
212
- add_filter( 'pre_option_enable_xmlrpc', '__return_true' );
213
- } elseif ( is_admin() && isset( $_POST['action'] ) && 'jetpack_upload_file' == $_POST['action'] ) {
214
- $this->require_jetpack_authentication();
215
- $this->add_remote_request_handlers();
216
- } else {
217
- if ( Jetpack::is_active() ) {
218
- add_action( 'login_form_jetpack_json_api_authorization', array( &$this, 'login_form_json_api_authorization' ) );
219
- }
220
- }
221
-
222
- add_action( 'jetpack_clean_nonces', array( 'Jetpack', 'clean_nonces' ) );
223
- if ( !wp_next_scheduled( 'jetpack_clean_nonces' ) ) {
224
- wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
225
- }
226
-
227
- add_filter( 'xmlrpc_blog_options', array( $this, 'xmlrpc_options' ) );
228
-
229
- add_action( 'admin_menu', array( $this, 'admin_menu' ), 999 ); // run late so that other plugins hooking into this menu don't get left out
230
- add_action( 'admin_init', array( $this, 'admin_init' ) );
231
- add_action( 'admin_init', array( $this, 'dismiss_jetpack_notice' ) );
232
-
233
- add_action( 'wp_ajax_jetpack-check-news-subscription', array( $this, 'check_news_subscription' ) );
234
- add_action( 'wp_ajax_jetpack-subscribe-to-news', array( $this, 'subscribe_to_news' ) );
235
-
236
- add_action( 'wp_loaded', array( $this, 'register_assets' ) );
237
- add_action( 'wp_enqueue_scripts', array( $this, 'devicepx' ) );
238
- add_action( 'customize_controls_enqueue_scripts', array( $this, 'devicepx' ) );
239
- add_action( 'admin_enqueue_scripts', array( $this, 'devicepx' ) );
240
-
241
- add_action( 'jetpack_activate_module', array( $this, 'activate_module_actions' ) );
242
-
243
- /**
244
- * These actions run checks to load additional files.
245
- * They check for external files or plugins, so thef need to run as late as possible.
246
- */
247
- add_action( 'plugins_loaded', array( $this, 'check_open_graph' ), 999 );
248
- add_action( 'plugins_loaded', array( $this, 'check_rest_api_compat' ), 1000 );
249
- }
250
-
251
- function require_jetpack_authentication() {
252
- // Don't let anyone authenticate
253
- $_COOKIE = array();
254
- remove_all_filters( 'authenticate' );
255
-
256
- if ( Jetpack::is_active() ) {
257
- // Allow Jetpack authentication
258
- add_filter( 'authenticate', array( $this, 'authenticate_jetpack' ), 10, 3 );
259
- }
260
- }
261
-
262
- /**
263
- * Register assets for use in various modules and the Jetpack admin page.
264
- *
265
- * @uses wp_script_is, wp_register_script, plugins_url
266
- * @action wp_loaded
267
- * @return null
268
- */
269
- public function register_assets() {
270
- if ( ! wp_script_is( 'spin', 'registered' ) )
271
- wp_register_script( 'spin', plugins_url( '_inc/spin.js', __FILE__ ), false, '1.2.4' );
272
-
273
- if ( ! wp_script_is( 'jquery.spin', 'registered' ) )
274
- wp_register_script( 'jquery.spin', plugins_url( '_inc/jquery.spin.js', __FILE__ ) , array( 'jquery', 'spin' ) );
275
-
276
- if ( ! wp_script_is( 'jetpack-gallery-settings', 'registered' ) )
277
- wp_register_script( 'jetpack-gallery-settings', plugins_url( '_inc/gallery-settings.js', __FILE__ ), array( 'media-views' ), '20121225' );
278
- }
279
-
280
- /**
281
- * Device Pixels support
282
- * This improves the resolution of gravatars and wordpress.com uploads on hi-res and zoomed browsers.
283
- */
284
- function devicepx() {
285
- wp_enqueue_script( 'devicepx', ( is_ssl() ? 'https' : 'http' ) . '://s0.wp.com/wp-content/js/devicepx-jetpack.js', array(), gmdate('oW'), true );
286
- }
287
-
288
- /**
289
- * Is Jetpack active?
290
- */
291
- public static function is_active() {
292
- return (bool) Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
293
- }
294
-
295
- /**
296
- * Is Jetpack in development (offline) mode?
297
- */
298
- public static function is_development_mode() {
299
- $development_mode = false;
300
-
301
- if ( defined( 'JETPACK_DEV_DEBUG' ) ) {
302
- $development_mode = JETPACK_DEV_DEBUG;
303
- }
304
-
305
- elseif ( site_url() && false === strpos( site_url(), '.' ) ) {
306
- $development_mode = true;
307
- }
308
-
309
- return apply_filters( 'jetpack_development_mode', $development_mode );
310
- }
311
-
312
- /**
313
- * Is a given user (or the current user if none is specified) linked to a WordPress.com user?
314
- */
315
- public static function is_user_connected( $user_id = false ) {
316
- $user_id = false === $user_id ? get_current_user_id() : absint( $user_id );
317
- if ( !$user_id ) {
318
- return false;
319
- }
320
- return (bool) Jetpack_Data::get_access_token( $user_id );
321
- }
322
-
323
- function current_user_is_connection_owner() {
324
- $user_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
325
- return $user_token && is_object( $user_token ) && isset( $user_token->external_user_id ) && get_current_user_id() === $user_token->external_user_id;
326
- }
327
-
328
- /**
329
- * Synchronize connected user role changes
330
- */
331
- function user_role_change( $user_id ) {
332
- if ( Jetpack::is_active() && Jetpack::is_user_connected( $user_id ) ) {
333
-
334
- $current_user_id = get_current_user_id();
335
- wp_set_current_user( $user_id );
336
- $role = $this->translate_current_user_to_role();
337
- $signed_role = $this->sign_role( $role );
338
- wp_set_current_user( $current_user_id );
339
-
340
- $master_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
341
- $master_user_id = absint( $master_token->external_user_id );
342
-
343
- if ( !$master_user_id )
344
- return; // this shouldn't happen
345
-
346
- Jetpack::xmlrpc_async_call( 'jetpack.updateRole', $user_id, $signed_role );
347
- //@todo retry on failure
348
-
349
- //try to choose a new master if we're demoting the current one
350
- if ( $user_id == $master_user_id && 'administrator' != $role ) {
351
- $query = new WP_User_Query( array(
352
- 'fields' => array( 'id' ),
353
- 'role' => 'administrator',
354
- 'orderby' => 'id',
355
- 'exclude' => array( $master_user_id ),
356
- )
357
- );
358
- $new_master = false;
359
- foreach ( $query->results as $result ) {
360
- $uid = absint( $result->id );
361
- if ( $uid && Jetpack::is_user_connected( $uid ) ) {
362
- $new_master = $uid;
363
- break;
364
- }
365
- }
366
-
367
- if ( $new_master ) {
368
- Jetpack::update_option( 'master_user', $new_master );
369
- }
370
- // else disconnect..?
371
- }
372
- }
373
- }
374
-
375
- /**
376
- * Loads the currently active modules.
377
- */
378
- public static function load_modules() {
379
- if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
380
- return;
381
- }
382
-
383
- $version = Jetpack::get_option( 'version' );
384
- if ( !$version ) {
385
- $version = $old_version = JETPACK__VERSION . ':' . time();
386
- Jetpack::update_options( compact( 'version', 'old_version' ) );
387
- }
388
- list( $version ) = explode( ':', $version );
389
-
390
- $modules = array_filter( Jetpack::get_active_modules(), array( 'Jetpack', 'is_module' ) );
391
-
392
- $modules_data = array();
393
-
394
- // Don't load modules that have had "Major" changes since the stored version until they have been deactivated/reactivated through the lint check.
395
- if ( version_compare( $version, JETPACK__VERSION, '<' ) ) {
396
- $updated_modules = array();
397
- foreach ( $modules as $module ) {
398
- $modules_data[ $module ] = Jetpack::get_module( $module );
399
- if ( ! isset( $modules_data[ $module ]['changed'] ) ) {
400
- continue;
401
- }
402
-
403
- if ( version_compare( $modules_data[ $module ]['changed'], $version, '<=' ) ) {
404
- continue;
405
- }
406
-
407
- $updated_modules[] = $module;
408
- }
409
-
410
- $modules = array_diff( $modules, $updated_modules );
411
- }
412
-
413
- foreach ( $modules as $module ) {
414
- // If not connected and we're in dev mode, disable modules requiring a connection
415
- if ( ! Jetpack::is_active() && Jetpack::is_development_mode() ) {
416
- if ( empty( $modules_data[ $module ] ) ) {
417
- $modules_data[ $module ] = Jetpack::get_module( $module );
418
- }
419
-
420
- if ( $modules_data[ $module ]['requires_connection'] ) {
421
- Jetpack::deactivate_module( $module );
422
- continue;
423
- }
424
- }
425
-
426
- if ( did_action( 'jetpack_module_loaded_' . $module ) ) {
427
- continue;
428
- }
429
- require Jetpack::get_module_path( $module );
430
- do_action( 'jetpack_module_loaded_' . $module );
431
- }
432
-
433
- do_action( 'jetpack_modules_loaded' );
434
-
435
- // Load module-specific code that is needed even when a module isn't active. Loaded here because code contained therein may need actions such as setup_theme.
436
- require_once( dirname( __FILE__ ) . '/modules/module-extras.php' );
437
- }
438
-
439
- /**
440
- * Check if Jetpack's REST API compat file should be included
441
- * @action plugins_loaded
442
- * @return null
443
- */
444
- public function check_rest_api_compat() {
445
- $_jetpack_rest_api_compat_includes = apply_filters( 'jetpack_rest_api_compat', array() );
446
-
447
- if ( function_exists( 'bbpress' ) )
448
- $_jetpack_rest_api_compat_includes[] = dirname( __FILE__ ) . '/class.jetpack-bbpress-json-api-compat.php';
449
-
450
- foreach ( $_jetpack_rest_api_compat_includes as $_jetpack_rest_api_compat_include )
451
- require_once $_jetpack_rest_api_compat_include;
452
- }
453
-
454
- /**
455
- * Check if Jetpack's Open Graph tags should be used.
456
- * If certain plugins are active, Jetpack's og tags are suppressed.
457
- *
458
- * @uses Jetpack::get_active_modules, add_filter, get_option, apply_filters
459
- * @action plugins_loaded
460
- * @return null
461
- */
462
- public function check_open_graph() {
463
- if ( in_array( 'publicize', Jetpack::get_active_modules() ) || in_array( 'sharedaddy', Jetpack::get_active_modules() ) )
464
- add_filter( 'jetpack_enable_open_graph', '__return_true', 0 );
465
-
466
- $active_plugins = get_option( 'active_plugins', array() );
467
-
468
- $conflicting_plugins = array(
469
- 'facebook/facebook.php', // Official Facebook plugin
470
- 'wordpress-seo/wp-seo.php', // WordPress SEO by Yoast
471
- 'add-link-to-facebook/add-link-to-facebook.php', // Add Link to Facebook
472
- 'facebook-awd/AWD_facebook.php', // Facebook AWD All in one
473
- 'header-footer/plugin.php', // Header and Footer
474
- 'nextgen-facebook/nextgen-facebook.php', // NextGEN Facebook OG
475
- 'seo-facebook-comments/seofacebook.php', // SEO Facebook Comments
476
- 'seo-ultimate/seo-ultimate.php', // SEO Ultimate
477
- 'sexybookmarks/sexy-bookmarks.php', // Shareaholic
478
- 'shareaholic/sexy-bookmarks.php', // Shareaholic
479
- 'social-discussions/social-discussions.php', // Social Discussions
480
- 'social-networks-auto-poster-facebook-twitter-g/NextScripts_SNAP.php', // NextScripts SNAP
481
- 'wordbooker/wordbooker.php', // Wordbooker
482
- 'socialize/socialize.php', // Socialize
483
- 'simple-facebook-connect/sfc.php', // Simple Facebook Connect
484
- 'social-sharing-toolkit/social_sharing_toolkit.php', // Social Sharing Toolkit
485
- 'wp-facebook-open-graph-protocol/wp-facebook-ogp.php', // WP Facebook Open Graph protocol
486
- 'opengraph/opengraph.php', // Open Graph
487
- 'sharepress/sharepress.php', // SharePress
488
- );
489
-
490
- foreach ( $conflicting_plugins as $plugin ) {
491
- if ( in_array( $plugin, $active_plugins ) ) {
492
- add_filter( 'jetpack_enable_open_graph', '__return_false', 99 );
493
- break;
494
- }
495
- }
496
-
497
- if ( apply_filters( 'jetpack_enable_open_graph', false ) )
498
- require_once dirname( __FILE__ ) . '/functions.opengraph.php';
499
- }
500
-
501
- /* Jetpack Options API */
502
-
503
- public static function get_option_names( $type = 'compact' ) {
504
- switch ( $type ) {
505
- case 'non-compact' :
506
- case 'non_compact' :
507
- return array(
508
- 'register',
509
- 'activated',
510
- 'active_modules',
511
- 'do_activate',
512
- 'publicize',
513
- 'widget_twitter',
514
- );
515
- }
516
-
517
- return array(
518
- 'id', // (int) The Client ID/WP.com Blog ID of this site.
519
- 'blog_token', // (string) The Client Secret/Blog Token of this site.
520
- 'user_token', // (string) The User Token of this site. (deprecated)
521
- 'publicize_connections', // (array) An array of Publicize connections from WordPress.com
522
- 'master_user', // (int) The local User ID of the user who connected this site to jetpack.wordpress.com.
523
- 'user_tokens', // (array) User Tokens for each user of this site who has connected to jetpack.wordpress.com.
524
- 'version', // (string) Used during upgrade procedure to auto-activate new modules. version:time
525
- 'old_version', // (string) Used to determine which modules are the most recently added. previous_version:time
526
- 'fallback_no_verify_ssl_certs', // (int) Flag for determining if this host must skip SSL Certificate verification due to misconfigured SSL.
527
- 'time_diff', // (int) Offset between Jetpack server's clocks and this server's clocks. Jetpack Server Time = time() + (int) Jetpack::get_option( 'time_diff' )
528
- 'public', // (int|bool) If we think this site is public or not (1, 0), false if we haven't yet tried to figure it out.
529
- );
530
- }
531
-
532
- /**
533
- * Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate.
534
- *
535
- * @param string $name Option name
536
- * @param mixed $default (optional)
537
- */
538
- public static function get_option( $name, $default = false ) {
539
- if ( in_array( $name, Jetpack::get_option_names( 'non_compact' ) ) ) {
540
- return get_option( "jetpack_$name" );
541
- } else if ( !in_array( $name, Jetpack::get_option_names() ) ) {
542
- trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
543
- return false;
544
- }
545
-
546
- $options = get_option( 'jetpack_options' );
547
- if ( is_array( $options ) && isset( $options[$name] ) ) {
548
- return $options[$name];
549
- }
550
-
551
- return $default;
552
- }
553
-
554
- /**
555
- * Stores two secrets and a timestamp so WordPress.com can make a request back and verify an action
556
- * Does some extra verification so urls (such as those to public-api, register, etc) cant just be crafted
557
- * $name must be a registered option name.
558
- */
559
- public static function create_nonce( $name ) {
560
- $secret = wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 );
561
-
562
- Jetpack::update_option( $name, $secret );
563
- @list( $secret_1, $secret_2, $eol ) = explode( ':', Jetpack::get_option( $name ) );
564
- if ( empty( $secret_1 ) || empty( $secret_2 ) || $eol < time() )
565
- return new Jetpack_Error( 'missing_secrets' );
566
-
567
- return array(
568
- 'secret_1' => $secret_1,
569
- 'secret_2' => $secret_2,
570
- 'eol' => $eol,
571
- );
572
- }
573
-
574
- /**
575
- * Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate.
576
- *
577
- * @param string $name Option name
578
- * @param mixed $value Option value
579
- */
580
- public static function update_option( $name, $value ) {
581
- if ( in_array( $name, Jetpack::get_option_names( 'non_compact' ) ) ) {
582
- return update_option( "jetpack_$name", $value );
583
- } else if ( !in_array( $name, Jetpack::get_option_names() ) ) {
584
- trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
585
- return false;
586
- }
587
-
588
- $options = get_option( 'jetpack_options' );
589
- if ( !is_array( $options ) ) {
590
- $options = array();
591
- }
592
-
593
- $options[$name] = $value;
594
-
595
- return update_option( 'jetpack_options', $options );
596
- }
597
-
598
- /**
599
- * Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate.
600
- *
601
- * @param array $array array( option name => option value, ... )
602
- */
603
- public static function update_options( $array ) {
604
- $names = array_keys( $array );
605
-
606
- foreach ( array_diff( $names, Jetpack::get_option_names(), Jetpack::get_option_names( 'non_compact' ) ) as $unknown_name ) {
607
- trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
608
- unset( $array[$unknown_name] );
609
- }
610
-
611
- foreach ( array_intersect( $names, Jetpack::get_option_names( 'non_compact' ) ) as $name ) {
612
- update_option( "jetpack_$name", $array[$name] );
613
- unset( $array[$name] );
614
- }
615
-
616
- $options = get_option( 'jetpack_options' );
617
- if ( !is_array( $options ) ) {
618
- $options = array();
619
- }
620
-
621
- return update_option( 'jetpack_options', array_merge( $options, $array ) );
622
- }
623
-
624
- /**
625
- * Deletes the given option. May be passed multiple option names as an array.
626
- * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
627
- *
628
- * @param string|array $names
629
- */
630
- public static function delete_option( $names ) {
631
- $names = (array) $names;
632
-
633
- foreach ( array_diff( $names, Jetpack::get_option_names(), Jetpack::get_option_names( 'non_compact' ) ) as $unknown_name ) {
634
- trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
635
- }
636
-
637
- foreach ( array_intersect( $names, Jetpack::get_option_names( 'non_compact' ) ) as $name ) {
638
- delete_option( "jetpack_$name" );
639
- }
640
-
641
- $options = get_option( 'jetpack_options' );
642
- if ( !is_array( $options ) ) {
643
- $options = array();
644
- }
645
-
646
- $to_delete = array_intersect( $names, Jetpack::get_option_names(), array_keys( $options ) );
647
- if ( $to_delete ) {
648
- foreach ( $to_delete as $name ) {
649
- unset( $options[$name] );
650
- }
651
-
652
- return update_option( 'jetpack_options', $options );
653
- }
654
-
655
- return true;
656
- }
657
-
658
- /**
659
- * Enters a user token into the user_tokens option
660
- *
661
- * @param int $user_id
662
- * @param string $token
663
- * return bool
664
- */
665
- public static function update_user_token( $user_id, $token, $is_master_user ) {
666
- // not designed for concurrent updates
667
- $user_tokens = Jetpack::get_option( 'user_tokens' );
668
- if ( ! is_array( $user_tokens ) )
669
- $user_tokens = array();
670
- $user_tokens[$user_id] = $token;
671
- if ( $is_master_user ) {
672
- $master_user = $user_id;
673
- $options = compact('user_tokens', 'master_user');
674
- } else {
675
- $options = compact('user_tokens');
676
- }
677
- return Jetpack::update_options( $options );
678
- }
679
-
680
- /**
681
- * Returns an array of all PHP files in the specified absolute path.
682
- * Equivalent to glob( "$absolute_path/*.php" ).
683
- *
684
- * @param string $absolute_path The absolute path of the directory to search.
685
- * @return array Array of absolute paths to the PHP files.
686
- */
687
- public static function glob_php( $absolute_path ) {
688
- $absolute_path = untrailingslashit( $absolute_path );
689
- $files = array();
690
- if ( !$dir = @opendir( $absolute_path ) ) {
691
- return $files;
692
- }
693
-
694
- while ( false !== $file = readdir( $dir ) ) {
695
- if ( '.' == substr( $file, 0, 1 ) || '.php' != substr( $file, -4 ) ) {
696
- continue;
697
- }
698
-
699
- $file = "$absolute_path/$file";
700
-
701
- if ( !is_file( $file ) ) {
702
- continue;
703
- }
704
-
705
- $files[] = $file;
706
- }
707
-
708
- closedir( $dir );
709
-
710
- return $files;
711
- }
712
-
713
- public function activate_new_modules() {
714
- if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
715
- return;
716
- }
717
-
718
- $jetpack_old_version = Jetpack::get_option( 'version' ); // [sic]
719
- if ( !$jetpack_old_version ) {
720
- $jetpack_old_version = $version = $old_version = '1.1:' . time();
721
- Jetpack::update_options( compact( 'version', 'old_version' ) );
722
- }
723
-
724
- list( $jetpack_version ) = explode( ':', $jetpack_old_version ); // [sic]
725
-
726
- if ( version_compare( JETPACK__VERSION, $jetpack_version, '<=' ) ) {
727
- return;
728
- }
729
-
730
- $active_modules = Jetpack::get_active_modules();
731
- $reactivate_modules = array();
732
- foreach ( $active_modules as $active_module ) {
733
- $module = Jetpack::get_module( $active_module );
734
- if ( !isset( $module['changed'] ) ) {
735
- continue;
736
- }
737
-
738
- if ( version_compare( $module['changed'], $jetpack_version, '<=' ) ) {
739
- continue;
740
- }
741
-
742
- $reactivate_modules[] = $active_module;
743
- Jetpack::deactivate_module( $active_module );
744
- }
745
-
746
- if ( version_compare( $jetpack_version, '1.9.2', '<' ) && version_compare( '1.9-something', JETPACK__VERSION, '<' ) ) {
747
- add_action( 'jetpack_activate_default_modules', array( $this->sync, 'sync_all_registered_options' ), 1000 );
748
- }
749
-
750
- Jetpack::update_options( array(
751
- 'version' => JETPACK__VERSION . ':' . time(),
752
- 'old_version' => $jetpack_old_version,
753
- ) );
754
-
755
- Jetpack::state( 'message', 'modules_activated' );
756
- Jetpack::activate_default_modules( $jetpack_version, JETPACK__VERSION, $reactivate_modules );
757
- wp_safe_redirect( Jetpack::admin_url() );
758
- exit;
759
- }
760
-
761
- /**
762
- * List available Jetpack modules. Simply lists .php files in /modules/.
763
- * Make sure to tuck away module "library" files in a sub-directory.
764
- */
765
- public static function get_available_modules( $min_version = false, $max_version = false ) {
766
- static $modules = null;
767
-
768
- if ( !isset( $modules ) ) {
769
- $files = Jetpack::glob_php( dirname( __FILE__ ) . '/modules' );
770
-
771
- $modules = array();
772
-
773
- foreach ( $files as $file ) {
774
- if ( !$headers = Jetpack::get_module( $file ) ) {
775
- continue;
776
- }
777
-
778
- $modules[ Jetpack::get_module_slug( $file ) ] = $headers['introduced'];
779
- }
780
- }
781
-
782
- if ( !$min_version && !$max_version ) {
783
- return array_keys( $modules );
784
- }
785
-
786
- $r = array();
787
- foreach ( $modules as $slug => $introduced ) {
788
- if ( $min_version && version_compare( $min_version, $introduced, '>=' ) ) {
789
- continue;
790
- }
791
-
792
- if ( $max_version && version_compare( $max_version, $introduced, '<' ) ) {
793
- continue;
794
- }
795
-
796
- $r[] = $slug;
797
- }
798
-
799
- return $r;
800
- }
801
-
802
- /**
803
- * Default modules loaded on activation.
804
- */
805
- public static function get_default_modules( $min_version = false, $max_version = false ) {
806
- $return = array();
807
-
808
- foreach ( Jetpack::get_available_modules( $min_version, $max_version ) as $module ) {
809
- // Add special cases here for modules to avoid auto-activation
810
- switch ( $module ) {
811
-
812
- // These modules are default off: they change things blog-side
813
- case 'comments' :
814
- case 'carousel' :
815
- case 'minileven':
816
- case 'infinite-scroll' :
817
- case 'photon' :
818
- case 'tiled-gallery' :
819
- case 'likes' :
820
- break;
821
-
822
- // These modules are default off if we think the site is a private one
823
- case 'enhanced-distribution' :
824
- case 'json-api' :
825
- if ( !Jetpack::get_option( 'public' ) ) {
826
- break;
827
- }
828
- // else no break
829
- // The rest are default on
830
- default :
831
- $return[] = $module;
832
- }
833
- }
834
-
835
- return $return;
836
- }
837
-
838
- /**
839
- * Extract a module's slug from its full path.
840
- */
841
- public static function get_module_slug( $file ) {
842
- return str_replace( '.php', '', basename( $file ) );
843
- }
844
-
845
- /**
846
- * Generate a module's path from its slug.
847
- */
848
- public static function get_module_path( $slug ) {
849
- return dirname( __FILE__ ) . "/modules/$slug.php";
850
- }
851
-
852
- /**
853
- * Load module data from module file. Headers differ from WordPress
854
- * plugin headers to avoid them being identified as standalone
855
- * plugins on the WordPress plugins page.
856
- */
857
- public static function get_module( $module ) {
858
- $headers = array(
859
- 'name' => 'Module Name',
860
- 'description' => 'Module Description',
861
- 'sort' => 'Sort Order',
862
- 'introduced' => 'First Introduced',
863
- 'changed' => 'Major Changes In',
864
- 'deactivate' => 'Deactivate',
865
- 'free' => 'Free',
866
- 'requires_connection' => 'Requires Connection',
867
- );
868
-
869
- $file = Jetpack::get_module_path( Jetpack::get_module_slug( $module ) );
870
- if ( !file_exists( $file ) )
871
- return false;
872
-
873
- $mod = get_file_data( $file, $headers );
874
- if ( empty( $mod['name'] ) )
875
- return false;
876
-
877
- $mod['name'] = translate( $mod['name'], 'jetpack' );
878
- $mod['description'] = translate( $mod['description'], 'jetpack' );
879
- if ( empty( $mod['sort'] ) )
880
- $mod['sort'] = 10;
881
- $mod['deactivate'] = empty( $mod['deactivate'] );
882
- $mod['free'] = empty( $mod['free'] );
883
- $mod['requires_connection'] = ( ! empty( $mod['requires_connection'] ) && 'No' == $mod['requires_connection'] ) ? false : true;
884
- return $mod;
885
- }
886
-
887
- /**
888
- * Get a list of activated modules as an array of module slugs.
889
- */
890
- public static function get_active_modules() {
891
- $active = Jetpack::get_option( 'active_modules' );
892
- if ( !is_array( $active ) )
893
- $active = array();
894
- if ( is_admin() ) {
895
- $active[] = 'vaultpress';
896
- } else {
897
- $active = array_diff( $active, array( 'vaultpress' ) );
898
- }
899
- return array_unique( $active );
900
- }
901
-
902
- public static function is_module( $module ) {
903
- return !empty( $module ) && !validate_file( $module, Jetpack::get_available_modules() );
904
- }
905
-
906
- /**
907
- * Catches PHP errors. Must be used in conjunction with output buffering.
908
- *
909
- * @param bool $catch True to start catching, False to stop.
910
- *
911
- * @static
912
- */
913
- public static function catch_errors( $catch ) {
914
- static $display_errors, $error_reporting;
915
-
916
- if ( $catch ) {
917
- $display_errors = @ini_set( 'display_errors', 1 );
918
- $error_reporting = @error_reporting( E_ALL );
919
- add_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 0 );
920
- } else {
921
- @ini_set( 'display_errors', $display_errors );
922
- @error_reporting( $error_reporting );
923
- remove_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 1 );
924
- }
925
- }
926
-
927
- /**
928
- * Saves any generated PHP errors in ::state( 'php_errors', {errors} )
929
- */
930
- public static function catch_errors_on_shutdown() {
931
- Jetpack::state( 'php_errors', ob_get_clean() );
932
- }
933
-
934
- public static function activate_default_modules( $min_version = false, $max_version = false, $other_modules = array() ) {
935
- $jetpack = Jetpack::init();
936
-
937
- $modules = Jetpack::get_default_modules( $min_version, $max_version );
938
- $modules = array_merge( $other_modules, $modules );
939
-
940
- // Look for standalone plugins and disable if active.
941
-
942
- $to_deactivate = array();
943
- foreach ( $modules as $module ) {
944
- if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) {
945
- $to_deactivate[$module] = $jetpack->plugins_to_deactivate[$module];
946
- }
947
- }
948
-
949
- $deactivated = array();
950
- foreach ( $to_deactivate as $module => $deactivate_me ) {
951
- list( $probable_file, $probable_title ) = $deactivate_me;
952
- if ( Jetpack_Client_Server::deactivate_plugin( $probable_file, $probable_title ) ) {
953
- $deactivated[] = $module;
954
- }
955
- }
956
-
957
- if ( $deactivated ) {
958
- Jetpack::state( 'deactivated_plugins', join( ',', $deactivated ) );
959
-
960
- $url = add_query_arg( array(
961
- 'action' => 'activate_default_modules',
962
- '_wpnonce' => wp_create_nonce( 'activate_default_modules' ),
963
- ), add_query_arg( compact( 'min_version', 'max_version', 'other_modules' ), Jetpack::admin_url() ) );
964
- wp_safe_redirect( $url );
965
- exit;
966
- }
967
-
968
- do_action( 'jetpack_before_activate_default_modules', $min_version, $max_version, $other_modules );
969
-
970
- // Check each module for fatal errors, a la wp-admin/plugins.php::activate before activating
971
- $redirect = menu_page_url( 'jetpack', false );
972
- Jetpack::restate();
973
- Jetpack::catch_errors( true );
974
- foreach ( $modules as $module ) {
975
- $active = Jetpack::get_active_modules();
976
- if ( in_array( $module, $active ) ) {
977
- $module_info = Jetpack::get_module( $module );
978
- if ( !$module_info['deactivate'] ) {
979
- $state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules';
980
- if ( $active_state = Jetpack::state( $state ) ) {
981
- $active_state = explode( ',', $active_state );
982
- } else {
983
- $active_state = array();
984
- }
985
- $active_state[] = $module;
986
- Jetpack::state( $state, implode( ',', $active_state ) );
987
- }
988
- continue;
989
- }
990
-
991
- $file = Jetpack::get_module_path( $module );
992
- if ( !file_exists( $file ) ) {
993
- continue;
994
- }
995
-
996
- // we'll override this later if the plugin can be included without fatal error
997
- wp_safe_redirect( Jetpack::admin_url() );
998
- Jetpack::state( 'error', 'module_activation_failed' );
999
- Jetpack::state( 'module', $module );
1000
- ob_start();
1001
- require $file;
1002
- do_action( 'jetpack_activate_module', $module );
1003
- $active[] = $module;
1004
- $state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules';
1005
- if ( $active_state = Jetpack::state( $state ) ) {
1006
- $active_state = explode( ',', $active_state );
1007
- } else {
1008
- $active_state = array();
1009
- }
1010
- $active_state[] = $module;
1011
- Jetpack::state( $state, implode( ',', $active_state ) );
1012
- Jetpack::update_option( 'active_modules', array_unique( $active ) );
1013
- ob_end_clean();
1014
- }
1015
- Jetpack::state( 'error', false );
1016
- Jetpack::state( 'module', false );
1017
- Jetpack::catch_errors( false );
1018
- do_action( 'jetpack_activate_default_modules', $min_version, $max_version, $other_modules );
1019
- }
1020
-
1021
- public static function activate_module( $module ) {
1022
- $jetpack = Jetpack::init();
1023
-
1024
- if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() )
1025
- return false;
1026
-
1027
- if ( ! strlen( $module ) )
1028
- return false;
1029
-
1030
- if ( ! Jetpack::is_module( $module ) )
1031
- return false;
1032
-
1033
- // If it's already active, then don't do it again
1034
- $active = Jetpack::get_active_modules();
1035
- foreach ( $active as $act ) {
1036
- if ( $act == $module )
1037
- return true;
1038
- }
1039
-
1040
- // If we're not connected but in development mode, make sure the module doesn't require a connection
1041
- if ( ! Jetpack::is_active() && Jetpack::is_development_mode() ) {
1042
- $module_data = Jetpack::get_module( $module );
1043
-
1044
- if ( $module_data['requires_connection'] ) {
1045
- return false;
1046
- }
1047
- }
1048
-
1049
- // Check and see if the old plugin is active
1050
- if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) {
1051
- // Deactivate the old plugin
1052
- if ( Jetpack_Client_Server::deactivate_plugin( $jetpack->plugins_to_deactivate[$module][0], $jetpack->plugins_to_deactivate[$module][1] ) ) {
1053
- // If we deactivated the old plugin, remembere that with ::state() and redirect back to this page to activate the module
1054
- // We can't activate the module on this page load since the newly deactivated old plugin is still loaded on this page load.
1055
- Jetpack::state( 'deactivated_plugins', $module );
1056
- wp_safe_redirect( add_query_arg( 'jetpack_restate', 1 ) );
1057
- exit;
1058
- }
1059
- }
1060
-
1061
- // Check the file for fatal errors, a la wp-admin/plugins.php::activate
1062
- Jetpack::state( 'module', $module );
1063
- Jetpack::state( 'error', 'module_activation_failed' ); // we'll override this later if the plugin can be included without fatal error
1064
- wp_safe_redirect( Jetpack::admin_url() );
1065
-
1066
- Jetpack::catch_errors( true );
1067
- ob_start();
1068
- require Jetpack::get_module_path( $module );
1069
- do_action( 'jetpack_activate_module', $module );
1070
- $active[] = $module;
1071
- Jetpack::update_option( 'active_modules', array_unique( $active ) );
1072
- Jetpack::state( 'error', false ); // the override
1073
- Jetpack::state( 'message', 'module_activated' );
1074
- Jetpack::state( 'module', $module );
1075
- ob_end_clean();
1076
- Jetpack::catch_errors( false );
1077
- exit;
1078
- }
1079
-
1080
- function activate_module_actions( $module ) {
1081
- do_action( "jetpack_activate_module_$module" );
1082
-
1083
- $this->sync->sync_all_module_options( $module );
1084
- }
1085
-
1086
- public static function deactivate_module( $module ) {
1087
- $active = Jetpack::get_active_modules();
1088
- $new = array();
1089
- foreach ( $active as $check ) {
1090
- if ( !empty( $check ) && $module != $check )
1091
- $new[] = $check;
1092
- }
1093
-
1094
- do_action( "jetpack_deactivate_module_$module" );
1095
- return Jetpack::update_option( 'active_modules', array_unique( $new ) );
1096
- }
1097
-
1098
- public static function enable_module_configurable( $module ) {
1099
- $module = Jetpack::get_module_slug( $module );
1100
- add_filter( 'jetpack_module_configurable_' . $module, '__return_true' );
1101
- }
1102
-
1103
- public static function module_configuration_url( $module ) {
1104
- $module = Jetpack::get_module_slug( $module );
1105
- return Jetpack::admin_url( array( 'configure' => $module ) );
1106
- }
1107
-
1108
- public static function module_configuration_load( $module, $method ) {
1109
- $module = Jetpack::get_module_slug( $module );
1110
- add_action( 'jetpack_module_configuration_load_' . $module, $method );
1111
- }
1112
-
1113
- public static function module_configuration_head( $module, $method ) {
1114
- $module = Jetpack::get_module_slug( $module );
1115
- add_action( 'jetpack_module_configuration_head_' . $module, $method );
1116
- }
1117
-
1118
- public static function module_configuration_screen( $module, $method ) {
1119
- $module = Jetpack::get_module_slug( $module );
1120
- add_action( 'jetpack_module_configuration_screen_' . $module, $method );
1121
- }
1122
-
1123
- /* Installation */
1124
-
1125
- public static function bail_on_activation( $message, $deactivate = true ) {
1126
- ?>
1127
- <!doctype html>
1128
- <html>
1129
- <head>
1130
- <meta charset="<?php bloginfo( 'charset' ); ?>">
1131
- <style>
1132
- * {
1133
- text-align: center;
1134
- margin: 0;
1135
- padding: 0;
1136
- font-family: "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif;
1137
- }
1138
- p {
1139
- margin-top: 1em;
1140
- font-size: 18px;
1141
- }
1142
- </style>
1143
- <body>
1144
- <p><?php echo esc_html( $message ); ?></p>
1145
- </body>
1146
- </html>
1147
- <?php
1148
- if ( $deactivate ) {
1149
- $plugins = get_option( 'active_plugins' );
1150
- $jetpack = plugin_basename( __FILE__ );
1151
- $update = false;
1152
- foreach ( $plugins as $i => $plugin ) {
1153
- if ( $plugin === $jetpack ) {
1154
- $plugins[$i] = false;
1155
- $update = true;
1156
- }
1157
- }
1158
-
1159
- if ( $update ) {
1160
- update_option( 'active_plugins', array_filter( $plugins ) );
1161
- }
1162
- }
1163
- exit;
1164
- }
1165
-
1166
- /**
1167
- * Attached to activate_{ plugin_basename( __FILES__ ) } by register_activation_hook()
1168
- * @static
1169
- */
1170
- public static function plugin_activation( $network_wide ) {
1171
- Jetpack::update_option( 'activated', 1 );
1172
-
1173
- if ( version_compare( $GLOBALS['wp_version'], JETPACK__MINIMUM_WP_VERSION, '<' ) ) {
1174
- Jetpack::bail_on_activation( sprintf( __( 'Jetpack requires WordPress version %s or later.', 'jetpack' ), JETPACK__MINIMUM_WP_VERSION ) );
1175
- }
1176
-
1177
- if ( $network_wide )
1178
- Jetpack::state( 'network_nag', true );
1179
-
1180
- Jetpack::plugin_initialize();
1181
- }
1182
-
1183
- /**
1184
- * Sets the internal version number and activation state.
1185
- * @static
1186
- */
1187
- public static function plugin_initialize() {
1188
- if ( !Jetpack::get_option( 'activated' ) ) {
1189
- Jetpack::update_option( 'activated', 2 );
1190
- }
1191
-
1192
- if ( !Jetpack::get_option( 'version' ) ) {
1193
- $version = $old_version = JETPACK__VERSION . ':' . time();
1194
- Jetpack::update_options( compact( 'version', 'old_version' ) );
1195
- }
1196
-
1197
- Jetpack::load_modules();
1198
-
1199
- Jetpack::delete_option( 'do_activate' );
1200
- }
1201
-
1202
- /**
1203
- * Removes all connection options
1204
- * @static
1205
- */
1206
- public static function plugin_deactivation( $network_wide ) {
1207
- Jetpack::disconnect( false );
1208
- }
1209
-
1210
- /**
1211
- * Disconnects from the Jetpack servers.
1212
- * Forgets all connection details and tells the Jetpack servers to do the same.
1213
- * @static
1214
- */
1215
- public static function disconnect( $update_activated_state = true ) {
1216
- wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
1217
- Jetpack::clean_nonces( true );
1218
-
1219
- Jetpack::load_xml_rpc_client();
1220
- $xml = new Jetpack_IXR_Client();
1221
- $xml->query( 'jetpack.deregister' );
1222
-
1223
- Jetpack::delete_option( array(
1224
- 'register',
1225
- 'blog_token',
1226
- 'user_token',
1227
- 'user_tokens',
1228
- 'master_user',
1229
- 'time_diff',
1230
- 'fallback_no_verify_ssl_certs',
1231
- ) );
1232
-
1233
- if ( $update_activated_state ) {
1234
- Jetpack::update_option( 'activated', 4 );
1235
- }
1236
- }
1237
-
1238
- /**
1239
- * Unlinks the current user from the linked WordPress.com user
1240
- */
1241
- function unlink_user() {
1242
- if ( !$tokens = Jetpack::get_option( 'user_tokens' ) )
1243
- return false;
1244
-
1245
- $user_id = get_current_user_id();
1246
-
1247
- if ( Jetpack::get_option( 'master_user' ) == $user_id )
1248
- return false;
1249
-
1250
- if ( !isset( $tokens[$user_id] ) )
1251
- return false;
1252
-
1253
- Jetpack::load_xml_rpc_client();
1254
- $xml = new Jetpack_IXR_Client( compact( 'user_id' ) );
1255
- $xml->query( 'jetpack.unlink_user', $user_id );
1256
-
1257
- unset( $tokens[$user_id] );
1258
-
1259
- Jetpack::update_option( 'user_tokens', $tokens );
1260
-
1261
- return true;
1262
- }
1263
-
1264
- /**
1265
- * Attempts Jetpack registration. If it fail, a state flag is set: @see ::admin_page_load()
1266
- */
1267
- public static function try_registration() {
1268
- $result = Jetpack::register();
1269
-
1270
- // If there was an error with registration and the site was not registered, record this so we can show a message.
1271
- if ( !$result || is_wp_error( $result ) ) {
1272
- return $result;
1273
- } else {
1274
- return true;
1275
- }
1276
- }
1277
-
1278
- /* Admin Pages */
1279
-
1280
- function admin_init() {
1281
- // If the plugin is not connected, display a connect message.
1282
- if (
1283
- // the plugin was auto-activated and needs its candy
1284
- Jetpack::get_option( 'do_activate' )
1285
- ||
1286
- // the plugin is active, but was never activated. Probably came from a site-wide network activation
1287
- !Jetpack::get_option( 'activated' )
1288
- ) {
1289
- Jetpack::plugin_initialize();
1290
- }
1291
-
1292
- if ( !Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
1293
- if ( 4 != Jetpack::get_option( 'activated' ) ) {
1294
- // Show connect notice on dashboard and plugins pages
1295
- add_action( 'load-index.php', array( $this, 'prepare_connect_notice' ) );
1296
- add_action( 'load-plugins.php', array( $this, 'prepare_connect_notice' ) );
1297
- }
1298
- } elseif ( false === Jetpack::get_option( 'fallback_no_verify_ssl_certs' ) ) {
1299
- // Upgrade: 1.1 -> 1.1.1
1300
- // Check and see if host can verify the Jetpack servers' SSL certificate
1301
- $args = array();
1302
- Jetpack_Client::_wp_remote_request(
1303
- Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'test' ), $args ),
1304
- $args,
1305
- true
1306
- );
1307
- }
1308
-
1309
- add_action( 'load-plugins.php', array( $this, 'intercept_plugin_error_scrape_init' ) );
1310
- add_action( 'admin_head', array( $this, 'admin_menu_css' ) );
1311
- add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
1312
-
1313
- add_action( 'wp_ajax_jetpack_debug', array( $this, 'ajax_debug' ) );
1314
-
1315
- if ( Jetpack::is_active() || Jetpack::is_development_mode() ) {
1316
- // Artificially throw errors in certain whitelisted cases during plugin activation
1317
- add_action( 'activate_plugin', array( $this, 'throw_error_on_activate_plugin' ) );
1318
-
1319
- // Kick off synchronization of user role when it changes
1320
- add_action( 'set_user_role', array( $this, 'user_role_change' ) );
1321
-
1322
- // Add retina images hotfix to admin
1323
- global $wp_db_version;
1324
- if ( $wp_db_version > 19470 ) {
1325
- // WP 3.4.x
1326
- // TODO will need to add && $wp_db_version < xxxxx when 3.5 comes out.
1327
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_retina_scripts' ) );
1328
- // /wp-admin/customize.php omits the action above.
1329
- add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_retina_scripts' ) );
1330
- }
1331
- }
1332
- }
1333
-
1334
- function prepare_connect_notice() {
1335
- add_action( 'admin_print_styles', array( $this, 'admin_styles' ) );
1336
-
1337
- add_action( 'admin_notices', array( $this, 'admin_connect_notice' ) );
1338
-
1339
- if ( Jetpack::state( 'network_nag' ) )
1340
- add_action( 'network_admin_notices', array( $this, 'network_connect_notice' ) );
1341
- }
1342
-
1343
- /**
1344
- * Sometimes a plugin can activate without causing errors, but it will cause errors on the next page load.
1345
- * This function artificially throws errors for such cases (whitelisted).
1346
- *
1347
- * @param string $plugin The activated plugin.
1348
- */
1349
- function throw_error_on_activate_plugin( $plugin ) {
1350
- $active_modules = Jetpack::get_active_modules();
1351
-
1352
- // The Shortlinks module and the Stats plugin conflict, but won't cause errors on activation because of some function_exists() checks.
1353
- if ( function_exists( 'stats_get_api_key' ) && in_array( 'shortlinks', $active_modules ) ) {
1354
- $throw = false;
1355
-
1356
- // Try and make sure it really was the stats plugin
1357
- if ( !class_exists( 'ReflectionFunction' ) ) {
1358
- if ( 'stats.php' == basename( $plugin ) ) {
1359
- $throw = true;
1360
- }
1361
- } else {
1362
- $reflection = new ReflectionFunction( 'stats_get_api_key' );
1363
- if ( basename( $plugin ) == basename( $reflection->getFileName() ) ) {
1364
- $throw = true;
1365
- }
1366
- }
1367
-
1368
- if ( $throw ) {
1369
- trigger_error( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), 'WordPress.com Stats' ), E_USER_ERROR );
1370
- }
1371
- }
1372
- }
1373
-
1374
- function intercept_plugin_error_scrape_init() {
1375
- add_action( 'check_admin_referer', array( $this, 'intercept_plugin_error_scrape' ), 10, 2 );
1376
- }
1377
-
1378
- function intercept_plugin_error_scrape( $action, $result ) {
1379
- if ( !$result ) {
1380
- return;
1381
- }
1382
-
1383
- foreach ( $this->plugins_to_deactivate as $module => $deactivate_me ) {
1384
- if ( "plugin-activation-error_{$deactivate_me[0]}" == $action ) {
1385
- Jetpack::bail_on_activation( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), $deactivate_me[1] ), false );
1386
- }
1387
- }
1388
- }
1389
-
1390
- function admin_menu() {
1391
- list( $jetpack_version ) = explode( ':', Jetpack::get_option( 'version' ) );
1392
- if (
1393
- $jetpack_version
1394
- &&
1395
- $jetpack_version != JETPACK__VERSION
1396
- &&
1397
- ( $new_modules = Jetpack::get_default_modules( $jetpack_version, JETPACK__VERSION ) )
1398
- &&
1399
- is_array( $new_modules )
1400
- &&
1401
- ( $new_modules_count = count( $new_modules ) )
1402
- &&
1403
- ( Jetpack::is_active() || Jetpack::is_development_mode() )
1404
- ) {
1405
- $new_modules_count_i18n = number_format_i18n( $new_modules_count );
1406
- $span_title = esc_attr( sprintf( _n( 'One New Jetpack Module', '%s New Jetpack Modules', $new_modules_count, 'jetpack' ), $new_modules_count_i18n ) );
1407
- $title = sprintf( 'Jetpack %s', "<span class='update-plugins count-{$new_modules_count}' title='$span_title'><span class='update-count'>$new_modules_count_i18n</span></span>" );
1408
- } else {
1409
- $title = __( 'Jetpack', 'jetpack' );
1410
- }
1411
-
1412
- $hook = add_menu_page( 'Jetpack', $title, 'read', 'jetpack', array( $this, 'admin_page' ), 'div' );
1413
-
1414
- add_action( "load-$hook", array( $this, 'admin_page_load' ) );
1415
-
1416
- if ( version_compare( $GLOBALS['wp_version'], '3.3', '<' ) ) {
1417
- if ( isset( $_GET['page'] ) && 'jetpack' == $_GET['page'] ) {
1418
- add_contextual_help( $hook, $this->jetpack_help() );
1419
- }
1420
- } else {
1421
- add_action( "load-$hook", array( $this, 'admin_help' ) );
1422
- }
1423
- add_action( "admin_head-$hook", array( $this, 'admin_head' ) );
1424
- add_filter( 'custom_menu_order', array( $this, 'admin_menu_order' ) );
1425
- add_filter( 'menu_order', array( $this, 'jetpack_menu_order' ) );
1426
-
1427
- add_action( "admin_print_styles-$hook", array( $this, 'admin_styles' ) );
1428
-
1429
- add_action( "admin_print_scripts-$hook", array( $this, 'admin_scripts' ) );
1430
-
1431
- do_action( 'jetpack_admin_menu' );
1432
- }
1433
-
1434
- function add_remote_request_handlers() {
1435
- add_action( 'wp_ajax_nopriv_jetpack_upload_file', array( $this, 'remote_request_handlers' ) );
1436
- }
1437
-
1438
- function remote_request_handlers() {
1439
- switch ( current_filter() ) {
1440
- case 'wp_ajax_nopriv_jetpack_upload_file' :
1441
- $response = $this->upload_handler();
1442
- break;
1443
- default :
1444
- $response = new Jetpack_Error( 'unknown_handler', 'Unknown Handler', 400 );
1445
- break;
1446
- }
1447
-
1448
- if ( !$response ) {
1449
- $response = new Jetpack_Error( 'unknown_error', 'Unknown Error', 400 );
1450
- }
1451
-
1452
- if ( is_wp_error( $response ) ) {
1453
- $status_code = $response->get_error_data();
1454
- $error = $response->get_error_code();
1455
- $error_description = $response->get_error_message();
1456
-
1457
- if ( !is_int( $status_code ) ) {
1458
- $status_code = 400;
1459
- }
1460
-
1461
- status_header( $status_code );
1462
- die( json_encode( (object) compact( 'error', 'error_description' ) ) );
1463
- }
1464
-
1465
- status_header( 200 );
1466
- if ( true === $response ) {
1467
- exit;
1468
- }
1469
-
1470
- die( json_encode( (object) $response ) );
1471
- }
1472
-
1473
- function upload_handler() {
1474
- if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
1475
- return new Jetpack_Error( 405, get_status_header_desc( 405 ), 405 );
1476
- }
1477
-
1478
- $user = wp_authenticate( '', '' );
1479
- if ( !$user || is_wp_error( $user ) ) {
1480
- return new Jetpack_Error( 403, get_status_header_desc( 403 ), 403 );
1481
- }
1482
-
1483
- wp_set_current_user( $user->ID );
1484
-
1485
- if ( !current_user_can( 'upload_files' ) ) {
1486
- return new Jetpack_Error( 'cannot_upload_files', 'User does not have permission to upload files', 403 );
1487
- }
1488
-
1489
- if ( empty( $_FILES ) ) {
1490
- return new Jetpack_Error( 'no_files_uploaded', 'No files were uploaded: nothing to process', 400 );
1491
- }
1492
-
1493
- foreach ( array_keys( $_FILES ) as $files_key ) {
1494
- if ( !isset( $_POST["_jetpack_file_hmac_{$files_key}"] ) ) {
1495
- return new Jetpack_Error( 'missing_hmac', 'An HMAC for one or more files is missing', 400 );
1496
- }
1497
- }
1498
-
1499
- $media_keys = array_keys( $_FILES['media'] );
1500
-
1501
- $token = Jetpack_Data::get_access_token( get_current_user_id() );
1502
- if ( !$token || is_wp_error( $token ) ) {
1503
- return new Jetpack_Error( 'unknown_token', 'Unknown Jetpack token', 403 );
1504
- }
1505
-
1506
- $uploaded_files = array();
1507
- $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
1508
- unset( $GLOBALS['post'] );
1509
- foreach ( $_FILES['media']['name'] as $index => $name ) {
1510
- $file = array();
1511
- foreach ( $media_keys as $media_key ) {
1512
- $file[$media_key] = $_FILES['media'][$media_key][$index];
1513
- }
1514
-
1515
- list( $hmac_provided, $salt ) = explode( ':', $_POST['_jetpack_file_hmac_media'][$index] );
1516
-
1517
- $hmac_file = hash_hmac_file( 'sha1', $file['tmp_name'], $salt . $token->secret );
1518
- if ( $hmac_provided !== $hmac_file ) {
1519
- $uploaded_files[$index] = (object) array( 'error' => 'invalid_hmac', 'error_description' => 'The corresponding HMAC for this file does not match' );
1520
- continue;
1521
- }
1522
-
1523
- $_FILES['.jetpack.upload.'] = $file;
1524
- $post_id = isset( $_POST['post_id'][$index] ) ? absint( $_POST['post_id'][$index] ) : 0;
1525
- if ( !current_user_can( 'edit_post', $post_id ) ) {
1526
- $post_id = 0;
1527
- }
1528
- $attachment_id = media_handle_upload( '.jetpack.upload.', $post_id, array(), array(
1529
- 'action' => 'jetpack_upload_file',
1530
- ) );
1531
-
1532
- if ( !$attachment_id ) {
1533
- $uploaded_files[$index] = (object) array( 'error' => 'unknown', 'error_description' => 'An unknown problem occurred processing the upload on the Jetpack site' );
1534
- } elseif ( is_wp_error( $attachment_id ) ) {
1535
- $uploaded_files[$index] = (object) array( 'error' => 'attachment_' . $attachment_id->get_error_code(), 'error_description' => $attachment_id->get_error_message() );
1536
- } else {
1537
- $attachment = get_post( $attachment_id );
1538
- $uploaded_files[$index] = (object) array(
1539
- 'id' => (string) $attachment_id,
1540
- 'file' => $attachment->post_title,
1541
- 'url' => wp_get_attachment_url( $attachment_id ),
1542
- 'type' => $attachment->post_mime_type,
1543
- 'meta' => wp_get_attachment_metadata( $attachment_id ),
1544
- );
1545
- }
1546
- }
1547
- if ( !is_null( $global_post ) ) {
1548
- $GLOBALS['post'] = $global_post;
1549
- }
1550
-
1551
- return $uploaded_files;
1552
- }
1553
-
1554
- /**
1555
- * Add help to the Jetpack page
1556
- *
1557
- * Deprecated. Remove when Jetpack requires WP 3.3+
1558
- */
1559
- function jetpack_help() {
1560
- return
1561
- '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
1562
- '<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' .
1563
- '<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>' .
1564
- '<p><strong>' . __( 'Jetpack Module Options', 'jetpack' ) . '</strong></p>' .
1565
- '<p>' . __( '<strong>To Activate/Deactivate a Module</strong> - Click on Learn More. An Activate or Deactivate button will now appear next to the Learn More button. Click the Activate/Deactivate button.', 'jetpack' ) . '</p>' .
1566
- '<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' .
1567
- '<p><a href="http://jetpack.me/faq/" target="_blank">' . __( 'Jetpack FAQ', 'jetpack' ) . '</a></p>' .
1568
- '<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></p>';
1569
- }
1570
-
1571
- /**
1572
- * Add help to the Jetpack page
1573
- *
1574
- * @since Jetpack (1.2.3)
1575
- * @return false if not the Jetpack page
1576
- */
1577
- function admin_help() {
1578
- $current_screen = get_current_screen();
1579
-
1580
- // Overview
1581
- $current_screen->add_help_tab( array(
1582
- 'id' => 'overview',
1583
- 'title' => __( 'Overview', 'jetpack' ),
1584
- 'content' =>
1585
- '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
1586
- '<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' .
1587
- '<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>'
1588
- ) );
1589
-
1590
- // Screen Content
1591
- if ( current_user_can( 'manage_options' ) ) {
1592
- $current_screen->add_help_tab( array(
1593
- 'id' => 'modules',
1594
- 'title' => __( 'Modules', 'jetpack' ),
1595
- 'content' =>
1596
- '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
1597
- '<p>' . __( 'You can activate or deactivate individual Jetpack modules to suit your needs.', 'jetpack' ) . '</p>' .
1598
- '<ol>' .
1599
- '<li>' . __( 'Find the component you want to manage', 'jetpack' ) . '</li>' .
1600
- '<li>' . __( 'Click on Learn More', 'jetpack' ) . '</li>' .
1601
- '<li>' . __( 'An Activate or Deactivate button will appear', 'jetpack' ) . '</li>' .
1602
- '<li>' . __( 'If additional settings are available, a link to them will appear', 'jetpack' ) . '</li>' .
1603
- '</ol>'
1604
- ) );
1605
- }
1606
-
1607
- // Help Sidebar
1608
- $current_screen->set_help_sidebar(
1609
- '<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' .
1610
- '<p><a href="http://jetpack.me/faq/" target="_blank">' . __( 'Jetpack FAQ', 'jetpack' ) . '</a></p>' .
1611
- '<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></p>'
1612
- );
1613
- }
1614
-
1615
- function admin_menu_css() { ?>
1616
- <style type="text/css" id="jetpack-menu-css">
1617
- #toplevel_page_jetpack .wp-menu-image {
1618
- background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite.png' ) ?> ) 0 90% no-repeat;
1619
- }
1620
- /* Retina Jetpack Menu Icon */
1621
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
1622
- #toplevel_page_jetpack .wp-menu-image {
1623
- background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite-2x.png' ) ?> ) 0 90% no-repeat;
1624
- background-size:30px 64px;
1625
- }
1626
- }
1627
- #toplevel_page_jetpack.current .wp-menu-image,
1628
- #toplevel_page_jetpack.wp-has-current-submenu .wp-menu-image,
1629
- #toplevel_page_jetpack:hover .wp-menu-image {
1630
- background-position: top left;
1631
- }
1632
- </style><?php
1633
- }
1634
-
1635
- function admin_menu_order() {
1636
- return true;
1637
- }
1638
-
1639
- function jetpack_menu_order( $menu_order ) {
1640
- $jp_menu_order = array();
1641
-
1642
- foreach ( $menu_order as $index => $item ) {
1643
- if ( $item != 'jetpack' )
1644
- $jp_menu_order[] = $item;
1645
-
1646
- if ( $index == 0 )
1647
- $jp_menu_order[] = 'jetpack';
1648
- }
1649
-
1650
- return $jp_menu_order;
1651
- }
1652
-
1653
- function admin_head() {
1654
- if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) )
1655
- do_action( 'jetpack_module_configuration_head_' . $_GET['configure'] );
1656
- }
1657
-
1658
- function admin_styles() {
1659
- global $wp_styles;
1660
- wp_enqueue_style( 'jetpack', plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/jetpack.css' ), false, JETPACK__VERSION . '-20121016' );
1661
- $wp_styles->add_data( 'jetpack', 'rtl', true );
1662
- }
1663
-
1664
- function admin_scripts() {
1665
- wp_enqueue_script( 'jetpack-js', plugins_url( basename( dirname( __FILE__ ) ) ) . '/_inc/jetpack.js', array( 'jquery' ), JETPACK__VERSION . '-20121111' );
1666
- wp_localize_script( 'jetpack-js', 'jetpackL10n', array(
1667
- 'ays_disconnect' => "This will deactivate all Jetpack modules.\nAre you sure you want to disconnect?",
1668
- 'ays_unlink' => "This will prevent user-specific modules such as Publicize, Notifications and Post By Email from working.\nAre you sure you want to unlink?",
1669
- 'ays_dismiss' => "This will deactivate Jetpack.\nAre you sure you want to deactivate Jetpack?",
1670
- ) );
1671
- add_action( 'admin_footer', array( $this, 'do_stats' ) );
1672
- }
1673
-
1674
- function enqueue_retina_scripts() {
1675
- wp_enqueue_style( 'jetpack-retina', plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/jetpack-retina.css' ), false, JETPACK__VERSION . '-20120730' );
1676
- }
1677
-
1678
- function plugin_action_links( $actions ) {
1679
- return array_merge(
1680
- array( 'settings' => sprintf( '<a href="%s">%s</a>', Jetpack::admin_url(), __( 'Settings', 'jetpack' ) ) ),
1681
- $actions
1682
- );
1683
- return $actions;
1684
- }
1685
-
1686
- function admin_connect_notice() {
1687
- // Don't show the connect notice on the jetpack settings page. @todo: must be a better way?
1688
- if ( false !== strpos( $_SERVER['QUERY_STRING'], 'page=jetpack' ) )
1689
- return;
1690
-
1691
- if ( !current_user_can( 'manage_options' ) )
1692
- return;
1693
- ?>
1694
-
1695
- <div id="message" class="updated jetpack-message jp-connect">
1696
- <div id="jp-dismiss" class="jetpack-close-button-container">
1697
- <a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?></a>
1698
- </div>
1699
- <div class="jetpack-wrap-container">
1700
- <div class="jetpack-text-container">
1701
- <h4>
1702
- <?php if ( 1 == Jetpack::get_option( 'activated' ) ) : ?>
1703
- <p><?php _e( '<strong>Your Jetpack is almost ready</strong> &#8211; A connection to WordPress.com is needed to enable features like Stats, Contact Forms, and Subscriptions. Connect now to get fueled up!', 'jetpack' ); ?></p>
1704
- <?php else : ?>
1705
- <p><?php _e( '<strong>Jetpack is installed</strong> and ready to bring awesome, WordPress.com cloud-powered features to your site.', 'jetpack' ) ?></p>
1706
- <?php endif; ?>
1707
- </h4>
1708
- </div>
1709
- <div class="jetpack-install-container">
1710
- <?php if ( 1 == Jetpack::get_option( 'activated' ) ) : ?>
1711
- <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
1712
- <?php else : ?>
1713
- <p class="submit"><a href="<?php echo Jetpack::admin_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Learn More', 'jetpack' ); ?></a></p>
1714
- <?php endif; ?>
1715
- </div>
1716
- </div>
1717
- </div>
1718
-
1719
- <?php
1720
- }
1721
-
1722
- function network_connect_notice() {
1723
- ?>
1724
- <div id="message" class="updated jetpack-message">
1725
- <div class="squeezer">
1726
- <h4><?php _e( '<strong>Jetpack is activated!</strong> Each site on your network must be connected individually by an admin on that site.', 'jetpack' ) ?></h4>
1727
- </div>
1728
- </div>
1729
- <?php
1730
- }
1731
-
1732
- public static function jetpack_comment_notice() {
1733
- if ( in_array( 'comments', Jetpack::get_active_modules() ) ) {
1734
- return '';
1735
- }
1736
-
1737
- $jetpack_old_version = explode( ':', Jetpack::get_option( 'old_version' ) );
1738
- $jetpack_new_version = explode( ':', Jetpack::get_option( 'version' ) );
1739
-
1740
- if ( $jetpack_old_version ) {
1741
- if ( version_compare( $jetpack_old_version[0], '1.4', '>=' ) ) {
1742
- return '';
1743
- }
1744
- }
1745
-
1746
- if ( $jetpack_new_version ) {
1747
- if ( version_compare( $jetpack_new_version[0], '1.4-something', '<' ) ) {
1748
- return '';
1749
- }
1750
- }
1751
-
1752
- return '<br /><br />' . sprintf(
1753
- __( 'Jetpack now includes Jetpack Comments, which enables your visitors to use their WordPress.com, Twitter, or Facebook accounts when commenting on your site. To activate Jetpack Comments, <a href="%s">%s</a>.', 'jetpack' ),
1754
- wp_nonce_url(
1755
- Jetpack::admin_url( array(
1756
- 'action' => 'activate',
1757
- 'module' => 'comments',
1758
- ) ),
1759
- "jetpack_activate-comments"
1760
- ),
1761
- __( 'click here', 'jetpack' )
1762
- );
1763
- }
1764
-
1765
- /*
1766
- * Registration flow:
1767
- * 1 - ::admin_page_load() action=register
1768
- * 2 - ::try_registration()
1769
- * 3 - ::register()
1770
- * - Creates jetpack_register option containing two secrets and a timestamp
1771
- * - Calls https://jetpack.wordpress.com/jetpack.register/1/ with
1772
- * siteurl, home, gmt_offset, timezone_string, site_name, secret_1, secret_2, site_lang, timeout, stats_id
1773
- * - That request to jetpack.wordpress.com does not immediately respond. It first makes a request BACK to this site's
1774
- * xmlrpc.php?for=jetpack: RPC method: jetpack.verifyRegistration, Parameters: secret_1
1775
- * - The XML-RPC request verifies secret_1, deletes both secrets and responds with: secret_2
1776
- * - https://jetpack.wordpress.com/jetpack.register/1/ verifies that XML-RPC response (secret_2) then finally responds itself with
1777
- * jetpack_id, jetpack_secret, jetpack_public
1778
- * - ::register() then stores jetpack_options: id => jetpack_id, blog_token => jetpack_secret
1779
- * 4 - redirect to https://jetpack.wordpress.com/jetpack.authorize/1/
1780
- * 5 - user logs in with WP.com account
1781
- * 6 - redirect to this site's wp-admin/index.php?page=jetpack&action=authorize with
1782
- * code <-- OAuth2 style authorization code
1783
- * 7 - ::admin_page_load() action=authorize
1784
- * 8 - Jetpack_Client_Server::authorize()
1785
- * 9 - Jetpack_Client_Server::get_token()
1786
- * 10- GET https://jetpack.wordpress.com/jetpack.token/1/ with
1787
- * client_id, client_secret, grant_type, code, redirect_uri:action=authorize, state, scope, user_email, user_login
1788
- * 11- which responds with
1789
- * access_token, token_type, scope
1790
- * 12- Jetpack_Client_Server::authorize() stores jetpack_options: user_token => access_token.$user_id
1791
- * 13- Jetpack::activate_default_modules()
1792
- * Deactivates deprecated plugins
1793
- * Activates all default modules
1794
- * Catches errors: redirects to wp-admin/index.php?page=jetpack state:error=something
1795
- * 14- redirect to this site's wp-admin/index.php?page=jetpack with state:message=authorized
1796
- * Done!
1797
- */
1798
-
1799
- /**
1800
- * Handles the page load events for the Jetpack admin page
1801
- */
1802
- function admin_page_load() {
1803
- $error = false;
1804
-
1805
- if ( !empty( $_GET['jetpack_restate'] ) ) {
1806
- // Should only be used in intermediate redirects to preserve state across redirects
1807
- Jetpack::restate();
1808
- }
1809
-
1810
- if ( isset( $_GET['connect_url_redirect'] ) ) {
1811
- // User clicked in the iframe to link their accounts
1812
- if ( ! Jetpack::is_user_connected() ) {
1813
- $connect_url = $this->build_connect_url( true );
1814
- if ( isset( $_GET['notes_iframe'] ) )
1815
- $connect_url .= '&notes_iframe';
1816
- wp_redirect( $connect_url );
1817
- exit;
1818
- } else {
1819
- Jetpack::state( 'message', 'already_authorized' );
1820
- wp_safe_redirect( Jetpack::admin_url() );
1821
- exit;
1822
- }
1823
- }
1824
-
1825
- if ( isset( $_GET['action'] ) ) {
1826
- switch ( $_GET['action'] ) {
1827
- case 'authorize' :
1828
- if ( Jetpack::is_active() && Jetpack::is_user_connected() ) {
1829
- Jetpack::state( 'message', 'already_authorized' );
1830
- wp_safe_redirect( Jetpack::admin_url() );
1831
- exit;
1832
- }
1833
- $client_server = new Jetpack_Client_Server;
1834
- $client_server->authorize();
1835
- exit;
1836
- case 'register' :
1837
- check_admin_referer( 'jetpack-register' );
1838
- $registered = Jetpack::try_registration();
1839
- if ( is_wp_error( $registered ) ) {
1840
- $error = $registered->get_error_code();
1841
- Jetpack::state( 'error_description', $registered->get_error_message() );
1842
- break;
1843
- }
1844
-
1845
- wp_redirect( $this->build_connect_url( true ) );
1846
- exit;
1847
- case 'activate' :
1848
- $module = stripslashes( $_GET['module'] );
1849
- check_admin_referer( "jetpack_activate-$module" );
1850
- Jetpack::activate_module( $module );
1851
- wp_safe_redirect( Jetpack::admin_url() );
1852
- exit;
1853
- case 'activate_default_modules' :
1854
- check_admin_referer( 'activate_default_modules' );
1855
- Jetpack::restate();
1856
- $min_version = isset( $_GET['min_version'] ) ? $_GET['min_version'] : false;
1857
- $max_version = isset( $_GET['max_version'] ) ? $_GET['max_version'] : false;
1858
- $other_modules = isset( $_GET['other_modules'] ) && is_array( $_GET['other_modules'] ) ? $_GET['other_modules'] : array();
1859
- Jetpack::activate_default_modules( $min_version, $max_version, $other_modules );
1860
- wp_safe_redirect( Jetpack::admin_url() );
1861
- exit;
1862
- case 'disconnect' :
1863
- check_admin_referer( 'jetpack-disconnect' );
1864
- Jetpack::disconnect();
1865
- wp_safe_redirect( Jetpack::admin_url() );
1866
- exit;
1867
- case 'deactivate' :
1868
- $modules = stripslashes( $_GET['module'] );
1869
- check_admin_referer( "jetpack_deactivate-$modules" );
1870
- foreach ( explode( ',', $modules ) as $module ) {
1871
- Jetpack::deactivate_module( $module );
1872
- Jetpack::state( 'message', 'module_deactivated' );
1873
- }
1874
- Jetpack::state( 'module', $modules );
1875
- wp_safe_redirect( Jetpack::admin_url() );
1876
- exit;
1877
- case 'unlink' :
1878
- check_admin_referer( 'jetpack-unlink' );
1879
- $this->unlink_user();
1880
- Jetpack::state( 'message', 'unlinked' );
1881
- wp_safe_redirect( Jetpack::admin_url() );
1882
- exit;
1883
- }
1884
- }
1885
-
1886
- if ( !$error = $error ? $error : Jetpack::state( 'error' ) ) {
1887
- $this->activate_new_modules();
1888
- }
1889
-
1890
- switch ( $error ) {
1891
- case 'access_denied' :
1892
- $this->error = __( 'You need to authorize the Jetpack connection between your site and WordPress.com to enable the awesome features.', 'jetpack' );
1893
- break;
1894
- case 'wrong_state' :
1895
- $this->error = __( "Don&#8217;t cross the streams! You need to stay logged in to your WordPress blog while you authorize Jetpack.", 'jetpack' );
1896
- break;
1897
- case 'invalid_client' :
1898
- // @todo re-register instead of deactivate/reactivate
1899
- $this->error = __( 'Return to sender. Whoops! It looks like you got the wrong Jetpack in the mail; deactivate then reactivate the Jetpack plugin to get a new one.', 'jetpack' );
1900
- break;
1901
- case 'invalid_grant' :
1902
- $this->error = __( "Wrong size. Hm&#8230; it seems your Jetpack doesn&#8217;t quite fit. Have you lost weight? Click &#8220;Connect to WordPress.com&#8221; again to get your Jetpack adjusted.", 'jetpack' );
1903
- break;
1904
- case 'site_inaccessible' :
1905
- case 'site_requires_authorization' :
1906
- $this->error = sprintf( __( 'Your website needs to be publicly accessible to use Jetpack: %s', 'jetpack' ), "<code>$error</code>" );
1907
- break;
1908
- case 'module_activation_failed' :
1909
- $module = Jetpack::state( 'module' );
1910
- if ( !empty( $module ) && $mod = Jetpack::get_module( $module ) ) {
1911
- $this->error = sprintf( __( '%s could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' ), $mod['name'] );
1912
- if ( isset( $this->plugins_to_deactivate[$module] ) ) {
1913
- $this->error .= ' ' . sprintf( __( 'Do you still have the %s plugin installed?', 'jetpack' ), $this->plugins_to_deactivate[$module][1] );
1914
- }
1915
- } else {
1916
- $this->error = __( 'Module could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' );
1917
- }
1918
- if ( $php_errors = Jetpack::state( 'php_errors' ) ) {
1919
- $this->error .= "<br />\n";
1920
- $this->error .= $php_errors;
1921
- }
1922
- break;
1923
- case 'not_public' :
1924
- $this->error = __( "<strong>Your Jetpack has a glitch.</strong> Connecting this site with WordPress.com is not possible. This usually means your site is not publicly accessible (localhost).", 'jetpack' );
1925
- break;
1926
- case 'wpcom_408' :
1927
- case 'wpcom_5??' :
1928
- case 'wpcom_bad_response' :
1929
- case 'wpcom_outage' :
1930
- $this->error = __( 'WordPress.com is currently having problems and is unable to fuel up your Jetpack. Please try again later.', 'jetpack' );
1931
- break;
1932
- case 'register_http_request_failed' :
1933
- case 'token_http_request_failed' :
1934
- $this->error = sprintf( __( 'Jetpack could not contact WordPress.com: %s. This usually means something is incorrectly configured on your web host.', 'jetpack' ), "<code>$error</code>" );
1935
- break;
1936
- default :
1937
- if ( empty( $error ) ) {
1938
- break;
1939
- }
1940
- $error = trim( substr( strip_tags( $error ), 0, 20 ) );
1941
- // no break: fall through
1942
- case 'no_role' :
1943
- case 'no_cap' :
1944
- case 'no_code' :
1945
- case 'no_state' :
1946
- case 'invalid_state' :
1947
- case 'invalid_request' :
1948
- case 'invalid_scope' :
1949
- case 'unsupported_response_type' :
1950
- case 'invalid_token' :
1951
- case 'no_token' :
1952
- case 'missing_secrets' :
1953
- case 'home_missing' :
1954
- case 'siteurl_missing' :
1955
- case 'gmt_offset_missing' :
1956
- case 'site_name_missing' :
1957
- case 'secret_1_missing' :
1958
- case 'secret_2_missing' :
1959
- case 'site_lang_missing' :
1960
- case 'home_malformed' :
1961
- case 'siteurl_malformed' :
1962
- case 'gmt_offset_malformed' :
1963
- case 'timezone_string_malformed' :
1964
- case 'site_name_malformed' :
1965
- case 'secret_1_malformed' :
1966
- case 'secret_2_malformed' :
1967
- case 'site_lang_malformed' :
1968
- case 'secrets_mismatch' :
1969
- case 'verify_secret_1_missing' :
1970
- case 'verify_secret_1_malformed' :
1971
- case 'verify_secrets_missing' :
1972
- case 'verify_secrets_mismatch' :
1973
- $error = esc_html( $error );
1974
- $this->error = sprintf( __( "<strong>Your Jetpack has a glitch.</strong> Something went wrong that&#8217;s never supposed to happen. Guess you&#8217;re just lucky: %s", 'jetpack' ), "<code>$error</code>" );
1975
- if ( !Jetpack::is_active() ) {
1976
- $this->error .= '<br />';
1977
- $this->error .= sprintf( __( 'Try connecting again.', 'jetpack' ) );
1978
- }
1979
- break;
1980
- }
1981
-
1982
- $message_code = Jetpack::state( 'message' );
1983
-
1984
- $active_state = Jetpack::state( 'activated_modules' );
1985
- if ( !empty( $active_state ) ) {
1986
- $available = Jetpack::get_available_modules();
1987
- $active_state = explode( ',', $active_state );
1988
- $active_state = array_intersect( $active_state, $available );
1989
- if ( count( $active_state ) ) {
1990
- foreach ( $active_state as $mod ) {
1991
- $this->stat( 'module-activated', $mod );
1992
- }
1993
- } else {
1994
- $active_state = false;
1995
- }
1996
- }
1997
-
1998
- switch ( $message_code ) {
1999
- case 'modules_activated' :
2000
- $this->message = sprintf(
2001
- __( 'Welcome to <strong>Jetpack %s</strong>!', 'jetpack' ),
2002
- JETPACK__VERSION
2003
- );
2004
-
2005
- if ( $active_state ) {
2006
- $titles = array();
2007
- foreach ( $active_state as $mod ) {
2008
- if ( $mod_headers = Jetpack::get_module( $mod ) ) {
2009
- $titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', '&nbsp;', $mod_headers['name'] ) . '</strong>';
2010
- }
2011
- }
2012
- if ( $titles ) {
2013
- $this->message .= '<br /><br />' . wp_sprintf( __( 'The following new modules have been activated: %l.', 'jetpack' ), $titles );
2014
- }
2015
- }
2016
-
2017
- if ( $reactive_state = Jetpack::state( 'reactivated_modules' ) ) {
2018
- $titles = array();
2019
- foreach ( explode( ',', $reactive_state ) as $mod ) {
2020
- if ( $mod_headers = Jetpack::get_module( $mod ) ) {
2021
- $titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', '&nbsp;', $mod_headers['name'] ) . '</strong>';
2022
- }
2023
- }
2024
- if ( $titles ) {
2025
- $this->message .= '<br /><br />' . wp_sprintf( __( 'The following modules have been updated: %l.', 'jetpack' ), $titles );
2026
- }
2027
- }
2028
-
2029
- $this->message .= Jetpack::jetpack_comment_notice();
2030
- break;
2031
-
2032
- case 'module_activated' :
2033
- if ( $module = Jetpack::get_module( Jetpack::state( 'module' ) ) ) {
2034
- $this->message = sprintf( __( '<strong>%s Activated!</strong> You can deactivate at any time by clicking Learn More and then Deactivate on the module card.', 'jetpack' ), $module['name'] );
2035
- $this->stat( 'module-activated', Jetpack::state( 'module' ) );
2036
- }
2037
- break;
2038
-
2039
- case 'module_deactivated' :
2040
- $modules = Jetpack::state( 'module' );
2041
- if ( !$modules ) {
2042
- break;
2043
- }
2044
-
2045
- $module_names = array();
2046
- foreach ( explode( ',', $modules ) as $module_slug ) {
2047
- $module = Jetpack::get_module( $module_slug );
2048
- if ( $module ) {
2049
- $module_names[] = $module['name'];
2050
- }
2051
-
2052
- $this->stat( 'module-deactivated', $module_slug );
2053
- }
2054
-
2055
- if ( !$module_names ) {
2056
- break;
2057
- }
2058
-
2059
- $this->message = wp_sprintf(
2060
- _nx(
2061
- '<strong>%l Deactivated!</strong> You can activate it again at any time using the activate button on the module card.',
2062
- '<strong>%l Deactivated!</strong> You can activate them again at any time using the activate buttons on their module cards.',
2063
- count( $module_names ),
2064
- '%l = list of Jetpack module/feature names',
2065
- 'jetpack'
2066
- ),
2067
- $module_names
2068
- );
2069
- break;
2070
-
2071
- case 'module_configured' :
2072
- $this->message = __( '<strong>Module settings were saved.</strong> ', 'jetpack' );
2073
- break;
2074
-
2075
- case 'already_authorized' :
2076
- $this->message = __( '<strong>Your Jetpack is already connected.</strong> ', 'jetpack' );
2077
- break;
2078
-
2079
- case 'authorized' :
2080
- $this->message = __( "<strong>You&#8217;re fueled up and ready to go.</strong> ", 'jetpack' );
2081
- $this->message .= "<br />\n";
2082
- $this->message .= __( 'The features below are now active. Click the learn more buttons to explore each feature.', 'jetpack' );
2083
- $this->message .= Jetpack::jetpack_comment_notice();
2084
- break;
2085
-
2086
- case 'linked' :
2087
- $this->message = __( "<strong>You&#8217;re fueled up and ready to go.</strong> ", 'jetpack' );
2088
- $this->message .= Jetpack::jetpack_comment_notice();
2089
- break;
2090
-
2091
- case 'unlinked' :
2092
- $user = wp_get_current_user();
2093
- $this->message = sprintf( __( '<strong>You have unlinked your account (%s) from WordPress.com.</strong>', 'jetpack' ), $user->user_login );
2094
- break;
2095
- }
2096
-
2097
- $deactivated_plugins = Jetpack::state( 'deactivated_plugins' );
2098
-
2099
- if ( !empty( $deactivated_plugins ) ) {
2100
- $deactivated_plugins = explode( ',', $deactivated_plugins );
2101
- $deactivated_titles = array();
2102
- foreach ( $deactivated_plugins as $deactivated_plugin ) {
2103
- if ( !isset( $this->plugins_to_deactivate[$deactivated_plugin] ) ) {
2104
- continue;
2105
- }
2106
-
2107
- $deactivated_titles[] = '<strong>' . str_replace( ' ', '&nbsp;', $this->plugins_to_deactivate[$deactivated_plugin][1] ) . '</strong>';
2108
- }
2109
-
2110
- if ( $deactivated_titles ) {
2111
- if ( $this->message ) {
2112
- $this->message .= "<br /><br />\n";
2113
- }
2114
-
2115
- $this->message .= wp_sprintf( _n(
2116
- 'Jetpack contains the most recent version of the old %l plugin.',
2117
- 'Jetpack contains the most recent versions of the old %l plugins.',
2118
- count( $deactivated_titles ),
2119
- 'jetpack'
2120
- ), $deactivated_titles );
2121
-
2122
- $this->message .= "<br />\n";
2123
-
2124
- $this->message .= _n(
2125
- 'The old version has been deactivated and can be removed from your site.',
2126
- 'The old versions have been deactivated and can be removed from your site.',
2127
- count( $deactivated_titles ),
2128
- 'jetpack'
2129
- );
2130
- }
2131
- }
2132
-
2133
- $this->privacy_checks = Jetpack::state( 'privacy_checks' );
2134
-
2135
- if ( $this->message || $this->error || $this->privacy_checks ) {
2136
- add_action( 'jetpack_notices', array( $this, 'admin_notices' ) );
2137
- }
2138
-
2139
- if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
2140
- do_action( 'jetpack_module_configuration_load_' . $_GET['configure'] );
2141
- }
2142
-
2143
- add_filter( 'jetpack_short_module_description', 'wptexturize' );
2144
- }
2145
-
2146
- function admin_notices() {
2147
-
2148
- if ( $this->error ) {
2149
- ?>
2150
- <div id="message" class="jetpack-message jetpack-err">
2151
- <div class="squeezer">
2152
- <h4><?php echo wp_kses( $this->error, array( 'code' => true, 'strong' => true, 'br' => true, 'b' => true ) ); ?></h4>
2153
- <?php if ( $desc = Jetpack::state( 'error_description' ) ) : ?>
2154
- <p><?php echo esc_html( stripslashes( $desc ) ); ?></p>
2155
- <?php endif; ?>
2156
- </div>
2157
- </div>
2158
- <?php
2159
- }
2160
-
2161
- if ( $this->message ) {
2162
- ?>
2163
- <div id="message" class="jetpack-message">
2164
- <div class="squeezer">
2165
- <h4><?php echo wp_kses( $this->message, array( 'strong' => array(), 'a' => array( 'href' => true ), 'br' => true ) ); ?></h4>
2166
- </div>
2167
- </div>
2168
- <?php
2169
-
2170
- }
2171
-
2172
- if ( $this->privacy_checks ) :
2173
- $module_names = $module_slugs = array();
2174
-
2175
- $privacy_checks = explode( ',', $this->privacy_checks );
2176
- foreach ( $privacy_checks as $module_slug ) {
2177
- $module = Jetpack::get_module( $module_slug );
2178
- if ( !$module ) {
2179
- continue;
2180
- }
2181
-
2182
- $module_slugs[] = $module_slug;
2183
- $module_names[] = "<strong>{$module['name']}</strong>";
2184
- }
2185
-
2186
- $module_slugs = join( ',', $module_slugs );
2187
- ?>
2188
- <div id="message" class="jetpack-message jetpack-err">
2189
- <div class="squeezer">
2190
- <h4><strong><?php esc_html_e( 'Is this site private?', 'jetpack' ); ?></strong></h4><br />
2191
- <p><?php
2192
- echo wp_kses( wptexturize( wp_sprintf(
2193
- _nx(
2194
- "Like your site's RSS feeds, %l allows access to your posts and other content to third parties.",
2195
- "Like your site's RSS feeds, %l allow access to your posts and other content to third parties.",
2196
- count( $privacy_checks ),
2197
- '%l = list of Jetpack module/feature names',
2198
- 'jetpack'
2199
- ),
2200
- $module_names
2201
- ) ), array( 'strong' => true ) );
2202
-
2203
- echo "\n<br />\n";
2204
-
2205
- echo wp_kses( sprintf(
2206
- _nx(
2207
- 'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating this feature</a>.',
2208
- 'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating these features</a>.',
2209
- count( $privacy_checks ),
2210
- '%1$s = deactivation URL, %2$s = "Deactivate {list of Jetpack module/feature names}',
2211
- 'jetpack'
2212
- ),
2213
- wp_nonce_url(
2214
- Jetpack::admin_url( array(
2215
- 'action' => 'deactivate',
2216
- 'module' => urlencode( $module_slugs ),
2217
- ) ),
2218
- "jetpack_deactivate-$module_slugs"
2219
- ),
2220
- esc_attr( wp_kses( wp_sprintf( _x( 'Deactivate %l', '%l = list of Jetpack module/feature names', 'jetpack' ), $module_names ), array() ) )
2221
- ), array( 'a' => array( 'href' => true, 'title' => true ) ) );
2222
- ?></p>
2223
- </div>
2224
- </div>
2225
- <?php
2226
- endif;
2227
- }
2228
-
2229
- /**
2230
- * Record a stat for later output
2231
- */
2232
- function stat( $group, $detail ) {
2233
- if ( !isset( $this->stats[ $group ] ) )
2234
- $this->stats[ $group ] = array();
2235
- $this->stats[ $group ][] = $detail;
2236
- }
2237
-
2238
- /**
2239
- * Load stats pixels. $group is auto-prefixed with "jetpack-"
2240
- */
2241
- function do_stats() {
2242
- if ( is_array( $this->stats ) && count( $this->stats ) ) {
2243
- foreach ( $this->stats as $group => $stats ) {
2244
- if ( is_array( $stats ) && count( $stats ) )
2245
- echo '<img src="' . ( is_ssl() ? 'https' : 'http' ) . '://stats.wordpress.com/g.gif?v=wpcom2&x_jetpack-' . esc_attr( $group ) . '=' . esc_attr( implode( ',', $stats ) ) . '&rand=' . md5( mt_rand( 0, 999 ) . time() ) . '" width="1" height="1" style="display:none;" />';
2246
- }
2247
- }
2248
- }
2249
-
2250
- function translate_current_user_to_role() {
2251
- foreach ( $this->capability_translations as $role => $cap ) {
2252
- if ( current_user_can( $role ) || current_user_can( $cap ) ) {
2253
- return $role;
2254
- }
2255
- }
2256
-
2257
- return false;
2258
- }
2259
-
2260
- function translate_role_to_cap( $role ) {
2261
- if ( !isset( $this->capability_translations[$role] ) ) {
2262
- return false;
2263
- }
2264
-
2265
- return $this->capability_translations[$role];
2266
- }
2267
-
2268
- function sign_role( $role ) {
2269
- if ( !$user_id = (int) get_current_user_id() ) {
2270
- return false;
2271
- }
2272
-
2273
- $token = Jetpack_Data::get_access_token();
2274
- if ( !$token || is_wp_error( $token ) ) {
2275
- return false;
2276
- }
2277
-
2278
- return $role . ':' . hash_hmac( 'md5', "{$role}|{$user_id}", $token->secret );
2279
- }
2280
-
2281
- function build_connect_url( $raw = false, $redirect = false ) {
2282
- if ( !Jetpack::get_option( 'blog_token' ) ) {
2283
- $url = wp_nonce_url( add_query_arg( 'action', 'register', menu_page_url( 'jetpack', false ) ), 'jetpack-register' );
2284
- } else {
2285
- $role = $this->translate_current_user_to_role();
2286
- $signed_role = $this->sign_role( $role );
2287
-
2288
- $user = wp_get_current_user();
2289
-
2290
- $redirect = $redirect ? esc_url_raw( $redirect ) : '';
2291
-
2292
- $args = urlencode_deep( array(
2293
- 'response_type' => 'code',
2294
- 'client_id' => Jetpack::get_option( 'id' ),
2295
- 'redirect_uri' => add_query_arg( array(
2296
- 'action' => 'authorize',
2297
- '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
2298
- 'redirect' => $redirect ? urlencode( $redirect ) : false,
2299
- ), menu_page_url( 'jetpack', false ) ),
2300
- 'state' => $user->ID,
2301
- 'scope' => $signed_role,
2302
- 'user_email' => $user->user_email,
2303
- 'user_login' => $user->user_login,
2304
- 'is_active' => Jetpack::is_active(),
2305
- 'jp_version' => JETPACK__VERSION,
2306
- ) );
2307
-
2308
- $url = add_query_arg( $args, Jetpack::api_url( 'authorize' ) );
2309
- }
2310
-
2311
- return $raw ? $url : esc_url( $url );
2312
- }
2313
-
2314
- public static function admin_url( $args = null ) {
2315
- $url = admin_url( 'admin.php?page=jetpack' );
2316
- if ( is_array( $args ) )
2317
- $url = add_query_arg( $args, $url );
2318
- return $url;
2319
- }
2320
-
2321
- function dismiss_jetpack_notice() {
2322
- if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] && ! is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
2323
- require_once ABSPATH . 'wp-admin/includes/plugin.php';
2324
-
2325
- deactivate_plugins( plugin_basename( __FILE__ ), false, false );
2326
-
2327
- wp_safe_redirect( admin_url() . 'plugins.php?deactivate=true&plugin_status=all&paged=1&s=' );
2328
- exit;
2329
- }
2330
- }
2331
-
2332
- function admin_page() {
2333
- global $current_user;
2334
-
2335
- $role = $this->translate_current_user_to_role();
2336
- $is_connected = Jetpack::is_active();
2337
- $user_token = Jetpack_Data::get_access_token($current_user->ID);
2338
- $is_user_connected = $user_token && !is_wp_error($user_token);
2339
- $is_master_user = $current_user->ID == Jetpack::get_option( 'master_user' );
2340
- $module = false;
2341
- ?>
2342
- <div class="wrap" id="jetpack-settings">
2343
-
2344
- <h2 style="display: none"></h2> <!-- For WP JS message relocation -->
2345
-
2346
- <div id="jp-header"<?php if ( $is_connected ) : ?> class="small"<?php endif; ?>>
2347
- <div id="jp-clouds">
2348
- <?php if ( $is_connected ) : ?>
2349
- <div id="jp-disconnectors">
2350
- <?php if ( current_user_can( 'manage_options' ) ) : ?>
2351
- <div id="jp-disconnect" class="jp-disconnect">
2352
- <a href="<?php echo wp_nonce_url( Jetpack::admin_url( array( 'action' => 'disconnect' ) ), 'jetpack-disconnect' ); ?>"><div class="deftext"><?php _e( 'Connected to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Disconnect from WordPress.com', 'jetpack' ) ?></div></a>
2353
- </div>
2354
- <?php endif; ?>
2355
- <?php if ( $is_user_connected && !$is_master_user ) : ?>
2356
- <div id="jp-unlink" class="jp-disconnect">
2357
- <a href="<?php echo wp_nonce_url( Jetpack::admin_url( array( 'action' => 'unlink' ) ), 'jetpack-unlink' ); ?>"><div class="deftext"><?php _e( 'User linked to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Unlink user from WordPress.com', 'jetpack' ) ?></div></a>
2358
- </div>
2359
- <?php endif; ?>
2360
- </div>
2361
- <?php endif; ?>
2362
- <h3><?php _e( 'Jetpack by WordPress.com', 'jetpack' ) ?></h3>
2363
- <?php if ( !$is_connected ) : ?>
2364
- <div id="jp-notice">
2365
- <p><?php _e( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ); ?></p>
2366
- </div>
2367
- <?php endif; ?>
2368
- </div>
2369
- </div>
2370
-
2371
- <?php if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] ) : ?>
2372
- <div id="message" class="error">
2373
- <p><?php _e( 'Jetpack is network activated and notices can not be dismissed.', 'jetpack' ); ?></p>
2374
- </div>
2375
- <?php endif; ?>
2376
-
2377
- <?php do_action( 'jetpack_notices' ) ?>
2378
-
2379
- <?php
2380
- // If the connection has not been made then show the marketing text.
2381
- if ( ! Jetpack::is_development_mode() ) :
2382
- ?>
2383
- <?php if ( ! $is_connected ) : ?>
2384
-
2385
- <div id="message" class="updated jetpack-message jp-connect">
2386
- <div id="jp-dismiss" class="jetpack-close-button-container">
2387
- <a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice.', 'jetpack' ); ?></a>
2388
- </div>
2389
- <div class="jetpack-wrap-container">
2390
- <div class="jetpack-text-container">
2391
- <h4>
2392
- <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to connect your website to WordPress.com using the button to the right. Once you&#8217;ve made the connection you&#8217;ll activate all the delightful features below.", 'jetpack' ) ?></p>
2393
- </h4>
2394
- </div>
2395
- <div class="jetpack-install-container">
2396
- <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
2397
- </div>
2398
- </div>
2399
- </div>
2400
-
2401
- <?php elseif ( ! $is_user_connected ) : ?>
2402
-
2403
- <div id="message" class="updated jetpack-message jp-connect">
2404
- <div class="jetpack-wrap-container">
2405
- <div class="jetpack-text-container">
2406
- <h4>
2407
- <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to link your account here to your WordPress.com account using the button to the right.", 'jetpack' ) ?></p>
2408
- </h4>
2409
- </div>
2410
- <div class="jetpack-install-container">
2411
- <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Link account with WordPress.com', 'jetpack' ); ?></a></p>
2412
- </div>
2413
- </div>
2414
- </div>
2415
-
2416
- <?php else /* blog and user are connected */ : ?>
2417
- <?php /* TODO: if not master user, show user disconnect button? */ ?>
2418
- <?php endif; ?>
2419
- <?php endif; // ! Jetpack::is_development_mode() ?>
2420
-
2421
- <?php
2422
- // If we select the configure option for a module, show the configuration screen.
2423
- if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) :
2424
- $this->admin_screen_configure_module( $_GET['configure'] );
2425
-
2426
- // List all the available modules.
2427
- else :
2428
- $this->admin_screen_list_modules();
2429
- ?>
2430
-
2431
- <div id="survey" class="jp-survey">
2432
- <div class="jp-survey-container">
2433
- <div class="jp-survey-text">
2434
- <h4><?php _e( 'Have feedback on Jetpack?', 'jetpack' ); ?></h4>
2435
- <br />
2436
- <?php _e( 'Answer a short survey to let us know how we&#8217;re doing and what to add in the future.', 'jetpack' ); ?>
2437
- </div>
2438
- <div class="jp-survey-button-container">
2439
- <p class="submit"><?php printf( '<a id="jp-survey-button" class="button-primary" target="_blank" href="%1$s">%2$s</a>', 'http://jetpack.me/survey/?rel=' . JETPACK__VERSION, __( 'Take Survey', 'jetpack' ) ); ?></p>
2440
- </div>
2441
- </div>
2442
- </div>
2443
-
2444
- <?php if ( $is_connected && $this->current_user_is_connection_owner() ) : ?>
2445
- <p id="news-sub"><?php _e( 'Checking email updates status&hellip;', 'jetpack' ); ?></p>
2446
- <script type="text/javascript">
2447
- jQuery(document).ready(function($){
2448
- $.get( ajaxurl, { action: 'jetpack-check-news-subscription', rand: jQuery.now().toString() + Math.random().toString() }, function( data ) {
2449
- if ( 'subscribed' == data ) {
2450
- $( '#news-sub' ).html( '<?php printf(
2451
- esc_js( _x( 'You are currently subscribed to email updates. %s', '%s = Unsubscribe link', 'jetpack' ) ),
2452
- '<a href="#" class="jp-news-link button">' . esc_js( __( 'Unsubscribe', 'jetpack' ) ) . '</a>'
2453
- ); ?>' );
2454
- } else {
2455
- $( '#news-sub' ).html( '<?php printf(
2456
- esc_js( _x( 'Want to receive updates about Jetpack by email? %s', '%s = Subscribe link', 'jetpack' ) ),
2457
- '<a href="#" class="jp-news-link button-primary">' . esc_js( __( 'Subscribe', 'jetpack' ) ) . '</a>'
2458
- ); ?>' );
2459
- }
2460
- $( '.jp-news-link' ).click( function() {
2461
- $( '#news-sub' ).append( ' <img src="<?php echo esc_js( esc_url( admin_url( 'images/loading.gif' ) ) ); ?>" align="absmiddle" id="jp-news-loading" />' );
2462
- $.get( ajaxurl, { action: 'jetpack-subscribe-to-news', rand: jQuery.now().toString() + Math.random().toString() }, function( data ) {
2463
- if ( 'subscribed' == data ) {
2464
- $( '#news-sub' ).text( '<?php echo esc_js( __( 'You have been subscribed to receive email updates.', 'jetpack' ) ); ?>' );
2465
- } else {
2466
- $( '#news-sub' ).text( '<?php echo esc_js( __( 'You will no longer receive email updates about Jetpack.', 'jetpack' ) ); ?>' );
2467
- }
2468
- $( '#jp-news-loading' ).remove();
2469
- } );
2470
- return false;
2471
- } );
2472
- } );
2473
- } );
2474
- </script>
2475
- <?php endif; ?>
2476
- <?php endif; ?>
2477
-
2478
- <div id="jp-footer">
2479
- <p class="automattic"><?php _e( 'An <span>Automattic</span> Airline', 'jetpack' ) ?></p>
2480
- <p class="small">
2481
- <a href="http://jetpack.me/" target="_blank">Jetpack <?php echo esc_html( JETPACK__VERSION ); ?></a> |
2482
- <a href="http://automattic.com/privacy/" target="_blank"><?php _e( 'Privacy Policy', 'jetpack' ); ?></a> |
2483
- <a href="http://wordpress.com/tos/" target="_blank"><?php _e( 'Terms of Service', 'jetpack' ); ?></a> |
2484
- <?php if ( current_user_can( 'manage_options' ) ) : ?>
2485
- <a href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-ajax.php?action=jetpack_debug' ), 'jetpack_debug' ) ); ?>" id="jp-debug"><?php _e( 'Debug', 'jetpack' ); ?></a> |
2486
- <?php endif; ?>
2487
- <a href="http://jetpack.me/support/" target="_blank"><?php _e( 'Support', 'jetpack' ); ?></a>
2488
- </p>
2489
- </div>
2490
-
2491
- <div id="jetpack-configuration" style="display:none;">
2492
- <p><img width="16" src="<?php echo esc_url( plugins_url( '_inc/images/wpspin_light-2x.gif', __FILE__ ) ); ?>" alt="Loading ..." /></p>
2493
- </div>
2494
- </div>
2495
- <?php
2496
- }
2497
-
2498
- function ajax_debug() {
2499
- nocache_headers();
2500
-
2501
- check_ajax_referer( 'jetpack_debug' );
2502
-
2503
- if ( !current_user_can( 'manage_options' ) ) {
2504
- die( '-1' );
2505
- }
2506
- ?>
2507
- <p><?php esc_html_e( 'This is sensitive information. Please do not post your BLOG_TOKEN or USER_TOKEN publicly; they are like passwords.', 'jetpack' ); ?></p>
2508
- <ul>
2509
- <?php
2510
- // Extract the current_user's token
2511
- $user_id = get_current_user_id();
2512
- $user_tokens = Jetpack::get_option( 'user_tokens' );
2513
- if ( is_array( $user_tokens ) && array_key_exists( $user_id, $user_tokens ) ) {
2514
- $user_token = $user_tokens[$user_id];
2515
- } else {
2516
- $user_token = '[this user has no token]';
2517
- }
2518
- unset( $user_tokens );
2519
-
2520
- foreach ( array(
2521
- 'CLIENT_ID' => 'id',
2522
- 'BLOG_TOKEN' => 'blog_token',
2523
- 'MASTER_USER' => 'master_user',
2524
- 'CERT' => 'fallback_no_verify_ssl_certs',
2525
- 'TIME_DIFF' => 'time_diff',
2526
- 'VERSION' => 'version',
2527
- 'OLD_VERSION' => 'old_version',
2528
- 'PUBLIC' => 'public',
2529
- ) as $label => $option_name ) :
2530
- ?>
2531
- <li><?php echo esc_html( $label ); ?>: <code><?php echo esc_html( Jetpack::get_option( $option_name ) ); ?></code></li>
2532
- <?php endforeach; ?>
2533
- <li>USER_ID: <code><?php echo esc_html( $user_id ); ?></code></li>
2534
- <li>USER_TOKEN: <code><?php echo esc_html( $user_token ); ?></code></li>
2535
- <li>PHP_VERSION: <code><?php echo esc_html( PHP_VERSION ); ?></code></li>
2536
- <li>WORDPRESS_VERSION: <code><?php echo esc_html( $GLOBALS['wp_version'] ); ?></code></li>
2537
- </ul>
2538
- <?php
2539
- exit;
2540
- }
2541
-
2542
- function admin_screen_configure_module( $module_id ) {
2543
- if ( !in_array( $module_id, Jetpack::get_active_modules() ) || !current_user_can( 'manage_options' ) )
2544
- return false; ?>
2545
-
2546
- <div id="jp-settings-screen" style="position: relative">
2547
- <h3>
2548
- <?php
2549
- $module = Jetpack::get_module( $module_id );
2550
- echo '<a href="' . menu_page_url( 'jetpack', false ) . '">' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</a> &rarr; ';
2551
- printf( __( 'Configure %s', 'jetpack' ), $module['name'] );
2552
- ?>
2553
- </h3>
2554
-
2555
- <?php do_action( 'jetpack_module_configuration_screen_' . $module_id ); ?>
2556
- </div><?php
2557
- }
2558
-
2559
- public static function sort_modules( $a, $b ) {
2560
- if ( $a['sort'] == $b['sort'] )
2561
- return 0;
2562
-
2563
- return ( $a['sort'] < $b['sort'] ) ? -1 : 1;
2564
- }
2565
-
2566
- function admin_screen_list_modules() {
2567
- require_once dirname( __FILE__ ) . '/modules/module-info.php';
2568
- $jetpack_connected = true;
2569
- if ( !Jetpack::is_active() )
2570
- $jetpack_connected = false;
2571
-
2572
- ?>
2573
- <div class="module-container">
2574
- <?php
2575
-
2576
- $avail_raw = Jetpack::get_available_modules();
2577
- $available = array();
2578
- $active = Jetpack::get_active_modules();
2579
- $counter = 0;
2580
-
2581
- foreach ( (array) $avail_raw as $module ) {
2582
- if ( $plugin = Jetpack::get_module( $module ) ) {
2583
- $plugin['module'] = $module;
2584
- $available[] = $plugin;
2585
- }
2586
- }
2587
- unset( $avail_raw );
2588
- usort( $available, array( 'Jetpack', 'sort_modules' ) );
2589
- $jetpack_version = Jetpack::get_option( 'version' );
2590
- if ( $jetpack_version ) {
2591
- list( $jetpack_version, $jetpack_version_time ) = explode( ':', $jetpack_version );
2592
- } else {
2593
- $jetpack_version = 0;
2594
- $jetpack_version_time = 0;
2595
- }
2596
-
2597
- $jetpack_old_version = Jetpack::get_option( 'old_version' );
2598
- if ( $jetpack_old_version ) {
2599
- list( $jetpack_old_version ) = explode( ':', $jetpack_old_version );
2600
- } else {
2601
- $jetpack_old_version = 0;
2602
- }
2603
- $now = time();
2604
-
2605
- foreach ( (array) $available as $module_data ) {
2606
- $module = $module_data['module'];
2607
- $activated = in_array( $module, $active );
2608
- if ( $activated ) {
2609
- $css = 'active';
2610
- $toggle = __( 'Deactivate', 'jetpack' );
2611
- $toggle_url = wp_nonce_url(
2612
- Jetpack::admin_url( array(
2613
- 'action' => 'deactivate',
2614
- 'module' => $module
2615
- ) ),
2616
- "jetpack_deactivate-$module"
2617
- );
2618
- } else {
2619
- $css = 'inactive';
2620
- $toggle = __( 'Activate', 'jetpack' );
2621
- $toggle_url = wp_nonce_url(
2622
- Jetpack::admin_url( array(
2623
- 'action' => 'activate',
2624
- 'module' => $module
2625
- ) ),
2626
- "jetpack_activate-$module"
2627
- );
2628
- }
2629
-
2630
- if ( $counter % 4 == 0 ) {
2631
- $classes = $css . ' jetpack-newline';
2632
- $counter = 0;
2633
- } else {
2634
- $classes = $css;
2635
- }
2636
-
2637
- $free_text = esc_html( $module_data['free'] ? __( 'Free', 'jetpack' ) : __( 'Purchase', 'jetpack' ) );
2638
- $free_text = apply_filters( 'jetpack_module_free_text_' . $module, $free_text );
2639
- $badge_text = $free_text;
2640
-
2641
- if ( ( ! $jetpack_connected && ! Jetpack::is_development_mode() ) ) {
2642
- $classes = 'x disabled';
2643
- } else if ( $jetpack_version_time + 604800 > $now ) { // 1 week
2644
- if ( version_compare( $module_data['introduced'], $jetpack_old_version, '>' ) ) {
2645
- $badge_text = esc_html__( 'New', 'jetpack' );
2646
- $classes .= ' jetpack-new-module';
2647
- } elseif ( isset( $module_data['changed'] ) && version_compare( $module_data['changed'], $jetpack_old_version, '>' ) ) {
2648
- $badge_text = esc_html__( 'Updated', 'jetpack' );
2649
- $classes .= ' jetpack-updated-module';
2650
- } else {
2651
- $badge_text = $free_text;
2652
- }
2653
- }
2654
-
2655
- ?>
2656
- <div class="jetpack-module jetpack-<?php echo $classes; ?>" id="<?php echo $module ?>">
2657
- <h3><?php echo $module_data['name']; ?></h3>
2658
- <div class="jetpack-module-description">
2659
- <div class="module-image">
2660
- <p><span class="module-image-badge"><?php echo $badge_text; ?></span><span class="module-image-free" style="display: none"><?php echo $free_text; ?></span></p>
2661
- </div>
2662
-
2663
- <p><?php echo apply_filters( 'jetpack_short_module_description', $module_data['description'], $module ); ?></p>
2664
- </div>
2665
-
2666
- <div class="jetpack-module-actions">
2667
- <?php if ( $jetpack_connected || ( Jetpack::is_development_mode() && ! $module_data['requires_connection'] ) ) : ?>
2668
- <?php if ( !$activated && current_user_can( 'manage_options' ) && apply_filters( 'jetpack_can_activate_' . $module, true ) ) : ?>
2669
- <a href="<?php echo esc_url( $toggle_url ); ?>" class="<?php echo ( 'inactive' == $css ? ' button-primary' : ' button-secondary' ); ?>"><?php echo $toggle; ?></a>&nbsp;
2670
- <?php endif; ?>
2671
-
2672
- <?php do_action( 'jetpack_learn_more_button_' . $module ) ?>
2673
-
2674
- <?php
2675
- if ( current_user_can( 'manage_options' ) && apply_filters( 'jetpack_module_configurable_' . $module, false ) ) {
2676
- echo '<a href="' . esc_attr( Jetpack::module_configuration_url( $module ) ) . '" class="jetpack-configure-button button-secondary">' . __( 'Configure', 'jetpack' ) . '</a>';
2677
- }
2678
- ?><?php if ( $activated && $module_data['deactivate'] && current_user_can( 'manage_options' ) ) : ?><a style="display: none;" href="<?php echo esc_url( $toggle_url ); ?>" class="jetpack-deactivate-button button-secondary"><?php echo $toggle; ?></a>&nbsp;<?php endif; ?>
2679
-
2680
- <?php else : ?>
2681
- <?php do_action( 'jetpack_learn_more_button_' . $module ) ?>
2682
- <?php endif; ?>
2683
- </div>
2684
- </div>
2685
- <?php if ( 'inactive' == $css && $jetpack_connected ) : ?>
2686
- <script type="text/javascript">
2687
- jQuery( '#<?php echo esc_js( $module ); ?>' ).bind( 'click', function(e){
2688
- if ( !jQuery(e.target).hasClass('more-info-link') )
2689
- document.location.href = '<?php echo str_replace( '&amp;', '&', esc_js( esc_url( $toggle_url ) ) ); ?>';
2690
- } );
2691
- </script>
2692
- <?php endif; ?>
2693
-
2694
- <div id="jp-more-info-<?php echo esc_attr( $module ); ?>" style="display:none;">
2695
- <?php
2696
- if ( $jetpack_connected && has_action( 'jetpack_module_more_info_connected_' . $module ) )
2697
- do_action( 'jetpack_module_more_info_connected_' . $module );
2698
- else
2699
- do_action( 'jetpack_module_more_info_' . $module );
2700
- ?>
2701
- </div>
2702
-
2703
- <?php
2704
- $counter++;
2705
- }
2706
-
2707
- // Add in some "Coming soon..." placeholders to fill up the current row and one more
2708
- for ( $i = 0; $i < 4; $i++ ) { ?>
2709
- <div class="jetpack-module placeholder"<?php if ( $i > 8 - $counter ) echo ' style="display: none;"'; ?>>
2710
- <h3><?php _e( 'Coming soon&#8230;', 'jetpack' ) ?></h3>
2711
- </div>
2712
- <?php
2713
- }
2714
-
2715
- echo '</div><!-- .module-container -->';
2716
- }
2717
-
2718
- function check_news_subscription() {
2719
- if ( !$this->current_user_is_connection_owner() ) {
2720
- exit;
2721
- }
2722
-
2723
- Jetpack::load_xml_rpc_client();
2724
- $xml = new Jetpack_IXR_Client( array(
2725
- 'user_id' => JETPACK_MASTER_USER,
2726
- ) );
2727
- $xml->query( 'jetpack.checkNewsSubscription' );
2728
- if ( $xml->isError() ) {
2729
- printf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() );
2730
- } else {
2731
- print_r( $xml->getResponse() );
2732
- }
2733
- exit;
2734
- }
2735
-
2736
- function subscribe_to_news() {
2737
- if ( !$this->current_user_is_connection_owner() ) {
2738
- exit;
2739
- }
2740
-
2741
- Jetpack::load_xml_rpc_client();
2742
- $xml = new Jetpack_IXR_Client( array(
2743
- 'user_id' => JETPACK_MASTER_USER,
2744
- ) );
2745
- $xml->query( 'jetpack.subscribeToNews' );
2746
- if ( $xml->isError() ) {
2747
- printf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() );
2748
- } else {
2749
- print_r( $xml->getResponse() );
2750
- }
2751
- exit;
2752
- }
2753
-
2754
- /* Client API */
2755
-
2756
- /**
2757
- * Returns the requested Jetpack API URL
2758
- *
2759
- * @return string
2760
- */
2761
- public static function api_url( $relative_url ) {
2762
- return trailingslashit( JETPACK__API_BASE . $relative_url ) . JETPACK__API_VERSION . '/';
2763
- }
2764
-
2765
- /**
2766
- * Some hosts disable the OpenSSL extension and so cannot make outgoing HTTPS requsets
2767
- */
2768
- public static function fix_url_for_bad_hosts( $url, &$args ) {
2769
- if ( 0 !== strpos( $url, 'https://' ) ) {
2770
- return $url;
2771
- }
2772
-
2773
- switch ( JETPACK_CLIENT__HTTPS ) {
2774
- case 'ALWAYS' :
2775
- return $url;
2776
- case 'NEVER' :
2777
- return substr_replace( $url, '', 4, 1 );
2778
- // default : case 'AUTO' :
2779
- }
2780
-
2781
- $jetpack = Jetpack::init();
2782
-
2783
- // Yay! Your host is good!
2784
- if ( wp_http_supports( array( 'ssl' => true ) ) ) {
2785
- return $url;
2786
- }
2787
-
2788
- // Boo! Your host is bad and makes Jetpack cry!
2789
- return substr_replace( $url, '', 4, 1 );
2790
- }
2791
-
2792
- /**
2793
- * Returns the Jetpack XML-RPC API
2794
- *
2795
- * @return string
2796
- */
2797
- public static function xmlrpc_api_url() {
2798
- $base = preg_replace( '#(https?://[^?/]+)(/?.*)?$#', '\\1', JETPACK__API_BASE );
2799
- return untrailingslashit( $base ) . '/xmlrpc.php';
2800
- }
2801
-
2802
- /**
2803
- * @return bool|WP_Error
2804
- */
2805
- public static function register() {
2806
- Jetpack::update_option( 'register', wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 ) );
2807
-
2808
- @list( $secret_1, $secret_2, $secret_eol ) = explode( ':', Jetpack::get_option( 'register' ) );
2809
- if ( empty( $secret_1 ) || empty( $secret_2 ) || empty( $secret_eol ) || $secret_eol < time() )
2810
- return new Jetpack_Error( 'missing_secrets' );
2811
-
2812
- $timeout = (int) ini_get( 'max_execution_time' );
2813
- if ( !$timeout )
2814
- $timeout = 30;
2815
- $timeout = intval( $timeout / 2 );
2816
-
2817
- $gmt_offset = get_option( 'gmt_offset' );
2818
- if ( !$gmt_offset ) {
2819
- $gmt_offset = 0;
2820
- }
2821
-
2822
- $stats_options = get_option( 'stats_options' );
2823
- $stats_id = isset($stats_options['blog_id']) ? $stats_options['blog_id'] : null;
2824
-
2825
- $args = array(
2826
- 'method' => 'POST',
2827
- 'body' => array(
2828
- 'siteurl' => site_url(),
2829
- 'home' => home_url(),
2830
- 'gmt_offset' => $gmt_offset,
2831
- 'timezone_string' => (string) get_option( 'timezone_string' ),
2832
- 'site_name' => (string) get_option( 'blogname' ),
2833
- 'secret_1' => $secret_1,
2834
- 'secret_2' => $secret_2,
2835
- 'site_lang' => get_locale(),
2836
- 'timeout' => $timeout,
2837
- 'stats_id' => $stats_id,
2838
- ),
2839
- 'headers' => array(
2840
- 'Accept' => 'application/json',
2841
- ),
2842
- 'timeout' => $timeout,
2843
- );
2844
- $response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'register' ), $args ), $args, true );
2845
-
2846
- if ( is_wp_error( $response ) ) {
2847
- return new Jetpack_Error( 'register_http_request_failed', $response->get_error_message() );
2848
- }
2849
-
2850
- $code = wp_remote_retrieve_response_code( $response );
2851
- $entity = wp_remote_retrieve_body( $response );
2852
-
2853
- if ( $entity )
2854
- $json = json_decode( $entity );
2855
- else
2856
- $json = false;
2857
-
2858
- $code_type = intval( $code / 100 );
2859
- if ( 5 == $code_type ) {
2860
- return new Jetpack_Error( 'wpcom_5??', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
2861
- } elseif ( 408 == $code ) {
2862
- return new Jetpack_Error( 'wpcom_408', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
2863
- } elseif ( !empty( $json->error ) ) {
2864
- $error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
2865
- return new Jetpack_Error( (string) $json->error, $error_description, $code );
2866
- } elseif ( 200 != $code ) {
2867
- return new Jetpack_Error( 'wpcom_bad_response', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
2868
- }
2869
-
2870
- // Jetpack ID error block
2871
- if ( empty( $json->jetpack_id ) ) {
2872
- return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is empty. Do not publicly post this error message! %s', 'jetpack' ), $entity ), $entity );
2873
- } elseif ( ! is_scalar( $json->jetpack_id ) ) {
2874
- return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is not a scalar. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity );
2875
- } elseif ( preg_match( '/[^0-9]/', $json->jetpack_id ) ) {
2876
- return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID begins with a numeral. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity);
2877
- }
2878
-
2879
- if ( empty( $json->jetpack_secret ) || !is_string( $json->jetpack_secret ) )
2880
- return new Jetpack_Error( 'jetpack_secret', '', $code );
2881
-
2882
- if ( isset( $json->jetpack_public ) ) {
2883
- $jetpack_public = (int) $json->jetpack_public;
2884
- } else {
2885
- $jetpack_public = false;
2886
- }
2887
-
2888
- Jetpack::update_options( array(
2889
- 'id' => (int) $json->jetpack_id,
2890
- 'blog_token' => (string) $json->jetpack_secret,
2891
- 'public' => $jetpack_public,
2892
- ) );
2893
-
2894
- return true;
2895
- }
2896
-
2897
-
2898
- /* Client Server API */
2899
-
2900
- /**
2901
- * Loads the Jetpack XML-RPC client
2902
- */
2903
- public static function load_xml_rpc_client() {
2904
- require_once ABSPATH . WPINC . '/class-IXR.php';
2905
- require_once dirname( __FILE__ ) . '/class.jetpack-ixr-client.php';
2906
- }
2907
-
2908
- function verify_xml_rpc_signature() {
2909
- if ( $this->xmlrpc_verification ) {
2910
- return $this->xmlrpc_verification;
2911
- }
2912
-
2913
- // It's not for us
2914
- if ( !isset( $_GET['token'] ) || empty( $_GET['signature'] ) ) {
2915
- return false;
2916
- }
2917
-
2918
- @list( $token_key, $version, $user_id ) = explode( ':', $_GET['token'] );
2919
- if (
2920
- empty( $token_key )
2921
- ||
2922
- empty( $version ) || strval( JETPACK__API_VERSION ) !== $version
2923
- ) {
2924
- return false;
2925
- }
2926
-
2927
- if ( '0' === $user_id ) {
2928
- $token_type = 'blog';
2929
- $user_id = 0;
2930
- } else {
2931
- $token_type = 'user';
2932
- if ( empty( $user_id ) || ! ctype_digit( $user_id ) ) {
2933
- return false;
2934
- }
2935
- $user_id = (int) $user_id;
2936
-
2937
- $user = new WP_User( $user_id );
2938
- if ( ! $user || ! $user->exists() ) {
2939
- return false;
2940
- }
2941
- }
2942
-
2943
- $token = Jetpack_Data::get_access_token( $user_id );
2944
- if ( !$token ) {
2945
- return false;
2946
- }
2947
-
2948
- if ( 0 !== strpos( $token->secret, "$token_key." ) ) {
2949
- return false;
2950
- }
2951
-
2952
- require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
2953
-
2954
- $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
2955
- if ( isset( $_POST['_jetpack_is_multipart'] ) ) {
2956
- $post_data = $_POST;
2957
- $file_hashes = array();
2958
- foreach ( $post_data as $post_data_key => $post_data_value ) {
2959
- if ( 0 !== strpos( $post_data_key, '_jetpack_file_hmac_' ) ) {
2960
- continue;
2961
- }
2962
- $post_data_key = substr( $post_data_key, strlen( '_jetpack_file_hmac_' ) );
2963
- $file_hashes[$post_data_key] = $post_data_value;
2964
- }
2965
-
2966
- foreach ( $file_hashes as $post_data_key => $post_data_value ) {
2967
- unset( $post_data["_jetpack_file_hmac_{$post_data_key}"] );
2968
- $post_data[$post_data_key] = $post_data_value;
2969
- }
2970
-
2971
- ksort( $post_data );
2972
-
2973
- $body = http_build_query( stripslashes_deep( $post_data ) );
2974
- } elseif ( is_null( $this->HTTP_RAW_POST_DATA ) ) {
2975
- $body = file_get_contents( 'php://input' );
2976
- } else {
2977
- $body = null;
2978
- }
2979
- $signature = $jetpack_signature->sign_current_request( array(
2980
- 'body' => is_null( $body ) ? $this->HTTP_RAW_POST_DATA : $body
2981
- ) );
2982
-
2983
- if ( !$signature ) {
2984
- return false;
2985
- } else if ( is_wp_error( $signature ) ) {
2986
- return $signature;
2987
- } else if ( $signature !== $_GET['signature'] ) {
2988
- return false;
2989
- }
2990
-
2991
- $timestamp = (int) $_GET['timestamp'];
2992
- $nonce = stripslashes( (string) $_GET['nonce'] );
2993
-
2994
- if ( !$this->add_nonce( $timestamp, $nonce ) ) {
2995
- return false;
2996
- }
2997
-
2998
- $this->xmlrpc_verification = array(
2999
- 'type' => $token_type,
3000
- 'user_id' => $token->external_user_id,
3001
- );
3002
-
3003
- return $this->xmlrpc_verification;
3004
- }
3005
-
3006
- /**
3007
- * Authenticates XML-RPC and other requests from the Jetpack Server
3008
- */
3009
- function authenticate_jetpack( $user, $username, $password ) {
3010
- if ( is_a( $user, 'WP_User' ) ) {
3011
- return $user;
3012
- }
3013
-
3014
- $token_details = $this->verify_xml_rpc_signature();
3015
-
3016
- if ( ! $token_details || is_wp_error( $token_details ) ) {
3017
- return $user;
3018
- }
3019
-
3020
- if ( 'user' !== $token_details['type'] ) {
3021
- return $user;
3022
- }
3023
-
3024
- if ( ! $token_details['user_id'] ) {
3025
- return $user;
3026
- }
3027
-
3028
- nocache_headers();
3029
-
3030
- return new WP_User( $token_details['user_id'] );
3031
- }
3032
-
3033
- function add_nonce( $timestamp, $nonce ) {
3034
- global $wpdb;
3035
- static $nonces_used_this_request = array();
3036
-
3037
- if ( isset( $nonces_used_this_request["$timestamp:$nonce"] ) ) {
3038
- return $nonces_used_this_request["$timestamp:$nonce"];
3039
- }
3040
-
3041
- // This should always have gone through Jetpack_Signature::sign_request() first to check $timestamp an $nonce
3042
- $timestamp = (int) $timestamp;
3043
- $nonce = $wpdb->escape( $nonce );
3044
-
3045
- // Raw query so we can avoid races: add_option will also update
3046
- $show_errors = $wpdb->show_errors( false );
3047
- $return = $wpdb->query( $wpdb->prepare(
3048
- "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s)",
3049
- "jetpack_nonce_{$timestamp}_{$nonce}",
3050
- time(),
3051
- 'no'
3052
- ) );
3053
- $wpdb->show_errors( $show_errors );
3054
-
3055
- $nonces_used_this_request["$timestamp:$nonce"] = $return;
3056
-
3057
- return $return;
3058
- }
3059
-
3060
- /**
3061
- * In some setups, $HTTP_RAW_POST_DATA can be emptied during some IXR_Server paths since it is passed by reference to various methods.
3062
- * Capture it here so we can verify the signature later.
3063
- */
3064
- function xmlrpc_methods( $methods ) {
3065
- $this->HTTP_RAW_POST_DATA = $GLOBALS['HTTP_RAW_POST_DATA'];
3066
- return $methods;
3067
- }
3068
-
3069
- function xmlrpc_options( $options ) {
3070
- $options['jetpack_version'] = array(
3071
- 'desc' => __( 'Jetpack Plugin Version' , 'jetpack'),
3072
- 'readonly' => true,
3073
- 'value' => JETPACK__VERSION,
3074
- );
3075
-
3076
- $options['jetpack_client_id'] = array(
3077
- 'desc' => __( 'The Client ID/WP.com Blog ID of this site' , 'jetpack'),
3078
- 'readonly' => true,
3079
- 'value' => Jetpack::get_option( 'id' ),
3080
- );
3081
- return $options;
3082
- }
3083
-
3084
- public static function clean_nonces( $all = false ) {
3085
- global $wpdb;
3086
-
3087
- $sql = "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE %s";
3088
- $sql_args = array( like_escape( 'jetpack_nonce_' ) . '%' );
3089
-
3090
- if ( true !== $all ) {
3091
- $sql .= ' AND CAST( `option_value` AS UNSIGNED ) < %d';
3092
- $sql_args[] = time() - 3600;
3093
- }
3094
-
3095
- $sql .= ' LIMIT 100';
3096
-
3097
- $sql = $wpdb->prepare( $sql, $sql_args );
3098
-
3099
- for ( $i = 0; $i < 1000; $i++ ) {
3100
- if ( !$wpdb->query( $sql ) ) {
3101
- break;
3102
- }
3103
- }
3104
- }
3105
-
3106
- /**
3107
- * State is passed via cookies from one request to the next, but never to subsequent requests.
3108
- * SET: state( $key, $value );
3109
- * GET: $value = state( $key );
3110
- *
3111
- * @param string $key
3112
- * @param string $value
3113
- * @param bool $restate private
3114
- */
3115
- public static function state( $key = null, $value = null, $restate = false ) {
3116
- static $state = array();
3117
- static $path, $domain;
3118
- if ( !isset( $path ) ) {
3119
- require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
3120
- $admin_url = Jetpack::admin_url();
3121
- $bits = parse_url( $admin_url );
3122
-
3123
- if ( is_array( $bits ) ) {
3124
- $path = ( isset( $bits['path'] ) ) ? dirname( $bits['path'] ) : null;
3125
- $domain = ( isset( $bits['host'] ) ) ? $bits['host'] : null;
3126
- } else {
3127
- $path = $domain = null;
3128
- }
3129
- }
3130
-
3131
- // Extract state from cookies and delete cookies
3132
- if ( isset( $_COOKIE[ 'jetpackState' ] ) && is_array( $_COOKIE[ 'jetpackState' ] ) ) {
3133
- $yum = $_COOKIE[ 'jetpackState' ];
3134
- unset( $_COOKIE[ 'jetpackState' ] );
3135
- foreach ( $yum as $k => $v ) {
3136
- if ( strlen( $v ) )
3137
- $state[ $k ] = $v;
3138
- setcookie( "jetpackState[$k]", false, 0, $path, $domain );
3139
- }
3140
- }
3141
-
3142
- if ( $restate ) {
3143
- foreach ( $state as $k => $v ) {
3144
- setcookie( "jetpackState[$k]", $v, 0, $path, $domain );
3145
- }
3146
- return;
3147
- }
3148
-
3149
- // Get a state variable
3150
- if ( isset( $key ) && !isset( $value ) ) {
3151
- if ( array_key_exists( $key, $state ) )
3152
- return $state[ $key ];
3153
- return null;
3154
- }
3155
-
3156
- // Set a state variable
3157
- if ( isset ( $key ) && isset( $value ) ) {
3158
- $state[ $key ] = $value;
3159
- setcookie( "jetpackState[$key]", $value, 0, $path, $domain );
3160
- }
3161
- }
3162
-
3163
- public static function restate() {
3164
- Jetpack::state( null, null, true );
3165
- }
3166
-
3167
- public static function check_privacy( $file ) {
3168
- static $is_site_publicly_accessible = null;
3169
-
3170
- if ( is_null( $is_site_publicly_accessible ) ) {
3171
- $is_site_publicly_accessible = false;
3172
-
3173
- Jetpack::load_xml_rpc_client();
3174
- $rpc = new Jetpack_IXR_Client();
3175
-
3176
- $success = $rpc->query( 'jetpack.isSitePubliclyAccessible', home_url() );
3177
- if ( $success ) {
3178
- $response = $rpc->getResponse();
3179
- if ( $response ) {
3180
- $is_site_publicly_accessible = true;
3181
- }
3182
- }
3183
-
3184
- Jetpack::update_option( 'public', (int) $is_site_publicly_accessible );
3185
- }
3186
-
3187
- if ( $is_site_publicly_accessible ) {
3188
- return;
3189
- }
3190
-
3191
- $module_slug = self::get_module_slug( $file );
3192
-
3193
- $privacy_checks = Jetpack::state( 'privacy_checks' );
3194
- if ( !$privacy_checks ) {
3195
- $privacy_checks = $module_slug;
3196
- } else {
3197
- $privacy_checks .= ",$module_slug";
3198
- }
3199
-
3200
- Jetpack::state( 'privacy_checks', $privacy_checks );
3201
- }
3202
-
3203
- /**
3204
- * Helper method for multicall XMLRPC.
3205
- */
3206
- public static function xmlrpc_async_call() {
3207
- global $blog_id;
3208
- static $clients = array();
3209
-
3210
- $client_blog_id = is_multisite() ? $blog_id : 0;
3211
-
3212
- if ( !isset( $clients[$client_blog_id] ) ) {
3213
- Jetpack::load_xml_rpc_client();
3214
- $clients[$client_blog_id] = new Jetpack_IXR_ClientMulticall( array(
3215
- 'user_id' => JETPACK_MASTER_USER,
3216
- ) );
3217
- ignore_user_abort( true );
3218
- add_action( 'shutdown', array( 'Jetpack', 'xmlrpc_async_call' ) );
3219
- }
3220
-
3221
- $args = func_get_args();
3222
-
3223
- if ( !empty( $args[0] ) ) {
3224
- call_user_func_array( array( $clients[$client_blog_id], 'addCall' ), $args );
3225
- } elseif ( is_multisite() ) {
3226
- foreach ( $clients as $client_blog_id => $client ) {
3227
- if ( !$client_blog_id || empty( $client->calls ) ) {
3228
- continue;
3229
- }
3230
-
3231
- $switch_success = switch_to_blog( $client_blog_id, true );
3232
- if ( !$switch_success ) {
3233
- continue;
3234
- }
3235
-
3236
- flush();
3237
- $client->query();
3238
-
3239
- restore_current_blog();
3240
- }
3241
- } else {
3242
- if ( isset( $clients[0] ) && !empty( $clients[0]->calls ) ) {
3243
- flush();
3244
- $clients[0]->query();
3245
- }
3246
- }
3247
- }
3248
-
3249
- public static function staticize_subdomain( $url ) {
3250
- $host = parse_url( $url, PHP_URL_HOST );
3251
- if ( !preg_match( '/.?(?:wordpress|wp)\.com$/', $host ) ) {
3252
- return $url;
3253
- }
3254
-
3255
- if ( is_ssl() ) {
3256
- return preg_replace( '|https?://[^/]++/|', 'https://s-ssl.wordpress.com/', $url );
3257
- }
3258
-
3259
- srand( crc32( basename( $url ) ) );
3260
- $static_counter = rand( 0, 2 );
3261
- srand(); // this resets everything that relies on this, like array_rand() and shuffle()
3262
-
3263
- return preg_replace( '|://[^/]+?/|', "://s$static_counter.wp.com/", $url );
3264
- }
3265
-
3266
- /* JSON API Authorization */
3267
-
3268
- /**
3269
- * Handles the login action for Authorizing the JSON API
3270
- */
3271
- function login_form_json_api_authorization() {
3272
- $this->verify_json_api_authorization_request();
3273
-
3274
- add_action( 'wp_login', array( &$this, 'store_json_api_authorization_token' ), 10, 2 );
3275
-
3276
- add_action( 'login_message', array( &$this, 'login_message_json_api_authorization' ) );
3277
- add_action( 'login_form', array( &$this, 'preserve_action_in_login_form_for_json_api_authorization' ) );
3278
- add_filter( 'site_url', array( &$this, 'post_login_form_to_signed_url' ), 10, 3 );
3279
- }
3280
-
3281
- // Make sure the login form is POSTed to the signed URL so we can reverify the request
3282
- function post_login_form_to_signed_url( $url, $path, $scheme ) {
3283
- if ( 'wp-login.php' !== $path || 'login_post' !== $scheme ) {
3284
- return $url;
3285
- }
3286
-
3287
- return "$url?{$_SERVER['QUERY_STRING']}";
3288
- }
3289
-
3290
- // Make sure the POSTed request is handled by the same action
3291
- function preserve_action_in_login_form_for_json_api_authorization() {
3292
- echo "<input type='hidden' name='action' value='jetpack_json_api_authorization' />\n";
3293
- }
3294
-
3295
- // If someone logs in to approve API access, store the Access Code in usermeta
3296
- function store_json_api_authorization_token( $user_login, $user ) {
3297
- add_filter( 'login_redirect', array( &$this, 'add_token_to_login_redirect_json_api_authorization' ), 10, 3 );
3298
- add_filter( 'allowed_redirect_hosts', array( &$this, 'allow_wpcom_public_api_domain' ) );
3299
- $token = wp_generate_password( 32, false );
3300
- update_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], $token );
3301
- }
3302
-
3303
- // Add public-api.wordpress.com to the safe redirect whitelist - only added when someone allows API access
3304
- function allow_wpcom_public_api_domain( $domains ) {
3305
- $domains[] = 'public-api.wordpress.com';
3306
- return $domains;
3307
- }
3308
-
3309
- // Add the Access Code details to the public-api.wordpress.com redirect
3310
- function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) {
3311
- return add_query_arg( urlencode_deep( array(
3312
- 'jetpack-code' => get_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], true ),
3313
- 'jetpack-user-id' => (int) $user->ID,
3314
- 'jetpack-state' => $this->json_api_authorization_request['state'],
3315
- ) ), $redirect_to );
3316
- }
3317
-
3318
- // Verifies the request by checking the signature
3319
- function verify_json_api_authorization_request() {
3320
- require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
3321
-
3322
- $token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
3323
- if ( !$token || empty( $token->secret ) ) {
3324
- wp_die( __( 'You must connect your Jetpack plugin to WordPress.com to use this feature.' , 'jetpack') );
3325
- }
3326
-
3327
- $die_error = __( 'Someone may be trying to trick you into giving them access to your site. Or it could be you just encountered a bug :). Either way, please close this window.', 'jetpack' );
3328
-
3329
- $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
3330
- $signature = $jetpack_signature->sign_current_request( array( 'body' => null, 'method' => 'GET' ) );
3331
- if ( !$signature ) {
3332
- wp_die( $die_error );
3333
- } else if ( is_wp_error( $signature ) ) {
3334
- wp_die( $die_error );
3335
- } else if ( $signature !== $_GET['signature'] ) {
3336
- if ( is_ssl() ) {
3337
- // If we signed an HTTP request on the Jetpack Servers, but got redirected to HTTPS by the local blog, check the HTTP signature as well
3338
- $signature = $jetpack_signature->sign_current_request( array( 'scheme' => 'http', 'body' => null, 'method' => 'GET' ) );
3339
- if ( !$signature || is_wp_error( $signature ) || $signature !== $_GET['signature'] ) {
3340
- wp_die( $die_error );
3341
- }
3342
- } else {
3343
- wp_die( $die_error );
3344
- }
3345
- }
3346
-
3347
- $timestamp = (int) $_GET['timestamp'];
3348
- $nonce = stripslashes( (string) $_GET['nonce'] );
3349
-
3350
- if ( !$this->add_nonce( $timestamp, $nonce ) ) {
3351
- // De-nonce the nonce, at least for 5 minutes.
3352
- // We have to reuse this nonce at least once (used the first time when the initial request is made, used a second time when the login form is POSTed)
3353
- $old_nonce_time = get_option( "jetpack_nonce_{$timestamp}_{$nonce}" );
3354
- if ( $old_nonce_time < time() - 300 ) {
3355
- wp_die( __( 'The authorization process expired. Please go back and try again.' , 'jetpack') );
3356
- }
3357
- }
3358
-
3359
- $data = json_decode( base64_decode( stripslashes( $_GET['data'] ) ) );
3360
- $data_filters = array(
3361
- 'state' => 'opaque',
3362
- 'client_id' => 'int',
3363
- 'client_title' => 'string',
3364
- 'client_image' => 'url',
3365
- );
3366
-
3367
- foreach ( $data_filters as $key => $sanitation ) {
3368
- if ( !isset( $data->$key ) ) {
3369
- wp_die( $die_error );
3370
- }
3371
-
3372
- switch ( $sanitation ) {
3373
- case 'int' :
3374
- $this->json_api_authorization_request[$key] = (int) $data->$key;
3375
- break;
3376
- case 'opaque' :
3377
- $this->json_api_authorization_request[$key] = (string) $data->$key;
3378
- break;
3379
- case 'string' :
3380
- $this->json_api_authorization_request[$key] = wp_kses( (string) $data->$key, array() );
3381
- break;
3382
- case 'url' :
3383
- $this->json_api_authorization_request[$key] = esc_url_raw( (string) $data->$key );
3384
- break;
3385
- }
3386
- }
3387
-
3388
- if ( empty( $this->json_api_authorization_request['client_id'] ) ) {
3389
- wp_die( $die_error );
3390
- }
3391
- }
3392
-
3393
- function login_message_json_api_authorization( $message ) {
3394
- return '<p class="message">' . sprintf(
3395
- esc_html__( '%s wants to access your site&#8217;s data. Log in to authorize that access.' , 'jetpack'),
3396
- '<strong>' . esc_html( $this->json_api_authorization_request['client_title'] ) . '</strong>'
3397
- ) . '<img src="' . esc_url( $this->json_api_authorization_request['client_image'] ) . '" /></p>';
3398
- }
3399
-
3400
- /**
3401
- * Get $content_width, but with a <s>twist</s> filter.
3402
- */
3403
- public static function get_content_width() {
3404
- return apply_filters( 'jetpack_content_width', $GLOBALS['content_width'] );
3405
- }
3406
- }
3407
-
3408
- class Jetpack_Client {
3409
- /**
3410
- * Makes an authorized remote request using Jetpack_Signature
3411
- *
3412
- * @return array|WP_Error WP HTTP response on success
3413
- */
3414
- public static function remote_request( $args, $body = null ) {
3415
- $defaults = array(
3416
- 'url' => '',
3417
- 'user_id' => 0,
3418
- 'blog_id' => 0,
3419
- 'auth_location' => JETPACK_CLIENT__AUTH_LOCATION,
3420
- 'method' => 'POST',
3421
- 'timeout' => 10,
3422
- 'redirection' => 0,
3423
- );
3424
-
3425
- $args = wp_parse_args( $args, $defaults );
3426
-
3427
- $args['blog_id'] = (int) $args['blog_id'];
3428
-
3429
- if ( 'header' != $args['auth_location'] ) {
3430
- $args['auth_location'] = 'query_string';
3431
- }
3432
-
3433
- $token = Jetpack_Data::get_access_token( $args['user_id'] );
3434
- if ( !$token ) {
3435
- return new Jetpack_Error( 'missing_token' );
3436
- }
3437
-
3438
- $method = strtoupper( $args['method'] );
3439
-
3440
- $timeout = intval( $args['timeout'] );
3441
-
3442
- $redirection = $args['redirection'];
3443
-
3444
- $request = compact( 'method', 'body', 'timeout', 'redirection' );
3445
-
3446
- @list( $token_key, $secret ) = explode( '.', $token->secret );
3447
- if ( empty( $token ) || empty( $secret ) ) {
3448
- return new Jetpack_Error( 'malformed_token' );
3449
- }
3450
-
3451
- $token_key = sprintf( '%s:%d:%d', $token_key, JETPACK__API_VERSION, $token->external_user_id );
3452
-
3453
- require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
3454
-
3455
- $time_diff = (int) Jetpack::get_option( 'time_diff' );
3456
- $jetpack_signature = new Jetpack_Signature( $token->secret, $time_diff );
3457
-
3458
- $timestamp = time() + $time_diff;
3459
- $nonce = wp_generate_password( 10, false );
3460
-
3461
- // Kind of annoying. Maybe refactor Jetpack_Signature to handle body-hashing
3462
- if ( is_null( $body ) ) {
3463
- $body_hash = '';
3464
- } else {
3465
- if ( !is_string( $body ) ) {
3466
- return new Jetpack_Error( 'invalid_body', 'Body is malformed.' );
3467
- }
3468
- $body_hash = jetpack_sha1_base64( $body );
3469
- }
3470
-
3471
- $auth = array(
3472
- 'token' => $token_key,
3473
- 'timestamp' => $timestamp,
3474
- 'nonce' => $nonce,
3475
- 'body-hash' => $body_hash,
3476
- );
3477
-
3478
- if ( false !== strpos( $args['url'], 'xmlrpc.php' ) ) {
3479
- $url_args = array( 'for' => 'jetpack' );
3480
- } else {
3481
- $url_args = array();
3482
- }
3483
-
3484
- if ( 'header' != $args['auth_location'] ) {
3485
- $url_args += $auth;
3486
- }
3487
-
3488
- $url = add_query_arg( urlencode_deep( $url_args ), $args['url'] );
3489
- $url = Jetpack::fix_url_for_bad_hosts( $url, $request );
3490
-
3491
- $signature = $jetpack_signature->sign_request( $token_key, $timestamp, $nonce, $body_hash, $method, $url, $body, false );
3492
-
3493
- if ( !$signature || is_wp_error( $signature ) ) {
3494
- return $signature;
3495
- }
3496
-
3497
- // Send an Authorization header so various caches/proxies do the right thing
3498
- $auth['signature'] = $signature;
3499
- $auth['version'] = JETPACK__VERSION;
3500
- $header_pieces = array();
3501
- foreach ( $auth as $key => $value ) {
3502
- $header_pieces[] = sprintf( '%s="%s"', $key, $value );
3503
- }
3504
- $request['headers'] = array(
3505
- 'Authorization' => "X_JETPACK " . join( ' ', $header_pieces ),
3506
- );
3507
-
3508
- if ( 'header' != $args['auth_location'] ) {
3509
- $url = add_query_arg( 'signature', urlencode( $signature ), $url );
3510
- }
3511
-
3512
- return Jetpack_Client::_wp_remote_request( $url, $request );
3513
- }
3514
-
3515
- /**
3516
- * Wrapper for wp_remote_request(). Turns off SSL verification for certain SSL errors.
3517
- * This is lame, but many, many, many hosts have misconfigured SSL.
3518
- *
3519
- * When Jetpack is registered, the jetpack_fallback_no_verify_ssl_certs option is set to the current time if:
3520
- * 1. a certificate error is found AND
3521
- * 2. not verifying the certificate works around the problem.
3522
- *
3523
- * The option is checked on each request.
3524
- *
3525
- * @internal
3526
- * @todo: Better fallbacks (bundled certs?), feedback, UI, ....
3527
- * @see Jetpack::fix_url_for_bad_hosts()
3528
- *
3529
- * @return array|WP_Error WP HTTP response on success
3530
- */
3531
- public static function _wp_remote_request( $url, $args, $set_fallback = false ) {
3532
- $fallback = Jetpack::get_option( 'fallback_no_verify_ssl_certs' );
3533
- if ( false === $fallback ) {
3534
- Jetpack::update_option( 'fallback_no_verify_ssl_certs', 0 );
3535
- }
3536
-
3537
- if ( (int) $fallback ) {
3538
- // We're flagged to fallback
3539
- $args['sslverify'] = false;
3540
- }
3541
-
3542
- $response = wp_remote_request( $url, $args );
3543
-
3544
- if (
3545
- !$set_fallback // We're not allowed to set the flag on this request, so whatever happens happens
3546
- ||
3547
- isset( $args['sslverify'] ) && !$args['sslverify'] // No verification - no point in doing it again
3548
- ||
3549
- !is_wp_error( $response ) // Let it ride
3550
- ) {
3551
- Jetpack_Client::set_time_diff( $response, $set_fallback );
3552
- return $response;
3553
- }
3554
-
3555
- // At this point, we're not flagged to fallback and we are allowed to set the flag on this request.
3556
-
3557
- $message = $response->get_error_message();
3558
-
3559
- // Is it an SSL Certificate verification error?
3560
- if (
3561
- false === strpos( $message, '14090086' ) // OpenSSL SSL3 certificate error
3562
- &&
3563
- false === strpos( $message, '1407E086' ) // OpenSSL SSL2 certificate error
3564
- &&
3565
- false === strpos( $message, 'error setting certificate verify locations' ) // cURL CA bundle not found
3566
- &&
3567
- false === strpos( $message, 'Peer certificate cannot be authenticated with' ) // cURL CURLE_SSL_CACERT: CA bundle found, but not helpful
3568
- // different versions of curl have different error messages
3569
- // this string should catch them all
3570
- &&
3571
- false === strpos( $message, 'Problem with the SSL CA cert' ) // cURL CURLE_SSL_CACERT_BADFILE: probably access rights
3572
- ) {
3573
- // No, it is not.
3574
- return $response;
3575
- }
3576
-
3577
- // Redo the request without SSL certificate verification.
3578
- $args['sslverify'] = false;
3579
- $response = wp_remote_request( $url, $args );
3580
-
3581
- if ( !is_wp_error( $response ) ) {
3582
- // The request went through this time, flag for future fallbacks
3583
- Jetpack::update_option( 'fallback_no_verify_ssl_certs', time() );
3584
- Jetpack_Client::set_time_diff( $response, $set_fallback );
3585
- }
3586
-
3587
- return $response;
3588
- }
3589
-
3590
- public static function set_time_diff( &$response, $force_set = false ) {
3591
- $code = wp_remote_retrieve_response_code( $response );
3592
-
3593
- // Only trust the Date header on some responses
3594
- if ( 200 != $code && 304 != $code && 400 != $code && 401 != $code ) {
3595
- return;
3596
- }
3597
-
3598
- if ( !$date = wp_remote_retrieve_header( $response, 'date' ) ) {
3599
- return;
3600
- }
3601
-
3602
- if ( 0 >= $time = (int) strtotime( $date ) ) {
3603
- return;
3604
- }
3605
-
3606
- $time_diff = $time - time();
3607
-
3608
- if ( $force_set ) { // during register
3609
- Jetpack::update_option( 'time_diff', $time_diff );
3610
- } else { // otherwise
3611
- $old_diff = Jetpack::get_option( 'time_diff' );
3612
- if ( false === $old_diff || abs( $time_diff - (int) $old_diff ) > 10 ) {
3613
- Jetpack::update_option( 'time_diff', $time_diff );
3614
- }
3615
- }
3616
- }
3617
- }
3618
-
3619
- class Jetpack_Data {
3620
- /**
3621
- * Gets locally stored token
3622
- *
3623
- * @return object|false
3624
- */
3625
- public static function get_access_token( $user_id = false ) {
3626
- if ( $user_id ) {
3627
- if ( !$tokens = Jetpack::get_option( 'user_tokens' ) ) {
3628
- return false;
3629
- }
3630
- if ( $user_id === JETPACK_MASTER_USER ) {
3631
- if ( !$user_id = Jetpack::get_option( 'master_user' ) ) {
3632
- return false;
3633
- }
3634
- }
3635
- if ( !isset( $tokens[$user_id] ) || !$token = $tokens[$user_id] ) {
3636
- return false;
3637
- }
3638
- $token_chunks = explode( '.', $token );
3639
- if ( empty( $token_chunks[1] ) || empty( $token_chunks[2] ) ) {
3640
- return false;
3641
- }
3642
- if ( $user_id != $token_chunks[2] ) {
3643
- return false;
3644
- }
3645
- $token = "{$token_chunks[0]}.{$token_chunks[1]}";
3646
- } else {
3647
- $token = Jetpack::get_option( 'blog_token' );
3648
- if ( empty( $token ) ) {
3649
- return false;
3650
- }
3651
- }
3652
-
3653
- return (object) array(
3654
- 'secret' => $token,
3655
- 'external_user_id' => (int) $user_id,
3656
- );
3657
- }
3658
- }
3659
-
3660
- /**
3661
- * Client = Plugin
3662
- * Client Server = API Methods the Plugin must respond to
3663
- *
3664
- * @todo Roll this into Jetpack? There's only one 'public' method now: ::authorize().
3665
- */
3666
- class Jetpack_Client_Server {
3667
- function authorize() {
3668
- $data = stripslashes_deep( $_GET );
3669
-
3670
- $args = array();
3671
-
3672
- $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
3673
-
3674
- do {
3675
- $jetpack = Jetpack::init();
3676
- $role = $jetpack->translate_current_user_to_role();
3677
- if ( !$role ) {
3678
- Jetpack::state( 'error', 'no_role' );
3679
- break;
3680
- }
3681
-
3682
- $cap = $jetpack->translate_role_to_cap( $role );
3683
- if ( !$cap ) {
3684
- Jetpack::state( 'error', 'no_cap' );
3685
- break;
3686
- }
3687
-
3688
- check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
3689
-
3690
- if ( !empty( $data['error'] ) ) {
3691
- Jetpack::state( 'error', $data['error'] );
3692
- break;
3693
- }
3694
-
3695
- if ( empty( $data['state'] ) ) {
3696
- Jetpack::state( 'error', 'no_state' );
3697
- break;
3698
- }
3699
-
3700
- if ( !ctype_digit( $data['state'] ) ) {
3701
- Jetpack::state( 'error', 'invalid_state' );
3702
- break;
3703
- }
3704
-
3705
- $current_user_id = get_current_user_id();
3706
- if ( $current_user_id != $data['state'] ) {
3707
- Jetpack::state( 'error', 'wrong_state' );
3708
- break;
3709
- }
3710
-
3711
- if ( empty( $data['code'] ) ) {
3712
- Jetpack::state( 'error', 'no_code' );
3713
- break;
3714
- }
3715
-
3716
- $token = $this->get_token( $data );
3717
-
3718
- if ( is_wp_error( $token ) ) {
3719
- if ( $error = $token->get_error_code() )
3720
- Jetpack::state( 'error', $error );
3721
- else
3722
- Jetpack::state( 'error', 'invalid_token' );
3723
-
3724
- Jetpack::state( 'error_description', $token->get_error_message() );
3725
-
3726
- break;
3727
- }
3728
-
3729
- if ( !$token ) {
3730
- Jetpack::state( 'error', 'no_token' );
3731
- break;
3732
- }
3733
-
3734
- $is_master_user = ! Jetpack::is_active();
3735
-
3736
- Jetpack::update_user_token( $current_user_id, sprintf( '%s.%d', $token, $current_user_id ), $is_master_user );
3737
-
3738
-
3739
- if ( $is_master_user ) {
3740
- Jetpack::state( 'message', 'authorized' );
3741
- } else {
3742
- Jetpack::state( 'message', 'linked' );
3743
- // Don't activate anything since we are just connecting a user.
3744
- break;
3745
- }
3746
-
3747
- if ( $active_modules = Jetpack::get_option( 'active_modules' ) ) {
3748
- Jetpack::delete_option( 'active_modules' );
3749
-
3750
- Jetpack::activate_default_modules( 999, 1, $active_modules );
3751
- } else {
3752
- Jetpack::activate_default_modules();
3753
- }
3754
-
3755
- $jetpack->sync->register( 'noop' ); // Spawn a sync to make sure the Jetpack Servers know what modules are active.
3756
-
3757
- // Start nonce cleaner
3758
- wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
3759
- wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
3760
- } while ( false );
3761
-
3762
- if ( wp_validate_redirect( $redirect ) ) {
3763
- wp_safe_redirect( $redirect );
3764
- } else {
3765
- wp_safe_redirect( Jetpack::admin_url() );
3766
- }
3767
-
3768
- exit;
3769
- }
3770
-
3771
- public static function deactivate_plugin( $probable_file, $probable_title ) {
3772
- if ( is_plugin_active( $probable_file ) ) {
3773
- deactivate_plugins( $probable_file );
3774
- return 1;
3775
- } else {
3776
- // If the plugin is not in the usual place, try looking through all active plugins.
3777
- $active_plugins = get_option( 'active_plugins', array() );
3778
- foreach ( $active_plugins as $plugin ) {
3779
- $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
3780
- if ( $data['Name'] == $probable_title ) {
3781
- deactivate_plugins( $plugin );
3782
- return 1;
3783
- }
3784
- }
3785
- }
3786
-
3787
- return 0;
3788
- }
3789
-
3790
- /**
3791
- * @return object|WP_Error
3792
- */
3793
- function get_token( $data ) {
3794
- $jetpack = Jetpack::init();
3795
- $role = $jetpack->translate_current_user_to_role();
3796
-
3797
- if ( !$role ) {
3798
- return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
3799
- }
3800
-
3801
- $client_secret = Jetpack_Data::get_access_token();
3802
- if ( !$client_secret ) {
3803
- return new Jetpack_Error( 'client_secret', __( 'You need to register your Jetpack before connecting it.', 'jetpack' ) );
3804
- }
3805
-
3806
- $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
3807
-
3808
- $body = array(
3809
- 'client_id' => Jetpack::get_option( 'id' ),
3810
- 'client_secret' => $client_secret->secret,
3811
- 'grant_type' => 'authorization_code',
3812
- 'code' => $data['code'],
3813
- 'redirect_uri' => add_query_arg( array(
3814
- 'action' => 'authorize',
3815
- '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
3816
- 'redirect' => $redirect ? urlencode( $redirect ) : false,
3817
- ), menu_page_url( 'jetpack', false ) ),
3818
- );
3819
-
3820
- $args = array(
3821
- 'method' => 'POST',
3822
- 'body' => $body,
3823
- 'headers' => array(
3824
- 'Accept' => 'application/json',
3825
- ),
3826
- );
3827
- $response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'token' ), $args ), $args );
3828
-
3829
- if ( is_wp_error( $response ) ) {
3830
- return new Jetpack_Error( 'token_http_request_failed', $response->get_error_message() );
3831
- }
3832
-
3833
- $code = wp_remote_retrieve_response_code( $response );
3834
- $entity = wp_remote_retrieve_body( $response );
3835
-
3836
- if ( $entity )
3837
- $json = json_decode( $entity );
3838
- else
3839
- $json = false;
3840
-
3841
- if ( 200 != $code || !empty( $json->error ) ) {
3842
- if ( empty( $json->error ) )
3843
- return new Jetpack_Error( 'unknown', '', $code );
3844
-
3845
- $error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
3846
-
3847
- return new Jetpack_Error( (string) $json->error, $error_description, $code );
3848
- }
3849
-
3850
- if ( empty( $json->access_token ) || !is_scalar( $json->access_token ) ) {
3851
- return new Jetpack_Error( 'access_token', '', $code );
3852
- }
3853
-
3854
- if ( empty( $json->token_type ) || 'X_JETPACK' != strtoupper( $json->token_type ) ) {
3855
- return new Jetpack_Error( 'token_type', '', $code );
3856
- }
3857
-
3858
- if ( empty( $json->scope ) ) {
3859
- return new Jetpack_Error( 'scope', 'No Scope', $code );
3860
- }
3861
- @list( $role, $hmac ) = explode( ':', $json->scope );
3862
- if ( empty( $role ) || empty( $hmac ) ) {
3863
- return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
3864
- }
3865
- if ( $jetpack->sign_role( $role ) !== $json->scope ) {
3866
- return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
3867
- }
3868
-
3869
- if ( !$cap = $jetpack->translate_role_to_cap( $role ) )
3870
- return new Jetpack_Error( 'scope', 'No Cap', $code );
3871
- if ( !current_user_can( $cap ) )
3872
- return new Jetpack_Error( 'scope', 'current_user_cannot', $code );
3873
-
3874
- return (string) $json->access_token;
3875
- }
3876
- }
3877
-
3878
-
3879
- /**
3880
- * Request that a piece of data on this WordPress install be synced back to the
3881
- * Jetpack server for remote processing/notifications/etc
3882
- */
3883
- class Jetpack_Sync {
3884
- // What modules want to sync what content
3885
- var $sync_conditions = array( 'posts' => array(), 'comments' => array() );
3886
-
3887
- // We keep track of all the options registered for sync so that we can sync them all if needed
3888
- var $sync_options = array();
3889
-
3890
- // Keep trac of status transitions, which we wouldn't always know about on the Jetpack Servers but are important when deciding what to do with the sync.
3891
- var $post_transitions = array();
3892
- var $comment_transitions = array();
3893
-
3894
- // Objects to sync
3895
- var $sync = array();
3896
-
3897
- function __construct() {
3898
- // WP Cron action. Only used on upgrade
3899
- add_action( 'jetpack_sync_all_registered_options', array( $this, 'sync_all_registered_options' ) );
3900
- }
3901
-
3902
- /* Static Methods for Modules */
3903
-
3904
- /**
3905
- * @param string $file __FILE__
3906
- * @param array settings:
3907
- * post_types => array( post_type slugs ): The post types to sync. Default: post, page
3908
- * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
3909
- */
3910
- static function sync_posts( $file, array $settings = null ) {
3911
- $jetpack = Jetpack::init();
3912
- $args = func_get_args();
3913
- return call_user_func_array( array( $jetpack->sync, 'posts' ), $args );
3914
- }
3915
-
3916
- /**
3917
- * @param string $file __FILE__
3918
- * @param array settings:
3919
- * post_types => array( post_type slugs ): The post types to sync. Default: post, page
3920
- * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
3921
- * comment_types => array( comment_type slugs ): The comment types to sync. Default: '', comment, trackback, pingback
3922
- * comment_stati => array( comment_status slugs ): The comment stati to sync. Default: approved
3923
- */
3924
- static function sync_comments( $file, array $settings = null ) {
3925
- $jetpack = Jetpack::init();
3926
- $args = func_get_args();
3927
- return call_user_func_array( array( $jetpack->sync, 'comments' ), $args );
3928
- }
3929
-
3930
- /**
3931
- * @param string $file __FILE__
3932
- * @param string $option, Option name to sync
3933
- * @param string $option ...
3934
- */
3935
- static function sync_options( $file, $option /*, $option, ... */ ) {
3936
- $jetpack = Jetpack::init();
3937
- $args = func_get_args();
3938
- return call_user_func_array( array( $jetpack->sync, 'options' ), $args );
3939
- }
3940
-
3941
- /* Internal Methods */
3942
-
3943
- /**
3944
- * Create a sync object/request
3945
- *
3946
- * @param string $object Type of object to sync -- [ post | comment | option ]
3947
- * @param int $id Unique identifier
3948
- * @param array $settings
3949
- */
3950
- function register( $object, $id = false, array $settings = null ) {
3951
- // Since we've registered something for sync, hook it up to execute on shutdown if we haven't already
3952
- if ( !$this->sync ) {
3953
- ignore_user_abort( true );
3954
- add_action( 'shutdown', array( $this, 'sync' ), 9 ); // Right before async XML-RPC
3955
- }
3956
-
3957
- $defaults = array(
3958
- 'on_behalf_of' => array(), // What modules want this data
3959
- );
3960
- $settings = wp_parse_args( $settings, $defaults );
3961
-
3962
- if ( !isset( $this->sync[$object] ) ) {
3963
- $this->sync[$object] = array();
3964
- }
3965
-
3966
- // Store the settings for this object
3967
- if (
3968
- // First time for this object
3969
- !isset( $this->sync[$object][$id] )
3970
- ) {
3971
- // Easy: store the current settings
3972
- $this->sync[$object][$id] = $settings;
3973
- } else {
3974
- // Not as easy: we have to manually merge the settings from previous runs for this object with the settings for this run
3975
-
3976
- $this->sync[$object][$id]['on_behalf_of'] = array_unique( array_merge( $this->sync[$object][$id]['on_behalf_of'], $settings['on_behalf_of'] ) );
3977
- }
3978
-
3979
- $delete_prefix = 'delete_';
3980
- if ( 0 === strpos( $object, $delete_prefix ) ) {
3981
- $unset_object = substr( $object, strlen( $delete_prefix ) );
3982
- } else {
3983
- $unset_object = "{$delete_prefix}{$object}";
3984
- }
3985
-
3986
- // Ensure post ... delete_post yields a delete operation
3987
- // Ensure delete_post ... post yields a sync post operation
3988
- // Ensure update_option() ... delete_option() ends up as a delete
3989
- // Ensure delete_option() ... update_option() ends up as an update
3990
- // Etc.
3991
- unset( $this->sync[$unset_object][$id] );
3992
-
3993
- return true;
3994
- }
3995
-
3996
- function get_common_sync_data() {
3997
- $available_modules = Jetpack::get_available_modules();
3998
- $active_modules = Jetpack::get_active_modules();
3999
- $modules = array();
4000
- foreach ( $available_modules as $available_module ) {
4001
- $modules[$available_module] = in_array( $available_module, $active_modules );
4002
- }
4003
- $modules['vaultpress'] = class_exists( 'VaultPress' ) || function_exists( 'vaultpress_contact_service' );
4004
-
4005
- $sync_data = array(
4006
- 'modules' => $modules,
4007
- 'version' => JETPACK__VERSION,
4008
- );
4009
-
4010
- return $sync_data;
4011
- }
4012
-
4013
- /**
4014
- * Set up all the data and queue it for the outgoing XML-RPC request
4015
- */
4016
- function sync() {
4017
- if ( !$this->sync ) {
4018
- return false;
4019
- }
4020
-
4021
- $sync_data = $this->get_common_sync_data();
4022
-
4023
- $wp_importing = defined( 'WP_IMPORTING' ) && WP_IMPORTING;
4024
-
4025
- foreach ( $this->sync as $sync_operation_type => $sync_operations ) {
4026
- switch ( $sync_operation_type ) {
4027
- case 'post':
4028
- if ( $wp_importing ) {
4029
- break;
4030
- }
4031
-
4032
- $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
4033
- $GLOBALS['post'] = null;
4034
- foreach ( $sync_operations as $post_id => $settings ) {
4035
- $sync_data['post'][$post_id] = $this->get_post( $post_id );
4036
- if ( isset( $this->post_transitions[$post_id] ) ) {
4037
- $sync_data['post'][$post_id]['transitions'] = $this->post_transitions[$post_id];
4038
- } else {
4039
- $sync_data['post'][$post_id]['transitions'] = array( false, false );
4040
- }
4041
- $sync_data['post'][$post_id]['on_behalf_of'] = $settings['on_behalf_of'];
4042
- }
4043
- $GLOBALS['post'] = $global_post;
4044
- unset( $global_post );
4045
- break;
4046
- case 'comment':
4047
- if ( $wp_importing ) {
4048
- break;
4049
- }
4050
-
4051
- $global_comment = isset( $GLOBALS['comment'] ) ? $GLOBALS['comment'] : null;
4052
- unset( $GLOBALS['comment'] );
4053
- foreach ( $sync_operations as $comment_id => $settings ) {
4054
- $sync_data['comment'][$comment_id] = $this->get_comment( $comment_id );
4055
- if ( isset( $this->comment_transitions[$comment_id] ) ) {
4056
- $sync_data['comment'][$comment_id]['transitions'] = $this->comment_transitions[$comment_id];
4057
- } else {
4058
- $sync_data['comment'][$comment_id]['transitions'] = array( false, false );
4059
- }
4060
- $sync_data['comment'][$comment_id]['on_behalf_of'] = $settings['on_behalf_of'];
4061
- }
4062
- $GLOBALS['comment'] = $global_comment;
4063
- unset( $global_comment );
4064
- break;
4065
- case 'option' :
4066
- foreach ( $sync_operations as $option => $settings ) {
4067
- $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
4068
- }
4069
- break;
4070
-
4071
- case 'delete_post':
4072
- case 'delete_comment':
4073
- foreach ( $sync_operations as $object_id => $settings ) {
4074
- $sync_data[$sync_operation_type][$object_id] = array( 'on_behalf_of' => $settings['on_behalf_of'] );
4075
- }
4076
- break;
4077
- case 'delete_option' :
4078
- foreach ( $sync_operations as $object_id => $settings ) {
4079
- $sync_data[$sync_operation_type][$object_id] = true;
4080
- }
4081
- break;
4082
- }
4083
- }
4084
-
4085
- Jetpack::xmlrpc_async_call( 'jetpack.syncContent', $sync_data );
4086
- }
4087
-
4088
- /**
4089
- * Format and return content data from a direct xmlrpc request for it.
4090
- *
4091
- * @param array $content_ids: array( 'posts' => array of ids, 'comments' => array of ids, 'options' => array of options )
4092
- */
4093
- function get_content( $content_ids ) {
4094
- $sync_data = $this->get_common_sync_data();
4095
-
4096
- if ( isset( $content_ids['posts'] ) ) {
4097
- foreach ( $content_ids['posts'] as $id ) {
4098
- $sync_data['post'][$id] = $this->get_post( $id );
4099
- }
4100
- }
4101
-
4102
- if ( isset( $content_ids['comments'] ) ) {
4103
- foreach ( $content_ids['comments'] as $id ) {
4104
- $sync_data['comment'][$id] = $this->get_post( $id );
4105
- }
4106
- }
4107
-
4108
- if ( isset( $content_ids['options'] ) ) {
4109
- foreach ( $content_ids['options'] as $option ) {
4110
- $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
4111
- }
4112
- }
4113
-
4114
- return $sync_data;
4115
- }
4116
-
4117
- /**
4118
- * Helper method for registering a post for sync
4119
- *
4120
- * @param int $id wp_posts.ID
4121
- * @param array $settings Sync data
4122
- */
4123
- function register_post( $id, array $settings = null ) {
4124
- $id = (int) $id;
4125
- if ( !$id ) {
4126
- return false;
4127
- }
4128
-
4129
- $post = get_post( $id );
4130
- if ( !$post ) {
4131
- return false;
4132
- }
4133
-
4134
- $settings = wp_parse_args( $settings, array(
4135
- 'on_behalf_of' => array(),
4136
- ) );
4137
-
4138
- return $this->register( 'post', $id, $settings );
4139
- }
4140
-
4141
- /**
4142
- * Helper method for registering a comment for sync
4143
- *
4144
- * @param int $id wp_comments.comment_ID
4145
- * @param array $settings Sync data
4146
- */
4147
- function register_comment( $id, array $settings = null ) {
4148
- $id = (int) $id;
4149
- if ( !$id ) {
4150
- return false;
4151
- }
4152
-
4153
- $comment = get_comment( $id );
4154
- if ( !$comment || empty( $comment->comment_post_ID ) ) {
4155
- return false;
4156
- }
4157
-
4158
- $post = get_post( $comment->comment_post_ID );
4159
- if ( !$post ) {
4160
- return false;
4161
- }
4162
-
4163
- $settings = wp_parse_args( $settings, array(
4164
- 'on_behalf_of' => array(),
4165
- ) );
4166
-
4167
- return $this->register( 'comment', $id, $settings );
4168
- }
4169
-
4170
- /* Posts Sync */
4171
-
4172
- function posts( $file, array $settings = null ) {
4173
- $module_slug = Jetpack::get_module_slug( $file );
4174
-
4175
- $defaults = array(
4176
- 'post_types' => array( 'post', 'page' ),
4177
- 'post_stati' => array( 'publish' ),
4178
- );
4179
-
4180
- $this->sync_conditions['posts'][$module_slug] = wp_parse_args( $settings, $defaults );
4181
-
4182
- add_action( 'transition_post_status', array( $this, 'transition_post_status_action' ), 10, 3 );
4183
- add_action( 'delete_post', array( $this, 'delete_post_action' ) );
4184
- }
4185
-
4186
- function delete_post_action( $post_id ) {
4187
- $post = get_post( $post_id );
4188
- if ( !$post ) {
4189
- return $this->register( 'delete_post', (int) $post_id );
4190
- }
4191
-
4192
- $this->transition_post_status_action( 'delete', $post->post_status, $post );
4193
- }
4194
-
4195
- function transition_post_status_action( $new_status, $old_status, $post ) {
4196
- $sync = $this->get_post_sync_operation( $new_status, $old_status, $post, $this->sync_conditions['posts'] );
4197
- if ( !$sync ) {
4198
- // No module wants to sync this post
4199
- return false;
4200
- }
4201
-
4202
- // Track post transitions
4203
- if ( isset( $this->post_transitions[$post->ID] ) ) {
4204
- // status changed more than once - keep tha most recent $new_status
4205
- $this->post_transitions[$post->ID][0] = $new_status;
4206
- } else {
4207
- $this->post_transitions[$post->ID] = array( $new_status, $old_status );
4208
- }
4209
-
4210
- $operation = $sync['operation'];
4211
- unset( $sync['operation'] );
4212
-
4213
- switch ( $operation ) {
4214
- case 'delete' :
4215
- return $this->register( 'delete_post', (int) $post->ID, $sync );
4216
- case 'submit' :
4217
- return $this->register_post( (int) $post->ID, $sync );
4218
- }
4219
- }
4220
-
4221
- function get_post_sync_operation( $new_status, $old_status, $post, $module_conditions ) {
4222
- $delete_on_behalf_of = array();
4223
- $submit_on_behalf_of = array();
4224
- $delete_stati = array( 'delete' );
4225
-
4226
- foreach ( $module_conditions as $module => $conditions ) {
4227
- if ( !in_array( $post->post_type, $conditions['post_types'] ) ) {
4228
- continue;
4229
- }
4230
-
4231
- $deleted_post = in_array( $new_status, $delete_stati );
4232
-
4233
- if ( $deleted_post ) {
4234
- $delete_on_behalf_of[] = $module;
4235
- } else {
4236
- clean_post_cache( $post->ID );
4237
- $new_status = get_post_status( $post->ID ); // Inherited status is resolved here
4238
- }
4239
-
4240
- $old_status_in_stati = in_array( $old_status, $conditions['post_stati'] );
4241
- $new_status_in_stati = in_array( $new_status, $conditions['post_stati'] );
4242
-
4243
- if ( $old_status_in_stati && !$new_status_in_stati ) {
4244
- // Jetpack no longer needs the post
4245
- if ( !$deleted_post ) {
4246
- $delete_on_behalf_of[] = $module;
4247
- } // else, we've already flagged it above
4248
- continue;
4249
- }
4250
-
4251
- if ( !$new_status_in_stati ) {
4252
- continue;
4253
- }
4254
-
4255
- // At this point, we know we want to sync the post, not delete it
4256
- $submit_on_behalf_of[] = $module;
4257
- }
4258
-
4259
- if ( !empty( $submit_on_behalf_of ) ) {
4260
- return array( 'operation' => 'submit', 'on_behalf_of' => $submit_on_behalf_of );
4261
- }
4262
-
4263
- if ( !empty( $delete_on_behalf_of ) ) {
4264
- return array( 'operation' => 'delete', 'on_behalf_of' => $delete_on_behalf_of );
4265
- }
4266
-
4267
- return false;
4268
- }
4269
-
4270
- /**
4271
- * Get a post and associated data in the standard JP format.
4272
- * Cannot be called statically
4273
- *
4274
- * @param int $id Post ID
4275
- * @return Array containing full post details
4276
- */
4277
- function get_post( $id ) {
4278
- $post_obj = get_post( $id );
4279
- if ( !$post_obj )
4280
- return false;
4281
-
4282
- if ( is_callable( $post_obj, 'to_array' ) ) {
4283
- // WP >= 3.5
4284
- $post = $post_obj->to_array();
4285
- } else {
4286
- // WP < 3.5
4287
- $post = get_object_vars( $post_obj );
4288
- }
4289
-
4290
- if ( 0 < strlen( $post['post_password'] ) ) {
4291
- $post['post_password'] = 'auto-' . wp_generate_password( 10, false ); // We don't want the real password. Just pass something random.
4292
- }
4293
-
4294
- // local optimizations
4295
- unset(
4296
- $post['filter'],
4297
- $post['ancestors'],
4298
- $post['post_content_filtered'],
4299
- $post['to_ping'],
4300
- $post['pinged']
4301
- );
4302
-
4303
- if ( $this->is_post_public( $post ) ) {
4304
- $post['post_is_public'] = Jetpack::get_option( 'public' );
4305
- } else {
4306
- //obscure content
4307
- $post['post_content'] = '';
4308
- $post['post_excerpt'] = '';
4309
- $post['post_is_public'] = false;
4310
- }
4311
- $post_type_obj = get_post_type_object( $post['post_type'] );
4312
- $post['post_is_excluded_from_search'] = $post_type_obj->exclude_from_search;
4313
-
4314
- $post['tax'] = array();
4315
- $taxonomies = get_object_taxonomies( $post_obj );
4316
- foreach ( $taxonomies as $taxonomy ) {
4317
- $terms = get_object_term_cache( $post_obj->ID, $taxonomy );
4318
- if ( empty( $terms ) )
4319
- $terms = wp_get_object_terms( $post_obj->ID, $taxonomy );
4320
- $term_names = array();
4321
- foreach ( $terms as $term ) {
4322
- $term_names[] = $term->name;
4323
- }
4324
- $post['tax'][$taxonomy] = $term_names;
4325
- }
4326
-
4327
- $meta = get_post_meta( $post_obj->ID, false );
4328
- $post['meta'] = array();
4329
- foreach ( $meta as $key => $value ) {
4330
- $post['meta'][$key] = array_map( 'maybe_unserialize', $value );
4331
- }
4332
-
4333
- $post['extra'] = array(
4334
- 'author' => get_the_author_meta( 'display_name', $post_obj->post_author ),
4335
- 'author_email' => get_the_author_meta( 'email', $post_obj->post_author ),
4336
- );
4337
-
4338
- if ( $fid = get_post_thumbnail_id( $id ) ) {
4339
- $feature = wp_get_attachment_image_src( $fid, 'large' );
4340
- if ( !empty( $feature[0] ) )
4341
- $post['extra']['featured_image'] = $feature[0];
4342
- }
4343
-
4344
- $post['permalink'] = get_permalink( $post_obj->ID );
4345
- $post['shortlink'] = wp_get_shortlink( $post_obj->ID );
4346
- return $post;
4347
- }
4348
-
4349
- /**
4350
- * Decide whether a post/page/attachment is visible to the public.
4351
- *
4352
- * @param array $post
4353
- * @return bool
4354
- */
4355
- function is_post_public( $post ) {
4356
- if ( !is_array( $post ) ) {
4357
- $post = (array) $post;
4358
- }
4359
-
4360
- if ( 0 < strlen( $post['post_password'] ) )
4361
- return false;
4362
- if ( ! in_array( $post['post_type'], get_post_types( array( 'public' => true ) ) ) )
4363
- return false;
4364
- $post_status = get_post_status( $post['ID'] ); // Inherited status is resolved here.
4365
- if ( ! in_array( $post_status, get_post_stati( array( 'public' => true ) ) ) )
4366
- return false;
4367
- return true;
4368
- }
4369
-
4370
- /* Comments Sync */
4371
-
4372
- function comments( $file, array $settings = null ) {
4373
- $module_slug = Jetpack::get_module_slug( $file );
4374
-
4375
- $defaults = array(
4376
- 'post_types' => array( 'post', 'page' ), // For what post types will we sync comments?
4377
- 'post_stati' => array( 'publish' ), // For what post stati will we sync comments?
4378
- 'comment_types' => array( '', 'comment', 'trackback', 'pingback' ), // What comment types will we sync?
4379
- 'comment_stati' => array( 'approved' ), // What comment stati will we sync?
4380
- );
4381
-
4382
- $settings = wp_parse_args( $settings, $defaults );
4383
-
4384
- $this->sync_conditions['comments'][$module_slug] = $settings;
4385
-
4386
- add_action( 'wp_insert_comment', array( $this, 'wp_insert_comment_action' ), 10, 2 );
4387
- add_action( 'transition_comment_status', array( $this, 'transition_comment_status_action' ), 10, 3 );
4388
- add_action( 'edit_comment', array( $this, 'edit_comment_action' ) );
4389
- }
4390
-
4391
- /*
4392
- * This is really annoying. If you edit a comment, but don't change the status, WordPress doesn't fire the transition_comment_status hook.
4393
- * That means we have to catch these comments on the edit_comment hook, but ignore comments on that hook when the transition_comment_status does fire.
4394
- */
4395
- function edit_comment_action( $comment_id ) {
4396
- $comment = get_comment( $comment_id );
4397
- $new_status = $this->translate_comment_status( $comment->comment_approved );
4398
- add_action( "comment_{$new_status}_{$comment->comment_type}", array( $this, 'transition_comment_status_for_comments_whose_status_does_not_change' ), 10, 2 );
4399
- }
4400
-
4401
- function wp_insert_comment_action( $comment_id, $comment ) {
4402
- $this->transition_comment_status_action( $comment->comment_approved, 'new', $comment );
4403
- }
4404
-
4405
- function transition_comment_status_for_comments_whose_status_does_not_change( $comment_id, $comment ) {
4406
- if ( isset( $this->comment_transitions[$comment_id] ) ) {
4407
- return $this->transition_comment_status_action( $comment->comment_approved, $this->comment_transitions[$comment_id][1], $comment );
4408
- }
4409
-
4410
- return $this->transition_comment_status_action( $comment->comment_approved, $comment->comment_approved, $comment );
4411
- }
4412
-
4413
- function translate_comment_status( $status ) {
4414
- switch ( (string) $status ) {
4415
- case '0' :
4416
- case 'hold' :
4417
- return 'unapproved';
4418
- case '1' :
4419
- case 'approve' :
4420
- return 'approved';
4421
- }
4422
-
4423
- return $status;
4424
- }
4425
-
4426
- function transition_comment_status_action( $new_status, $old_status, $comment ) {
4427
- $post = get_post( $comment->comment_post_ID );
4428
- if ( !$post ) {
4429
- return false;
4430
- }
4431
-
4432
- foreach ( array( 'new_status', 'old_status' ) as $_status ) {
4433
- $$_status = $this->translate_comment_status( $$_status );
4434
- }
4435
-
4436
- // Track comment transitions
4437
- if ( isset( $this->comment_transitions[$comment->comment_ID] ) ) {
4438
- // status changed more than once - keep tha most recent $new_status
4439
- $this->comment_transitions[$comment->comment_ID][0] = $new_status;
4440
- } else {
4441
- $this->comment_transitions[$comment->comment_ID] = array( $new_status, $old_status );
4442
- }
4443
-
4444
- $post_sync = $this->get_post_sync_operation( $post->post_status, '_jetpack_test_sync', $post, $this->sync_conditions['comments'] );
4445
-
4446
- if ( !$post_sync ) {
4447
- // No module wants to sync this comment because its post doesn't match any sync conditions
4448
- return false;
4449
- }
4450
-
4451
- if ( 'delete' == $post_sync['operation'] ) {
4452
- // Had we been looking at post sync operations (instead of comment sync operations),
4453
- // this comment's post would have been deleted. Don't sync the comment.
4454
- return false;
4455
- }
4456
-
4457
- $delete_on_behalf_of = array();
4458
- $submit_on_behalf_of = array();
4459
- $delete_stati = array( 'delete' );
4460
-
4461
- foreach ( $this->sync_conditions['comments'] as $module => $conditions ) {
4462
- if ( !in_array( $comment->comment_type, $conditions['comment_types'] ) ) {
4463
- continue;
4464
- }
4465
-
4466
- $deleted_comment = in_array( $new_status, $delete_stati );
4467
-
4468
- if ( $deleted_comment ) {
4469
- $delete_on_behalf_of[] = $module;
4470
- }
4471
-
4472
- $old_status_in_stati = in_array( $old_status, $conditions['comment_stati'] );
4473
- $new_status_in_stati = in_array( $new_status, $conditions['comment_stati'] );
4474
-
4475
- if ( $old_status_in_stati && !$new_status_in_stati ) {
4476
- // Jetpack no longer needs the comment
4477
- if ( !$deleted_comment ) {
4478
- $delete_on_behalf_of[] = $module;
4479
- } // else, we've already flagged it above
4480
- continue;
4481
- }
4482
-
4483
- if ( !$new_status_in_stati ) {
4484
- continue;
4485
- }
4486
-
4487
- // At this point, we know we want to sync the comment, not delete it
4488
- $submit_on_behalf_of[] = $module;
4489
- }
4490
-
4491
- if ( ! empty( $submit_on_behalf_of ) ) {
4492
- $this->register_post( $comment->comment_post_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
4493
- return $this->register_comment( $comment->comment_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
4494
- }
4495
-
4496
- if ( !empty( $delete_on_behalf_of ) ) {
4497
- return $this->register( 'delete_comment', $comment->comment_ID, array( 'on_behalf_of' => $delete_on_behalf_of ) );
4498
- }
4499
-
4500
- return false;
4501
- }
4502
-
4503
- /**
4504
- * Get a comment and associated data in the standard JP format.
4505
- * Cannot be called statically
4506
- *
4507
- * @param int $id Comment ID
4508
- * @return Array containing full comment details
4509
- */
4510
- function get_comment( $id ) {
4511
- $comment_obj = get_comment( $id );
4512
- if ( !$comment_obj )
4513
- return false;
4514
- $comment = get_object_vars( $comment_obj );
4515
-
4516
- $meta = get_comment_meta( $id, false );
4517
- $comment['meta'] = array();
4518
- foreach ( $meta as $key => $value ) {
4519
- $comment['meta'][$key] = array_map( 'maybe_unserialize', $value );
4520
- }
4521
-
4522
- return $comment;
4523
- }
4524
-
4525
- /* Options Sync */
4526
-
4527
- /* Ah... so much simpler than Posts and Comments :) */
4528
- function options( $file, $option /*, $option, ... */ ) {
4529
- $options = func_get_args();
4530
- $file = array_shift( $options );
4531
-
4532
- $module_slug = Jetpack::get_module_slug( $file );
4533
-
4534
- if ( !isset( $this->sync_options[$module_slug] ) ) {
4535
- $this->sync_options[$module_slug] = array();
4536
- }
4537
-
4538
- foreach ( $options as $option ) {
4539
- $this->sync_options[$module_slug][] = $option;
4540
- add_action( "delete_option_{$option}", array( $this, 'deleted_option_action' ) );
4541
- add_action( "update_option_{$option}", array( $this, 'updated_option_action' ) );
4542
- add_action( "add_option_{$option}", array( $this, 'added_option_action' ) );
4543
- }
4544
-
4545
- $this->sync_options[$module_slug] = array_unique( $this->sync_options[$module_slug] );
4546
- }
4547
-
4548
- function deleted_option_action( $option ) {
4549
- $this->register( 'delete_option', $option );
4550
- }
4551
-
4552
- function updated_option_action( $old_value ) {
4553
- // The value of $option isn't passed to the filter
4554
- // Calculate it
4555
- $option = current_filter();
4556
- $prefix = 'update_option_';
4557
- if ( 0 !== strpos( $option, $prefix ) ) {
4558
- return;
4559
- }
4560
- $option = substr( $option, strlen( $prefix ) );
4561
-
4562
- $this->added_option_action( $option );
4563
- }
4564
-
4565
- function added_option_action( $option ) {
4566
- $this->register( 'option', $option );
4567
- }
4568
-
4569
- function sync_all_module_options( $module_slug ) {
4570
- if ( empty( $this->sync_options[$module_slug] ) ) {
4571
- return;
4572
- }
4573
-
4574
- foreach ( $this->sync_options[$module_slug] as $option ) {
4575
- $this->added_option_action( $option );
4576
- }
4577
- }
4578
-
4579
- function sync_all_registered_options( $options = array() ) {
4580
- if ( 'jetpack_sync_all_registered_options' == current_filter() ) {
4581
- $all_registered_options = array_unique( call_user_func_array( 'array_merge', $this->sync_options ) );
4582
- foreach ( $all_registered_options as $option ) {
4583
- $this->added_option_action( $option );
4584
- }
4585
- } else {
4586
- wp_schedule_single_event( time(), 'jetpack_sync_all_registered_options', array( $this->sync_options ) );
4587
- }
4588
- }
4589
- }
4590
-
4591
- require_once dirname( __FILE__ ) . '/class.jetpack-user-agent.php';
4592
- require_once dirname( __FILE__ ) . '/class.jetpack-post-images.php';
4593
- require_once dirname( __FILE__ ) . '/class.photon.php';
4594
- require dirname( __FILE__ ) . '/functions.photon.php';
4595
- require dirname( __FILE__ ) . '/functions.compat.php';
4596
- require dirname( __FILE__ ) . '/functions.gallery.php';
4597
-
4598
- class Jetpack_Error extends WP_Error {}
4599
 
4600
  register_activation_hook( __FILE__, array( 'Jetpack', 'plugin_activation' ) );
4601
  register_deactivation_hook( __FILE__, array( 'Jetpack', 'plugin_deactivation' ) );
@@ -4604,4 +57,10 @@ add_action( 'init', array( 'Jetpack', 'init' ) );
4604
  add_action( 'plugins_loaded', array( 'Jetpack', 'load_modules' ), 100 );
4605
  add_filter( 'jetpack_static_url', array( 'Jetpack', 'staticize_subdomain' ) );
4606
 
 
 
 
 
 
 
4607
  Jetpack_Sync::sync_options( __FILE__, 'widget_twitter' );
5
  * Plugin URI: http://wordpress.org/extend/plugins/jetpack/
6
  * Description: Bring the power of the WordPress.com cloud to your self-hosted WordPress. Jetpack enables you to connect your blog to a WordPress.com account to use the powerful features normally only available to WordPress.com users.
7
  * Author: Automattic
8
+ * Version: 2.3.8
9
  * Author URI: http://jetpack.me
10
  * License: GPL2+
11
  * Text Domain: jetpack
14
 
15
  defined( 'JETPACK__API_BASE' ) or define( 'JETPACK__API_BASE', 'https://jetpack.wordpress.com/jetpack.' );
16
  define( 'JETPACK__API_VERSION', 1 );
17
+ define( 'JETPACK__MINIMUM_WP_VERSION', '3.5' );
18
  defined( 'JETPACK_CLIENT__AUTH_LOCATION' ) or define( 'JETPACK_CLIENT__AUTH_LOCATION', 'header' );
19
  defined( 'JETPACK_CLIENT__HTTPS' ) or define( 'JETPACK_CLIENT__HTTPS', 'AUTO' );
20
+ define( 'JETPACK__VERSION', '2.3.8' );
21
  define( 'JETPACK__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
22
  defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) or define( 'JETPACK__GLOTPRESS_LOCALES_PATH', JETPACK__PLUGIN_DIR . 'locales.php' );
23
 
24
  define( 'JETPACK_MASTER_USER', true );
25
 
26
+ // Constants for expressing human-readable intervals
27
+ // in their respective number of seconds.
28
+ // Introduced in WordPress 3.5, specified here for backward compatability.
29
+ defined( 'MINUTE_IN_SECONDS' ) or define( 'MINUTE_IN_SECONDS', 60 );
30
+ defined( 'HOUR_IN_SECONDS' ) or define( 'HOUR_IN_SECONDS', 60 * MINUTE_IN_SECONDS );
31
+ defined( 'DAY_IN_SECONDS' ) or define( 'DAY_IN_SECONDS', 24 * HOUR_IN_SECONDS );
32
+ defined( 'WEEK_IN_SECONDS' ) or define( 'WEEK_IN_SECONDS', 7 * DAY_IN_SECONDS );
33
+ defined( 'YEAR_IN_SECONDS' ) or define( 'YEAR_IN_SECONDS', 365 * DAY_IN_SECONDS );
34
+
35
+ // @todo: Abstract out the admin functions, and only include them if is_admin()
36
+ // @todo: Only include things like class.jetpack-sync.php if we're connected.
37
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack.php' );
38
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-client.php' );
39
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-data.php' );
40
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-client-server.php' );
41
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-sync.php' );
42
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-options.php' );
43
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-user-agent.php' );
44
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-post-images.php' );
45
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-error.php' );
46
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-debugger.php' );
47
+ require_once( JETPACK__PLUGIN_DIR . 'class.jetpack-heartbeat.php' );
48
+ require_once( JETPACK__PLUGIN_DIR . 'class.photon.php' );
49
+ require_once( JETPACK__PLUGIN_DIR . 'functions.photon.php' );
50
+ require_once( JETPACK__PLUGIN_DIR . 'functions.compat.php' );
51
+ require_once( JETPACK__PLUGIN_DIR . 'functions.gallery.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  register_activation_hook( __FILE__, array( 'Jetpack', 'plugin_activation' ) );
54
  register_deactivation_hook( __FILE__, array( 'Jetpack', 'plugin_deactivation' ) );
57
  add_action( 'plugins_loaded', array( 'Jetpack', 'load_modules' ), 100 );
58
  add_filter( 'jetpack_static_url', array( 'Jetpack', 'staticize_subdomain' ) );
59
 
60
+ /*
61
+ if ( is_admin() && ! Jetpack::check_identity_crisis() ) {
62
+ Jetpack_Sync::sync_options( __FILE__, 'db_version', 'jetpack_active_modules', 'active_plugins' );
63
+ }
64
+ */
65
+
66
  Jetpack_Sync::sync_options( __FILE__, 'widget_twitter' );
languages/jetpack-ar.mo CHANGED
Binary file
languages/jetpack-az.mo CHANGED
Binary file
languages/jetpack-bs_BA.mo CHANGED
Binary file
languages/jetpack-ca.mo CHANGED
Binary file
languages/jetpack-cs_CZ.mo CHANGED
Binary file
languages/jetpack-da_DK.mo CHANGED
Binary file
languages/jetpack-de_DE.mo CHANGED
Binary file
languages/jetpack-el.mo CHANGED
Binary file
languages/jetpack-es_ES.mo CHANGED
Binary file
languages/jetpack-fa_IR.mo CHANGED
Binary file
languages/jetpack-fi.mo CHANGED
Binary file
languages/jetpack-fr_FR.mo CHANGED
Binary file
languages/jetpack-gl_ES.mo CHANGED
Binary file
languages/jetpack-he_IL.mo CHANGED
Binary file
languages/jetpack-hr.mo CHANGED
Binary file
languages/jetpack-hu_HU.mo CHANGED
Binary file
languages/jetpack-id_ID.mo CHANGED
Binary file
languages/jetpack-it_IT.mo CHANGED
Binary file
languages/jetpack-ja.mo CHANGED
Binary file
languages/jetpack-ko_KR.mo CHANGED
Binary file
languages/jetpack-lt_LT.mo CHANGED
Binary file
languages/jetpack-mk_MK.mo CHANGED
Binary file
languages/jetpack-my_MM.mo CHANGED
Binary file
languages/jetpack-nb_NO.mo CHANGED
Binary file
languages/jetpack-nl_NL.mo CHANGED
Binary file
languages/jetpack-nn_NO.mo CHANGED
Binary file
languages/jetpack-pl_PL.mo CHANGED
Binary file
languages/jetpack-pt_BR.mo CHANGED
Binary file
languages/jetpack-pt_PT.mo CHANGED
Binary file
languages/jetpack-ro_RO.mo CHANGED
Binary file
languages/jetpack-ru_RU.mo CHANGED
Binary file
languages/jetpack-sa_IN.mo CHANGED
Binary file
languages/jetpack-sk_SK.mo CHANGED
Binary file
languages/jetpack-sq.mo CHANGED
Binary file
languages/jetpack-sr_RS.mo CHANGED
Binary file
languages/jetpack-sv_SE.mo CHANGED
Binary file
languages/jetpack-th.mo CHANGED
Binary file
languages/jetpack-tr_TR.mo CHANGED
Binary file
languages/jetpack-uk.mo ADDED
Binary file
languages/jetpack-ur.mo ADDED
Binary file
languages/jetpack-zh_CN.mo CHANGED
Binary file
languages/jetpack-zh_TW.mo CHANGED
Binary file
locales.php CHANGED
@@ -1551,7 +1551,7 @@ class GP_Locales {
1551
  $tg->google_code = 'tg';
1552
  $tg->nplurals = 2;
1553
  $tg->plural_expression = 'n != 1;';
1554
-
1555
  $th = new GP_Locale();
1556
  $th->english_name = 'Thai';
1557
  $th->native_name = 'ไทย';
@@ -1701,7 +1701,7 @@ class GP_Locales {
1701
  $yi->slug = 'yi';
1702
  $yi->google_code = 'yi';
1703
  $yi->rtl = true;
1704
-
1705
  $yo = new GP_Locale();
1706
  $yo->english_name = 'Yorùbá';
1707
  $yo->native_name = 'èdè Yorùbá';
@@ -1773,28 +1773,28 @@ class GP_Locales {
1773
  }
1774
  }
1775
 
1776
- function &instance() {
1777
  if ( !isset( $GLOBALS['gp_locales'] ) )
1778
  $GLOBALS['gp_locales'] = new GP_Locales;
1779
  return $GLOBALS['gp_locales'];
1780
  }
1781
 
1782
- function locales() {
1783
  $instance = GP_Locales::instance();
1784
  return $instance->locales;
1785
  }
1786
 
1787
- function exists( $slug ) {
1788
  $instance = GP_Locales::instance();
1789
  return isset( $instance->locales[$slug] );
1790
  }
1791
 
1792
- function by_slug( $slug ) {
1793
  $instance = GP_Locales::instance();
1794
  return isset( $instance->locales[$slug] )? $instance->locales[$slug] : null;
1795
  }
1796
 
1797
- function by_field( $field_name, $field_value ) {
1798
  $instance = GP_Locales::instance();
1799
  $result = false;
1800
  foreach( $instance->locales() as $locale ) {
1551
  $tg->google_code = 'tg';
1552
  $tg->nplurals = 2;
1553
  $tg->plural_expression = 'n != 1;';
1554
+
1555
  $th = new GP_Locale();
1556
  $th->english_name = 'Thai';
1557
  $th->native_name = 'ไทย';
1701
  $yi->slug = 'yi';
1702
  $yi->google_code = 'yi';
1703
  $yi->rtl = true;
1704
+
1705
  $yo = new GP_Locale();
1706
  $yo->english_name = 'Yorùbá';
1707
  $yo->native_name = 'èdè Yorùbá';
1773
  }
1774
  }
1775
 
1776
+ static function instance() {
1777
  if ( !isset( $GLOBALS['gp_locales'] ) )
1778
  $GLOBALS['gp_locales'] = new GP_Locales;
1779
  return $GLOBALS['gp_locales'];
1780
  }
1781
 
1782
+ static function locales() {
1783
  $instance = GP_Locales::instance();
1784
  return $instance->locales;
1785
  }
1786
 
1787
+ static function exists( $slug ) {
1788
  $instance = GP_Locales::instance();
1789
  return isset( $instance->locales[$slug] );
1790
  }
1791
 
1792
+ static function by_slug( $slug ) {
1793
  $instance = GP_Locales::instance();
1794
  return isset( $instance->locales[$slug] )? $instance->locales[$slug] : null;
1795
  }
1796
 
1797
+ static function by_field( $field_name, $field_value ) {
1798
  $instance = GP_Locales::instance();
1799
  $result = false;
1800
  foreach( $instance->locales() as $locale ) {
modules/carousel/jetpack-carousel.js CHANGED
@@ -444,12 +444,14 @@ jQuery(document).ready(function($) {
444
 
445
  $(window).unbind('keydown', keyListener);
446
  $(window).unbind('resize', resizeListener);
 
 
 
447
  if ( history.pushState ) {
448
  history.pushState("", document.title, window.location.pathname + window.location.search);
449
  } else {
450
  document.location.hash = '';
451
  }
452
- $(window).scrollTop(scroll);
453
  gallery.opened = false;
454
  });
455
 
444
 
445
  $(window).unbind('keydown', keyListener);
446
  $(window).unbind('resize', resizeListener);
447
+ $(window).scrollTop(scroll);
448
+ })
449
+ .bind('jp_carousel.afterClose', function(){
450
  if ( history.pushState ) {
451
  history.pushState("", document.title, window.location.pathname + window.location.search);
452
  } else {
453
  document.location.hash = '';
454
  }
 
455
  gallery.opened = false;
456
  });
457
 
modules/carousel/jetpack-carousel.php CHANGED
@@ -129,7 +129,7 @@ class Jetpack_Carousel {
129
  $localize_strings['local_comments_commenting_as'] = '<p id="jp-carousel-commenting-as">' . sprintf( __( 'Commenting as %s', 'jetpack' ), $current_user->data->display_name ) . '</p>';
130
  } else {
131
  if ( $comment_registration ) {
132
- $localize_strings['local_comments_commenting_as'] = '<p id="jp-carousel-commenting-as">' . __( 'You must be <a href="#" class="jp-carousel-comment-login">logged in</a> to post a comment.' ) . '</p>';
133
  } else {
134
  $required = ( $require_name_email ) ? __( '%s (Required)', 'jetpack' ) : '%s';
135
  $localize_strings['local_comments_commenting_as'] = ''
129
  $localize_strings['local_comments_commenting_as'] = '<p id="jp-carousel-commenting-as">' . sprintf( __( 'Commenting as %s', 'jetpack' ), $current_user->data->display_name ) . '</p>';
130
  } else {
131
  if ( $comment_registration ) {
132
+ $localize_strings['local_comments_commenting_as'] = '<p id="jp-carousel-commenting-as">' . __( 'You must be <a href="#" class="jp-carousel-comment-login">logged in</a> to post a comment.', 'jetpack' ) . '</p>';
133
  } else {
134
  $required = ( $require_name_email ) ? __( '%s (Required)', 'jetpack' ) : '%s';
135
  $localize_strings['local_comments_commenting_as'] = ''
modules/comments/comments.php CHANGED
@@ -184,7 +184,7 @@ class Jetpack_Comments extends Highlander_Comments_Base {
184
 
185
  // If users are required to be logged in, and they're not, then we don't need to do anything else
186
  if ( get_option( 'comment_registration' ) && !is_user_logged_in() ) {
187
- echo '<p id="must-log-in-to-comment">' . sprintf( apply_filters( 'jetpack_must_log_in_to_comment', __( 'You must <a href="%s">log in</a> to post a comment.', 'jetpack' ) ), wp_login_url( get_permalink() . '#respond' ) ) . '</p>';
188
  return;
189
  }
190
 
@@ -209,6 +209,7 @@ class Jetpack_Comments extends Highlander_Comments_Base {
209
  'show_avatars' => ( get_option( 'show_avatars' ) ? '1' : '0' ),
210
  'avatar_default' => get_option( 'avatar_default' ),
211
  'greeting' => get_option( 'highlander_comment_form_prompt', __( 'Leave a Reply', 'jetpack' ) ),
 
212
  'color_scheme' => get_option( 'jetpack_comment_form_color_scheme', $this->default_color_scheme ),
213
  'lang' => get_bloginfo( 'language' ),
214
  'jetpack_version' => JETPACK__VERSION,
@@ -246,9 +247,9 @@ class Jetpack_Comments extends Highlander_Comments_Base {
246
  // The actual iframe (loads comment form from Jetpack server)
247
  ?>
248
 
249
- <div id="respond">
250
- <h3 id="reply-title"><?php comment_form_title( __( 'Leave a Reply' ), __( 'Leave a Reply to %s' ) ); ?> <small><?php cancel_comment_reply_link( __( 'Cancel reply' ) ); ?></small></h3>
251
- <div id="commentform">
252
  <iframe src="<?php echo esc_url( $url ); ?>" allowtransparency="<?php echo $transparent; ?>" style="width:100%; height: <?php echo $height; ?>px;border:0px;" frameBorder="0" scrolling="no" name="jetpack_remote_comment" id="jetpack_remote_comment"></iframe>
253
  </div>
254
  </div>
184
 
185
  // If users are required to be logged in, and they're not, then we don't need to do anything else
186
  if ( get_option( 'comment_registration' ) && !is_user_logged_in() ) {
187
+ echo '<p class="must-log-in">' . sprintf( apply_filters( 'jetpack_must_log_in_to_comment', __( 'You must <a href="%s">log in</a> to post a comment.', 'jetpack' ) ), wp_login_url( get_permalink() . '#respond' ) ) . '</p>';
188
  return;
189
  }
190
 
209
  'show_avatars' => ( get_option( 'show_avatars' ) ? '1' : '0' ),
210
  'avatar_default' => get_option( 'avatar_default' ),
211
  'greeting' => get_option( 'highlander_comment_form_prompt', __( 'Leave a Reply', 'jetpack' ) ),
212
+ 'greeting_reply' => apply_filters( 'jetpack_comment_form_prompt_reply', __( 'Leave a Reply to %s' , 'jetpack' ) ),
213
  'color_scheme' => get_option( 'jetpack_comment_form_color_scheme', $this->default_color_scheme ),
214
  'lang' => get_bloginfo( 'language' ),
215
  'jetpack_version' => JETPACK__VERSION,
247
  // The actual iframe (loads comment form from Jetpack server)
248
  ?>
249
 
250
+ <div id="respond" class="comment-respond">
251
+ <h3 id="reply-title" class="comment-reply-title"><?php comment_form_title( esc_html( $params['greeting'] ), esc_html( $params['greeting_reply'] ) ); ?> <small><?php cancel_comment_reply_link( esc_html__( 'Cancel reply' , 'jetpack') ); ?></small></h3>
252
+ <div id="commentform" class="comment-form">
253
  <iframe src="<?php echo esc_url( $url ); ?>" allowtransparency="<?php echo $transparent; ?>" style="width:100%; height: <?php echo $height; ?>px;border:0px;" frameBorder="0" scrolling="no" name="jetpack_remote_comment" id="jetpack_remote_comment"></iframe>
254
  </div>
255
  </div>
modules/contact-form/admin.php CHANGED
@@ -1,25 +1,10 @@
1
  <?php
2
 
3
- function menu_alter() {
4
- echo '
5
- <style>
6
- #menu-posts-feedback .wp-menu-image img { display: none; }
7
- #adminmenu .menu-icon-feedback:hover div.wp-menu-image, #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image, #adminmenu .menu-icon-feedback.current div.wp-menu-image { background: url("' .GRUNION_PLUGIN_URL . 'images/grunion-menu-hover.png") no-repeat 7px 7px !important; }
8
- #adminmenu .menu-icon-feedback div.wp-menu-image, #adminmenu .menu-icon-feedback div.wp-menu-image, #adminmenu .menu-icon-feedback div.wp-menu-image { background: url("' . GRUNION_PLUGIN_URL . 'images/grunion-menu.png") no-repeat 7px 7px !important; }
9
- body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image, body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image, body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image { background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSItNDc5LjUgMzAwLjUgMjAgMjAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgLTQ3OS41IDMwMC41IDIwIDIwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0eWxlMHtmaWxsOgkjOTk5OTk5O308L3N0eWxlPjxwYXRoIGQ9Ik0tNDcxLjUgMzA3LjVoNnYzaC02VjMwNy41eiBNLTQ3MS41IDMxMS41aDZ2M2gtNlYzMTEuNXogTS00NzQuNSAzMDcuNWgydjFoLTJWMzA3LjV6IE0tNDc0LjUgMzExLjVoMnYxaC0yIFYzMTEuNXogTS00NjMuNSAzMDEuNWgtMTNjLTAuNDg5IDAtMSAwLjUxMi0xIDF2MTRjMCAwLjUgMC41IDEgMSAxaDEzYzAuNDg5IDAgMS0wLjUxMiAxLTF2LTE0IEMtNDYyLjUgMzAyLjAxMi00NjMuMDExIDMwMS41LTQ2My41IDMwMS41eiBNLTQ2NC41IDMxNS41aC0xMXYtOWgxMVYzMTUuNXoiIGNsYXNzPSJzdHlsZTAiLz48L3N2Zz4=) no-repeat 7px 7px !important; background-size: 20px 20px !important;}
10
- body.admin-color-mp6 #adminmenu .menu-icon-feedback:hover div.wp-menu-image { background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSItNDc5LjUgMzAwLjUgMjAgMjAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgLTQ3OS41IDMwMC41IDIwIDIwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0eWxlMHtmaWxsOgkjMkVBMkNDO308L3N0eWxlPjxwYXRoIGQ9Ik0tNDcxLjUgMzA3LjVoNnYzaC02VjMwNy41eiBNLTQ3MS41IDMxMS41aDZ2M2gtNlYzMTEuNXogTS00NzQuNSAzMDcuNWgydjFoLTJWMzA3LjV6IE0tNDc0LjUgMzExLjVoMnYxaC0yIFYzMTEuNXogTS00NjMuNSAzMDEuNWgtMTNjLTAuNDg5IDAtMSAwLjUxMi0xIDF2MTRjMCAwLjUgMC41IDEgMSAxaDEzYzAuNDg5IDAgMS0wLjUxMiAxLTF2LTE0IEMtNDYyLjUgMzAyLjAxMi00NjMuMDExIDMwMS41LTQ2My41IDMwMS41eiBNLTQ2NC41IDMxNS41aC0xMXYtOWgxMVYzMTUuNXoiIGNsYXNzPSJzdHlsZTAiLz48L3N2Zz4=) no-repeat 7px 7px !important; }
11
- body.admin-color-mp6 #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image, body.admin-color-mp6 #adminmenu .menu-icon-feedback.current div.wp-menu-image { background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iMjBweCIgaGVpZ2h0PSIyMHB4IiB2aWV3Qm94PSItNDc5LjUgMzAwLjUgMjAgMjAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgLTQ3OS41IDMwMC41IDIwIDIwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0eWxlMHtmaWxsOgkjRkZGRkZGO308L3N0eWxlPjxwYXRoIGQ9Ik0tNDcxLjUgMzA3LjVoNnYzaC02VjMwNy41eiBNLTQ3MS41IDMxMS41aDZ2M2gtNlYzMTEuNXogTS00NzQuNSAzMDcuNWgydjFoLTJWMzA3LjV6IE0tNDc0LjUgMzExLjVoMnYxaC0yIFYzMTEuNXogTS00NjMuNSAzMDEuNWgtMTNjLTAuNDg5IDAtMSAwLjUxMi0xIDF2MTRjMCAwLjUgMC41IDEgMSAxaDEzYzAuNDg5IDAgMS0wLjUxMiAxLTF2LTE0IEMtNDYyLjUgMzAyLjAxMi00NjMuMDExIDMwMS41LTQ2My41IDMwMS41eiBNLTQ2NC41IDMxNS41aC0xMXYtOWgxMVYzMTUuNXoiIGNsYXNzPSJzdHlsZTAiLz48L3N2Zz4=) no-repeat 7px 7px !important; }
12
-
13
- .grunion-menu-button { background: url("' . GRUNION_PLUGIN_URL . 'images/grunion-form.png") no-repeat; width: 13px; height: 13px; display: inline-block; vertical-align: middle; ) }
14
- @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
15
- #adminmenu .menu-icon-feedback:hover div.wp-menu-image, #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image, #adminmenu .menu-icon-feedback.current div.wp-menu-image { background: url("' .GRUNION_PLUGIN_URL . 'images/grunion-menu-hover-2x.png") no-repeat 7px 7px !important; background-size: 15px 16px !important; }
16
- #adminmenu .menu-icon-feedback div.wp-menu-image, #adminmenu .menu-icon-feedback div.wp-menu-image, #adminmenu .menu-icon-feedback div.wp-menu-image { background: url("' . GRUNION_PLUGIN_URL . 'images/grunion-menu-2x.png") no-repeat 7px 7px !important; background-size: 15px 16px !important; }
17
- .grunion-menu-button { background-image: url("' . GRUNION_PLUGIN_URL . 'images/grunion-form-2x.png"); background-size: 13px 12px !important; vertical-align: bottom; }
18
- }
19
- </style>';
20
  }
21
 
22
- add_action('admin_head', 'menu_alter');
23
 
24
  /**
25
  * Add a contact form button to the post composition screen
@@ -31,8 +16,13 @@ function grunion_media_button( ) {
31
  $title = esc_attr( __( 'Add a custom form', 'jetpack' ) );
32
  $plugin_url = esc_url( GRUNION_PLUGIN_URL );
33
  $site_url = esc_url( admin_url( "/admin-ajax.php?post_id={$iframe_post_id}&action=grunion_form_builder&TB_iframe=true&width=768" ) );
 
34
 
35
- echo '<a href="' . $site_url . '&id=add_form" class="thickbox" title="' . $title . '"><div class="grunion-menu-button" alt="' . $title . '"></div></a>';
 
 
 
 
36
  }
37
 
38
  add_action( 'wp_ajax_grunion_form_builder', 'display_form_view' );
@@ -46,7 +36,7 @@ function display_form_view() {
46
  add_action( 'admin_print_styles', 'grunion_admin_css' );
47
  function grunion_admin_css() {
48
  global $current_screen;
49
- if ( 'edit-feedback' != $current_screen->id )
50
  return;
51
 
52
  wp_enqueue_script( 'wp-lists' );
@@ -635,3 +625,12 @@ function grunion_ajax_spam() {
635
  echo $status_html;
636
  exit;
637
  }
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ function grunion_menu_alter() {
4
+ wp_enqueue_style( 'grunion-menu-alter', plugins_url( 'css/menu-alter.css', __FILE__ ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  }
6
 
7
+ add_action( 'admin_enqueue_scripts', 'grunion_menu_alter' );
8
 
9
  /**
10
  * Add a contact form button to the post composition screen
16
  $title = esc_attr( __( 'Add a custom form', 'jetpack' ) );
17
  $plugin_url = esc_url( GRUNION_PLUGIN_URL );
18
  $site_url = esc_url( admin_url( "/admin-ajax.php?post_id={$iframe_post_id}&action=grunion_form_builder&TB_iframe=true&width=768" ) );
19
+ ?>
20
 
21
+ <a id="insert-jetpack-contact-form" class="button thickbox" title="<?php esc_html_e( 'Add Contact Form', 'jetpack' ); ?>" data-editor="content" href="<?php echo $site_url ?>&id=add_form">
22
+ <span class="jetpack-contact-form-icon"></span> <?php esc_html_e( 'Add Contact Form', 'jetpack' ); ?>
23
+ </a>
24
+
25
+ <?php
26
  }
27
 
28
  add_action( 'wp_ajax_grunion_form_builder', 'display_form_view' );
36
  add_action( 'admin_print_styles', 'grunion_admin_css' );
37
  function grunion_admin_css() {
38
  global $current_screen;
39
+ if ( ! in_array( $current_screen->id, array( 'edit-feedback', 'jetpack_page_omnisearch', 'dashboard_page_omnisearch' ) ) )
40
  return;
41
 
42
  wp_enqueue_script( 'wp-lists' );
625
  echo $status_html;
626
  exit;
627
  }
628
+
629
+ add_action( 'omnisearch_add_providers', 'grunion_omnisearch_add_providers' );
630
+ function grunion_omnisearch_add_providers() {
631
+ // Feedback uses capability_type 'page'
632
+ if ( current_user_can( 'edit_pages' ) ) {
633
+ require_once( GRUNION_PLUGIN_DIR . '/grunion-omnisearch.php' );
634
+ new Jetpack_Omnisearch_Grunion;
635
+ }
636
+ }
modules/contact-form/css/menu-alter.css ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #menu-posts-feedback .wp-menu-image img {
2
+ display: none;
3
+ }
4
+
5
+ #adminmenu .menu-icon-feedback:hover div.wp-menu-image,
6
+ #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image,
7
+ #adminmenu .menu-icon-feedback.current div.wp-menu-image {
8
+ background: url(../images/grunion-menu-hover.png) no-repeat 7px 7px !important;
9
+ }
10
+
11
+ #adminmenu .menu-icon-feedback div.wp-menu-image {
12
+ background: url(../images/grunion-menu.png) no-repeat 7px 7px !important;
13
+ }
14
+
15
+ body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image {
16
+ background: none !important;
17
+ }
18
+
19
+ body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image:before {
20
+ content: '\f175';
21
+ margin-left: -1px;
22
+ }
23
+
24
+ .jetpack-contact-form-icon {
25
+ background: url(../images/grunion-form.png) no-repeat;
26
+ width: 16px;
27
+ height: 16px;
28
+ display: inline-block;
29
+ vertical-align: middle;
30
+ }
31
+
32
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
33
+ only screen and (-o-min-device-pixel-ratio: 3/2),
34
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
35
+ only screen and (min-device-pixel-ratio: 1.5) {
36
+
37
+ #adminmenu .menu-icon-feedback:hover div.wp-menu-image,
38
+ #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image,
39
+ #adminmenu .menu-icon-feedback.current div.wp-menu-image {
40
+ background: url(../images/grunion-menu-hover-2x.png) no-repeat 7px 7px !important;
41
+ background-size: 15px 16px !important;
42
+ }
43
+
44
+ #adminmenu .menu-icon-feedback div.wp-menu-image {
45
+ background: url(../images/grunion-menu-2x.png) no-repeat 7px 7px !important;
46
+ background-size: 15px 16px !important;
47
+ }
48
+
49
+ .jetpack-contact-form-icon {
50
+ background-image: url(../images/grunion-form-2x.png);
51
+ background-size: 13px 12px !important;
52
+ vertical-align: bottom;
53
+ }
54
+
55
+ }
56
+
modules/contact-form/css/rtl/menu-alter-rtl.css ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file was automatically generated on Jun 19 2013 15:20:57 */
2
+
3
+ #menu-posts-feedback .wp-menu-image img {
4
+ display: none;
5
+ }
6
+
7
+ #adminmenu .menu-icon-feedback:hover div.wp-menu-image,
8
+ #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image,
9
+ #adminmenu .menu-icon-feedback.current div.wp-menu-image {
10
+ background: url(../../images/grunion-menu-hover.png) no-repeat 7px 7px !important;
11
+ }
12
+
13
+ #adminmenu .menu-icon-feedback div.wp-menu-image {
14
+ background: url(../../images/grunion-menu.png) no-repeat 7px 7px !important;
15
+ }
16
+
17
+ body.admin-color-mp6 #adminmenu .toplevel_page_feedback div.wp-menu-image img {
18
+ display: none;
19
+ }
20
+
21
+ body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image, body.admin-color-mp6 #adminmenu .toplevel_page_feedback div.wp-menu-image {
22
+ background: none !important;
23
+ }
24
+
25
+ body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image:before, body.admin-color-mp6 #adminmenu .toplevel_page_feedback div.wp-menu-image:before {
26
+ content: '\f175';
27
+ margin-right: -1px;
28
+ }
29
+
30
+ .jetpack-contact-form-icon {
31
+ background: url(../../images/grunion-form.png) no-repeat;
32
+ width: 16px;
33
+ height: 16px;
34
+ display: inline-block;
35
+ vertical-align: middle;
36
+ }
37
+
38
+ @media only screen and (-moz-min-device-pixel-ratio: 1.5),
39
+ only screen and (-o-min-device-pixel-ratio: 3/2),
40
+ only screen and (-webkit-min-device-pixel-ratio: 1.5),
41
+ only screen and (min-device-pixel-ratio: 1.5) {
42
+
43
+ #adminmenu .menu-icon-feedback:hover div.wp-menu-image,
44
+ #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image,
45
+ #adminmenu .menu-icon-feedback.current div.wp-menu-image {
46
+ background: url(../../images/grunion-menu-hover-2x.png) no-repeat 7px 7px !important;
47
+ background-size: 15px 16px !important;
48
+ }
49
+
50
+ #adminmenu .menu-icon-feedback div.wp-menu-image {
51
+ background: url(../../images/grunion-menu-2x.png) no-repeat 7px 7px !important;
52
+ background-size: 15px 16px !important;
53
+ }
54
+
55
+ .jetpack-contact-form-icon {
56
+ background-image: url(../../images/grunion-form-2x.png);
57
+ background-size: 13px 12px !important;
58
+ vertical-align: bottom;
59
+ }
60
+
61
+ }
62
+
modules/contact-form/grunion-contact-form.php CHANGED
@@ -70,10 +70,16 @@ class Grunion_Contact_Form_Plugin {
70
  add_action( 'wp_ajax_grunion-contact-form', array( $this, 'ajax_request' ) );
71
  add_action( 'wp_ajax_nopriv_grunion-contact-form', array( $this, 'ajax_request' ) );
72
 
 
 
 
 
 
 
73
  // custom post type we'll use to keep copies of the feedback items
74
  register_post_type( 'feedback', array(
75
  'labels' => array(
76
- 'name' => __( 'Feedbacks', 'jetpack' ),
77
  'singular_name' => __( 'Feedback', 'jetpack' ),
78
  'search_items' => __( 'Search Feedback', 'jetpack' ),
79
  'not_found' => __( 'No feedback found', 'jetpack' ),
@@ -181,7 +187,7 @@ class Grunion_Contact_Form_Plugin {
181
  if ( ! $submission_result ) {
182
  header( "HTTP/1.1 500 Server Error", 500, true );
183
  echo '<div class="form-error"><ul class="form-errors"><li class="form-error-message">';
184
- esc_html_e( 'An error occurred. Please try again later.' );
185
  echo '</li></ul></div>';
186
  } elseif ( is_wp_error( $submission_result ) ) {
187
  header( "HTTP/1.1 400 Bad Request", 403, true );
@@ -189,7 +195,7 @@ class Grunion_Contact_Form_Plugin {
189
  echo esc_html( $submission_result->get_error_message() );
190
  echo '</li></ul></div>';
191
  } else {
192
- echo '<h3>' . esc_html__( 'Message Sent' ) . '</h3>' . $submission_result;
193
  }
194
 
195
  die;
@@ -333,6 +339,182 @@ class Grunion_Contact_Form_Plugin {
333
  $response = akismet_http_post( $query_string, $akismet_api_host, "/1.1/submit-{$as}", $akismet_api_port );
334
  return trim( $response[1] );
335
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
336
  }
337
 
338
  /**
@@ -546,11 +728,12 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
546
  }
547
 
548
  $this->defaults = array(
549
- 'to' => $default_to,
550
- 'subject' => $default_subject,
551
- 'show_subject' => 'no', // only used in back-compat mode
552
- 'widget' => 0, // Not exposed to the user. Works with Grunion_Contact_Form_Plugin::widget_atts()
553
- 'id' => null, // Not exposed to the user. Set above.
 
554
  );
555
 
556
  $attributes = shortcode_atts( $this->defaults, $attributes );
@@ -692,7 +875,7 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
692
  $r .= "<form action='" . esc_url( $url ) . "' method='post' class='contact-form commentsblock'>\n";
693
  $r .= $form->body;
694
  $r .= "\t<p class='contact-submit'>\n";
695
- $r .= "\t\t<input type='submit' value='" . esc_attr__( 'Submit &#187;', 'jetpack' ) . "' class='pushbutton-wide'/>\n";
696
  $r .= "\t\t" . wp_nonce_field( 'contact-form_' . $id, '_wpnonce', true, false ) . "\n"; // nonce and referer
697
  $r .= "\t\t<input type='hidden' name='contact-form-id' value='$id' />\n";
698
  $r .= "\t\t<input type='hidden' name='action' value='grunion-contact-form' />\n";
@@ -997,7 +1180,9 @@ class Grunion_Contact_Form extends Crunion_Contact_Form_Shortcode {
997
 
998
  $subject = apply_filters( 'contact_form_subject', $contact_form_subject );
999
 
1000
- $time = date_i18n( __( 'l F j, Y \a\t g:i a', 'jetpack' ), current_time( 'timestamp' ) );
 
 
1001
 
1002
  $extra_content = '';
1003
 
@@ -1419,7 +1604,7 @@ function grunion_delete_old_spam() {
1419
  # nothing special about 5000 or 11
1420
  # just trying to periodically recover deleted rows
1421
  $random_num = mt_rand( 1, 5000 );
1422
- if ( apply_filters( 'grunion_optimize_table', ( $random_number == 11 ) ) ) {
1423
  $wpdb->query( "OPTIMIZE TABLE $wpdb->posts" );
1424
  }
1425
 
70
  add_action( 'wp_ajax_grunion-contact-form', array( $this, 'ajax_request' ) );
71
  add_action( 'wp_ajax_nopriv_grunion-contact-form', array( $this, 'ajax_request' ) );
72
 
73
+ // Export to CSV feature
74
+ if ( is_admin() ) {
75
+ add_action( 'admin_init', array( $this, 'download_feedback_as_csv' ) );
76
+ add_action( 'admin_footer-edit.php', array( $this, 'export_form' ) );
77
+ }
78
+
79
  // custom post type we'll use to keep copies of the feedback items
80
  register_post_type( 'feedback', array(
81
  'labels' => array(
82
+ 'name' => __( 'Feedback', 'jetpack' ),
83
  'singular_name' => __( 'Feedback', 'jetpack' ),
84
  'search_items' => __( 'Search Feedback', 'jetpack' ),
85
  'not_found' => __( 'No feedback found', 'jetpack' ),
187
  if ( ! $submission_result ) {
188
  header( "HTTP/1.1 500 Server Error", 500, true );
189
  echo '<div class="form-error"><ul class="form-errors"><li class="form-error-message">';
190
+ esc_html_e( 'An error occurred. Please try again later.', 'jetpack' );
191
  echo '</li></ul></div>';
192
  } elseif ( is_wp_error( $submission_result ) ) {
193
  header( "HTTP/1.1 400 Bad Request", 403, true );
195
  echo esc_html( $submission_result->get_error_message() );
196
  echo '</li></ul></div>';
197
  } else {
198
+ echo '<h3>' . esc_html__( 'Message Sent', 'jetpack' ) . '</h3>' . $submission_result;
199
  }
200
 
201
  die;
339
  $response = akismet_http_post( $query_string, $akismet_api_host, "/1.1/submit-{$as}", $akismet_api_port );
340
  return trim( $response[1] );
341
  }
342
+
343
+ /**
344
+ * Prints the menu
345
+ */
346
+ function export_form() {
347
+ if ( get_current_screen()->id != 'edit-feedback' )
348
+ return;
349
+
350
+ // if there aren't any feedbacks, bail out
351
+ if ( ! (int) wp_count_posts( 'feedback' )->publish )
352
+ return;
353
+ ?>
354
+
355
+ <div id="feedback-export" style="display:none">
356
+ <h2><?php _e( 'Export feedback as CSV', 'jetpack' ) ?></h2>
357
+ <div class="clear"></div>
358
+ <form action="<?php echo admin_url( 'admin-post.php' ); ?>" method="post" class="form">
359
+ <?php wp_nonce_field( 'feedback_export','feedback_export_nonce' ); ?>
360
+
361
+ <input name="action" value="feedback_export" type="hidden">
362
+ <label for="post"><? _e( 'Select feedback to download', 'jetpack' ) ?></label>
363
+ <select name="post">
364
+ <option value="all"><?php esc_html_e( 'All posts', 'jetpack' ) ?></option>
365
+ <?php echo $this->get_feedbacks_as_options() ?>
366
+ </select>
367
+
368
+ <br><br>
369
+ <input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_html_e( 'Download', 'jetpack' ); ?>">
370
+ </form>
371
+ </div>
372
+
373
+ <?php
374
+ // There aren't any usable actions in core to output the "export feedback" form in the correct place,
375
+ // so this inline JS moves it from the top of the page to the bottom.
376
+ ?>
377
+ <script type='text/javascript'>
378
+ var menu = document.getElementById( 'feedback-export' ),
379
+ wrapper = document.getElementsByClassName( 'wrap' )[0];
380
+ wrapper.appendChild(menu);
381
+ menu.style.display = 'block';
382
+ </script>
383
+ <?php
384
+ }
385
+
386
+ /**
387
+ * download as a csv a contact form or all of them in a csv file
388
+ */
389
+ function download_feedback_as_csv() {
390
+ if ( empty( $_POST['feedback_export_nonce'] ) )
391
+ return;
392
+
393
+ check_admin_referer( 'feedback_export', 'feedback_export_nonce' );
394
+
395
+ $args = array(
396
+ 'posts_per_page' => -1,
397
+ 'post_type' => 'feedback',
398
+ 'post_status' => 'publish',
399
+ 'meta_key' => '_feedback_subject',
400
+ 'orderby' => 'meta_value',
401
+ 'fields' => 'ids',
402
+ 'suppress_filters' => false,
403
+ );
404
+
405
+ $filename = date( "Y-m-d" ) . '-feedback-export.csv';
406
+
407
+ // Check if we want to download all the feedbacks or just a certain contact form
408
+ if ( ! empty( $_POST['post'] ) && $_POST['post'] !== 'all' ) {
409
+ $args['post_parent'] = (int) $_POST['post'];
410
+ $filename = date( "Y-m-d" ) . '-' . str_replace( '&nbsp;', '-', get_the_title( (int) $_POST['post'] ) ) . '.csv';
411
+ }
412
+
413
+ $feedbacks = get_posts( $args );
414
+ $filename = sanitize_file_name( $filename );
415
+ $fields = $this->get_field_names( $feedbacks );
416
+ array_unshift( $fields, __( 'Contact Form', 'jetpack' ) );
417
+
418
+ if ( empty( $feedbacks ) )
419
+ return;
420
+
421
+ // Forces the download of the CSV instead of echoing
422
+ header( 'Content-Disposition: attachment; filename=' . $filename );
423
+ header( 'Pragma: no-cache' );
424
+ header( 'Expires: 0' );
425
+ header( 'Content-Type: text/csv; charset=utf-8' );
426
+
427
+ $output = fopen( 'php://output', 'w' );
428
+
429
+ // Prints the header
430
+ fputcsv( $output, $fields );
431
+
432
+ // Create the csv string from the array of post ids
433
+ foreach ( $feedbacks as $feedback ) {
434
+ fputcsv( $output, self::make_csv_row_from_feedback( $feedback, $fields ) );
435
+ }
436
+
437
+ fclose( $output );
438
+ }
439
+
440
+ /**
441
+ * Returns a string of HTML <option> items from an array of posts
442
+ *
443
+ * @return string a string of HTML <option> items
444
+ */
445
+ protected function get_feedbacks_as_options() {
446
+ $options = '';
447
+
448
+ // Get the feedbacks' parents' post IDs
449
+ $feedbacks = get_posts( array(
450
+ 'fields' => 'id=>parent',
451
+ 'posts_per_page' => -1,
452
+ 'post_type' => 'feedback',
453
+ 'post_status' => 'publish',
454
+ 'suppress_filters' => false,
455
+ ) );
456
+ $parents = array_unique( array_values( $feedbacks ) );
457
+
458
+ $posts = get_posts( array(
459
+ 'orderby' => 'ID',
460
+ 'posts_per_page' => -1,
461
+ 'post_type' => 'any',
462
+ 'post__in' => array_values( $parents ),
463
+ 'suppress_filters' => false,
464
+ ) );
465
+
466
+ // creates the string of <option> elements
467
+ foreach ( $posts as $post ) {
468
+ $options .= sprintf( '<option value="%s">%s</option>', esc_attr( $post->ID ), esc_html( $post->post_title ) );
469
+ }
470
+
471
+ return $options;
472
+ }
473
+
474
+ /**
475
+ * Get the names of all the form's fields
476
+ *
477
+ * @param array|int $posts the post we want the fields of
478
+ * @return array the array of fields
479
+ */
480
+ protected function get_field_names( $posts ) {
481
+ $posts = (array) $posts;
482
+ $all_fields = array();
483
+
484
+ foreach ( $posts as $post ){
485
+ $extra_fields = array_keys( get_post_meta( $post, '_feedback_all_fields', true ) );
486
+ $all_fields = array_merge( $all_fields, $extra_fields );
487
+ }
488
+
489
+ $all_fields = array_unique( $all_fields );
490
+ return $all_fields;
491
+ }
492
+
493
+ /**
494
+ * Creates a valid csv row from a post id
495
+ *
496
+ * @param int $post_id The id of the post
497
+ * @param array $fields An array containing the names of all the fields of the csv
498
+ * @return String The csv row
499
+ */
500
+ protected static function make_csv_row_from_feedback( $post_id, $fields ) {
501
+ $all_fields = get_post_meta( $post_id, '_feedback_all_fields', true );
502
+
503
+ // The first element in all of the exports will be the subject
504
+ $row_items[] = get_post_meta( $post_id, '_feedback_subject', true );
505
+
506
+ // Loop the fields array in order to fill the $row_items array correctly
507
+ foreach ( $fields as $field ) {
508
+ if ( $field === __( 'Contact Form', 'jetpack' ) ) // the first field will ever be the contact form, so we can continue
509
+ continue;
510
+ elseif ( array_key_exists( $field, $all_fields ) )
511
+ $row_items[] = $all_fields[$field];
512
+ else
513
+ $row_items[] = '';
514
+ }
515
+
516
+ return $row_items;
517
+ }
518
  }
519
 
520
  /**
728
  }
729
 
730
  $this->defaults = array(
731
+ 'to' => $default_to,
732
+ 'subject' => $default_subject,
733
+ 'show_subject' => 'no', // only used in back-compat mode
734
+ 'widget' => 0, // Not exposed to the user. Works with Grunion_Contact_Form_Plugin::widget_atts()
735
+ 'id' => null, // Not exposed to the user. Set above.
736
+ 'submit_button_text' => __( 'Submit &#187;', 'jetpack' ),
737
  );
738
 
739
  $attributes = shortcode_atts( $this->defaults, $attributes );
875
  $r .= "<form action='" . esc_url( $url ) . "' method='post' class='contact-form commentsblock'>\n";
876
  $r .= $form->body;
877
  $r .= "\t<p class='contact-submit'>\n";
878
+ $r .= "\t\t<input type='submit' value='" . esc_attr( $form->get_attribute( 'submit_button_text' ) ) . "' class='pushbutton-wide'/>\n";
879
  $r .= "\t\t" . wp_nonce_field( 'contact-form_' . $id, '_wpnonce', true, false ) . "\n"; // nonce and referer
880
  $r .= "\t\t<input type='hidden' name='contact-form-id' value='$id' />\n";
881
  $r .= "\t\t<input type='hidden' name='action' value='grunion-contact-form' />\n";
1180
 
1181
  $subject = apply_filters( 'contact_form_subject', $contact_form_subject );
1182
 
1183
+ $date_time_format = _x( '%1$s \a\t %2$s', '{$date_format} \a\t {$time_format}', 'jetpack' );
1184
+ $date_time_format = sprintf( $date_time_format, get_option( 'date_format' ), get_option( 'time_format' ) );
1185
+ $time = date_i18n( $date_time_format, current_time( 'timestamp' ) );
1186
 
1187
  $extra_content = '';
1188
 
1604
  # nothing special about 5000 or 11
1605
  # just trying to periodically recover deleted rows
1606
  $random_num = mt_rand( 1, 5000 );
1607
+ if ( apply_filters( 'grunion_optimize_table', ( $random_num == 11 ) ) ) {
1608
  $wpdb->query( "OPTIMIZE TABLE $wpdb->posts" );
1609
  }
1610
 
modules/contact-form/grunion-form-view.php CHANGED
@@ -72,8 +72,8 @@ wp_localize_script( 'grunion', 'GrunionFB_i18n', array(
72
  #sidemenu a { text-decoration:none; border-top: 1px solid #FFF; display:block; float:left; line-height:28px; padding:0 13px; outline: none; }
73
  #sidemenu a.current { background-color:#F9F9F9; border-color:#DFDFDF #DFDFDF #F9F9F9; color:#D54E21; -moz-border-radius:4px 4px 0 0; border-radius:4px 4px 0 0; -webkit-border-radius:4px 4px 0 0; border-style:solid; border-width:1px; font-weight:normal; }
74
  #sidemenu li { display:inline; margin-bottom:6px; line-height:200%; list-style:none outside none; margin:0; padding:0; text-align:center; white-space:nowrap; }
75
- .button { background-color:#FFFFFF; background:url("<?php echo get_bloginfo('url'); ?>/wp-admin/images/white-grad.png") repeat-x scroll left top #F2F2F2; border-color:#BBBBBB; min-width:80px; text-align:center; color:#464646; text-shadow:0 1px 0 #FFFFFF; border-style:solid; border-width:1px; cursor:pointer; width: auto; font-size:11px !important; line-height:13px; padding:3px 11px; margin-top: 12px; text-decoration:none; -moz-border-radius:11px; border-radius:11px; -webkit-border-radius:11px }
76
- .button-primary { background-color:#FFFFFF; font-weight: bold; background: url('<?php echo get_bloginfo('url'); ?>/wp-admin/images/button-grad-active.png') repeat-x scroll left top #21759B; border-color:#298CBA; text-align:center; color:#EAF2FA; text-shadow:0 -1px 0 rgba(0, 0, 0, 0.3); border-style:solid; border-width:1px; cursor:pointer; width: auto; font-size:11px !important; line-height:13px; padding:3px 11px; margin-top: 21px; text-decoration:none; -moz-border-radius:11px; border-radius:11px; -webkit-border-radius:11px }
77
  .clear { clear: both; }
78
  .fb-add-field { padding-left: 10px; }
79
  .fb-add-option { margin: 0 0 14px 100px; }
@@ -132,8 +132,8 @@ wp_localize_script( 'grunion', 'GrunionFB_i18n', array(
132
  ); ?></p>
133
  <h3 style="margin-top: 21px;"><?php esc_html_e( 'Can I view my feedback within WordPress?', 'jetpack' ); ?></h3>
134
  <p><?php printf(
135
- esc_html( _x( 'Yep, you can read your feedback at any time by clicking the "%1$s" link in the admin menu.', '%1$s = "Feedbacks" in an HTML link', 'jetpack' ) ),
136
- '<a id="fb-feedback" href="' . admin_url( 'edit.php?post_type=feedback' ) . '">' . esc_html__( 'Feedbacks', 'jetpack' ) . '</a>'
137
  ); ?></p>
138
  <div class="clear"></div>
139
  </div>
72
  #sidemenu a { text-decoration:none; border-top: 1px solid #FFF; display:block; float:left; line-height:28px; padding:0 13px; outline: none; }
73
  #sidemenu a.current { background-color:#F9F9F9; border-color:#DFDFDF #DFDFDF #F9F9F9; color:#D54E21; -moz-border-radius:4px 4px 0 0; border-radius:4px 4px 0 0; -webkit-border-radius:4px 4px 0 0; border-style:solid; border-width:1px; font-weight:normal; }
74
  #sidemenu li { display:inline; margin-bottom:6px; line-height:200%; list-style:none outside none; margin:0; padding:0; text-align:center; white-space:nowrap; }
75
+ .button { background-color:#f2f2f2; border-color:#BBBBBB; min-width:80px; text-align:center; color:#464646; text-shadow:0 1px 0 #FFFFFF; border-style:solid; border-width:1px; cursor:pointer; width: auto; font-size:11px !important; line-height:13px; padding:3px 11px; margin-top: 12px; text-decoration:none; -moz-border-radius:11px; border-radius:11px; -webkit-border-radius:11px }
76
+ .button-primary { background-color:#21759B; font-weight: bold; border-color:#298CBA; text-align:center; color:#EAF2FA; text-shadow:0 -1px 0 rgba(0, 0, 0, 0.3); border-style:solid; border-width:1px; cursor:pointer; width: auto; font-size:11px !important; line-height:13px; padding:3px 11px; margin-top: 21px; text-decoration:none; -moz-border-radius:11px; border-radius:11px; -webkit-border-radius:11px }
77
  .clear { clear: both; }
78
  .fb-add-field { padding-left: 10px; }
79
  .fb-add-option { margin: 0 0 14px 100px; }
132
  ); ?></p>
133
  <h3 style="margin-top: 21px;"><?php esc_html_e( 'Can I view my feedback within WordPress?', 'jetpack' ); ?></h3>
134
  <p><?php printf(
135
+ esc_html( _x( 'Yep, you can read your feedback at any time by clicking the "%1$s" link in the admin menu.', '%1$s = "Feedback" in an HTML link', 'jetpack' ) ),
136
+ '<a id="fb-feedback" href="' . admin_url( 'edit.php?post_type=feedback' ) . '">' . esc_html__( 'Feedback', 'jetpack' ) . '</a>'
137
  ); ?></p>
138
  <div class="clear"></div>
139
  </div>
modules/contact-form/grunion-omnisearch.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists( 'WP_List_Table' ) )
4
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
5
+
6
+ class Jetpack_Omnisearch_Grunion extends WP_List_Table {
7
+ static $instance;
8
+ var $post_type = 'feedback';
9
+
10
+ function __construct() {
11
+ self::$instance = $this;
12
+ add_filter( 'omnisearch_results', array( $this, 'search'), 12, 2 );
13
+ }
14
+
15
+ function search( $results, $search_term ) {
16
+ parent::__construct();
17
+
18
+ $this->post_type_obj = get_post_type_object( $this->post_type );
19
+
20
+ $search_url = esc_url( admin_url( sprintf( 'edit.php?post_type=%s&s=%s', urlencode( $this->post_type_obj->name ), urlencode( $search_term ) ) ) );
21
+ $search_link = sprintf( ' <a href="%s" class="add-new-h2">%s</a>', $search_url, esc_html( $this->post_type_obj->labels->search_items ) );
22
+ $html = '<h2>' . esc_html( $this->post_type_obj->labels->name ) . $search_link .'</h2>';
23
+
24
+ $this->prepare_items( $search_term );
25
+
26
+ ob_start();
27
+ $this->display();
28
+ $html .= ob_get_clean();
29
+
30
+ $results[ $this->post_type_obj->labels->name ] = $html;
31
+ return $results;
32
+ }
33
+
34
+ function get_columns() {
35
+ $columns = array(
36
+ 'feedback_from' => __('From', 'jetpack'),
37
+ 'feedback_message' => __('Message', 'jetpack'),
38
+ 'feedback_date' => __('Date', 'jetpack'),
39
+ );
40
+ return $columns;
41
+ }
42
+
43
+ function prepare_items( $search_term = '' ) {
44
+ $this->_column_headers = array( $this->get_columns(), array(), array() );
45
+ $num_results = apply_filters( 'omnisearch_num_results', 5 );
46
+ $this->items = get_posts( array(
47
+ 's' => $search_term,
48
+ 'post_type' => $this->post_type,
49
+ 'posts_per_page' => $num_results,
50
+ ) );
51
+ }
52
+
53
+ function column_default( $post, $column_name ) {
54
+ switch ( $column_name ) {
55
+ case 'feedback_from':
56
+ case 'feedback_message':
57
+ case 'feedback_date':
58
+ ob_start();
59
+ grunion_manage_post_columns( $column_name, $post->ID );
60
+ return ob_get_clean();
61
+ default:
62
+ return '<pre>' . print_r( $post, true ) . '</pre>';
63
+ }
64
+ }
65
+ }
modules/contact-form/js/grunion.js CHANGED
@@ -426,7 +426,7 @@ FB.ContactForm = function() {
426
  function showAndHideMessage (message) {
427
  try {
428
  var newMessage = (!message) ? GrunionFB_i18n.savedMessage : message;
429
- jQuery('#fb-success').html(newMessage);
430
  jQuery('#fb-success').slideDown('fast');
431
  setTimeout(function () {
432
  jQuery('#fb-success').slideUp('fast');
@@ -463,9 +463,9 @@ FB.ContactForm = function() {
463
  var thisLabel = jQuery('#fb-new-label').val();
464
  // Update preview
465
  if (thisLabel.length === 0) {
466
- jQuery('#fb-new-field' + thisId + ' label .label-text').html("New field");
467
  } else {
468
- jQuery('#fb-new-field' + thisId + ' label .label-text').html(thisLabel);
469
  }
470
  // Update fbForm object
471
  fbForm.fields[thisId].label = thisLabel;
@@ -493,7 +493,7 @@ FB.ContactForm = function() {
493
  var thisType = jQuery('#fb-new-type').val();
494
  // Update preview
495
  if (thisType === "radio") {
496
- jQuery('#fb-radio-' + thisId + '-' + thisOptionid + ' span').html(thisOptionValue);
497
  } else {
498
  jQuery('#fb-' + thisId + '-' + thisOptionid).text(thisOptionValue);
499
  }
@@ -538,7 +538,7 @@ FB.ContactForm = function() {
538
  var isLoaded = thisType;
539
  var thisId = jQuery('#fb-field-id').val();
540
  if (!thisType) { var thisType = jQuery('#fb-new-type').val(); }
541
- if (!thisLabelText) { var thisLabelText = jQuery('#fb-new-field' + thisId + ' .label-text').html(); }
542
  var isRequired = (thisRequired) ? '<span class="label-required">' + GrunionFB_i18n.requiredLabel + '</span>' : '';
543
  var thisLabel = '<label fieldid="' + thisId + '" for="fb-field' + thisId + '"><span class="label-text">' + FB.esc_html( thisLabelText ) + '</span>' + isRequired + '</label>';
544
  var thisRadio = '<input type="radio" name="radio-' + thisId + '" id="fb-field' + thisId + ' "disabled="disabled" />';
426
  function showAndHideMessage (message) {
427
  try {
428
  var newMessage = (!message) ? GrunionFB_i18n.savedMessage : message;
429
+ jQuery('#fb-success').text(newMessage);
430
  jQuery('#fb-success').slideDown('fast');
431
  setTimeout(function () {
432
  jQuery('#fb-success').slideUp('fast');
463
  var thisLabel = jQuery('#fb-new-label').val();
464
  // Update preview
465
  if (thisLabel.length === 0) {
466
+ jQuery('#fb-new-field' + thisId + ' label .label-text').text( GrunionFB_i18n.newLabel );
467
  } else {
468
+ jQuery('#fb-new-field' + thisId + ' label .label-text').text( thisLabel );
469
  }
470
  // Update fbForm object
471
  fbForm.fields[thisId].label = thisLabel;
493
  var thisType = jQuery('#fb-new-type').val();
494
  // Update preview
495
  if (thisType === "radio") {
496
+ jQuery('#fb-radio-' + thisId + '-' + thisOptionid + ' span').text(thisOptionValue);
497
  } else {
498
  jQuery('#fb-' + thisId + '-' + thisOptionid).text(thisOptionValue);
499
  }
538
  var isLoaded = thisType;
539
  var thisId = jQuery('#fb-field-id').val();
540
  if (!thisType) { var thisType = jQuery('#fb-new-type').val(); }
541
+ if (!thisLabelText) { var thisLabelText = jQuery('#fb-new-field' + thisId + ' .label-text').text(); }
542
  var isRequired = (thisRequired) ? '<span class="label-required">' + GrunionFB_i18n.requiredLabel + '</span>' : '';
543
  var thisLabel = '<label fieldid="' + thisId + '" for="fb-field' + thisId + '"><span class="label-text">' + FB.esc_html( thisLabelText ) + '</span>' + isRequired + '</label>';
544
  var thisRadio = '<input type="radio" name="radio-' + thisId + '" id="fb-field' + thisId + ' "disabled="disabled" />';
modules/contact-form/js/jquery-ui-1.8.4.custom.min.js DELETED
@@ -1,185 +0,0 @@
1
- /*!
2
- * jQuery UI 1.8.4
3
- *
4
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
5
- * Dual licensed under the MIT or GPL Version 2 licenses.
6
- * http://jquery.org/license
7
- *
8
- * http://docs.jquery.com/UI
9
- */
10
- (function(c,j){function k(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.4",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,
11
- b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&&c.ui.isOverAxis(b,e,i)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,
12
- CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable",
13
- "off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,
14
- "overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.each(["Width","Height"],function(a,b){function d(f,g,l,m){c.each(e,function(){g-=
15
- parseFloat(c.curCSS(f,"padding"+this,true))||0;if(l)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(m)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c.style(this,h,d(this,f)+"px")})};c.fn["outer"+
16
- b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c.style(this,h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");if("area"===b){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&k(a)}return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==
17
- b?a.href||!isNaN(d):!isNaN(d))&&k(a)},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}})(jQuery);
18
- ;/*!
19
- * jQuery UI Widget 1.8.4
20
- *
21
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
22
- * Dual licensed under the MIT or GPL Version 2 licenses.
23
- * http://jquery.org/license
24
- *
25
- * http://docs.jquery.com/UI/Widget
26
- */
27
- (function(b,j){var k=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return k.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);
28
- b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):
29
- this.each(function(){var g=b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});
30
- this._create();this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}b.each(d,function(f,
31
- h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=
32
- b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
33
- ;/*!
34
- * jQuery UI Mouse 1.8.4
35
- *
36
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
37
- * Dual licensed under the MIT or GPL Version 2 licenses.
38
- * http://jquery.org/license
39
- *
40
- * http://docs.jquery.com/UI/Mouse
41
- *
42
- * Depends:
43
- * jquery.ui.widget.js
44
- */
45
- (function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&
46
- this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();
47
- return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&
48
- this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
49
- a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
50
- ;/*
51
- * jQuery UI Draggable 1.8.4
52
- *
53
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
54
- * Dual licensed under the MIT or GPL Version 2 licenses.
55
- * http://jquery.org/license
56
- *
57
- * http://docs.jquery.com/UI/Draggables
58
- *
59
- * Depends:
60
- * jquery.ui.core.js
61
- * jquery.ui.mouse.js
62
- * jquery.ui.widget.js
63
- */
64
- (function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==
65
- "original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b=
66
- this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-
67
- this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();
68
- d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||
69
- this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,
70
- b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==
71
- a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
72
- 0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
73
- this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-
74
- (parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment==
75
- "parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&
76
- a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),
77
- 10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
78
- this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():
79
- f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])e=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+
80
- this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+
81
- Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-
82
- this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=
83
- this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.4"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");
84
- if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;
85
- c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=
86
- 1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;
87
- this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=
88
- this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","iframeFix",{start:function(){var a=
89
- d(this).data("draggable").options;d(a.iframeFix===true?"iframe":a.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;
90
- if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!=
91
- "HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-
92
- b.overflowOffset.left<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-
93
- c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,
94
- width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,g=b.offset.left,n=g+c.helperProportions.width,m=b.offset.top,o=m+c.helperProportions.height,h=c.snapElements.length-1;h>=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e<g&&g<k+e&&j-e<m&&m<l+e||i-e<g&&g<k+e&&j-e<o&&o<l+e||i-e<n&&n<k+e&&j-e<m&&m<l+e||i-e<n&&n<k+e&&j-e<o&&
95
- o<l+e){if(f.snapMode!="inner"){var p=Math.abs(j-o)<=e,q=Math.abs(l-m)<=e,r=Math.abs(i-n)<=e,s=Math.abs(k-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k}).left-c.margins.left}var t=
96
- p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.abs(i-g)<=e;s=Math.abs(k-n)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[h].snapping&&
97
- (p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
98
- 10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
99
- ;/*
100
- * jQuery UI Droppable 1.8.4
101
- *
102
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
103
- * Dual licensed under the MIT or GPL Version 2 licenses.
104
- * http://jquery.org/license
105
- *
106
- * http://docs.jquery.com/UI/Droppables
107
- *
108
- * Depends:
109
- * jquery.ui.core.js
110
- * jquery.ui.widget.js
111
- * jquery.ui.mouse.js
112
- * jquery.ui.draggable.js
113
- */
114
- (function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this);
115
- a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&
116
- this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
117
- this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
118
- d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
119
- a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.4"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
120
- switch(c){case "fit":return i<=e&&g<=k&&j<=f&&h<=l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=
121
- i&&e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
122
- "none";if(c[f].visible){c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight};e=="mousedown"&&c[f]._activate.call(c[f],b)}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
123
- a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=
124
- d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})}}})(jQuery);
125
- ;/*
126
- * jQuery UI Sortable 1.8.4
127
- *
128
- * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
129
- * Dual licensed under the MIT or GPL Version 2 licenses.
130
- * http://jquery.org/license
131
- *
132
- * http://docs.jquery.com/UI/Sortables
133
- *
134
- * Depends:
135
- * jquery.ui.core.js
136
- * jquery.ui.mouse.js
137
- * jquery.ui.widget.js
138
- */
139
- (function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
140
- this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,
141
- arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
142
- c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
143
- {click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
144
- if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
145
- a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
146
- if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
147
- this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
148
- b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
149
- "px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
150
- c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
151
- document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",
152
- null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):
153
- d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||
154
- "id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+
155
- this.helperProportions.width/2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?
156
- 2:1)},_intersectsWithSides:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},
157
- _getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=
158
- this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=
159
- this.currentItem.find(":data(sortable-item)"),b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");
160
- if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=
161
- 0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=
162
- this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},
163
- update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=
164
- null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));
165
- this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,
166
- null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||
167
- d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a==
168
- "string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition==
169
- "absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition==
170
- "relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},
171
- _setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-
172
- this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),
173
- 10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?
174
- this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=
175
- this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+
176
- this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?
177
- g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():
178
- e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==
179
- f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",
180
- f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",
181
- g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=
182
- 0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
183
- this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});
184
- d.extend(d.ui.sortable,{version:"1.8.4"})})(jQuery);
185
- ;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/custom-css/csstidy/class.csstidy_optimise.php CHANGED
@@ -262,8 +262,7 @@ class csstidy_optimise {
262
  */
263
  function compress_important(&$string) {
264
  if (csstidy::is_important($string)) {
265
- $string = csstidy::gvw_important($string) . '!important';
266
- }
267
  return $string;
268
  }
269
 
262
  */
263
  function compress_important(&$string) {
264
  if (csstidy::is_important($string)) {
265
+ $string = csstidy::gvw_important($string) . ' !important'; }
 
266
  return $string;
267
  }
268
 
modules/custom-css/csstidy/data.inc.php CHANGED
@@ -587,7 +587,7 @@ $GLOBALS['csstidy']['quoted_string_properties'] = array('content', 'font', 'font
587
  *
588
  * @global array $GLOBALS['csstidy']['quoted_string_properties']
589
  */
590
- $GLOBALS['csstidy']['multiple_properties'] = array_merge( $GLOBALS['csstidy']['color_values'], $GLOBALS['csstidy']['unit_values'], array('transition') );
591
 
592
  /**
593
  * An array containing all predefined templates.
587
  *
588
  * @global array $GLOBALS['csstidy']['quoted_string_properties']
589
  */
590
+ $GLOBALS['csstidy']['multiple_properties'] = array_merge( $GLOBALS['csstidy']['color_values'], $GLOBALS['csstidy']['unit_values'], array( 'transition', 'background-image', 'border-image', 'list-style-image' ) );
591
 
592
  /**
593
  * An array containing all predefined templates.
modules/custom-css/custom-css.php CHANGED
@@ -58,6 +58,9 @@ class Jetpack_Custom_CSS {
58
 
59
  add_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
60
 
 
 
 
61
  if ( !current_user_can( 'switch_themes' ) && !is_super_admin() )
62
  return;
63
 
@@ -86,9 +89,6 @@ class Jetpack_Custom_CSS {
86
  // Modify all internal links so that preview state persists
87
  if ( Jetpack_Custom_CSS::is_preview() )
88
  ob_start( array( 'Jetpack_Custom_CSS', 'buffer' ) );
89
-
90
- add_filter( 'jetpack_content_width', array( 'Jetpack_Custom_CSS', 'jetpack_content_width' ) );
91
- add_filter( 'editor_max_image_size', array( 'Jetpack_Custom_CSS', 'editor_max_image_size' ), 10, 3 );
92
  }
93
 
94
  /**
@@ -187,6 +187,9 @@ class Jetpack_Custom_CSS {
187
  update_metadata( 'post', $safecss_revision_id, 'content_width', $args['content_width'] );
188
  update_metadata( 'post', $safecss_revision_id, 'custom_css_preprocessor', $args['preprocessor'] );
189
 
 
 
 
190
  if ( $args['is_preview'] ) {
191
  return $safecss_revision_id;
192
  }
@@ -205,10 +208,16 @@ class Jetpack_Custom_CSS {
205
  update_post_meta( $safecss_post_id, 'custom_css_add', $add_to_existing );
206
  update_post_meta( $safecss_post_id, 'content_width', $args['content_width'] );
207
  update_post_meta( $safecss_post_id, 'custom_css_preprocessor', $args['preprocessor'] );
 
 
 
 
208
  update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_add', $add_to_existing );
209
  update_metadata( 'post', $safecss_post_revision['ID'], 'content_width', $args['content_width'] );
210
  update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_preprocessor', $args['preprocessor'] );
211
 
 
 
212
  return $safecss_post_id;
213
  }
214
 
@@ -373,10 +382,17 @@ class Jetpack_Custom_CSS {
373
  else {
374
  $custom_css_post_id = Jetpack_Custom_CSS::post_id();
375
 
376
- if ( $custom_css_post_id )
377
- return (bool) ( get_post_meta( $custom_css_post_id, 'custom_css_add', true ) == 'no' );
378
- else
379
- return (bool) ( get_option( 'safecss_add' ) == 'no' );
 
 
 
 
 
 
 
380
  }
381
  }
382
  }
@@ -508,7 +524,7 @@ class Jetpack_Custom_CSS {
508
  if ( $css == '' )
509
  return;
510
 
511
- $href = trailingslashit( site_url() );
512
  $href = add_query_arg( 'custom-css', 1, $href );
513
  $href = add_query_arg( 'csblog', $blog_id, $href );
514
  $href = add_query_arg( 'cscache', 6, $href );
@@ -957,9 +973,15 @@ class Jetpack_Custom_CSS {
957
  update_post_meta( $safecss_post_id, 'custom_css_add', 'yes' );
958
  update_post_meta( $safecss_post_id, 'content_width', false );
959
  update_post_meta( $safecss_post_id, 'custom_css_preprocessor', '' );
 
 
 
 
960
  update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', 'yes' );
961
  update_metadata( 'post', $safecss_revision['ID'], 'content_width', false );
962
  update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', '' );
 
 
963
  }
964
 
965
  static function is_customizer_preview() {
@@ -1017,9 +1039,15 @@ class Jetpack_Custom_CSS {
1017
  update_metadata( 'post', $safecss_revision['ID'], 'content_width', $content_width );
1018
  update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', $custom_css_add );
1019
  update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', $preprocessor );
 
 
 
 
1020
  update_post_meta( $_post->ID, 'content_width', $content_width );
1021
  update_post_meta( $_post->ID, 'custom_css_add', $custom_css_add );
1022
  update_post_meta( $_post->ID, 'custom_css_preprocessor', $preprocessor );
 
 
1023
  }
1024
 
1025
  /**
58
 
59
  add_action( 'wp_head', array( 'Jetpack_Custom_CSS', 'link_tag' ), 101 );
60
 
61
+ add_filter( 'jetpack_content_width', array( 'Jetpack_Custom_CSS', 'jetpack_content_width' ) );
62
+ add_filter( 'editor_max_image_size', array( 'Jetpack_Custom_CSS', 'editor_max_image_size' ), 10, 3 );
63
+
64
  if ( !current_user_can( 'switch_themes' ) && !is_super_admin() )
65
  return;
66
 
89
  // Modify all internal links so that preview state persists
90
  if ( Jetpack_Custom_CSS::is_preview() )
91
  ob_start( array( 'Jetpack_Custom_CSS', 'buffer' ) );
 
 
 
92
  }
93
 
94
  /**
187
  update_metadata( 'post', $safecss_revision_id, 'content_width', $args['content_width'] );
188
  update_metadata( 'post', $safecss_revision_id, 'custom_css_preprocessor', $args['preprocessor'] );
189
 
190
+ delete_option( 'safecss_add' );
191
+ delete_option( 'safecss_content_width' );
192
+
193
  if ( $args['is_preview'] ) {
194
  return $safecss_revision_id;
195
  }
208
  update_post_meta( $safecss_post_id, 'custom_css_add', $add_to_existing );
209
  update_post_meta( $safecss_post_id, 'content_width', $args['content_width'] );
210
  update_post_meta( $safecss_post_id, 'custom_css_preprocessor', $args['preprocessor'] );
211
+
212
+ delete_option( 'safecss_add' );
213
+ delete_option( 'safecss_content_width' );
214
+
215
  update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_add', $add_to_existing );
216
  update_metadata( 'post', $safecss_post_revision['ID'], 'content_width', $args['content_width'] );
217
  update_metadata( 'post', $safecss_post_revision['ID'], 'custom_css_preprocessor', $args['preprocessor'] );
218
 
219
+ delete_option( 'safecss_preview_add' );
220
+
221
  return $safecss_post_id;
222
  }
223
 
382
  else {
383
  $custom_css_post_id = Jetpack_Custom_CSS::post_id();
384
 
385
+ if ( $custom_css_post_id ) {
386
+ $custom_css_add = get_post_meta( $custom_css_post_id, 'custom_css_add', true );
387
+
388
+ // It is possible for the CSS to be stored in a post but for the safecss_add option
389
+ // to have not been upgraded yet if the user hasn't opened their Custom CSS editor
390
+ // since October 2012.
391
+ if ( ! empty( $custom_css_add ) )
392
+ return (bool) ( $custom_css_add === 'no' );
393
+ }
394
+
395
+ return (bool) ( get_option( 'safecss_add' ) == 'no' );
396
  }
397
  }
398
  }
524
  if ( $css == '' )
525
  return;
526
 
527
+ $href = home_url( '/' );
528
  $href = add_query_arg( 'custom-css', 1, $href );
529
  $href = add_query_arg( 'csblog', $blog_id, $href );
530
  $href = add_query_arg( 'cscache', 6, $href );
973
  update_post_meta( $safecss_post_id, 'custom_css_add', 'yes' );
974
  update_post_meta( $safecss_post_id, 'content_width', false );
975
  update_post_meta( $safecss_post_id, 'custom_css_preprocessor', '' );
976
+
977
+ delete_option( 'safecss_add' );
978
+ delete_option( 'safecss_content_width' );
979
+
980
  update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', 'yes' );
981
  update_metadata( 'post', $safecss_revision['ID'], 'content_width', false );
982
  update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', '' );
983
+
984
+ delete_option( 'safecss_preview_add' );
985
  }
986
 
987
  static function is_customizer_preview() {
1039
  update_metadata( 'post', $safecss_revision['ID'], 'content_width', $content_width );
1040
  update_metadata( 'post', $safecss_revision['ID'], 'custom_css_add', $custom_css_add );
1041
  update_metadata( 'post', $safecss_revision['ID'], 'custom_css_preprocessor', $preprocessor );
1042
+
1043
+ delete_option( 'safecss_add' );
1044
+ delete_option( 'safecss_content_width' );
1045
+
1046
  update_post_meta( $_post->ID, 'content_width', $content_width );
1047
  update_post_meta( $_post->ID, 'custom_css_add', $custom_css_add );
1048
  update_post_meta( $_post->ID, 'custom_css_preprocessor', $preprocessor );
1049
+
1050
+ delete_option( 'safecss_preview_add' );
1051
  }
1052
 
1053
  /**
modules/custom-post-types/comics.php ADDED
@@ -0,0 +1,467 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Jetpack_Comic {
4
+ const POST_TYPE = 'jetpack-comic';
5
+
6
+ function init() {
7
+ static $instance = false;
8
+
9
+ if ( ! $instance )
10
+ $instance = new Jetpack_Comic;
11
+
12
+ return $instance;
13
+ }
14
+
15
+ /**
16
+ * Conditionally hook into WordPress.
17
+ *
18
+ * Themes must declare that they support this module by adding
19
+ * add_theme_support( 'jetpack-comic' ); during after_setup_theme.
20
+ *
21
+ * If no theme support is found there is no need to hook into
22
+ * WordPress. We'll just return early instead.
23
+ */
24
+ function __construct() {
25
+ // Return early if theme does not support Jetpack Comic.
26
+ if ( ! ( $this->site_supports_comics() ) )
27
+ return;
28
+
29
+ $this->register_post_types();
30
+
31
+ add_action( 'pre_get_posts', array( $this, 'add_posts_to_loop' ) );
32
+
33
+ // In order for the Feedbag job to find Comic posts, we need to circumvent any pretty
34
+ // URLs in the RSS feed given to Feedbag in favor of /?p=123&post_type=jetpack-comic
35
+ add_filter( 'the_permalink_rss', array( $this, 'custom_permalink_for_feedbag' ) );
36
+
37
+ // There are some cases (like when Feedbag is fetching posts) that the comics
38
+ // post type needs to be registered no matter what, but none of the UI needs to be
39
+ // available.
40
+
41
+ // Enable Omnisearch for Comic posts.
42
+ // @see http://themedevp2.wordpress.com/2013/06/21/howdy-cainm-id-like-to // @wpcom
43
+ if ( class_exists( 'Jetpack_Omnisearch_Posts' ) )
44
+ new Jetpack_Omnisearch_Posts( self::POST_TYPE );
45
+
46
+ add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
47
+
48
+ add_action( 'publish_jetpack-comic', 'queue_publish_post', 10, 2 );
49
+ add_action( 'pre_get_posts', array( $this, 'include_in_feeds' ) );
50
+
51
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
52
+
53
+ add_filter( 'manage_' . self::POST_TYPE . '_posts_columns', array( $this, 'manage_posts_columns' ) );
54
+ add_action( 'manage_' . self::POST_TYPE . '_posts_custom_column', array( $this, 'manage_posts_custom_column' ), 10, 2 );
55
+ add_image_size( 'jetpack-comic-thumb', 150, 0, false );
56
+
57
+ // Enable front-end uploading for users special enough.
58
+ if ( current_user_can( 'upload_files' ) && current_user_can( 'edit_posts' ) ) {
59
+ add_action( 'wp_ajax_jetpack_comic_upload', array( $this, 'upload' ) );
60
+ add_action( 'wp_enqueue_scripts', array( $this, 'register_scripts' ) );
61
+ }
62
+
63
+ /**
64
+ * Add a "Convert to Comic" and "Convert to Post" option to the bulk
65
+ * edit dropdowns.
66
+ */
67
+ add_action( 'admin_footer-edit.php', array( $this, 'admin_footer' ) );
68
+ add_action( 'load-edit.php', array( $this, 'bulk_edit' ) );
69
+ add_action( 'admin_notices', array( $this, 'bulk_edit_notices' ) );
70
+ }
71
+
72
+ public function admin_footer() {
73
+ $post_type = get_post_type();
74
+
75
+ ?>
76
+ <script type="text/javascript">
77
+ jQuery( document ).ready( function( $ ) {
78
+ <?php if ( ! $post_type || 'post' == $post_type ) { ?>
79
+ $( '<option>' )
80
+ .val( 'post2comic' )
81
+ .text( <?php echo json_encode( __( 'Convert to Comic' ) ); ?> )
82
+ .appendTo( "select[name='action'], select[name='action2']" );
83
+ <?php } ?>
84
+ <?php if ( ! $post_type || self::POST_TYPE == $post_type ) { ?>
85
+ $( '<option>' )
86
+ .val( 'comic2post' )
87
+ .text( <?php echo json_encode( __( 'Convert to Post' ) ); ?> )
88
+ .appendTo( "select[name='action'], select[name='action2']" );
89
+ <?php } ?>
90
+
91
+ $( '#message.jetpack-comic-post-type-conversion' ).remove().insertAfter( $( '.wrap h2:first' ) ).show();
92
+ });
93
+ </script>
94
+ <?php
95
+ }
96
+
97
+ /**
98
+ * Handle the "Convert to [Post|Comic]" bulk action.
99
+ */
100
+ public function bulk_edit() {
101
+ if ( empty( $_REQUEST['post'] ) )
102
+ return;
103
+
104
+ $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
105
+ $action = $wp_list_table->current_action();
106
+
107
+ check_admin_referer( 'bulk-posts' );
108
+
109
+ if ( 'post2comic' == $action || 'comic2post' == $action ) {
110
+ if ( ! current_user_can( 'publish_posts' ) )
111
+ wp_die( __( 'You are not allowed to make this change.' ) );
112
+
113
+ $post_ids = array_map( 'intval', $_REQUEST['post'] );
114
+
115
+ $modified_count = 0;
116
+
117
+ foreach ( $post_ids as $post_id ) {
118
+ $destination_post_type = ( $action == 'post2comic' ) ? self::POST_TYPE : 'post';
119
+ $origin_post_type = ( $destination_post_type == 'post' ) ? self::POST_TYPE : 'post';
120
+
121
+ if ( current_user_can( 'edit_post', $post_id ) ) {
122
+ $post = get_post( $post_id );
123
+
124
+ // Only convert posts that are post => comic or comic => post.
125
+ // (e.g., Ignore comic => comic, page => post, etc. )
126
+ if ( $post->post_type != $destination_post_type && $post->post_type == $origin_post_type ) {
127
+ $post_type_object = get_post_type_object( $destination_post_type );
128
+
129
+ if ( current_user_can( $post_type_object->cap->publish_posts ) ) {
130
+ set_post_type( $post_id, $destination_post_type );
131
+ $modified_count++;
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ $sendback = remove_query_arg( array( 'exported', 'untrashed', 'deleted', 'ids' ), wp_get_referer() );
138
+
139
+ if ( ! $sendback )
140
+ $sendback = add_query_arg( array( 'post_type', get_post_type() ), admin_url( 'edit.php' ) );
141
+
142
+ $pagenum = $wp_list_table->get_pagenum();
143
+ $sendback = add_query_arg( array( 'paged' => $pagenum, 'post_type_changed' => $modified_count ), $sendback );
144
+
145
+ wp_redirect( $sendback );
146
+ exit();
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Show the post conversion success notice.
152
+ */
153
+ public function bulk_edit_notices() {
154
+ global $pagenow;
155
+
156
+ if ( 'edit.php' == $pagenow && ! empty( $_GET['post_type_changed'] ) ) {
157
+ ?><div id="message" class="updated below-h2 jetpack-comic-post-type-conversion" style="display: none;"><p><?php
158
+ printf( _n( 'Post converted.', '%s posts converted', $_GET['post_type_changed'] ), number_format_i18n( $_GET['post_type_changed'] ) );
159
+ ?></p></div><?php
160
+ }
161
+ }
162
+
163
+ public function register_scripts() {
164
+ wp_enqueue_style( 'jetpack-comics-style', plugins_url( 'comics/comics.css', __FILE__ ) );
165
+ wp_enqueue_script( 'jetpack-comics', plugins_url( 'comics/comics.js', __FILE__ ), array( 'jquery', 'jquery.spin' ) );
166
+
167
+ $options = array(
168
+ 'nonce' => wp_create_nonce( 'jetpack_comic_upload_nonce' ),
169
+ 'writeURL' => admin_url( 'admin-ajax.php?action=jetpack_comic_upload' ),
170
+ 'labels' => array(
171
+ 'dragging' => __( 'Drop images to upload', 'jetpack' ),
172
+ 'uploading' => __( 'Uploading...', 'jetpack' ),
173
+ 'processing' => __( 'Processing...', 'jetpack' ),
174
+ 'unsupported' => __( "Sorry, your browser isn't supported. Upgrade at browsehappy.com." ),
175
+ 'invalidUpload' => __( 'Only images can be uploaded here.', 'jetpack' ),
176
+ 'error' => __( "Your upload didn't complete; try again later or cross your fingers and try again right now.", 'jetpack' ),
177
+ )
178
+ );
179
+
180
+ wp_localize_script( 'jetpack-comics', 'Jetpack_Comics_Options', $options );
181
+ }
182
+
183
+ public function admin_enqueue_scripts() {
184
+ wp_enqueue_style( 'jetpack-comics-admin', plugins_url( 'comics/admin.css', __FILE__ ) );
185
+ }
186
+
187
+ function register_post_types() {
188
+ register_post_type( self::POST_TYPE, array(
189
+ 'description' => __( 'Comics', 'jetpack' ),
190
+ 'labels' => array(
191
+ 'name' => esc_html__( 'Comics', 'jetpack' ),
192
+ 'singular_name' => esc_html__( 'Comic', 'jetpack' ),
193
+ 'menu_name' => esc_html__( 'Comics', 'jetpack' ),
194
+ 'all_items' => esc_html__( 'All Comics', 'jetpack' ),
195
+ 'add_new' => esc_html__( 'Add New', 'jetpack' ),
196
+ 'add_new_item' => esc_html__( 'Add New Comic', 'jetpack' ),
197
+ 'edit_item' => esc_html__( 'Edit Comic', 'jetpack' ),
198
+ 'new_item' => esc_html__( 'New Comic', 'jetpack' ),
199
+ 'view_item' => esc_html__( 'View Comic', 'jetpack' ),
200
+ 'search_items' => esc_html__( 'Search Comics', 'jetpack' ),
201
+ 'not_found' => esc_html__( 'No Comics found', 'jetpack' ),
202
+ 'not_found_in_trash' => esc_html__( 'No Comics found in Trash', 'jetpack' ),
203
+ ),
204
+ 'supports' => array(
205
+ 'title',
206
+ 'editor',
207
+ 'thumbnail',
208
+ 'comments',
209
+ 'revisions',
210
+ 'publicize', // Jetpack
211
+ 'subscriptions', // wpcom
212
+ 'shortlinks', // Jetpack
213
+ ),
214
+ 'rewrite' => array(
215
+ 'slug' => 'comic',
216
+ 'with_front' => false,
217
+ ),
218
+ 'taxonomies' => array(
219
+ 'category',
220
+ 'post_tag',
221
+ ),
222
+ // Only make the type public for sites that support Comics.
223
+ 'public' => true,
224
+ 'menu_position' => 5, // below Posts
225
+ 'map_meta_cap' => true,
226
+ 'has_archive' => true,
227
+ 'query_var' => 'comic',
228
+ ) );
229
+ }
230
+
231
+ public function manage_posts_columns( $columns ) {
232
+ $new_columns = array(
233
+ 'preview-jetpack-comic' => __( 'Preview', 'jetpack' ),
234
+ );
235
+ return array_merge( array_slice( $columns, 0, 2 ), $new_columns, array_slice( $columns, 2 ) );
236
+ }
237
+
238
+ public function manage_posts_custom_column( $column_name, $post_ID ) {
239
+ if ( 'preview-jetpack-comic' == $column_name && has_post_thumbnail( $post_ID ) ) {
240
+ echo get_the_post_thumbnail( $post_ID, 'jetpack-comic-thumb' );
241
+ }
242
+ }
243
+
244
+ /**
245
+ * The function url_to_postid() doesn't handle pretty permalinks
246
+ * for CPTs very well. When we're generating an RSS feed to be consumed
247
+ * for Feedbag (the Reader's feed storage mechanism), eschew
248
+ * a pretty URL for one that will get the post into the Reader.
249
+ *
250
+ * @see http://core.trac.wordpress.org/ticket/19744
251
+ * @param string $permalink The existing (possibly pretty) permalink.
252
+ */
253
+ public function custom_permalink_for_feedbag( $permalink ) {
254
+ global $post;
255
+
256
+ if ( ! empty( $GLOBALS['is_feedbag_rss_script'] ) && self::POST_TYPE == $post->post_type ) {
257
+ $permalink = home_url( add_query_arg( array( 'p' => $post->ID, 'post_type' => self::POST_TYPE ), '?' ) );
258
+ }
259
+
260
+ return $permalink;
261
+ }
262
+
263
+ /*
264
+ * Update messages for the Comic admin.
265
+ */
266
+ function updated_messages( $messages ) {
267
+ global $post;
268
+
269
+ $messages['jetpack-comic'] = array(
270
+ 0 => '', // Unused. Messages start at index 1.
271
+ 1 => sprintf( __( 'Comic updated. <a href="%s">View comic</a>', 'jetpack'), esc_url( get_permalink( $post->ID ) ) ),
272
+ 2 => esc_html__( 'Custom field updated.', 'jetpack' ),
273
+ 3 => esc_html__( 'Custom field deleted.', 'jetpack' ),
274
+ 4 => esc_html__( 'Comic updated.', 'jetpack' ),
275
+ /* translators: %s: date and time of the revision */
276
+ 5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Comic restored to revision from %s', 'jetpack'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
277
+ 6 => sprintf( __( 'Comic published. <a href="%s">View comic</a>', 'jetpack' ), esc_url( get_permalink( $post->ID ) ) ),
278
+ 7 => esc_html__( 'Comic saved.', 'jetpack' ),
279
+ 8 => sprintf( __( 'Comic submitted. <a target="_blank" href="%s">Preview comic</a>', 'jetpack'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
280
+ 9 => sprintf( __( 'Comic scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview comic</a>', 'jetpack' ),
281
+ // translators: Publish box date format, see http://php.net/date
282
+ date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
283
+ 10 => sprintf( __( 'Comic draft updated. <a target="_blank" href="%s">Preview comic</a>', 'jetpack' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
284
+ );
285
+
286
+ return $messages;
287
+ }
288
+
289
+ public function site_supports_comics() {
290
+ if ( 'blog-rss.php' == substr( $_SERVER['PHP_SELF'], -12 ) && count( $_SERVER['argv'] ) > 1 ) {
291
+ // blog-rss.php isn't run in the context of the target blog when the init action fires,
292
+ // so check manually whether the target blog supports comics.
293
+ switch_to_blog( $_SERVER['argv'][1] );
294
+ // The add_theme_support( 'jetpack-comic' ) won't fire on switch_to_blog, so check for Panel manually.
295
+ $supports_comics = $this->_site_supports_comics() || get_stylesheet() == 'pub/panel';
296
+ restore_current_blog();
297
+ return $supports_comics;
298
+ }
299
+ else {
300
+ return $this->_site_supports_comics();
301
+ }
302
+ }
303
+
304
+ private function _site_supports_comics() {
305
+ return ( site_vertical() == 'comics' || current_theme_supports( self::POST_TYPE ) );
306
+ }
307
+
308
+ /**
309
+ * Anywhere that a feed is displaying posts, show comics too.
310
+ *
311
+ * @param WP_Query $query
312
+ */
313
+ public function include_in_feeds( $query ) {
314
+ if ( ! $query->is_feed() )
315
+ return;
316
+
317
+ // Don't modify the query if the post type isn't public.
318
+ if ( ! get_post_type_object( 'jetpack-comic' )->public )
319
+ return;
320
+
321
+ $query_post_types = $query->get( 'post_type' );
322
+
323
+ if ( empty( $query_post_types ) )
324
+ $query_post_types = 'post';
325
+
326
+ if ( ! is_array( $query_post_types ) )
327
+ $query_post_types = array( $query_post_types );
328
+
329
+ if ( in_array( 'post', $query_post_types ) ) {
330
+ $query_post_types[] = self::POST_TYPE;
331
+ $query->set( 'post_type', $query_post_types );
332
+ }
333
+ }
334
+
335
+ /**
336
+ * API endpoint for front-end image uploading.
337
+ */
338
+ public function upload() {
339
+ global $content_width;
340
+
341
+ header( 'Content-Type: application/json' );
342
+
343
+ if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'jetpack_comic_upload_nonce' ) )
344
+ die( json_encode( array( 'error' => __( 'Invalid or expired nonce.' ) ) ) );
345
+
346
+ $_POST['action'] = 'wp_handle_upload';
347
+
348
+ $image_id_arr = array();
349
+ $image_error_arr = array();
350
+
351
+ $i = 0;
352
+
353
+ while ( isset( $_FILES['image_' . $i ] ) ) {
354
+ // Create attachment for the image.
355
+ $image_id = media_handle_upload( "image_$i", 0 );
356
+
357
+ if ( is_wp_error( $image_id ) ) {
358
+ $error = array( $image_id, $image_id->get_error_message() );
359
+ array_push( $image_error_arr, $error );
360
+ } else {
361
+ array_push( $image_id_arr, $image_id );
362
+ }
363
+
364
+ $i++;
365
+ }
366
+
367
+ if ( count( $image_id_arr ) == 0 ) {
368
+ // All image uploads failed.
369
+ $rv = array( 'error' => '' );
370
+
371
+ foreach ( $image_error_arr as $error )
372
+ $rv['error'] .= $error[1] . "\n";
373
+ }
374
+ else {
375
+ if ( count( $image_id_arr ) == 1 ) {
376
+ $image_id = $image_id_arr[0];
377
+
378
+ // Get the image
379
+ $image_src = get_the_guid( $image_id );
380
+ $image_dims = wp_get_attachment_image_src( $image_id, 'full' );
381
+
382
+ // Take off 10px of width to account for padding and border. @todo make this smarter.
383
+ if ( $content_width )
384
+ $image_width = $content_width - 10;
385
+ else
386
+ $image_width = $image_dims[1] - 10;
387
+
388
+ $post_content = '<a href="' . esc_attr( $image_src ) .'"><img src="' . esc_attr( $image_src ) . '?w=' . esc_attr( $image_width ) . '" alt="' . esc_attr( $_FILES['image_0']['name'] ) . '" class="size-full wp-image alignnone" id="i-' . esc_attr( $image_id ) . '" data-filename="' . esc_attr( $_FILES['image_0']['name'] ) . '" /></a>';
389
+ }
390
+ else {
391
+ $post_content = '[gallery ids="' . esc_attr( implode( ',', $image_id_arr ) ) . '"]';
392
+ }
393
+
394
+ // Create a new post with the image(s)
395
+ $post_id = wp_insert_post( array(
396
+ 'post_content' => $post_content,
397
+ 'post_type' => 'jetpack-comic',
398
+ 'post_status' => 'draft',
399
+ ),
400
+ true
401
+ );
402
+
403
+ if ( is_wp_error( $post_id, 'WP_Error' ) ) {
404
+ // Failed to create the post.
405
+ $rv = array( 'error' => $post_id->get_error_message() );
406
+
407
+ // Delete the uploaded images.
408
+ foreach ( $image_id_arr as $image_id ) {
409
+ wp_delete_post( $image_id, true );
410
+ }
411
+ }
412
+ else {
413
+ foreach ( $image_id_arr as $image_id ) {
414
+ wp_update_post( array(
415
+ 'ID' => $image_id,
416
+ 'post_parent' => $post_id
417
+ ) );
418
+ }
419
+
420
+ if ( current_theme_supports( 'post-thumbnails' ) && count( $image_id_arr ) == 1 )
421
+ set_post_thumbnail( $post_id, $image_id_arr[0] );
422
+
423
+ $rv = array( 'url' => add_query_arg( array( 'post' => $post_id, 'action' => 'edit' ), admin_url( 'post.php' ) ) );
424
+ }
425
+ }
426
+
427
+ die( json_encode( $rv ) );
428
+ }
429
+
430
+ public function add_posts_to_loop( $query ) {
431
+ // Add comic posts to the tag and category pages.
432
+ if ( ! is_admin() && $query->is_main_query() && ( $query->is_category() || $query->is_tag() ) ) {
433
+ $post_types = $query->get( 'post_type' );
434
+
435
+ if ( ! $post_types || 'post' == $post_types )
436
+ $post_types = array( 'post', self::POST_TYPE );
437
+ else if ( is_array( $post_types ) )
438
+ $post_types[] = self::POST_TYPE;
439
+
440
+ $query->set( 'post_type', $post_types );
441
+ }
442
+
443
+ return $query;
444
+ }
445
+
446
+ }
447
+
448
+ add_action( 'init', array( 'Jetpack_Comic', 'init' ) );
449
+
450
+
451
+ function comics_welcome_email( $welcome_email, $blog_id, $user_id, $password, $title, $meta ) {
452
+ if ( ( isset( $meta['vertical'] ) && 'comics' == $meta['vertical'] ) || has_blog_sticker( 'vertical-comics', $blog_id ) ) {
453
+ return __( "Welcome! Ready to publish your first strip?
454
+
455
+ Your webcomic's new site is ready to go. Get started by <a href=\"BLOG_URLwp-admin/customize.php#title\">setting your comic's title and tagline</a> so your readers know what it's all about.
456
+
457
+ Looking for more help with setting up your site? Check out the WordPress.com <a href=\"http://learn.wordpress.com/\">beginner's tutorial</a> and the <a href=\"http://en.support.wordpress.com/comics/\">guide to comics on WordPress.com</a>. Dive right in by <a href=\"BLOG_URLwp-admin/customize.php#title\">publishing your first strip!</a>
458
+
459
+ Lots of laughs,
460
+ The WordPress.com Team" );
461
+ }
462
+
463
+ return $welcome_email;
464
+ }
465
+
466
+ add_filter( 'update_welcome_email_pre_replacement', 'comics_welcome_email', 10, 6 );
467
+
modules/custom-post-types/comics/admin.css ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+
2
+ #adminmenu #menu-posts-jetpack-comic .menu-icon-post div.wp-menu-image:before {
3
+ content: '\f125';
4
+ }
5
+
6
+ .edit-php .column-preview-jetpack-comic {
7
+ width: 150px;
8
+ }
modules/custom-post-types/comics/comics.css ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #jetpack-comic-drop-zone .dragging, #jetpack-comic-drop-zone .uploading {
2
+ margin-top: 200px;
3
+ display: none;
4
+ }
5
+
6
+ /* Display the appropriate loading message for each upload state. */
7
+ body.dragging #jetpack-comic-drop-zone .dragging, body.uploading #jetpack-comic-drop-zone .uploading {
8
+ display: block;
9
+ }
10
+
11
+ body.uploading #jetpack-comic-drop-zone .uploading .spinner {
12
+ display: inline-block;
13
+ width: 60px;
14
+ }
15
+
16
+ /* Add the drop zone overlay. */
17
+ body.dragging #jetpack-comic-drop-zone, body.uploading #jetpack-comic-drop-zone {
18
+ background: rgba( 0, 86, 132, 0.9 );
19
+ border: 1px dashed #fff;
20
+ color: #fff;
21
+ display: block;
22
+ font-size: 30px;
23
+ position: fixed;
24
+ top: 10px;
25
+ left: 10px;
26
+ right: 10px;
27
+ bottom: 10px;
28
+ text-align: center;
29
+ z-index: 99999;
30
+ }
modules/custom-post-types/comics/comics.js ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function ( $ ) {
2
+ /**
3
+ * Enable front-end uploading of images for Comics users.
4
+ */
5
+ var Jetpack_Comics = {
6
+ init : function () {
7
+ $( document ).on( 'dragover.jetpack-comics', 'body, #jetpack-comic-drop-zone', this.onDragOver );
8
+ $( document ).on( 'dragleave.jetpack-comics', 'body, #jetpack-comic-drop-zone', this.onDragLeave );
9
+ $( document ).on( 'drop.jetpack-comics', 'body, #jetpack-comic-drop-zone', this.onDrop );
10
+
11
+ $( 'body' ).append( $( '<div id="jetpack-comic-drop-zone"><p class="dragging" /><p class="uploading" /></div>' ) );
12
+ $( '#jetpack-comic-drop-zone' )
13
+ .find( '.dragging' )
14
+ .text( Jetpack_Comics_Options.labels.dragging )
15
+ .end()
16
+ .find( '.uploading' )
17
+ .text( Jetpack_Comics_Options.labels.uploading )
18
+ .prepend( $( '<span class="spinner"/>' ) );
19
+
20
+ if ( ! ( 'FileReader' in window && 'File' in window ) ) {
21
+ $( '#jetpack-comic-drop-zone .dragging' ).text( Jetpack_Comics_Options.labels.unsupported );
22
+ $( document ).off( 'drop.jetpack-comics' ).on( 'drop.jetpack-comics', 'body, #jetpack-comic-drop-zone', this.onDragLeave );
23
+ }
24
+ },
25
+
26
+ /**
27
+ * Only upload image files.
28
+ */
29
+ filterImageFiles : function ( files ) {
30
+ var validFiles = [];
31
+
32
+ for ( var i = 0, _len = files.length; i < _len; i++ ) {
33
+ if ( files[i].type.match( /^image\//i ) ) {
34
+ validFiles.push( files[i] );
35
+ }
36
+ }
37
+
38
+ return validFiles;
39
+ },
40
+
41
+ dragTimeout : null,
42
+
43
+ onDragOver: function ( event ) {
44
+ event.preventDefault();
45
+
46
+ clearTimeout( Jetpack_Comics.dragTimeout );
47
+
48
+ $( 'body' ).addClass( 'dragging' );
49
+ },
50
+
51
+ onDragLeave: function ( event ) {
52
+ clearTimeout( Jetpack_Comics.dragTimeout );
53
+
54
+ // In Chrome, the screen flickers because we're moving the drop zone in front of 'body'
55
+ // so the dragover/dragleave events happen frequently.
56
+ Jetpack_Comics.dragTimeout = setTimeout( function () {
57
+ $( 'body' ).removeClass( 'dragging' );
58
+ }, 100 );
59
+ },
60
+
61
+ onDrop: function ( event ) {
62
+ event.preventDefault();
63
+ event.stopPropagation();
64
+
65
+ // recent chrome bug requires this, see stackoverflow thread: http://bit.ly/13BU7b5
66
+ event.originalEvent.stopPropagation();
67
+ event.originalEvent.preventDefault();
68
+
69
+ var files = Jetpack_Comics.filterImageFiles( event.originalEvent.dataTransfer.files );
70
+
71
+ $( 'body' ).removeClass( 'dragging' );
72
+
73
+ if ( files.length == 0 ) {
74
+ alert( Jetpack_Comics_Options.labels.invalidUpload );
75
+ return;
76
+ }
77
+
78
+ $( 'body' ).addClass( 'uploading' );
79
+
80
+ var formData = new FormData();
81
+
82
+ for ( var i = 0, fl = files.length; i < fl; i++ ) {
83
+ formData.append( 'image_' + i, files[ i ] ); // won't work as image[]
84
+ }
85
+
86
+ $( '#jetpack-comic-drop-zone .uploading .spinner' ).spin();
87
+
88
+ $.ajax( {
89
+ url: Jetpack_Comics_Options.writeURL + '&nonce=' + Jetpack_Comics_Options.nonce,
90
+ data: formData,
91
+ processData: false,
92
+ contentType: false,
93
+ type: 'POST',
94
+ dataType: 'json',
95
+ xhrFields: {
96
+ withCredentials: true
97
+ }
98
+ } )
99
+ .done( function( data ) {
100
+ $( '#jetpack-comic-drop-zone .uploading' ).text( Jetpack_Comics_Options.labels.processing );
101
+
102
+ if ( 'url' in data ) {
103
+ document.location.href = data.url;
104
+ }
105
+ else if ( 'error' in data ) {
106
+ alert( data.error );
107
+
108
+ $( 'body' ).removeClass( 'uploading' );
109
+ }
110
+ } )
111
+ .fail( function ( req ) {
112
+ alert( Jetpack_Comics_Options.labels.error );
113
+ } );
114
+ }
115
+ };
116
+
117
+ Jetpack_Comics.init();
118
+ } );
modules/custom-post-types/comics/rtl/comics-rtl.css ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file was automatically generated on Jul 09 2013 05:18:56 */
2
+
3
+ #jetpack-comic-drop-zone .dragging, #jetpack-comic-drop-zone .uploading {
4
+ margin-top: 200px;
5
+ display: none;
6
+ }
7
+
8
+ /* Display the appropriate loading message for each upload state. */
9
+ body.dragging #jetpack-comic-drop-zone .dragging, body.uploading #jetpack-comic-drop-zone .uploading {
10
+ display: block;
11
+ }
12
+
13
+ body.uploading #jetpack-comic-drop-zone .uploading .spinner {
14
+ display: inline-block;
15
+ width: 60px;
16
+ }
17
+
18
+ /* Add the drop zone overlay. */
19
+ body.dragging #jetpack-comic-drop-zone, body.uploading #jetpack-comic-drop-zone {
20
+ background: rgba( 0, 86, 132, 0.9 );
21
+ border: 1px dashed #fff;
22
+ color: #fff;
23
+ display: block;
24
+ font-size: 30px;
25
+ position: fixed;
26
+ top: 10px;
27
+ right: 10px;
28
+ left: 10px;
29
+ bottom: 10px;
30
+ text-align: center;
31
+ z-index: 99999;
32
+ }
modules/custom-post-types/testimonial.php ADDED
@@ -0,0 +1,286 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Plugin Name: Jetpack Testimonial
4
+ * Plugin URI:
5
+ * Author: Automattic
6
+ * Version: 0.1
7
+ * License: GPL v2 or later
8
+ * Text Domain: jetpack
9
+ * Domain Path: /languages/
10
+ */
11
+
12
+ class Jetpack_Testimonial {
13
+ const TESTIMONIAL_POST_TYPE = 'jetpack-testimonial';
14
+
15
+ var $version = '0.1';
16
+
17
+ function init() {
18
+ static $instance = false;
19
+
20
+ if ( ! $instance )
21
+ $instance = new Jetpack_Testimonial;
22
+
23
+ return $instance;
24
+ }
25
+
26
+ /**
27
+ * Conditionally hook into WordPress.
28
+ *
29
+ * Themes must declare that they support this module by adding
30
+ * add_theme_support( 'jetpack-testimonial' ); during after_setup_theme.
31
+ *
32
+ * If no theme support is found there is no need to hook into
33
+ * WordPress. We'll just return early instead.
34
+ */
35
+ function __construct() {
36
+ // Return early if theme does not support Jetpack Testimonial.
37
+ if ( ! current_theme_supports( self::TESTIMONIAL_POST_TYPE ) )
38
+ return;
39
+
40
+ $this->register_post_types();
41
+ add_filter( 'enter_title_here', array( $this, 'change_default_title' ) );
42
+ add_filter( 'manage_jetpack-testimonial_posts_columns', array( $this, 'edit_title_column_label' ) );
43
+ add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
44
+ add_action( 'customize_register', array( $this, 'customize_register' ) );
45
+
46
+ $num_testimonials = self::count_testimonials();
47
+ if ( ! empty( $num_testimonials ) )
48
+ add_action( 'admin_menu', array( $this, 'add_customize_page' ) );
49
+ }
50
+
51
+ /* Setup */
52
+ function register_post_types() {
53
+ register_post_type( self::TESTIMONIAL_POST_TYPE, array(
54
+ 'description' => __( 'Customer Testimonials', 'jetpack' ),
55
+ 'labels' => array(
56
+ 'name' => esc_html__( 'Testimonials', 'jetpack' ),
57
+ 'singular_name' => esc_html__( 'Testimonial', 'jetpack' ),
58
+ 'menu_name' => esc_html__( 'Testimonials', 'jetpack' ),
59
+ 'all_items' => esc_html__( 'All Testimonials', 'jetpack' ),
60
+ 'add_new' => esc_html__( 'Add New', 'jetpack' ),
61
+ 'add_new_item' => esc_html__( 'Add New Testimonial', 'jetpack' ),
62
+ 'edit_item' => esc_html__( 'Edit Testimonial', 'jetpack' ),
63
+ 'new_item' => esc_html__( 'New Testimonial', 'jetpack' ),
64
+ 'view_item' => esc_html__( 'View Testimonial', 'jetpack' ),
65
+ 'search_items' => esc_html__( 'Search Testimonials', 'jetpack' ),
66
+ 'not_found' => esc_html__( 'No Testimonials found', 'jetpack' ),
67
+ 'not_found_in_trash' => esc_html__( 'No Testimonials found in Trash', 'jetpack' ),
68
+ ),
69
+ 'supports' => array(
70
+ 'title',
71
+ 'editor',
72
+ 'thumbnail',
73
+ 'page-attributes',
74
+ ),
75
+ 'rewrite' => array(
76
+ 'slug' => 'testimonial',
77
+ 'with_front' => false,
78
+ 'feeds' => false,
79
+ 'pages' => false,
80
+ ),
81
+ 'public' => true,
82
+ 'show_ui' => true, // set to false to replace with custom UI
83
+ 'menu_position' => 20, // below Pages
84
+ 'capability_type' => 'page',
85
+ 'map_meta_cap' => true,
86
+ 'has_archive' => true,
87
+ 'query_var' => 'testimonial',
88
+ ) );
89
+ }
90
+
91
+ /**
92
+ * Change ‘Enter Title Here’ text for the Testimonial.
93
+ */
94
+ function change_default_title( $title ) {
95
+ $screen = get_current_screen();
96
+
97
+ if ( 'jetpack-testimonial' == $screen->post_type )
98
+ $title = esc_html__( "Enter the customer's name here", 'jetpack' );
99
+
100
+ return $title;
101
+ }
102
+
103
+ /**
104
+ * Change ‘Title’ column label on all Testimonials page.
105
+ */
106
+ function edit_title_column_label( $columns ) {
107
+ $columns['title'] = esc_html__( 'Customer Name', 'jetpack' );
108
+
109
+ return $columns;
110
+ }
111
+
112
+ /**
113
+ * Update messages for the Testimonial admin.
114
+ */
115
+ function updated_messages( $messages ) {
116
+ global $post;
117
+
118
+ $messages['jetpack-testimonial'] = array(
119
+ 0 => '', // Unused. Messages start at index 1.
120
+ 1 => sprintf( __( 'Testimonial updated. <a href="%s">View testimonial</a>', 'jetpack'), esc_url( get_permalink( $post->ID ) ) ),
121
+ 2 => esc_html__( 'Custom field updated.', 'jetpack' ),
122
+ 3 => esc_html__( 'Custom field deleted.', 'jetpack' ),
123
+ 4 => esc_html__( 'Testimonial updated.', 'jetpack' ),
124
+ /* translators: %s: date and time of the revision */
125
+ 5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Testimonial restored to revision from %s', 'jetpack'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
126
+ 6 => sprintf( __( 'Testimonial published. <a href="%s">View testimonial</a>', 'jetpack' ), esc_url( get_permalink( $post->ID ) ) ),
127
+ 7 => esc_html__( 'Testimonial saved.', 'jetpack' ),
128
+ 8 => sprintf( __( 'Testimonial submitted. <a target="_blank" href="%s">Preview testimonial</a>', 'jetpack'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
129
+ 9 => sprintf( __( 'Testimonial scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview testimonial</a>', 'jetpack' ),
130
+ // translators: Publish box date format, see http://php.net/date
131
+ date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
132
+ 10 => sprintf( __( 'Testimonial draft updated. <a target="_blank" href="%s">Preview testimonial</a>', 'jetpack' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
133
+ );
134
+
135
+ return $messages;
136
+ }
137
+
138
+
139
+ function set_testimonial_option() {
140
+ $testimonials_option = get_option( 'jetpack_testimonial' );
141
+
142
+ $testimonials = wp_count_posts( 'jetpack-testimonial' );
143
+ $published_testimonials = $testimonials->publish;
144
+
145
+ update_option( 'jetpack_testimonial', $published_testimonials );
146
+ }
147
+
148
+ function count_testimonials() {
149
+ $testimonials = get_transient( 'jetpack-testimonial-count-cache' );
150
+
151
+ if ( false === $testimonials ) {
152
+ $testimonials = (int) wp_count_posts( 'jetpack-testimonial' )->publish;
153
+
154
+ if ( ! empty( $testimonials ) ) {
155
+ set_transient( 'jetpack-testimonial-count-cache', $testimonials, 60*60*12 );
156
+ }
157
+ }
158
+
159
+ return $testimonials;
160
+ }
161
+
162
+ /**
163
+ * Adds a submenu link to the Customizer.
164
+ */
165
+ function add_customize_page() {
166
+ add_submenu_page(
167
+ 'edit.php?post_type=jetpack-testimonial',
168
+ esc_html__( 'Customize Testimonials Archive', 'jetpack' ),
169
+ esc_html__( 'Customize', 'jetpack' ),
170
+ 'edit_theme_options',
171
+ add_query_arg( array( 'url' => urlencode( home_url( 'testimonial' ) ) ), 'customize.php' ) . '#accordion-section-jetpack_testimonials'
172
+ );
173
+ }
174
+
175
+ /**
176
+ * Adds testimonial section to the Customizer.
177
+ */
178
+ function customize_register( $wp_customize ) {
179
+ jetpack_testimonial_custom_control_classes();
180
+
181
+ $wp_customize->add_section( 'jetpack_testimonials', array(
182
+ 'title' => esc_html__( 'Testimonials', 'jetpack' ),
183
+ 'theme_supports' => 'jetpack-testimonial',
184
+ ) );
185
+
186
+ $wp_customize->add_setting( 'jetpack_testimonials[page-title]', array(
187
+ 'default' => esc_html__( 'Testimonials', 'jetpack' ),
188
+ 'sanitize_callback' => array( 'Jetpack_Testimonial_Title_Control', 'sanitize_content' ),
189
+ 'sanitize_js_callback' => array( 'Jetpack_Testimonial_Title_Control', 'sanitize_content' ),
190
+ ) );
191
+ $wp_customize->add_control( 'jetpack_testimonials[page-title]', array(
192
+ 'section' => 'jetpack_testimonials',
193
+ 'label' => esc_html__( 'Testimonial Page Title', 'jetpack' ),
194
+ 'type' => 'text',
195
+ ) );
196
+
197
+ $wp_customize->add_setting( 'jetpack_testimonials[page-content]', array(
198
+ 'default' => '',
199
+ 'sanitize_callback' => array( 'Jetpack_Testimonial_Textarea_Control', 'sanitize_content' ),
200
+ 'sanitize_js_callback' => array( 'Jetpack_Testimonial_Textarea_Control', 'sanitize_content' ),
201
+ ) );
202
+ $wp_customize->add_control( new Jetpack_Testimonial_Textarea_Control( $wp_customize, 'jetpack_testimonials[page-content]', array(
203
+ 'section' => 'jetpack_testimonials',
204
+ 'settings' => 'jetpack_testimonials[page-content]',
205
+ 'label' => esc_html__( 'Testimonial Page Content', 'jetpack' ),
206
+ ) ) );
207
+
208
+ if ( current_theme_supports( 'post-thumbnails' ) ) {
209
+ $wp_customize->add_setting( 'jetpack_testimonials[featured-image]', array(
210
+ 'default' => '',
211
+ 'sanitize_callback' => array( 'Jetpack_Testimonial_Image_Control', 'attachment_guid_to_id' ),
212
+ 'sanitize_js_callback' => array( 'Jetpack_Testimonial_Image_Control', 'attachment_guid_to_id' ),
213
+ ) );
214
+ $wp_customize->add_control( new Jetpack_Testimonial_Image_Control( $wp_customize, 'jetpack_testimonials[featured-image]', array(
215
+ 'section' => 'jetpack_testimonials',
216
+ 'label' => esc_html__( 'Testimonial Page Featured Image', 'jetpack' ),
217
+ ) ) );
218
+ }
219
+ }
220
+ }
221
+
222
+ function jetpack_testimonial_custom_control_classes() {
223
+ class Jetpack_Testimonial_Title_Control extends WP_Customize_Control {
224
+ public function sanitize_content( $value ) {
225
+ if ( '' != $value )
226
+ $value = trim( convert_chars( wptexturize( $value ) ) );
227
+
228
+ return $value;
229
+ }
230
+ }
231
+
232
+ class Jetpack_Testimonial_Textarea_Control extends WP_Customize_Control {
233
+ public $type = 'textarea';
234
+
235
+ public function render_content() {
236
+ ?>
237
+ <label>
238
+ <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
239
+ <textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
240
+ </label>
241
+ <?php
242
+ }
243
+
244
+ public function sanitize_content( $value ) {
245
+ if ( ! empty( $value ) )
246
+ $value = apply_filters( 'the_content', $value );
247
+
248
+ $value = preg_replace( '@<div id="jp-post-flair"([^>]+)?>(.+)?</div>@is', '', $value ); // Strip WPCOM and Jetpack post flair if included in content
249
+
250
+ return $value;
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Need to extend WP_Customize_Image_Control to return attachment ID instead of url
256
+ */
257
+ class Jetpack_Testimonial_Image_Control extends WP_Customize_Image_Control {
258
+ public $context = 'custom_image';
259
+
260
+ public function __construct( $manager, $id, $args ) {
261
+ $this->get_url = array( $this, 'get_img_url' );
262
+ parent::__construct( $manager, $id, $args );
263
+ }
264
+
265
+ public function get_img_url( $attachment_id = 0 ) {
266
+ if ( is_numeric( $attachment_id ) && wp_attachment_is_image( $attachment_id ) )
267
+ list( $image, $x, $y ) = wp_get_attachment_image_src( $attachment_id );
268
+
269
+ return ! empty( $image ) ? $image : $attachment_id;
270
+ }
271
+
272
+ public function attachment_guid_to_id( $value ) {
273
+ if ( is_numeric( $value ) )
274
+ return $value;
275
+
276
+ $matches = get_posts( array( 'post_type' => 'attachment', 'guid' => $value ) );
277
+
278
+ if ( empty( $matches ) )
279
+ return false;
280
+
281
+ return $matches[0]->ID; // this is the match we want
282
+ }
283
+ }
284
+ }
285
+
286
+ add_action( 'init', array( 'Jetpack_Testimonial', 'init' ) );
modules/custom-post-types/testimonials.php ADDED
File without changes
modules/featured-content/featured-content.php CHANGED
@@ -41,7 +41,7 @@ class Featured_Content {
41
  * All custom functionality will be hooked into the "init" action.
42
  */
43
  public static function setup() {
44
- add_action( 'init', array( __class__, 'init' ) );
45
  }
46
 
47
  /**
41
  * All custom functionality will be hooked into the "init" action.
42
  */
43
  public static function setup() {
44
+ add_action( 'init', array( __class__, 'init' ), 30 );
45
  }
46
 
47
  /**
modules/infinite-scroll/infinity.js CHANGED
@@ -79,14 +79,13 @@ Scroller = function( settings ) {
79
 
80
  /**
81
  * Check whether we should fetch any additional posts.
82
- *
83
- * By default, checks whether the bottom of the viewport is within one
84
- * viewport-height of the bottom of the content.
85
  */
86
  Scroller.prototype.check = function() {
87
  var bottom = this.window.scrollTop() + this.window.height(),
88
  threshold = this.element.offset().top + this.element.outerHeight(false) - this.window.height();
89
 
 
 
90
  return bottom > threshold;
91
  };
92
 
@@ -457,7 +456,7 @@ Scroller.prototype.updateURL = function( page ) {
457
  */
458
  $( document ).ready( function() {
459
  // Check for our variables
460
- if ( ! infiniteScroll )
461
  return;
462
 
463
  // Set ajaxurl (for brevity)
@@ -487,4 +486,4 @@ $( document ).ready( function() {
487
  });
488
 
489
 
490
- })(jQuery); // Close closure
79
 
80
  /**
81
  * Check whether we should fetch any additional posts.
 
 
 
82
  */
83
  Scroller.prototype.check = function() {
84
  var bottom = this.window.scrollTop() + this.window.height(),
85
  threshold = this.element.offset().top + this.element.outerHeight(false) - this.window.height();
86
 
87
+ threshold = Math.round( threshold * 0.75 );
88
+
89
  return bottom > threshold;
90
  };
91
 
456
  */
457
  $( document ).ready( function() {
458
  // Check for our variables
459
+ if ( 'object' != typeof infiniteScroll )
460
  return;
461
 
462
  // Set ajaxurl (for brevity)
486
  });
487
 
488
 
489
+ })(jQuery); // Close closure
modules/infinite-scroll/infinity.php CHANGED
@@ -17,7 +17,10 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
17
  */
18
  class The_Neverending_Home_Page {
19
  /**
 
20
  *
 
 
21
  */
22
  function __construct() {
23
  add_action( 'pre_get_posts', array( $this, 'posts_per_page_query' ) );
@@ -27,7 +30,7 @@ class The_Neverending_Home_Page {
27
  add_action( 'template_redirect', array( $this, 'ajax_response' ) );
28
  add_action( 'custom_ajax_infinite_scroll', array( $this, 'query' ) );
29
  add_action( 'the_post', array( $this, 'preserve_more_tag' ) );
30
- add_action( 'get_footer', array( $this, 'footer' ) );
31
 
32
  // Plugin compatibility
33
  add_filter( 'grunion_contact_form_redirect_url', array( $this, 'filter_grunion_redirect_url' ) );
@@ -55,14 +58,15 @@ class The_Neverending_Home_Page {
55
  $css_pattern = '#[^A-Z\d\-_]#i';
56
 
57
  $settings = $defaults = array(
58
- 'type' => 'scroll', // scroll | click
59
- 'requested_type' => 'scroll', // store the original type for use when logic overrides it
60
- 'footer_widgets' => false, // true | false | sidebar_id | array of sidebar_ids -- last two are checked with is_active_sidebar
61
- 'container' => 'content', // container html id
62
- 'wrapper' => true, // true | false | html class
63
- 'render' => false, // optional function, otherwise the `content` template part will be used
64
- 'footer' => true, // boolean to enable or disable the infinite footer | string to provide an html id to derive footer width from
65
- 'posts_per_page' => false // int | false to set based on IS type
 
66
  );
67
 
68
  // Validate settings passed through add_theme_support()
@@ -123,6 +127,14 @@ class The_Neverending_Home_Page {
123
 
124
  break;
125
 
 
 
 
 
 
 
 
 
126
  case 'posts_per_page' :
127
  if ( is_numeric( $value ) )
128
  $settings[ $key ] = (int) $value;
@@ -292,7 +304,7 @@ class The_Neverending_Home_Page {
292
  add_filter( 'body_class', array( $this, 'body_class' ) );
293
 
294
  // Add our scripts.
295
- wp_enqueue_script( 'the-neverending-homepage', plugins_url( 'infinity.js', __FILE__ ), array( 'jquery' ), '20130101' );
296
 
297
  // Add our default styles.
298
  wp_enqueue_style( 'the-neverending-homepage', plugins_url( 'infinity.css', __FILE__ ), array(), '20120612' );
@@ -869,7 +881,7 @@ class The_Neverending_Home_Page {
869
  /**
870
  * The Infinite Blog Footer
871
  *
872
- * @uses self::get_settings, self::set_last_post_time, self::archive_supports_infinity, __, wp_get_theme, get_current_theme, apply_filters, home_url, esc_attr, get_bloginfo, bloginfo
873
  * @return string or null
874
  */
875
  function footer() {
@@ -885,6 +897,20 @@ class The_Neverending_Home_Page {
885
  if ( 'scroll' != self::get_settings()->type || ! self::archive_supports_infinity() )
886
  return;
887
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
888
  $credits = '<a href="http://wordpress.org/" rel="generator">Proudly powered by WordPress</a> ';
889
  $credits .= sprintf( __( 'Theme: %1$s.', 'jetpack' ), function_exists( 'wp_get_theme' ) ? wp_get_theme()->Name : get_current_theme() );
890
  $credits = apply_filters( 'infinite_scroll_credit', $credits );
17
  */
18
  class The_Neverending_Home_Page {
19
  /**
20
+ * Register actions and filters, plus parse IS settings
21
  *
22
+ * @uses add_action, add_filter, self::get_settings
23
+ * @return null
24
  */
25
  function __construct() {
26
  add_action( 'pre_get_posts', array( $this, 'posts_per_page_query' ) );
30
  add_action( 'template_redirect', array( $this, 'ajax_response' ) );
31
  add_action( 'custom_ajax_infinite_scroll', array( $this, 'query' ) );
32
  add_action( 'the_post', array( $this, 'preserve_more_tag' ) );
33
+ add_action( 'wp_footer', array( $this, 'footer' ) );
34
 
35
  // Plugin compatibility
36
  add_filter( 'grunion_contact_form_redirect_url', array( $this, 'filter_grunion_redirect_url' ) );
58
  $css_pattern = '#[^A-Z\d\-_]#i';
59
 
60
  $settings = $defaults = array(
61
+ 'type' => 'scroll', // scroll | click
62
+ 'requested_type' => 'scroll', // store the original type for use when logic overrides it
63
+ 'footer_widgets' => false, // true | false | sidebar_id | array of sidebar_ids -- last two are checked with is_active_sidebar
64
+ 'container' => 'content', // container html id
65
+ 'wrapper' => true, // true | false | html class
66
+ 'render' => false, // optional function, otherwise the `content` template part will be used
67
+ 'footer' => true, // boolean to enable or disable the infinite footer | string to provide an html id to derive footer width from
68
+ 'footer_callback' => false, // function to be called to render the IS footer, in place of the default
69
+ 'posts_per_page' => false // int | false to set based on IS type
70
  );
71
 
72
  // Validate settings passed through add_theme_support()
127
 
128
  break;
129
 
130
+ case 'footer_callback' :
131
+ if ( is_callable( $value ) )
132
+ $settings[ $key ] = $value;
133
+ else
134
+ $settings[ $key ] = false;
135
+
136
+ break;
137
+
138
  case 'posts_per_page' :
139
  if ( is_numeric( $value ) )
140
  $settings[ $key ] = (int) $value;
304
  add_filter( 'body_class', array( $this, 'body_class' ) );
305
 
306
  // Add our scripts.
307
+ wp_enqueue_script( 'the-neverending-homepage', plugins_url( 'infinity.js', __FILE__ ), array( 'jquery' ), '20130523' );
308
 
309
  // Add our default styles.
310
  wp_enqueue_style( 'the-neverending-homepage', plugins_url( 'infinity.css', __FILE__ ), array(), '20120612' );
881
  /**
882
  * The Infinite Blog Footer
883
  *
884
+ * @uses self::get_settings, self::set_last_post_time, self::archive_supports_infinity, self::default_footer
885
  * @return string or null
886
  */
887
  function footer() {
897
  if ( 'scroll' != self::get_settings()->type || ! self::archive_supports_infinity() )
898
  return;
899
 
900
+ // Display a footer, either user-specified or a default
901
+ if ( false !== self::get_settings()->footer_callback && is_callable( self::get_settings()->footer_callback ) )
902
+ call_user_func( self::get_settings()->footer_callback, self::get_settings() );
903
+ else
904
+ self::default_footer();
905
+ }
906
+
907
+ /**
908
+ * Render default IS footer
909
+ *
910
+ * @uses __, wp_get_theme, get_current_theme, apply_filters, home_url, esc_attr, get_bloginfo, bloginfo
911
+ * @return string
912
+ */
913
+ private function default_footer() {
914
  $credits = '<a href="http://wordpress.org/" rel="generator">Proudly powered by WordPress</a> ';
915
  $credits .= sprintf( __( 'Theme: %1$s.', 'jetpack' ), function_exists( 'wp_get_theme' ) ? wp_get_theme()->Name : get_current_theme() );
916
  $credits = apply_filters( 'infinite_scroll_credit', $credits );
modules/infinite-scroll/themes/twentythirteen.css CHANGED
@@ -18,6 +18,10 @@
18
  .sidebar .infinite-loader .spinner {
19
  padding-right: 376px;
20
  }
 
 
 
 
21
 
22
  /* Click-to-load */
23
  #infinite-handle {
@@ -28,6 +32,10 @@
28
  .sidebar #infinite-handle {
29
  padding-right: 376px;
30
  }
 
 
 
 
31
  #infinite-handle span {
32
  background: #e05d22; /* Old browsers */
33
  background: -webkit-linear-gradient(top, #e05d22 0%, #d94412 100%); /* Chrome 10+, Safari 5.1+ */
@@ -65,4 +73,18 @@
65
  /* Hooks to infinity-end body class to restore footer. */
66
  .infinity-end.neverending #colophon {
67
  display: block;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  }
18
  .sidebar .infinite-loader .spinner {
19
  padding-right: 376px;
20
  }
21
+ .rtl.sidebar .infinite-loader .spinner {
22
+ padding-left: 376px;
23
+ padding-right: 0;
24
+ }
25
 
26
  /* Click-to-load */
27
  #infinite-handle {
32
  .sidebar #infinite-handle {
33
  padding-right: 376px;
34
  }
35
+ .rtl.sidebar #infinite-handle {
36
+ padding-left: 376px;
37
+ padding-right: 0;
38
+ }
39
  #infinite-handle span {
40
  background: #e05d22; /* Old browsers */
41
  background: -webkit-linear-gradient(top, #e05d22 0%, #d94412 100%); /* Chrome 10+, Safari 5.1+ */
73
  /* Hooks to infinity-end body class to restore footer. */
74
  .infinity-end.neverending #colophon {
75
  display: block;
76
+ }
77
+
78
+ /* For small viewports. */
79
+ @media (max-width: 999px) {
80
+ .sidebar .infinite-loader .spinner,
81
+ .rtl.sidebar .infinite-loader .spinner {
82
+ padding-right: 0;
83
+ padding-left: 0;
84
+ }
85
+ .infinite-scroll #infinite-handle,
86
+ .rtl.sidebar #infinite-handle {
87
+ padding-right: 0;
88
+ padding-left: 0;
89
+ }
90
  }
modules/likes.php CHANGED
@@ -4,11 +4,12 @@
4
  * Module Description: Likes are a way for people to show their appreciation for content you have written. It’s also a way for you to show the world how popular your content has become.
5
  * First Introduced: 2.2
6
  * Sort Order: 4
 
7
  */
8
  class Jetpack_Likes {
9
- var $version = '20130404';
10
 
11
- function &init() {
12
  static $instance = NULL;
13
 
14
  if ( ! $instance ) {
@@ -29,7 +30,7 @@ class Jetpack_Likes {
29
  add_action( 'jetpack_deactivate_module_likes', array( $this, 'module_toggle' ) );
30
 
31
  Jetpack::enable_module_configurable( __FILE__ );
32
- Jetpack::module_configuration_load( __FILE__, array( 'Jetpack_Likes', 'configuration_redirect' ) );
33
 
34
  add_action('admin_print_scripts-settings_page_sharing', array( &$this, 'load_jp_css' ) );
35
  add_filter( 'sharing_show_buttons_on_row_start', array( $this, 'configuration_target_area' ) );
@@ -206,8 +207,8 @@ class Jetpack_Likes {
206
 
207
  function admin_discussion_likes_settings_init() {
208
  // Add a temporary section, until we can move the setting out of there and with the rest of the email notification settings
209
- add_settings_section( 'likes-notifications', __( 'Likes Notifications' ), array( $this, 'admin_discussion_likes_settings_section' ), 'discussion' );
210
- add_settings_field( 'social-notifications', __( 'Email me whenever' ), array( $this, 'admin_discussion_likes_settings_field' ), 'discussion', 'likes-notifications' );
211
  // Register the setting
212
  register_setting( 'discussion', 'social_notifications_like', array( $this, 'admin_discussion_likes_settings_validate' ) );
213
  }
@@ -246,7 +247,7 @@ class Jetpack_Likes {
246
  function admin_discussion_likes_settings_field() {
247
  $like = $this->admin_likes_get_option( 'social_notifications_like' );
248
  ?>
249
- <label><input type="checkbox" id="social_notifications_like" name="social_notifications_like" value="1" <?php checked( $like ); ?> /> <?php esc_html_e( 'Someone likes one of my posts' ); ?></label>
250
  <?php
251
  }
252
 
@@ -519,6 +520,11 @@ class Jetpack_Likes {
519
  .fixed .column-likes .post-com-count { background-image: none; }
520
  .fixed .column-likes .comment-count { background-color: #888; }
521
  .fixed .column-likes .comment-count:hover { background-color: #D54E21; }
 
 
 
 
 
522
  </style> <?php
523
  }
524
 
@@ -568,7 +574,7 @@ class Jetpack_Likes {
568
  $date = $columns['date'];
569
  unset( $columns['date'] );
570
 
571
- $columns['likes'] = '<span class="vers"><img title="' . esc_attr__( 'Likes' ) . '" alt="' . esc_attr__( 'Likes' ) . '" src="//s0.wordpress.com/i/like-grey-icon.png" /></span>';
572
  $columns['date'] = $date;
573
 
574
  return $columns;
@@ -680,10 +686,10 @@ class Jetpack_Likes {
680
  }
681
 
682
  add_filter( 'wp_footer', array( $this, 'likes_master' ) );
683
-
684
  $src = sprintf( '%1$s://widgets.wp.com/likes/#blog_id=%2$d&amp;post_id=%3$d&amp;origin=%1$s://%4$s', $protocol, $blog_id, $post->ID, $domain );
685
 
686
- $html = "<iframe class='admin-bar-likes-widget jetpack-likes-widget' frameBorder='0' name='admin-bar-likes-widget' src='$src'></iframe>";
687
 
688
  $node = array(
689
  'id' => 'admin-bar-likes-widget',
@@ -701,11 +707,11 @@ class Jetpack_Likes {
701
  $protocol = 'https';
702
 
703
  $locale = ( '' == get_locale() || 'en' == get_locale() ) ? '' : '&amp;lang=' . strtolower( substr( get_locale(), 0, 2 ) );
704
- $src = sprintf( '%1$s://widgets.wp.com/likes/master.html?ver=%2$s#ver=%2$s%3$s', $protocol, $this->version, $locale );
705
 
706
- $likersText = wp_kses( __( '<span>%d</span> bloggers like this:', 'jetpack' ), array( 'span' => array() ) );
707
  ?>
708
- <iframe src='<?php echo $src; ?>' id='likes-master' name='likes-master' style='display:none;'></iframe>
709
  <div id='likes-other-gravatars'><div class="likes-text"><?php echo $likersText; ?></div><ul class="wpl-avatars sd-like-gravatars"></ul></div>
710
  <script type="text/javascript">
711
  //<![CDATA[
@@ -916,8 +922,9 @@ class Jetpack_Likes {
916
  $wrapper.find( 'iframe' ).Jetpack( 'resizeable' );
917
  }
918
  });
 
919
  }
920
- setInterval( JetpackLikesWidgetQueueHandler, 250 );
921
  //]]>
922
  </script>
923
  <?php
4
  * Module Description: Likes are a way for people to show their appreciation for content you have written. It’s also a way for you to show the world how popular your content has become.
5
  * First Introduced: 2.2
6
  * Sort Order: 4
7
+ * Requires Connection: Yes
8
  */
9
  class Jetpack_Likes {
10
+ var $version = '20130620a';
11
 
12
+ public static function init() {
13
  static $instance = NULL;
14
 
15
  if ( ! $instance ) {
30
  add_action( 'jetpack_deactivate_module_likes', array( $this, 'module_toggle' ) );
31
 
32
  Jetpack::enable_module_configurable( __FILE__ );
33
+ Jetpack::module_configuration_load( __FILE__, array( $this, 'configuration_redirect' ) );
34
 
35
  add_action('admin_print_scripts-settings_page_sharing', array( &$this, 'load_jp_css' ) );
36
  add_filter( 'sharing_show_buttons_on_row_start', array( $this, 'configuration_target_area' ) );
207
 
208
  function admin_discussion_likes_settings_init() {
209
  // Add a temporary section, until we can move the setting out of there and with the rest of the email notification settings
210
+ add_settings_section( 'likes-notifications', __( 'Likes Notifications', 'jetpack' ), array( $this, 'admin_discussion_likes_settings_section' ), 'discussion' );
211
+ add_settings_field( 'social-notifications', __( 'Email me whenever', 'jetpack' ), array( $this, 'admin_discussion_likes_settings_field' ), 'discussion', 'likes-notifications' );
212
  // Register the setting
213
  register_setting( 'discussion', 'social_notifications_like', array( $this, 'admin_discussion_likes_settings_validate' ) );
214
  }
247
  function admin_discussion_likes_settings_field() {
248
  $like = $this->admin_likes_get_option( 'social_notifications_like' );
249
  ?>
250
+ <label><input type="checkbox" id="social_notifications_like" name="social_notifications_like" value="1" <?php checked( $like ); ?> /> <?php esc_html_e( 'Someone likes one of my posts', 'jetpack' ); ?></label>
251
  <?php
252
  }
253
 
520
  .fixed .column-likes .post-com-count { background-image: none; }
521
  .fixed .column-likes .comment-count { background-color: #888; }
522
  .fixed .column-likes .comment-count:hover { background-color: #D54E21; }
523
+ .admin-color-mp6 .fixed .column-likes .post-com-count::after { border: none !important; }
524
+ .admin-color-mp6 .fixed .column-likes .comment-count { background-color: #bbb; }
525
+ .admin-color-mp6 .fixed .column-likes .comment-count:hover { background-color: #2ea2cc; }
526
+ .admin-color-mp6 .fixed .column-likes .vers img { display: none; }
527
+ .admin-color-mp6 .fixed .column-likes .vers:before {font:20px/1 dashicons;content: '\f155';-webkit-font-smoothing:antialiased;}
528
  </style> <?php
529
  }
530
 
574
  $date = $columns['date'];
575
  unset( $columns['date'] );
576
 
577
+ $columns['likes'] = '<span class="vers"><img title="' . esc_attr__( 'Likes', 'jetpack' ) . '" alt="' . esc_attr__( 'Likes', 'jetpack' ) . '" src="//s0.wordpress.com/i/like-grey-icon.png" /></span>';
578
  $columns['date'] = $date;
579
 
580
  return $columns;
686
  }
687
 
688
  add_filter( 'wp_footer', array( $this, 'likes_master' ) );
689
+
690
  $src = sprintf( '%1$s://widgets.wp.com/likes/#blog_id=%2$d&amp;post_id=%3$d&amp;origin=%1$s://%4$s', $protocol, $blog_id, $post->ID, $domain );
691
 
692
+ $html = "<iframe class='admin-bar-likes-widget jetpack-likes-widget' scrolling='no' frameBorder='0' name='admin-bar-likes-widget' src='$src'></iframe>";
693
 
694
  $node = array(
695
  'id' => 'admin-bar-likes-widget',
707
  $protocol = 'https';
708
 
709
  $locale = ( '' == get_locale() || 'en' == get_locale() ) ? '' : '&amp;lang=' . strtolower( substr( get_locale(), 0, 2 ) );
710
+ $src = sprintf( '%1$s://widgets.wp.com/likes/master.html?ver=%2$s#ver=%2$s%3$s&amp;mp6=%4$d', $protocol, $this->version, $locale, apply_filters( 'mp6_enabled', 0 ) );
711
 
712
+ $likersText = wp_kses( __( '<span>%d</span> bloggers like this:', 'jetpack' ), array( 'span' => array() ) );
713
  ?>
714
+ <iframe src='<?php echo $src; ?>' scrolling='no' id='likes-master' name='likes-master' style='display:none;'></iframe>
715
  <div id='likes-other-gravatars'><div class="likes-text"><?php echo $likersText; ?></div><ul class="wpl-avatars sd-like-gravatars"></ul></div>
716
  <script type="text/javascript">
717
  //<![CDATA[
922
  $wrapper.find( 'iframe' ).Jetpack( 'resizeable' );
923
  }
924
  });
925
+ setTimeout( JetpackLikesWidgetQueueHandler, 250 );
926
  }
927
+ JetpackLikesWidgetQueueHandler();
928
  //]]>
929
  </script>
930
  <?php
modules/minileven/theme/pub/minileven/content-gallery.php CHANGED
@@ -10,10 +10,10 @@
10
 
11
  <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
12
  <header class="entry-header">
13
- <hgroup>
14
  <h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
15
  <h3 class="entry-format"><?php _e( 'Gallery', 'jetpack' ); ?></h3>
16
- </hgroup>
17
  </header><!-- .entry-header -->
18
 
19
  <div class="entry-content">
10
 
11
  <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
12
  <header class="entry-header">
13
+ <div class="entry-heading">
14
  <h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
15
  <h3 class="entry-format"><?php _e( 'Gallery', 'jetpack' ); ?></h3>
16
+ </div>
17
  </header><!-- .entry-header -->
18
 
19
  <div class="entry-content">
modules/minileven/theme/pub/minileven/content.php CHANGED
@@ -8,11 +8,16 @@
8
 
9
  <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
10
  <header class="entry-header">
 
 
 
 
 
11
  <?php if ( is_sticky() ) : ?>
12
- <hgroup>
13
  <h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
14
  <h3 class="entry-format"><?php _e( 'Featured', 'jetpack' ); ?></h3>
15
- </hgroup>
16
  <?php else : ?>
17
  <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1>
18
  <?php endif; ?>
@@ -30,7 +35,7 @@
30
  </header><!-- .entry-header -->
31
 
32
  <div class="entry-content">
33
- <?php if ( '1' == get_option( 'wp_mobile_excerpt' ) && is_home() || is_search() || is_archive() ) : ?>
34
  <?php echo minileven_excerpt( 300 ); ?>
35
  <?php else : ?>
36
  <?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'jetpack' ) ); ?>
8
 
9
  <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
10
  <header class="entry-header">
11
+ <?php if ( '1' == get_option( 'wp_mobile_featured_images' ) && is_home() || is_search() || is_archive() ) : ?>
12
+ <div class="entry-thumbnail">
13
+ <a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="<?php the_ID(); ?>" class="minileven-featured-thumbnail"><?php the_post_thumbnail(); ?></a>
14
+ </div><!-- .entry-thumbnail -->
15
+ <?php endif; ?>
16
  <?php if ( is_sticky() ) : ?>
17
+ <div class="entry-heading">
18
  <h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
19
  <h3 class="entry-format"><?php _e( 'Featured', 'jetpack' ); ?></h3>
20
+ <div>
21
  <?php else : ?>
22
  <h1 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php echo esc_attr( sprintf( __( 'Permalink to %s', 'jetpack' ), the_title_attribute( 'echo=0' ) ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h1>
23
  <?php endif; ?>
35
  </header><!-- .entry-header -->
36
 
37
  <div class="entry-content">
38
+ <?php if ( '1' == get_option( 'wp_mobile_excerpt' ) && ( is_home() || is_search() || is_archive() ) ) : ?>
39
  <?php echo minileven_excerpt( 300 ); ?>
40
  <?php else : ?>
41
  <?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'jetpack' ) ); ?>
modules/minileven/theme/pub/minileven/inc/custom-header.php CHANGED
@@ -35,10 +35,10 @@ function minileven_header() {
35
 
36
  <header id="branding" role="banner">
37
  <?php if ( 'blank' != $header_text ) : ?>
38
- <hgroup>
39
  <h1 id="site-title"><span><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></span></h1>
40
  <h2 id="site-description"><?php bloginfo( 'description' ); ?></h2>
41
- </hgroup>
42
  <?php endif;
43
 
44
  if ( false !== $header_image ) : ?>
35
 
36
  <header id="branding" role="banner">
37
  <?php if ( 'blank' != $header_text ) : ?>
38
+ <div class="site-branding">
39
  <h1 id="site-title"><span><a href="<?php echo esc_url( home_url( '/' ) ); ?>" title="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a></span></h1>
40
  <h2 id="site-description"><?php bloginfo( 'description' ); ?></h2>
41
+ </div>
42
  <?php endif;
43
 
44
  if ( false !== $header_image ) : ?>
modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot CHANGED
Binary file
modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.svg CHANGED
@@ -6,19 +6,6 @@
6
  <font id="genericonsregular" horiz-adv-x="2048" >
7
  <font-face units-per-em="2048" ascent="1638" descent="-410" />
8
  <missing-glyph horiz-adv-x="500" />
9
- <glyph unicode="&#x2000;" horiz-adv-x="1024" />
10
- <glyph unicode="&#x2001;" />
11
- <glyph unicode="&#x2002;" horiz-adv-x="1024" />
12
- <glyph unicode="&#x2003;" />
13
- <glyph unicode="&#x2004;" horiz-adv-x="682" />
14
- <glyph unicode="&#x2005;" horiz-adv-x="512" />
15
- <glyph unicode="&#x2006;" horiz-adv-x="341" />
16
- <glyph unicode="&#x2007;" horiz-adv-x="341" />
17
- <glyph unicode="&#x2008;" horiz-adv-x="256" />
18
- <glyph unicode="&#x2009;" horiz-adv-x="409" />
19
- <glyph unicode="&#x200a;" horiz-adv-x="113" />
20
- <glyph unicode="&#x202f;" horiz-adv-x="409" />
21
- <glyph unicode="&#x205f;" horiz-adv-x="512" />
22
  <glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
23
  <glyph unicode="&#xf100;" d="M512 512v128h768v-128h-768zM512 768v128h256v-128h-256zM512 1024v128h640v-128h-640zM512 1280v128h1024v-128h-1024zM896 768v128h640v-128h-640zM1280 1024v128h256v-128h-256z" />
24
  <glyph unicode="&#xf101;" d="M256 1024q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM768 1024q0 -106 75 -181t181 -75t181 75t75 181t-75 181t-181 75t-181 -75t-75 -181z" />
@@ -27,21 +14,26 @@
27
  <glyph unicode="&#xf104;" d="M512 384v1280l1152 -640z" />
28
  <glyph unicode="&#xf105;" d="M640 1408q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5q0 -124 -71.5 -222t-184.5 -138v-536l-256 -128v664q-113 40 -184.5 138t-71.5 222z" />
29
  <glyph unicode="&#xf106;" d="M384 640l128 768h512l-256 -768h-384zM1152 640l128 768h512l-256 -768h-384z" />
30
- <glyph unicode="&#xf107;" d="M376 852q0 108 72 204l160 128l96 -96l-160 -128q-48 -96 0 -192l96 -96q96 -48 192 0l128 160l96 -96l-128 -160q-96 -72 -204 -72t-180 72l-96 96q-72 72 -72 180zM736 960l352 352l96 -96l-352 -352zM864 1440l128 160q96 72 204 72t180 -72l96 -96q72 -72 72 -180 t-72 -204l-160 -128l-96 96l160 128q48 96 0 192l-96 96q-96 48 -192 0l-128 -160z" />
31
  <glyph unicode="&#xf108;" d="M0 1152v384q0 96 80 176t176 80h1024q96 0 176 -80t80 -176v-384q0 -96 -80 -176t-176 -80h-448l-448 -448v448h-128q-96 0 -176 80t-80 176zM768 640l128 128h384q168 0 276 108t108 276v384q96 0 176 -80t80 -176v-384q0 -96 -80 -176t-176 -80h-128v-448l-448 448 h-320z" />
32
- <glyph unicode="&#xf109;" d="M256 768v512h384l384 384v-1280l-384 384h-384zM1216 832q21 43 32 66.5t21.5 59.5t10.5 66t-10.5 66t-21.5 59.5t-32 66.5l96 96q96 -144 96 -288q0 -160 -96 -256zM1376 672q74 74 117 166t43 186t-43 186t-117 166l96 96q95 -71 143.5 -186.5t48.5 -261.5 t-48.5 -261.5t-143.5 -186.5z" />
33
- <glyph unicode="&#xf200;" d="M0 1024q0 212 79.5 402t216 326.5t326.5 216t402 79.5t402 -79.5t326.5 -216t216 -326.5t79.5 -402t-79.5 -402t-216 -326.5t-326.5 -216t-402 -79.5t-402 79.5t-326.5 216t-216 326.5t-79.5 402zM128 1024q0 -307 173.5 -536.5t466.5 -327.5v224q0 224 128 224 q-125 0 -213.5 16t-146.5 47t-91.5 83t-47 115.5t-13.5 154.5q0 100 25 187t71 133q-28 71 -28 143t14 109l14 36q7 0 18 -1t44 -7.5t63 -18.5t67 -38.5t64 -62.5q144 24 300 24t276 -24q27 36 60 62.5t60.5 38.5t51.5 18.5t38 7.5l14 1q4 -5 10 -14.5t19 -40.5t20 -63 t4 -78.5t-21 -91.5q96 -144 96 -320q0 -113 -21 -187.5t-75 -128t-147.5 -77t-236.5 -23.5q49 -25 72.5 -77.5t23.5 -146.5v-224q293 98 466.5 327.5t173.5 536.5q0 176 -73 341.5t-194.5 287t-287 194.5t-341.5 73t-341.5 -73t-287 -194.5t-194.5 -287t-73 -341.5z" />
34
  <glyph unicode="&#xf201;" d="M0 1024q0 206 82 395.5t219.5 327t327 219.5t395.5 82t395.5 -82t327 -219.5t219.5 -327t82 -395.5t-82 -395.5t-219.5 -327t-327 -219.5t-395.5 -82t-395.5 82t-327 219.5t-219.5 327t-82 395.5zM128 1024q0 -167 58 -319.5t166 -272.5q125 205 339 360t445 232 q-16 48 -80 176q-282 -86 -481.5 -111t-446.5 -1v-64zM160 1232q194 -22 444 14t388 82q-141 282 -320 528q-194 -85 -329.5 -247.5t-182.5 -376.5zM480 320q216 -192 544 -192q181 0 368 80q-33 300 -208 688q-222 -74 -410 -225.5t-294 -350.5zM832 1904 q102 -166 304 -512q6 2 86 31t118.5 45t108 47t122 64t93.5 69q-126 126 -290.5 199t-349.5 73q-32 0 -96 -8t-96 -8zM1200 1248q22 -29 36.5 -54.5t34 -67.5t25.5 -54q170 33 336 30t288 -30q-26 285 -160 464q-71 -57 -162 -104.5t-214.5 -100.5t-183.5 -83zM1344 928 q14 -27 43 -103t74.5 -231t74.5 -306q156 108 258 278t126 362q-276 46 -576 0z" />
35
  <glyph unicode="&#xf202;" d="M0 381q50 -6 100 -6q293 0 522 180q-137 2 -244.5 83t-147.5 208q44 -7 79 -7q57 0 110 15q-145 29 -241 144.5t-96 267.5v5q86 -48 191 -53q-86 58 -136.5 150t-50.5 200q0 113 57 211q158 -194 383 -310t483 -129q-11 49 -11 96q0 174 123 297t297 123q89 0 168.5 -35 t138.5 -97q142 27 266 102q-47 -150 -184 -233q124 15 241 66q-84 -127 -210 -217q2 -36 2 -55q0 -168 -49 -337t-150 -323.5t-241 -273.5t-336 -190t-420 -71q-351 0 -644 189z" />
36
- <glyph unicode="&#xf203;" d="M0 117q0 -48 34.5 -82.5t82.5 -34.5h1814q48 0 82.5 34.5t34.5 82.5v1814q0 48 -34.5 82.5t-82.5 34.5h-1814q-48 0 -82.5 -34.5t-34.5 -82.5v-1814zM900 969v303h222v258q0 78 26 147t77 124t136.5 87t194.5 32q55 0 108 -3t79 -6l26 -3l-7 -282h-193q-76 0 -101.5 -32 t-25.5 -101v-3v-2v-9v-207h329l-14 -303h-315v-841h-320v841h-222z" />
37
  <glyph unicode="&#xf204;" d="M640 969v303h222v258q0 78 26 147t77 124t136.5 87t194.5 32q55 0 108 -3t79 -6l26 -3l-7 -282h-193q-76 0 -101.5 -32t-25.5 -101v-3v-2v-9v-207h329l-14 -303h-315v-841h-320v841h-222z" />
38
- <glyph unicode="&#xf205;" d="M0 1024q0 208 81 397.5t218.5 327t327 218.5t397.5 81t398 -81t327 -218.5t218 -327t81 -397.5q0 -209 -81 -398.5t-218 -326.5t-326.5 -218t-398.5 -81q-208 0 -397.5 81t-327 218t-218.5 327t-81 398zM128 1024q0 -259 135.5 -473.5t359.5 -327.5l-421 1156 q-74 -168 -74 -355zM285 1530q4 0 13.5 -0.5t15.5 -0.5q70 0 127.5 2.5t80.5 4.5l22 3q29 2 46.5 -16t19.5 -40.5t-13 -43t-44 -24.5q-27 -4 -70 -8l295 -877l198 591l-104 283l-90 11q-38 2 -51.5 34t4.5 62t56 28q54 -10 201 -10q70 0 127.5 2.5t80.5 4.5l22 3 q38 2 56.5 -27t5 -60.5t-51.5 -36.5q-27 -4 -69 -8l293 -870l90 301q69 177 69 293q0 51 -14 107q-18 45 -40 81q-2 3 -15 24t-15.5 25t-13 22t-13 24.5t-10 22t-10 24.5t-6.5 22t-5 25t-1 24q0 63 42 110.5t106 49.5q-121 108 -274.5 168t-321.5 60q-226 0 -421 -105 t-318 -285zM772 165q123 -37 252 -37q152 0 296 51q0 1 -1 1l-1 2l-278 763zM1485 256q199 120 317 324t118 444q0 216 -99 409q4 -44 4 -68q0 -153 -69 -324z" />
39
- <glyph unicode="&#xf206;" d="M128 486v485q125 -127 330 -127q30 0 59 3q-32 -61 -32 -118q0 -33 13 -63t28.5 -48.5t45.5 -47.5q-18 0 -54.5 -0.5t-55.5 -0.5q-183 0 -334 -83zM128 1599v97q0 93 65.5 158.5t158.5 65.5h1344q93 0 158.5 -65.5t65.5 -158.5v-224h-280v280h-140v-280h-280v-140h280 v-280h140v280h280v-980q0 -93 -65.5 -158.5t-158.5 -65.5h-539q5 28 5 50q0 143 -46.5 230t-189.5 194q-3 2 -20.5 15t-25 19t-25.5 20t-27.5 22.5t-24 22t-23 23.5t-17 22t-12.5 22.5t-4 20.5q0 52 23 87t99 94q180 141 180 324q0 113 -45 204.5t-128 139.5h160l135 142 h-607q-127 0 -241.5 -49t-194.5 -132zM134 301q56 89 166.5 143.5t241.5 53.5q84 -1 158 -26q19 -13 62 -42.5t61 -42t48 -37t44.5 -41.5t29 -41.5t21.5 -49.5q7 -29 7 -66q0 -16 -1 -24h-620q-79 0 -140 49t-78 124zM228 1307q-21 161 50.5 269.5t194.5 104.5 q121 -4 215.5 -118.5t116.5 -277.5q21 -160 -43 -256t-187 -92q-125 4 -225.5 108t-121.5 262z" />
40
  <glyph unicode="&#xf207;" d="M384 1422q0 -58 40.5 -97.5t105.5 -39.5h1q67 0 108.5 39.5t41.5 97.5q-2 60 -42 98.5t-106 38.5q-67 0 -108 -39t-41 -98zM400 384h263v793h-263v-793zM809 384h264v443q0 45 8 64q16 40 50.5 68t85.5 28q133 0 133 -179v-424h264v455q0 175 -83.5 266t-220.5 91 q-50 0 -90.5 -12t-68.5 -34t-45 -41t-33 -44v112h-264v-793z" />
41
  <glyph unicode="&#xf208;" d="M128 384v1280q0 106 75 181t181 75h1280q106 0 181 -75t75 -181v-1280q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM384 1422q0 -58 40.5 -97.5t105.5 -39.5h1q67 0 108.5 39.5t41.5 97.5q-2 60 -42 98.5t-106 38.5q-67 0 -108 -39t-41 -98zM400 384h263 v793h-263v-793zM809 384h264v443q0 45 8 64q16 40 50.5 68t85.5 28q133 0 133 -179v-424h264v455q0 175 -83.5 266t-220.5 91q-50 0 -90.5 -12t-68.5 -34t-45 -41t-33 -44v112h-264v-793z" />
42
  <glyph unicode="&#xf209;" d="M171 1260q0 109 35.5 219t110 213t179 182t254 126.5t323.5 47.5q176 0 327.5 -60.5t253.5 -161t160 -231t58 -270.5q0 -246 -85 -443t-241 -309.5t-355 -112.5q-99 0 -186.5 46.5t-121.5 110.5q-73 -290 -89 -347q-34 -123 -127 -270l-149 54q-7 167 22 290l162 688 q-40 81 -40 200q0 139 70.5 232.5t172.5 93.5q83 0 127 -53.5t44 -135.5q0 -51 -18.5 -124t-49 -170t-44.5 -154q-23 -99 37.5 -171t161.5 -72q117 0 209.5 92t142 244.5t49.5 334.5q0 214 -139 349t-387 135q-139 0 -257.5 -49.5t-197 -133t-122.5 -193t-44 -229.5 q0 -147 83 -247q18 -21 21.5 -34t-3.5 -37q-16 -61 -25 -101q-7 -24 -24.5 -32t-39.5 1q-127 51 -192.5 181.5t-65.5 300.5z" />
43
  <glyph unicode="&#xf210;" d="M0 1024q0 208 81 398t218.5 327t327 218t397.5 81q209 0 398.5 -81t326.5 -218t218 -326.5t81 -398.5t-81 -398.5t-218 -326.5t-326.5 -218t-398.5 -81q-147 0 -290 42q74 116 103 219l72 282q28 -53 99 -90.5t151 -37.5q162 0 288.5 91.5t195.5 251t69 359.5 q0 114 -47 220t-130 187.5t-206.5 130.5t-265.5 49q-141 0 -262 -38.5t-205.5 -103t-145.5 -147.5t-89.5 -172.5t-28.5 -178.5q0 -138 53 -243.5t156 -147.5q18 -8 32.5 -1t18.5 26q2 9 10 41t11 41q5 19 2.5 30t-16.5 28q-68 78 -68 200q0 97 35.5 186t99.5 156.5t160 108 t209 40.5q201 0 313.5 -109.5t112.5 -283.5q0 -148 -40 -271.5t-115 -198t-169 -74.5q-82 0 -131.5 58.5t-30.5 138.5q11 46 35.5 125t39.5 138t15 101q0 66 -35.5 109.5t-102.5 43.5q-82 0 -139.5 -76t-57.5 -189q0 -43 8 -83.5t16 -59.5l9 -19q-113 -475 -132 -558 q-24 -97 -18 -235q-275 120 -444 374t-169 564z" />
44
  <glyph unicode="&#xf211;" d="M160 1024q0 -172 122 -294t294 -122t294 122t122 294t-122 294t-294 122t-294 -122t-122 -294zM1056 1024q0 -172 122 -294t294 -122t294 122t122 294t-122 294t-294 122t-294 -122t-122 -294z" />
 
 
 
 
 
45
  <glyph unicode="&#xf300;" d="M256 896v384q0 106 75 181t181 75h1024q106 0 181 -75t75 -181v-384q0 -106 -75 -181t-181 -75h-448l-448 -448v448h-128q-106 0 -181 75t-75 181z" />
46
  <glyph unicode="&#xf301;" d="M384 512v1024h384l64 -128h448v-128h-640l-128 -256h128l64 128h960l-256 -640h-1024z" />
47
  <glyph unicode="&#xf302;" d="M256 768l768 768h512v-512l-768 -768zM1152 1280q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z" />
@@ -50,6 +42,7 @@
50
  <glyph unicode="&#xf305;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM768 1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45 v-512q0 -26 -19 -45t-45 -19t-45 19t-19 45v448h-64q-26 0 -45 19t-19 45z" />
51
  <glyph unicode="&#xf306;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM768 1216q0 26 19 45t45 19h256h2h1h3 q22 -2 38.5 -18t19.5 -39v-2v-2v-1v-2q0 -5 -2 -15l-128 -512q-6 -26 -28.5 -40t-48.5 -7q-26 6 -40 28.5t-7 48.5l108 433h-174q-26 0 -45 19t-19 45z" />
52
  <glyph unicode="&#xf307;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM512 640v128h128v-128h-128zM512 896v128h128v-128 h-128zM768 640v128h128v-128h-128zM768 896v128h128v-128h-128zM768 1152v128h128v-128h-128zM1024 640v128h128v-128h-128zM1024 896v128h128v-128h-128zM1024 1152v128h128v-128h-128zM1280 896v128h128v-128h-128zM1280 1152v128h128v-128h-128z" />
 
53
  <glyph unicode="&#xf400;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5z" />
54
  <glyph unicode="&#xf401;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5zM512 1152v128h640v-128h-640z" />
55
  <glyph unicode="&#xf402;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5zM512 1152v128h256v256h128v-256h256v-128h-256v-256h-128v256h-256z" />
@@ -57,10 +50,10 @@
57
  <glyph unicode="&#xf404;" d="M0 1024l506 506q101 103 234.5 160.5t283.5 57.5q193 0 358 -95l-143 -143q-103 46 -215 46q-108 0 -206.5 -41t-173.5 -119l-372 -372l240 -240l-136 -136zM339 429l90 -90l1280 1280l-90 90zM640 1024q0 159 112.5 271.5t271.5 112.5q44 0 98 -14l-468 -468 q-14 54 -14 98zM666 395l143 143q103 -46 215 -46q108 0 206 41.5t174 118.5l373 372l-241 241l136 135l376 -376l-506 -507q-101 -103 -234.5 -160t-283.5 -57q-193 0 -358 95zM926 654l468 468q14 -54 14 -98q0 -159 -112.5 -271.5t-271.5 -112.5q-44 0 -98 14z" />
58
  <glyph unicode="&#xf405;" d="M640 768l320 320l-320 320l128 128l320 -320l320 320l128 -128l-320 -320l320 -320l-128 -128l-320 320l-320 -320z" />
59
  <glyph unicode="&#xf406;" d="M128 256l832 832l-832 832l128 128l832 -832l832 832l128 -128l-832 -832l832 -832l-128 -128l-832 832l-832 -832z" />
60
- <glyph unicode="&#xf407;" d="M384 1280q0 106 75 181t181 75h140q20 56 69.5 92t110.5 36q62 0 111 -35.5t69 -92.5h140q106 0 181 -75t75 -181h-128v-768q0 -53 -37.5 -90.5t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v768h-128zM640 576q0 -26 19 -45t45 -19t45 19t19 45v640q0 26 -19 45 t-45 19t-45 -19t-19 -45v-640zM896 576q0 -26 19 -45t45 -19t45 19t19 45v640q0 26 -19 45t-45 19t-45 -19t-19 -45v-640zM1152 576q0 -26 19 -45t45 -19t45 19t19 45v640q0 26 -19 45t-45 19t-45 -19t-19 -45v-640z" />
61
  <glyph unicode="&#xf408;" d="M256 1151l476 -330l-183 -535l475 332l475 -332l-183 535l476 329h-587l-181 535l-180 -534h-588z" />
62
  <glyph unicode="&#xf409;" d="M384 1024l640 640l640 -640l-128 -128l-512 512l-512 -512zM640 512v384l384 384l384 -384v-384h-256v384h-256v-384h-256z" />
63
- <glyph unicode="&#xf410;" d="M0 384l640 640l384 -384l384 384l640 -640h-2048zM0 512v1152l576 -576zM0 1792h2048l-1024 -1024zM1472 1088l576 576v-1152z" />
64
  <glyph unicode="&#xf411;" d="M384 384v448l896 896l448 -448l-896 -896h-448zM512 768l256 -256l128 128l-256 256zM685 941l96 -96l595 595l-96 96zM845 781l96 -96l595 595l-96 96z" />
65
  <glyph unicode="&#xf412;" d="M256 640v704l384 384v-704h640v448l640 -640l-640 -640v448h-1024z" />
66
  <glyph unicode="&#xf413;" d="M128 384q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181zM128 971v345q240 0 459 -94t377.5 -253.5t252.5 -379.5t94 -461h-345q0 170 -63.5 324t-181.5 273q-119 119 -272 182.5t-321 63.5zM129 1582v345q243 0 475 -64.5t428.5 -181 t362 -282.5t281 -363.5t180 -430.5t64.5 -477h-345q0 197 -52 385.5t-145.5 348t-227 294t-292 228t-346 146t-383.5 52.5z" />
@@ -70,9 +63,40 @@
70
  <glyph unicode="&#xf417;" d="M384 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5t-44.5 -222.5t-124.5 -185.5l-407 -406l-407 406q-80 80 -124.5 185.5t-44.5 222.5zM640 1216q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5t93.5 226.5t-93.5 226.5 t-226.5 93.5t-226.5 -93.5t-93.5 -226.5z" />
71
  <glyph unicode="&#xf418;" d="M608 1056l128 128l224 -192l448 512l128 -96l-512 -768h-128z" />
72
  <glyph unicode="&#xf419;" d="M0 256v256h2048v-256h-2048zM0 896v256h2048v-256h-2048zM0 1536v256h2048v-256h-2048z" />
73
- <glyph unicode="&#xf420;" d="M384 512l640 640l640 -640h-1280zM384 1280v128h1280v-128h-1280z" />
74
  <glyph unicode="&#xf421;" d="M384 896v256h1152v-256h-1152z" />
75
  <glyph unicode="&#xf422;" d="M384 512v1024h1152v-1024h-1152zM512 640h896v640h-896v-640z" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  <glyph unicode="&#xf500;" d="M128 0l960 960l960 -960h-1920z" />
77
  <glyph unicode="&#xf501;" d="M0 128l960 960l-960 960v-1920z" />
78
  <glyph unicode="&#xf502;" d="M128 2048l960 -960l960 960h-1920z" />
6
  <font id="genericonsregular" horiz-adv-x="2048" >
7
  <font-face units-per-em="2048" ascent="1638" descent="-410" />
8
  <missing-glyph horiz-adv-x="500" />
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  <glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
10
  <glyph unicode="&#xf100;" d="M512 512v128h768v-128h-768zM512 768v128h256v-128h-256zM512 1024v128h640v-128h-640zM512 1280v128h1024v-128h-1024zM896 768v128h640v-128h-640zM1280 1024v128h256v-128h-256z" />
11
  <glyph unicode="&#xf101;" d="M256 1024q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM768 1024q0 -106 75 -181t181 -75t181 75t75 181t-75 181t-181 75t-181 -75t-75 -181z" />
14
  <glyph unicode="&#xf104;" d="M512 384v1280l1152 -640z" />
15
  <glyph unicode="&#xf105;" d="M640 1408q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5q0 -124 -71.5 -222t-184.5 -138v-536l-256 -128v664q-113 40 -184.5 138t-71.5 222z" />
16
  <glyph unicode="&#xf106;" d="M384 640l128 768h512l-256 -768h-384zM1152 640l128 768h512l-256 -768h-384z" />
17
+ <glyph unicode="&#xf107;" d="M387 862q0 106 75 181l136 135l91 -90l-136 -136q-38 -37 -38 -90t38 -91l90 -90q38 -38 91 -38t90 38l136 135l91 -90l-136 -136q-75 -75 -181 -75t-181 75l-91 91q-75 75 -75 181zM734 952l362 362l90 -90l-362 -362zM870 1450l135 136q75 75 181 75t181 -75l91 -91 q75 -75 75 -181t-75 -181l-136 -136l-90 91l135 136q38 37 38 90t-38 91l-90 90q-38 38 -91 38t-90 -38l-136 -135z" />
18
  <glyph unicode="&#xf108;" d="M0 1152v384q0 96 80 176t176 80h1024q96 0 176 -80t80 -176v-384q0 -96 -80 -176t-176 -80h-448l-448 -448v448h-128q-96 0 -176 80t-80 176zM768 640l128 128h384q168 0 276 108t108 276v384q96 0 176 -80t80 -176v-384q0 -96 -80 -176t-176 -80h-128v-448l-448 448 h-320z" />
19
+ <glyph unicode="&#xf109;" d="M256 768v512h384l384 384v-1280l-384 384h-384zM1205 843q75 75 75 181t-75 181l91 91q53 -54 82.5 -124t29.5 -148t-29.5 -148t-82.5 -124zM1386 662q71 71 110.5 164.5t39.5 197.5t-39.5 197.5t-110.5 164.5l91 91q88 -89 137.5 -206t49.5 -247q0 -87 -23 -170 t-64.5 -153.5t-99.5 -129.5z" />
20
+ <glyph unicode="&#xf200;" d="M0 1024q0 208 81 398t218.5 327t327 218t397.5 81q209 0 398.5 -81t326.5 -218t218 -326.5t81 -398.5q0 -335 -195.5 -601.5t-504.5 -369.5q-36 -7 -53 8.5t-17 40.5q0 4 0.5 102t0.5 179q0 130 -69 189q77 9 137.5 24.5t124.5 51.5t107 89t70.5 140t27.5 201 q0 161 -105 274q6 15 11 35t9 56t-3.5 83.5t-26.5 96.5q-4 1 -10.5 2t-32 -1t-55.5 -11t-79.5 -33.5t-104.5 -61.5q-118 33 -256 35q-138 -2 -256 -35q-55 37 -104 61.5t-80 33t-54.5 11.5t-33.5 1l-10 -2q-58 -146 -10 -271q-105 -115 -105 -274q0 -114 27.5 -201 t70.5 -140t107 -89t124.5 -52t136.5 -24q-53 -47 -65 -137q-28 -13 -59.5 -20t-75.5 -6.5t-87.5 28.5t-75.5 83q-2 4 -6.5 10.5t-19 24t-31.5 31t-44 25.5t-56 14h-10t-18.5 -3.5t-17 -9t4 -18.5t34.5 -31q3 -1 7.5 -4t19 -14.5t27.5 -27t30 -43.5t30 -61q1 -3 2.5 -7t8 -17 t15.5 -25.5t24.5 -28t33.5 -28t45 -23.5t57.5 -16t71.5 -3.5t87 11.5q0 -50 0.5 -110t0.5 -64q0 -24 -17 -40t-53 -10q-309 103 -504.5 370t-195.5 602z" />
21
  <glyph unicode="&#xf201;" d="M0 1024q0 206 82 395.5t219.5 327t327 219.5t395.5 82t395.5 -82t327 -219.5t219.5 -327t82 -395.5t-82 -395.5t-219.5 -327t-327 -219.5t-395.5 -82t-395.5 82t-327 219.5t-219.5 327t-82 395.5zM128 1024q0 -167 58 -319.5t166 -272.5q125 205 339 360t445 232 q-16 48 -80 176q-282 -86 -481.5 -111t-446.5 -1v-64zM160 1232q194 -22 444 14t388 82q-141 282 -320 528q-194 -85 -329.5 -247.5t-182.5 -376.5zM480 320q216 -192 544 -192q181 0 368 80q-33 300 -208 688q-222 -74 -410 -225.5t-294 -350.5zM832 1904 q102 -166 304 -512q6 2 86 31t118.5 45t108 47t122 64t93.5 69q-126 126 -290.5 199t-349.5 73q-32 0 -96 -8t-96 -8zM1200 1248q22 -29 36.5 -54.5t34 -67.5t25.5 -54q170 33 336 30t288 -30q-26 285 -160 464q-71 -57 -162 -104.5t-214.5 -100.5t-183.5 -83zM1344 928 q14 -27 43 -103t74.5 -231t74.5 -306q156 108 258 278t126 362q-276 46 -576 0z" />
22
  <glyph unicode="&#xf202;" d="M0 381q50 -6 100 -6q293 0 522 180q-137 2 -244.5 83t-147.5 208q44 -7 79 -7q57 0 110 15q-145 29 -241 144.5t-96 267.5v5q86 -48 191 -53q-86 58 -136.5 150t-50.5 200q0 113 57 211q158 -194 383 -310t483 -129q-11 49 -11 96q0 174 123 297t297 123q89 0 168.5 -35 t138.5 -97q142 27 266 102q-47 -150 -184 -233q124 15 241 66q-84 -127 -210 -217q2 -36 2 -55q0 -168 -49 -337t-150 -323.5t-241 -273.5t-336 -190t-420 -71q-351 0 -644 189z" />
23
+ <glyph unicode="&#xf203;" d="M128 384v1280q0 106 75 181t181 75h1280q106 0 181 -75t75 -181v-1280q0 -106 -75 -181t-181 -75h-282v711h270l12 260h-282v192v12q0 60 21.5 87.5t87.5 27.5l166 -1l6 242q-78 10 -183 10q-94 0 -167 -27.5t-117 -74.5t-66 -105.5t-22 -126.5v-236h-254v-260h254v-711 h-724q-106 0 -181 75t-75 181z" />
24
  <glyph unicode="&#xf204;" d="M640 969v303h222v258q0 78 26 147t77 124t136.5 87t194.5 32q55 0 108 -3t79 -6l26 -3l-7 -282h-193q-76 0 -101.5 -32t-25.5 -101v-3v-2v-9v-207h329l-14 -303h-315v-841h-320v841h-222z" />
25
+ <glyph unicode="&#xf205;" d="M128 1024q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348zM218 1024q0 -236 125 -430.5t329 -294.5l-384 1053q-70 -156 -70 -328zM351 1466h52q37 0 91 2.5t89 4.5 l34 3q21 1 30.5 -14.5t2.5 -32.5t-27 -20q-44 -5 -93 -7l294 -873l176 529l-125 344l-85 7q-20 2 -27.5 19t2.5 33t30 15q133 -10 212 -10q38 0 91.5 2.5t88.5 4.5l35 3q16 1 25.5 -8.5t10 -22t-7 -23.5t-23.5 -13q-43 -5 -92 -7l291 -866l80 268q25 79 33.5 107.5 t18.5 74.5t10 79q0 46 -11.5 90.5t-23.5 71t-32 60.5q-2 4 -11.5 19t-12 20t-10.5 18.5t-11 19t-9 17.5t-8.5 19t-6.5 18t-5.5 19.5t-3 18.5t-1.5 20q0 57 39 100t96 43q3 0 11 -1q-110 101 -249.5 156.5t-294.5 55.5q-208 0 -385.5 -98t-287.5 -266zM796 251 q112 -33 228 -33q138 0 267 46q-3 6 -5 11l-248 679zM1429 328q183 106 291.5 291.5t108.5 404.5q0 207 -98 386q5 -40 5 -82q0 -135 -61 -289z" />
26
+ <glyph unicode="&#xf206;" d="M128 486v485q125 -127 330 -127q30 0 59 3q-32 -61 -32 -118q0 -33 13 -63t28.5 -48.5t45.5 -47.5q-18 0 -54.5 -0.5t-55.5 -0.5q-183 0 -334 -83zM128 1599v65q0 106 75 181t181 75h1280q106 0 181 -75t75 -181v-128h-256v256h-128v-256h-256v-128h256v-256h128v256h256 v-1024q0 -106 -75 -181t-181 -75h-507q5 28 5 50q0 143 -46.5 230t-189.5 194q-3 2 -20.5 15t-25 19t-25.5 20t-27.5 22.5t-24 22t-23 23.5t-17 22t-12.5 22.5t-4 20.5q0 52 23 87t99 94q180 141 180 324q0 113 -45 204.5t-128 139.5h160l135 142h-607q-127 0 -241.5 -49 t-194.5 -132zM139 309q57 85 166 137.5t237 51.5q84 -1 158 -26q19 -13 62 -42.5t61 -42t48 -37t44.5 -41.5t29 -41.5t21.5 -49.5q7 -29 7 -66q0 -16 -1 -24h-588q-85 0 -153 50.5t-92 130.5zM228 1307q-21 161 50.5 269.5t194.5 104.5q121 -4 215.5 -118.5t116.5 -277.5 q21 -160 -43 -256t-187 -92q-125 4 -225.5 108t-121.5 262z" />
27
  <glyph unicode="&#xf207;" d="M384 1422q0 -58 40.5 -97.5t105.5 -39.5h1q67 0 108.5 39.5t41.5 97.5q-2 60 -42 98.5t-106 38.5q-67 0 -108 -39t-41 -98zM400 384h263v793h-263v-793zM809 384h264v443q0 45 8 64q16 40 50.5 68t85.5 28q133 0 133 -179v-424h264v455q0 175 -83.5 266t-220.5 91 q-50 0 -90.5 -12t-68.5 -34t-45 -41t-33 -44v112h-264v-793z" />
28
  <glyph unicode="&#xf208;" d="M128 384v1280q0 106 75 181t181 75h1280q106 0 181 -75t75 -181v-1280q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM384 1422q0 -58 40.5 -97.5t105.5 -39.5h1q67 0 108.5 39.5t41.5 97.5q-2 60 -42 98.5t-106 38.5q-67 0 -108 -39t-41 -98zM400 384h263 v793h-263v-793zM809 384h264v443q0 45 8 64q16 40 50.5 68t85.5 28q133 0 133 -179v-424h264v455q0 175 -83.5 266t-220.5 91q-50 0 -90.5 -12t-68.5 -34t-45 -41t-33 -44v112h-264v-793z" />
29
  <glyph unicode="&#xf209;" d="M171 1260q0 109 35.5 219t110 213t179 182t254 126.5t323.5 47.5q176 0 327.5 -60.5t253.5 -161t160 -231t58 -270.5q0 -246 -85 -443t-241 -309.5t-355 -112.5q-99 0 -186.5 46.5t-121.5 110.5q-73 -290 -89 -347q-34 -123 -127 -270l-149 54q-7 167 22 290l162 688 q-40 81 -40 200q0 139 70.5 232.5t172.5 93.5q83 0 127 -53.5t44 -135.5q0 -51 -18.5 -124t-49 -170t-44.5 -154q-23 -99 37.5 -171t161.5 -72q117 0 209.5 92t142 244.5t49.5 334.5q0 214 -139 349t-387 135q-139 0 -257.5 -49.5t-197 -133t-122.5 -193t-44 -229.5 q0 -147 83 -247q18 -21 21.5 -34t-3.5 -37q-16 -61 -25 -101q-7 -24 -24.5 -32t-39.5 1q-127 51 -192.5 181.5t-65.5 300.5z" />
30
  <glyph unicode="&#xf210;" d="M0 1024q0 208 81 398t218.5 327t327 218t397.5 81q209 0 398.5 -81t326.5 -218t218 -326.5t81 -398.5t-81 -398.5t-218 -326.5t-326.5 -218t-398.5 -81q-147 0 -290 42q74 116 103 219l72 282q28 -53 99 -90.5t151 -37.5q162 0 288.5 91.5t195.5 251t69 359.5 q0 114 -47 220t-130 187.5t-206.5 130.5t-265.5 49q-141 0 -262 -38.5t-205.5 -103t-145.5 -147.5t-89.5 -172.5t-28.5 -178.5q0 -138 53 -243.5t156 -147.5q18 -8 32.5 -1t18.5 26q2 9 10 41t11 41q5 19 2.5 30t-16.5 28q-68 78 -68 200q0 97 35.5 186t99.5 156.5t160 108 t209 40.5q201 0 313.5 -109.5t112.5 -283.5q0 -148 -40 -271.5t-115 -198t-169 -74.5q-82 0 -131.5 58.5t-30.5 138.5q11 46 35.5 125t39.5 138t15 101q0 66 -35.5 109.5t-102.5 43.5q-82 0 -139.5 -76t-57.5 -189q0 -43 8 -83.5t16 -59.5l9 -19q-113 -475 -132 -558 q-24 -97 -18 -235q-275 120 -444 374t-169 564z" />
31
  <glyph unicode="&#xf211;" d="M160 1024q0 -172 122 -294t294 -122t294 122t122 294t-122 294t-294 122t-294 -122t-122 -294zM1056 1024q0 -172 122 -294t294 -122t294 122t122 294t-122 294t-294 122t-294 -122t-122 -294z" />
32
+ <glyph unicode="&#xf212;" d="M128 1379l84 -108q121 84 141 84q92 0 173 -287q20 -73 46 -167.5t52 -190t46 -167.5q108 -287 265 -287q253 0 619 471q353 451 365 710q16 347 -260 355q-373 12 -505 -417q69 29 133 29q136 0 120 -152q-8 -92 -120 -268q-113 -176 -169 -176q-73 0 -133 271 q-20 78 -72 407q-49 303 -258 284q-89 -8 -265 -160q-126 -113 -262 -231z" />
33
+ <glyph unicode="&#xf213;" d="M128 768v512q0 159 112.5 271.5t271.5 112.5h1024q159 0 271.5 -112.5t112.5 -271.5v-512q0 -104 -51.5 -192.5t-140 -140t-192.5 -51.5h-1024q-104 0 -192.5 51.5t-140 140t-51.5 192.5zM768 640l640 384l-640 384v-768z" />
34
+ <glyph unicode="&#xf214;" d="M472 1186h198v-629q0 -121 26 -187q26 -65 92 -122t161 -89q93 -31 218 -31q110 0 201 22q88 20 208 76v282q-134 -88 -271 -88q-76 0 -136 36q-44 25 -61 70q-17 46 -17 200v460h426v281h-426v453h-255q-17 -139 -62 -228q-48 -93 -121 -154q-74 -64 -181 -99v-253z" />
35
+ <glyph unicode="&#xf215;" d="M128 384v1280q0 106 75 181t181 75h1280q106 0 181 -75t75 -181v-1280q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM256 384q0 -53 37.5 -90.5t90.5 -37.5h1280q53 0 90.5 37.5t37.5 90.5v768h-272q16 -66 16 -128q0 -212 -150 -362t-362 -150t-362 150 t-150 362q0 62 16 128h-272v-768zM640 1024q0 -159 112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5zM1408 1536q0 -53 37.5 -90.5t90.5 -37.5h128q53 0 90.5 37.5t37.5 90.5v128q0 53 -37.5 90.5t-90.5 37.5 h-128q-53 0 -90.5 -37.5t-37.5 -90.5v-128z" />
36
+ <glyph unicode="&#xf216;" d="M256 790v467q0 31 29 55l702 467q17 11 37 11t37 -11l702 -467q29 -24 29 -55v-467q0 -32 -29 -54l-702 -468q-17 -11 -37 -11q-18 0 -37 11l-702 468q-29 22 -29 54zM388 914l165 110l-165 110v-220zM441 790l517 -344v308l-286 191zM441 1257l231 -154l286 191v307z M791 1024l233 -156l234 156l-234 156zM1090 446l517 344l-231 155l-286 -191v-308zM1090 1294l286 -191l231 154l-517 344v-307zM1495 1024l165 -110v220z" />
37
  <glyph unicode="&#xf300;" d="M256 896v384q0 106 75 181t181 75h1024q106 0 181 -75t75 -181v-384q0 -106 -75 -181t-181 -75h-448l-448 -448v448h-128q-106 0 -181 75t-75 181z" />
38
  <glyph unicode="&#xf301;" d="M384 512v1024h384l64 -128h448v-128h-640l-128 -256h128l64 128h960l-256 -640h-1024z" />
39
  <glyph unicode="&#xf302;" d="M256 768l768 768h512v-512l-768 -768zM1152 1280q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z" />
42
  <glyph unicode="&#xf305;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM768 1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45 v-512q0 -26 -19 -45t-45 -19t-45 19t-19 45v448h-64q-26 0 -45 19t-19 45z" />
43
  <glyph unicode="&#xf306;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM768 1216q0 26 19 45t45 19h256h2h1h3 q22 -2 38.5 -18t19.5 -39v-2v-2v-1v-2q0 -5 -2 -15l-128 -512q-6 -26 -28.5 -40t-48.5 -7q-26 6 -40 28.5t-7 48.5l108 433h-174q-26 0 -45 19t-19 45z" />
44
  <glyph unicode="&#xf307;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM512 640v128h128v-128h-128zM512 896v128h128v-128 h-128zM768 640v128h128v-128h-128zM768 896v128h128v-128h-128zM768 1152v128h128v-128h-128zM1024 640v128h128v-128h-128zM1024 896v128h128v-128h-128zM1024 1152v128h128v-128h-128zM1280 896v128h128v-128h-128zM1280 1152v128h128v-128h-128z" />
45
+ <glyph unicode="&#xf308;" d="M256 384l512 512l128 -128l-512 -512zM576 1216v128h384l320 320v256h128l512 -512v-128h-256l-320 -320v-384h-128z" />
46
  <glyph unicode="&#xf400;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5z" />
47
  <glyph unicode="&#xf401;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5zM512 1152v128h640v-128h-640z" />
48
  <glyph unicode="&#xf402;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5zM512 1152v128h256v256h128v-256h256v-128h-256v-256h-128v256h-256z" />
50
  <glyph unicode="&#xf404;" d="M0 1024l506 506q101 103 234.5 160.5t283.5 57.5q193 0 358 -95l-143 -143q-103 46 -215 46q-108 0 -206.5 -41t-173.5 -119l-372 -372l240 -240l-136 -136zM339 429l90 -90l1280 1280l-90 90zM640 1024q0 159 112.5 271.5t271.5 112.5q44 0 98 -14l-468 -468 q-14 54 -14 98zM666 395l143 143q103 -46 215 -46q108 0 206 41.5t174 118.5l373 372l-241 241l136 135l376 -376l-506 -507q-101 -103 -234.5 -160t-283.5 -57q-193 0 -358 95zM926 654l468 468q14 -54 14 -98q0 -159 -112.5 -271.5t-271.5 -112.5q-44 0 -98 14z" />
51
  <glyph unicode="&#xf405;" d="M640 768l320 320l-320 320l128 128l320 -320l320 320l128 -128l-320 -320l320 -320l-128 -128l-320 320l-320 -320z" />
52
  <glyph unicode="&#xf406;" d="M128 256l832 832l-832 832l128 128l832 -832l832 832l128 -128l-832 -832l832 -832l-128 -128l-832 832l-832 -832z" />
53
+ <glyph unicode="&#xf407;" d="M384 1280v128l256 128q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5l256 -128v-128h-1152zM512 512v704h128v-704h128v704h128v-704h128v704h128v-704h128v704h128v-704q0 -53 -37.5 -90.5t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5zM768 1472 q0 -26 19 -45t45 -19h256q26 0 45 19t19 45t-19 45t-45 19h-256q-26 0 -45 -19t-19 -45z" />
54
  <glyph unicode="&#xf408;" d="M256 1151l476 -330l-183 -535l475 332l475 -332l-183 535l476 329h-587l-181 535l-180 -534h-588z" />
55
  <glyph unicode="&#xf409;" d="M384 1024l640 640l640 -640l-128 -128l-512 512l-512 -512zM640 512v384l384 384l384 -384v-384h-256v384h-256v-384h-256z" />
56
+ <glyph unicode="&#xf410;" d="M256 512v51l576 384l192 -128l192 128l576 -384v-51h-1536zM256 717v614l461 -307zM256 1485v51h1536v-51l-768 -512zM1331 1024l461 307v-614z" />
57
  <glyph unicode="&#xf411;" d="M384 384v448l896 896l448 -448l-896 -896h-448zM512 768l256 -256l128 128l-256 256zM685 941l96 -96l595 595l-96 96zM845 781l96 -96l595 595l-96 96z" />
58
  <glyph unicode="&#xf412;" d="M256 640v704l384 384v-704h640v448l640 -640l-640 -640v448h-1024z" />
59
  <glyph unicode="&#xf413;" d="M128 384q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181zM128 971v345q240 0 459 -94t377.5 -253.5t252.5 -379.5t94 -461h-345q0 170 -63.5 324t-181.5 273q-119 119 -272 182.5t-321 63.5zM129 1582v345q243 0 475 -64.5t428.5 -181 t362 -282.5t281 -363.5t180 -430.5t64.5 -477h-345q0 197 -52 385.5t-145.5 348t-227 294t-292 228t-346 146t-383.5 52.5z" />
63
  <glyph unicode="&#xf417;" d="M384 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5t-44.5 -222.5t-124.5 -185.5l-407 -406l-407 406q-80 80 -124.5 185.5t-44.5 222.5zM640 1216q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5t93.5 226.5t-93.5 226.5 t-226.5 93.5t-226.5 -93.5t-93.5 -226.5z" />
64
  <glyph unicode="&#xf418;" d="M608 1056l128 128l224 -192l448 512l128 -96l-512 -768h-128z" />
65
  <glyph unicode="&#xf419;" d="M0 256v256h2048v-256h-2048zM0 896v256h2048v-256h-2048zM0 1536v256h2048v-256h-2048z" />
 
66
  <glyph unicode="&#xf421;" d="M384 896v256h1152v-256h-1152z" />
67
  <glyph unicode="&#xf422;" d="M384 512v1024h1152v-1024h-1152zM512 640h896v640h-896v-640z" />
68
+ <glyph unicode="&#xf423;" d="M83 832l373 671l112 -62l-267 -481h403v-384h-128v256h-493zM768 1024q0 87 43 160.5t116.5 116.5t160.5 43t160.5 -43t116.5 -116.5t43 -160.5t-43 -160.5t-116.5 -116.5t-160.5 -43t-160.5 43t-116.5 116.5t-43 160.5zM896 1024q0 -79 56.5 -135.5t135.5 -56.5 t135.5 56.5t56.5 135.5t-56.5 135.5t-135.5 56.5t-135.5 -56.5t-56.5 -135.5zM1427 832l373 671l112 -62l-267 -481h403v-384h-128v256h-493z" />
69
+ <glyph unicode="&#xf424;" d="M256 640v768l384 384h768l384 -384v-768l-384 -384h-768zM896 640q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5zM896 1024q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v384q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5v-384z" />
70
+ <glyph unicode="&#xf425;" d="M384 384v1280h256q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5h256v-1280h-1152zM512 512h896v1024h-128v-128h-640v128h-128v-1024zM640 704q0 26 19 45t45 19t45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45zM640 960q0 26 19 45t45 19t45 -19t19 -45 t-19 -45t-45 -19t-45 19t-19 45zM640 1216q0 26 19 45t45 19t45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45zM768 1600q0 -26 19 -45t45 -19h256q26 0 45 19t19 45t-19 45t-45 19h-256q-26 0 -45 -19t-19 -45zM896 640v128h384v-128h-384zM896 896v128h384v-128h-384z M896 1152v128h384v-128h-384z" />
71
+ <glyph unicode="&#xf426;" d="M128 768q0 106 75 181t181 75h7q-7 29 -7 64q0 133 93.5 226.5t226.5 93.5q134 0 228 -96q47 101 140.5 162.5t207.5 61.5q159 0 271.5 -112.5t112.5 -271.5q0 -62 -23 -128h23q106 0 181 -75t75 -181t-75 -181t-181 -75h-1280q-106 0 -181 75t-75 181z" />
72
+ <glyph unicode="&#xf427;" d="M384 384v288l455 455l-1 1q-74 74 -74 180t74 181l233 233q75 74 181 74t180 -74l286 -286q74 -75 74 -180.5t-74 -180.5l-233 -233q-74 -73 -178.5 -74t-179.5 71l-455 -455h-288zM1088 1360l256 -256l160 160l-256 256z" />
73
+ <glyph unicode="&#xf428;" d="M768 1024q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181z" />
74
+ <glyph unicode="&#xf429;" d="M384 896v128h896l-343 343l87 86l493 -493l-493 -493l-87 86l343 343h-896z" />
75
+ <glyph unicode="&#xf430;" d="M531 960l493 -493l87 86l-343 343h896v128h-896l343 343l-87 86z" />
76
+ <glyph unicode="&#xf431;" d="M384 1152l128 128l448 -448l448 448l128 -128l-576 -576z" />
77
+ <glyph unicode="&#xf432;" d="M384 768l576 576l576 -576l-128 -128l-448 448l-448 -448z" />
78
+ <glyph unicode="&#xf433;" d="M0 0v896l896 -896h-896z" />
79
+ <glyph unicode="&#xf434;" d="M1152 0l896 896v-896h-896z" />
80
+ <glyph unicode="&#xf435;" d="M384 512l640 640l640 -640h-1280zM384 1280v128h1280v-128h-1280z" />
81
+ <glyph unicode="&#xf436;" d="M512 640v128h128v-128h-128zM512 896v128h128v-128h-128zM512 1152v128h128v-128h-128zM512 1408v128h128v-128h-128zM768 640v128h128v-128h-128zM768 896v128h128v-128h-128zM768 1152v128h128v-128h-128zM768 1408v128h128v-128h-128zM1024 640v128h128v-128h-128z M1024 896v128h128v-128h-128zM1024 1152v128h128v-128h-128zM1024 1408v128h128v-128h-128zM1280 640v128h128v-128h-128zM1280 896v128h128v-128h-128zM1280 1152v128h128v-128h-128zM1280 1408v128h128v-128h-128z" />
82
+ <glyph unicode="&#xf437;" d="M512 512v1024q0 106 75 181t181 75h512q106 0 181 -75t75 -181v-1024q0 -106 -75 -181t-181 -75h-512q-106 0 -181 75t-75 181zM640 768h768v768h-768v-768zM896 512q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z " />
83
+ <glyph unicode="&#xf438;" d="M256 1024v256h512v128l384 -256l-384 -256v128h-512zM512 512v384h128v-128h768v768h-768v-128h-128v128q0 106 75 181t181 75h512q106 0 181 -75t75 -181v-1024q0 -106 -75 -181t-181 -75h-512q-106 0 -181 75t-75 181zM896 512q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5 t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z" />
84
+ <glyph unicode="&#xf439;" d="M384 1152h1280q0 -231 -145.5 -406.5t-366.5 -220.5v-269h-256v269q-221 45 -366.5 220.5t-145.5 406.5zM640 1280v384q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5v-384h-256zM1152 1280v384q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5v-384h-256z" />
85
+ <glyph unicode="&#xf440;" d="M128 768q0 106 75 181t181 75h6q-6 32 -6 64q0 133 93.5 226.5t226.5 93.5q134 0 228 -96q47 101 140.5 162.5t207.5 61.5q159 0 271.5 -112.5t112.5 -271.5q0 -62 -23 -128h23q106 0 181 -75t75 -181t-75 -181t-181 -75h-384v256h-512v-256h-384q-106 0 -181 75t-75 181 zM640 384h256v256h256v-256h256l-384 -384z" />
86
+ <glyph unicode="&#xf441;" d="M128 768q0 106 75 181t181 75h6q-6 32 -6 64q0 133 93.5 226.5t226.5 93.5q134 0 228 -96q47 101 140.5 162.5t207.5 61.5q159 0 271.5 -112.5t112.5 -271.5q0 -62 -23 -128h23q106 0 181 -75t75 -181t-75 -181t-181 -75h-512v256h256l-384 384l-384 -384h256v-256h-512 q-106 0 -181 75t-75 181z" />
87
+ <glyph unicode="&#xf442;" d="M512 512v896h512l-128 -128h-256v-640h640v256l128 128v-512h-896zM896 987l550 549h-422v128h640v-640h-128v422l-550 -550z" />
88
+ <glyph unicode="&#xf443;" d="M512 384v1280h640l384 -384v-896h-1024zM640 512h768v640h-384v384h-384v-1024zM1152 1280h203l-203 203v-203z" />
89
+ <glyph unicode="&#xf444;" d="M384 512v1024q0 106 75 181t181 75h1024v-1152h-64q-53 0 -90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5h64v-128h-1024q-106 0 -181 75t-75 181zM512 512q0 -53 37.5 -90.5t90.5 -37.5h818q-50 55 -50 128t50 128h-818q-53 0 -90.5 -37.5t-37.5 -90.5z" />
90
+ <glyph unicode="&#xf445;" d="M160 747l232 201q-8 67 -8 76q0 8 8 75l-232 201l58 139l305 -21q47 60 107 107l-21 305l139 58l201 -232q67 8 75 8t75 -8l201 232l140 -58l-22 -305q56 -44 107 -107l305 22l58 -139l-232 -201q8 -67 8 -76q0 -8 -8 -75l232 -201l-58 -140l-305 22q-44 -56 -107 -107 l22 -305l-139 -58l-201 232q-67 -8 -76 -8q-8 0 -75 8l-201 -232l-139 58l21 305q-56 44 -107 107l-305 -22zM768 1024q0 -106 75 -181t181 -75t181 75t75 181t-75 181t-181 75t-181 -75t-75 -181z" />
91
+ <glyph unicode="&#xf446;" d="M256 1024q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM512 1024q0 -212 150 -362t362 -150q135 0 259 72l-699 699q-72 -126 -72 -259zM765 1464l699 -699 q72 123 72 259q0 212 -150 362t-362 150q-136 0 -259 -72z" />
92
+ <glyph unicode="&#xf447;" d="M256 1664v128h384v-256h1152l-256 -640h-896v-128h896v-128h-1024v1024h-256zM512 384q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5zM1280 384q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5 t-90.5 -37.5t-90.5 37.5t-37.5 90.5z" />
93
+ <glyph unicode="&#xf448;" d="M512 384v1280h384v-1280h-384zM1152 384v1280h384v-1280h-384z" />
94
+ <glyph unicode="&#xf449;" d="M512 512v1024h1024v-1024h-1024z" />
95
+ <glyph unicode="&#xf450;" d="M256 384v1280h384v-1280h-384zM768 1024l1024 640v-1280z" />
96
+ <glyph unicode="&#xf451;" d="M256 384v1280l1024 -640zM1408 384v1280h384v-1280h-384z" />
97
+ <glyph unicode="&#xf452;" d="M512 384v1280l1024 -640z" />
98
+ <glyph unicode="&#xf453;" d="M256 256v1536q0 106 75 181t181 75h1024q106 0 181 -75t75 -181v-1536q0 -106 -75 -181t-181 -75h-1024q-106 0 -181 75t-75 181zM512 512h1024v1280h-1024v-1280zM896 256q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5z" />
99
+ <glyph unicode="&#xf454;" d="M128 1024v256h512v128l384 -256l-384 -256v128h-512zM256 256v640h256v-384h1024v1280h-1024v-384h-256v384q0 106 75 181t181 75h1024q106 0 181 -75t75 -181v-1536q0 -106 -75 -181t-181 -75h-1024q-106 0 -181 75t-75 181zM896 256q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z" />
100
  <glyph unicode="&#xf500;" d="M128 0l960 960l960 -960h-1920z" />
101
  <glyph unicode="&#xf501;" d="M0 128l960 960l-960 960v-1920z" />
102
  <glyph unicode="&#xf502;" d="M128 2048l960 -960l960 960h-1920z" />
modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.ttf CHANGED
Binary file
modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.woff CHANGED
Binary file
modules/minileven/theme/pub/minileven/inc/tweaks.php CHANGED
@@ -13,7 +13,6 @@
13
  *
14
  */
15
  function minileven_excerpt( $count ) {
16
- $permalink = get_permalink( $post->ID );
17
  $excerpt = get_the_content();
18
  $excerpt = strip_tags( $excerpt );
19
  $excerpt = strip_shortcodes( $excerpt );
13
  *
14
  */
15
  function minileven_excerpt( $count ) {
 
16
  $excerpt = get_the_content();
17
  $excerpt = strip_tags( $excerpt );
18
  $excerpt = strip_shortcodes( $excerpt );
modules/minileven/theme/pub/minileven/style.css CHANGED
@@ -68,7 +68,7 @@ a img {
68
  border: 0;
69
  }
70
  article, aside, details, figcaption, figure,
71
- footer, header, hgroup, menu, nav, section {
72
  display: block;
73
  }
74
 
@@ -218,11 +218,20 @@ input#s {
218
  border-radius: 2px;
219
  height: 1.692em;
220
  line-height: 1.2;
221
- padding: 0.4em 0.6em;
 
 
 
222
  }
223
  input#searchsubmit {
224
  display: none;
225
  }
 
 
 
 
 
 
226
 
227
  /* Links */
228
  a {
@@ -286,7 +295,7 @@ object {
286
  /* =Header
287
  ----------------------------------------------- */
288
 
289
- #branding hgroup {
290
  margin-bottom: 1.3em;
291
  }
292
  #site-title,
@@ -515,6 +524,10 @@ body.singular .hentry {
515
  display: block;
516
  float: left;
517
  }
 
 
 
 
518
  .entry-meta .comments-link {
519
  display: block;
520
  float: right;
@@ -751,9 +764,16 @@ and remove the padding rules below.
751
  text-transform: uppercase;
752
  top: -5px;
753
  }
754
- .entry-header hgroup .entry-title {
755
  padding-top: 0.8em;
756
  }
 
 
 
 
 
 
 
757
 
758
  /* Singular content styles for Posts and Pages */
759
  .singular .hentry {
68
  border: 0;
69
  }
70
  article, aside, details, figcaption, figure,
71
+ footer, header, menu, nav, section {
72
  display: block;
73
  }
74
 
218
  border-radius: 2px;
219
  height: 1.692em;
220
  line-height: 1.2;
221
+ padding: 0.4em 0.6em 0.29em;
222
+ }
223
+ input#s:focus {
224
+ padding-bottom: 0.3em;
225
  }
226
  input#searchsubmit {
227
  display: none;
228
  }
229
+ input#s:focus,
230
+ input[type=text]:focus,
231
+ input[type=email]:focus,
232
+ textarea:focus {
233
+ font-size: 1.231em;
234
+ }
235
 
236
  /* Links */
237
  a {
295
  /* =Header
296
  ----------------------------------------------- */
297
 
298
+ #branding .site-branding {
299
  margin-bottom: 1.3em;
300
  }
301
  #site-title,
524
  display: block;
525
  float: left;
526
  }
527
+ .entry-meta .author-link {
528
+ display: block;
529
+ margin-top: 0.7em;
530
+ }
531
  .entry-meta .comments-link {
532
  display: block;
533
  float: right;
764
  text-transform: uppercase;
765
  top: -5px;
766
  }
767
+ .entry-header .entry-heading .entry-title {
768
  padding-top: 0.8em;
769
  }
770
+ .entry-header .entry-heading {
771
+ position: relative;
772
+ }
773
+ .entry-thumbnail {
774
+ margin-bottom: 0.7em;
775
+ text-align: center;
776
+ }
777
 
778
  /* Singular content styles for Posts and Pages */
779
  .singular .hentry {
modules/mobile-push.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /**
3
  * Module Name: Mobile Push Notifications
4
- * Module Description: Receive notifications on your Apple device.
5
  * Sort Order: 100
6
  * First Introduced: 1.9
7
  * Requires Connection: Yes
1
  <?php
2
  /**
3
  * Module Name: Mobile Push Notifications
4
+ * Module Description: Receive notifications on your mobile device.
5
  * Sort Order: 100
6
  * First Introduced: 1.9
7
  * Requires Connection: Yes
modules/module-extras.php CHANGED
@@ -56,3 +56,5 @@ add_filter( 'jetpack_can_activate_infinite-scroll', 'jetpack_can_activate_infini
56
  require_once( dirname( __FILE__ ) . '/holiday-snow.php' );
57
 
58
  require_once( dirname( __FILE__ ) . '/featured-content/featured-content.php' );
 
 
56
  require_once( dirname( __FILE__ ) . '/holiday-snow.php' );
57
 
58
  require_once( dirname( __FILE__ ) . '/featured-content/featured-content.php' );
59
+
60
+ require_once( dirname( __FILE__ ) . '/social-links.php' );
modules/module-info.php CHANGED
@@ -613,7 +613,7 @@ function jetpack_mobile_push_notifications_more_info() { ?>
613
 
614
  <h4><?php esc_html_e( 'Mobile Push Notifications' , 'jetpack' ); ?></h4>
615
 
616
- <p><?php _e( 'If you have your blog added to the <a href="http://ios.wordpress.org/">WordPress for iOS app</a>, you’ll now be able to opt in to receive push notifications of new comments, which makes it easier than ever to keep up with your readers and moderate comments on the go.', 'jetpack' ); ?></p>
617
 
618
  <?php
619
  }
@@ -776,3 +776,49 @@ function jetpack_likes_more_link() {
776
  }
777
  add_action( 'jetpack_learn_more_button_likes', 'jetpack_likes_more_link' );
778
  // Likes: STOP
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
 
614
  <h4><?php esc_html_e( 'Mobile Push Notifications' , 'jetpack' ); ?></h4>
615
 
616
+ <p><?php echo sprintf( __( 'If you use <a href="%1$s">WordPress for iOS</a> or <a href="%2$s">WordPress for Android</a>, you’ll now be able to opt in to receive push notifications of new comments, which makes it easier than ever to keep up with your readers and moderate comments on the go.', 'jetpack' ), 'http://ios.wordpress.org/', 'http://android.wordpress.org/' ); ?></p>
617
 
618
  <?php
619
  }
776
  }
777
  add_action( 'jetpack_learn_more_button_likes', 'jetpack_likes_more_link' );
778
  // Likes: STOP
779
+
780
+ // Debug: START
781
+ function jetpack_debug_more_info() { ?>
782
+
783
+ <h4><?php esc_html_e( 'Debug' , 'jetpack' ); ?></h4>
784
+
785
+ <p><?php esc_html_e( "A debugging platform for the Jetpack plugin. Find out why Jetpack isn't working for you and submit a help request direct from your Dashboard.", 'jetpack' ); ?></p>
786
+ <?php if ( Jetpack::is_module_active( 'debug' ) ) : ?>
787
+ <p><a href="<?php echo admin_url( 'admin.php?page=jetpack-debugger' ); ?>"><?php esc_html_e( "Click here to start debugging.", 'jetpack' ); ?></a></p>
788
+
789
+ <?php endif; ?>
790
+ <?php
791
+ }
792
+
793
+ function jetpack_debug_more_link() {
794
+ echo '<a class="button-secondary more-info-link" href="http://jetpack.me/support/debug/">' . __( 'Learn More', 'jetpack' ) . '</a>';
795
+ }
796
+
797
+ add_action( 'jetpack_module_more_info_debug', 'jetpack_debug_more_info' );
798
+ add_action( 'jetpack_module_more_info_connected_debug', 'jetpack_debug_more_info' );
799
+ add_action( 'jetpack_learn_more_button_debug', 'jetpack_debug_more_link' );
800
+ // Debug: STOP
801
+
802
+ // Omnisearch: START
803
+ function jetpack_omnisearch_more_info() { ?>
804
+
805
+ <h4><?php esc_html_e( 'Omnisearch' , 'jetpack' ); ?></h4>
806
+
807
+ <p><?php esc_html_e( 'Search once, get results from everything! Currently supports searching posts, pages, comments, and plugins.', 'jetpack' ); ?></p>
808
+
809
+ <p><?php esc_html_e( 'Omnisearch plays nice with other plugins by letting other providers offer results as well.', 'jetpack' ); ?></p>
810
+
811
+ <?php if( class_exists( 'Jetpack_Omnisearch' ) && current_user_can( 'edit_posts' ) ): ?>
812
+ <?php echo Jetpack_Omnisearch::get_omnisearch_form(); ?>
813
+ <?php endif; ?>
814
+
815
+ <?php
816
+ }
817
+
818
+ function jetpack_omnisearch_more_link() {
819
+ echo '<a class="button-secondary more-info-link" href="http://jetpack.me/support/omnisearch/">' . __( 'Learn More', 'jetpack' ) . '</a>';
820
+ }
821
+
822
+ add_action( 'jetpack_module_more_info_omnisearch', 'jetpack_omnisearch_more_info' );
823
+ add_action( 'jetpack_learn_more_button_omnisearch', 'jetpack_omnisearch_more_link' );
824
+ // Omnisearch: STOP
modules/notes.php CHANGED
@@ -29,7 +29,7 @@ class Jetpack_Notifications {
29
  * Singleton
30
  * @static
31
  */
32
- function &init() {
33
  static $instance = array();
34
 
35
  if ( !$instance ) {
29
  * Singleton
30
  * @static
31
  */
32
+ public static function init() {
33
  static $instance = array();
34
 
35
  if ( !$instance ) {
modules/omnisearch.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Module Name: Omnisearch
5
+ * Module Description: A single search box, that lets you search many different things.
6
+ * Sort Order: 8
7
+ * First Introduced: 2.3
8
+ * Requires Connection: No
9
+ */
10
+
11
+ // Only do Jetpack Omnisearch if there isn't already a Core WP_Omnisearch Class.
12
+ if ( ! class_exists( 'WP_Omnisearch' ) )
13
+ require_once( dirname( __FILE__ ) . '/omnisearch/omnisearch-core.php' );
14
+
modules/omnisearch/omnisearch-comments.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists( 'WP_Comments_List_Table' ) )
4
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-comments-list-table.php' );
5
+
6
+ class Jetpack_Omnisearch_Comments extends WP_Comments_List_Table {
7
+ static $instance;
8
+ var $checkbox = false;
9
+
10
+ function __construct() {
11
+ self::$instance = $this;
12
+ add_filter( 'omnisearch_results', array( $this, 'search'), 10, 2 );
13
+ }
14
+
15
+ function search( $results, $search_term ) {
16
+ $search_url = esc_url( admin_url( sprintf( 'edit-comments.php?s=%s', urlencode( $search_term ) ) ) );
17
+ $search_link = sprintf( ' <a href="%s" class="add-new-h2">%s</a>', $search_url, esc_html__('Search Comments', 'jetpack') );
18
+ $html = '<h2>' . esc_html__('Comments', 'jetpack') . $search_link . '</h2>';
19
+ parent::__construct();
20
+
21
+ ob_start();
22
+ $this->prepare_items();
23
+ $this->_column_headers = array( $this->get_columns(), array(), array() );
24
+ $this->display();
25
+ $html .= ob_get_clean();
26
+
27
+ $label = __( 'Comments', 'jetpack' );
28
+ $results[ $label ] = $html;
29
+ return $results;
30
+ }
31
+
32
+ function get_per_page( $comment_status = 'all' ) {
33
+ return apply_filters( 'omnisearch_num_results', 5 );
34
+ }
35
+
36
+ function get_sortable_columns() {
37
+ return array();
38
+ }
39
+
40
+ function get_bulk_actions() {
41
+ return array();
42
+ }
43
+
44
+ function pagination( $which ) {}
45
+
46
+ function extra_tablenav( $which ) {}
47
+ }
48
+
modules/omnisearch/omnisearch-core.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Include this here so that other plugins can extend it if they like.
4
+ require_once( dirname(__FILE__) . '/omnisearch-posts.php' );
5
+
6
+ class Jetpack_Omnisearch {
7
+ static $instance;
8
+ static $num_results = 5;
9
+
10
+ function __construct() {
11
+ self::$instance = $this;
12
+ add_action( 'wp_loaded', array( $this, 'wp_loaded' ) );
13
+ add_action( 'admin_init', array( $this, 'add_providers' ) );
14
+ add_action( 'jetpack_admin_menu', array( $this, 'jetpack_admin_menu' ) );
15
+ add_action( 'admin_menu', array( $this, 'admin_menu' ), 20 );
16
+ if( ! jetpack_is_mobile() ) {
17
+ add_action( 'admin_bar_menu', array( $this, 'admin_bar_search' ), 4 );
18
+ }
19
+ add_filter( 'omnisearch_num_results', array( $this, 'omnisearch_num_results' ) );
20
+ }
21
+
22
+ static function add_providers() {
23
+ // omnisearch-posts.php is included above, so that other plugins can more easily extend it.
24
+ new Jetpack_Omnisearch_Posts;
25
+ new Jetpack_Omnisearch_Posts( 'page' );
26
+
27
+ require_once( dirname(__FILE__) . '/omnisearch-comments.php' );
28
+ new Jetpack_Omnisearch_Comments;
29
+
30
+ if ( current_user_can( 'install_plugins' ) ) {
31
+ require_once( dirname(__FILE__) . '/omnisearch-plugins.php' );
32
+ new Jetpack_Omnisearch_Plugins;
33
+ }
34
+
35
+ do_action( 'omnisearch_add_providers' );
36
+ }
37
+
38
+ static function omnisearch_num_results( $num ) {
39
+ return self::$num_results;
40
+ }
41
+
42
+ function wp_loaded() {
43
+ $deps = null;
44
+ if ( wp_style_is( 'genericons', 'registered' ) ) {
45
+ $deps = array( 'genericons' );
46
+ }
47
+
48
+ wp_register_style( 'omnisearch-admin', plugins_url( 'omnisearch.css', __FILE__ ), $deps );
49
+ wp_register_style( 'omnisearch-jetpack', plugins_url( 'omnisearch-jetpack.css', __FILE__ ) );
50
+ }
51
+
52
+ function jetpack_admin_menu() {
53
+ remove_submenu_page( 'index.php', 'omnisearch' );
54
+ $this->slug = add_submenu_page( 'jetpack', __('Omnisearch', 'jetpack'), __('Omnisearch', 'jetpack'), 'edit_posts', 'omnisearch', array( $this, 'omnisearch_page' ) );
55
+ add_action( "admin_print_styles-{$this->slug}", array( $this, 'admin_print_styles_jetpack' ) );
56
+ }
57
+
58
+ function admin_menu() {
59
+ $this->slug = add_dashboard_page( __('Omnisearch', 'jetpack'), __('Omnisearch', 'jetpack'), 'edit_posts', 'omnisearch', array( $this, 'omnisearch_page' ) );
60
+ add_action( "admin_print_styles-{$this->slug}", array( $this, 'admin_print_styles' ) );
61
+ }
62
+
63
+ function admin_print_styles() {
64
+ wp_enqueue_style( 'omnisearch-admin' );
65
+ }
66
+
67
+ function admin_print_styles_jetpack() {
68
+ wp_enqueue_style( 'omnisearch-admin' );
69
+ wp_enqueue_style( 'omnisearch-jetpack' );
70
+ }
71
+
72
+ function omnisearch_page() {
73
+ $results = array();
74
+ $s = isset( $_GET['s'] ) ? $_GET['s'] : '';
75
+ if( $s ) {
76
+ $results = apply_filters( 'omnisearch_results', $results, $s );
77
+ }
78
+ ?>
79
+ <div class="wrap">
80
+ <h2 class="page-title"><?php esc_html_e('Omnisearch', 'jetpack'); ?> <small><?php esc_html_e('search everything', 'jetpack'); ?></small></h2>
81
+ <br class="clear" />
82
+ <?php echo self::get_omnisearch_form( array(
83
+ 'form_class' => 'omnisearch-form',
84
+ 'search_class' => 'omnisearch',
85
+ 'search_placeholder' => '',
86
+ 'submit_class' => 'omnisearch-submit',
87
+ 'alternate_submit' => true,
88
+ ) ); ?>
89
+ <?php if( ! empty( $results ) ): ?>
90
+ <h3 id="results-title"><?php esc_html_e('Results:', 'jetpack'); ?></h3>
91
+ <div class="jump-to"><strong><?php esc_html_e('Jump to:', 'jetpack'); ?></strong>
92
+ <?php foreach( $results as $label => $result ) : ?>
93
+ <a href="#result-<?php echo sanitize_title( $label ); ?>"><?php echo esc_html( $label ); ?></a>
94
+ <?php endforeach; ?>
95
+ </div>
96
+ <br class="clear" />
97
+ <script>var search_term = '<?php echo esc_js( $s ); ?>', num_results = <?php echo intval( apply_filters( 'omnisearch_num_results', 5 ) ); ?>;</script>
98
+ <ul class="omnisearch-results">
99
+ <?php foreach( $results as $label => $result ) : ?>
100
+ <li id="result-<?php echo sanitize_title( $label ); ?>" data-label="<?php echo esc_attr( $label ); ?>">
101
+ <?php echo $result; ?>
102
+ <a class="back-to-top" href="#results-title"><?php esc_html_e('Back to Top &uarr;', 'jetpack'); ?></a>
103
+ </li>
104
+ <?php endforeach; ?>
105
+ </ul>
106
+ <?php endif; ?>
107
+ </div><!-- /wrap -->
108
+ <?php
109
+ }
110
+
111
+ function admin_bar_search( $wp_admin_bar ) {
112
+ if( ! is_admin() || ! current_user_can( 'edit_posts' ) )
113
+ return;
114
+
115
+ $form = self::get_omnisearch_form( array(
116
+ 'form_id' => 'adminbarsearch',
117
+ 'search_id' => 'adminbar-search',
118
+ 'search_class' => 'adminbar-input',
119
+ 'submit_class' => 'adminbar-button',
120
+ ) );
121
+
122
+ $form .= "<style>
123
+ #adminbar-search::-webkit-input-placeholder,
124
+ #adminbar-search:-moz-placeholder,
125
+ #adminbar-search::-moz-placeholder,
126
+ #adminbar-search:-ms-input-placeholder {
127
+ text-shadow: none;
128
+ }
129
+ </style>";
130
+
131
+ $wp_admin_bar->add_menu( array(
132
+ 'parent' => 'top-secondary',
133
+ 'id' => 'search',
134
+ 'title' => $form,
135
+ 'meta' => array(
136
+ 'class' => 'admin-bar-search',
137
+ 'tabindex' => -1,
138
+ )
139
+ ) );
140
+ }
141
+
142
+ static function get_omnisearch_form( $args = array() ) {
143
+ $defaults = array(
144
+ 'form_id' => null,
145
+ 'form_class' => null,
146
+ 'search_class' => null,
147
+ 'search_id' => null,
148
+ 'search_value' => isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : null,
149
+ 'search_placeholder' => __( 'Search Everything', 'jetpack' ),
150
+ 'submit_class' => 'button',
151
+ 'submit_value' => __( 'Search', 'jetpack' ),
152
+ 'alternate_submit' => false,
153
+ );
154
+ extract( array_map( 'esc_attr', wp_parse_args( $args, $defaults ) ) );
155
+
156
+ $rand = rand();
157
+ if( empty( $form_id ) )
158
+ $form_id = "omnisearch_form_$rand";
159
+ if( empty( $search_id ) )
160
+ $search_id = "omnisearch_search_$rand";
161
+
162
+ ob_start();
163
+ ?>
164
+
165
+ <form action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>" method="get" class="<?php echo $form_class; ?>" id="<?php echo $form_id; ?>">
166
+ <input type="hidden" name="page" value="omnisearch" />
167
+ <input name="s" type="search" class="<?php echo $search_class; ?>" id="<?php echo $search_id; ?>" value="<?php echo $search_value; ?>" placeholder="<?php echo $search_placeholder; ?>" />
168
+ <?php if ( $alternate_submit ) : ?>
169
+ <button type="submit" class="<?php echo $submit_class; ?>"><span><?php echo $submit_value; ?></span></button>
170
+ <?php else : ?>
171
+ <input type="submit" class="<?php echo $submit_class; ?>" value="<?php echo $submit_value; ?>" />
172
+ <?php endif; ?>
173
+ </form>
174
+
175
+ <?php
176
+ return apply_filters( 'get_omnisearch_form', ob_get_clean(), $args, $defaults );
177
+ }
178
+
179
+ }
180
+ new Jetpack_Omnisearch;
181
+
modules/omnisearch/omnisearch-jetpack.css ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ .wp-admin #wpwrap {
3
+ background: url('../../_inc/images/header-clouds.png') 200% 0 repeat-x;
4
+ }
5
+
6
+ @media print,
7
+ (-o-min-device-pixel-ratio: 5/4),
8
+ (-webkit-min-device-pixel-ratio: 1.25),
9
+ (min-resolution: 120dpi) {
10
+ #wpwrap {
11
+ background: url('../../_inc/images/header-clouds-2x.png') 0 0 repeat-x;
12
+ background-size: 1600px 400px;
13
+ }
14
+ }
15
+
16
+ ul#adminmenu a.wp-has-current-submenu:after,
17
+ ul#adminmenu > li.current > a.current:after {
18
+ border-right-color:#8da94c;
19
+ display: none;
20
+ }
21
+
22
+ h2.page-title {
23
+ color: #fff;
24
+ text-shadow: 0 1px 1px rgba(0,0,0,0.5);
25
+ }
26
+
27
+ #results-title,
28
+ .jump-to {
29
+ color: #fff;
30
+ text-shadow: 0 1px 1px rgba(0,0,0,0.5);
31
+ }
32
+
33
+ .omnisearch-results > li:first-child > h2 {
34
+ text-shadow: none;
35
+ }
modules/omnisearch/omnisearch-plugins.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists( 'WP_Plugin_Install_List_Table' ) )
4
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-plugin-install-list-table.php' );
5
+
6
+ class Jetpack_Omnisearch_Plugins extends WP_Plugin_Install_List_Table {
7
+ static $instance;
8
+
9
+ function __construct() {
10
+ self::$instance = $this;
11
+ add_filter( 'omnisearch_results', array( $this, 'search'), 10, 2 );
12
+ add_action( 'wp_ajax_omnisearch_plugins', array( $this, 'wp_ajax_omnisearch_plugins' ) );
13
+ }
14
+
15
+ function search( $results, $search_term ) {
16
+ wp_enqueue_script( 'plugin-install' );
17
+ add_thickbox();
18
+
19
+ $search_url = esc_url( admin_url( sprintf( 'plugin-install.php?tab=search&s=%s', urlencode( $search_term ) ) ) );
20
+ $search_link = sprintf( ' <a href="%s" class="add-new-h2">%s</a>', $search_url, esc_html__('Search Plugins', 'jetpack') );
21
+ $html = '<h2>' . esc_html__('Plugins', 'jetpack') . $search_link . '</h2>';
22
+
23
+ $html .= '<div id="' . __CLASS__ . '_results">' . esc_html__('Loading &hellip;', 'jetpack') . '</div>';
24
+ $html .= '<script>jQuery("#' . __CLASS__ . '_results").load(ajaxurl,{action:"omnisearch_plugins",search_term:search_term,num_results:num_results});</script>';
25
+
26
+ $label = __( 'Plugins', 'jetpack' );
27
+ $results[ $label ] = $html;
28
+ return $results;
29
+ }
30
+
31
+ function results_html( $search_term, $num_results = null ) {
32
+ $_GET['tab'] = 'search';
33
+ $GLOBALS['hook_suffix'] = 'foo';
34
+ $_REQUEST['s'] = $search_term;
35
+ parent::__construct();
36
+
37
+ ob_start();
38
+ $this->prepare_items();
39
+ $num_results = intval( $num_results ) ? intval( $num_results ) : apply_filters( 'omnisearch_num_results', 5 );
40
+ $this->items = array_slice( $this->items, 0, $num_results );
41
+ remove_action( 'install_plugins_table_header', 'install_search_form' );
42
+ $this->display();
43
+ $html = ob_get_clean();
44
+
45
+ return $html;
46
+ }
47
+
48
+ function wp_ajax_omnisearch_plugins() {
49
+ $search_term = $_REQUEST['search_term'];
50
+ $num_results = isset( $_REQUEST['num_results'] ) ? $_REQUEST['num_results'] : null;
51
+ echo $this->results_html( $search_term, $num_results );
52
+ exit;
53
+ }
54
+
55
+ function get_bulk_actions() {
56
+ return array();
57
+ }
58
+
59
+ function pagination( $which ) {}
60
+ }
61
+
modules/omnisearch/omnisearch-posts.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( ! class_exists( 'WP_List_Table' ) )
4
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
5
+
6
+ class Jetpack_Omnisearch_Posts extends WP_List_Table {
7
+ var $post_type = 'post',
8
+ $post_type_object;
9
+
10
+ function __construct( $post_type = 'post' ) {
11
+ $this->post_type = $post_type;
12
+ add_filter( 'omnisearch_results', array( $this, 'search'), 10, 2 );
13
+ }
14
+
15
+ function search( $results, $search_term ) {
16
+ if( ! post_type_exists( $this->post_type ) )
17
+ return $results;
18
+
19
+ parent::__construct();
20
+
21
+ $this->post_type_obj = get_post_type_object( $this->post_type );
22
+
23
+ $search_url = esc_url( admin_url( sprintf( 'edit.php?post_type=%s&s=%s', urlencode( $this->post_type_obj->name ), urlencode( $search_term ) ) ) );
24
+ $search_link = sprintf( ' <a href="%s" class="add-new-h2">%s</a>', $search_url, esc_html( $this->post_type_obj->labels->search_items ) );
25
+ $html = '<h2>' . esc_html( $this->post_type_obj->labels->name ) . $search_link .'</h2>';
26
+
27
+ $num_results = apply_filters( 'omnisearch_num_results', 5 );
28
+
29
+ $this->posts = get_posts( array( 's' => $search_term, 'post_type' => $this->post_type, 'posts_per_page' => $num_results, 'post_status' => 'any' ) );
30
+
31
+ $this->prepare_items();
32
+
33
+ ob_start();
34
+ $this->display();
35
+ $html .= ob_get_clean();
36
+
37
+ $results[ $this->post_type_obj->labels->name ] = $html;
38
+ return $results;
39
+ }
40
+
41
+ function get_columns() {
42
+ $columns = array(
43
+ # 'id' => __('ID', 'jetpack'),
44
+ 'post_title' => __('Title', 'jetpack'),
45
+ 'snippet' => __('Snippet', 'jetpack'),
46
+ 'date' => __('Date', 'jetpack'),
47
+ );
48
+ return $columns;
49
+ }
50
+
51
+ function prepare_items() {
52
+ $columns = $this->get_columns();
53
+ $hidden = array();
54
+ $sortable = array();
55
+ $this->_column_headers = array( $columns, $hidden, $sortable );
56
+ $this->items = $this->posts;
57
+ }
58
+
59
+ function column_post_title( $post ) {
60
+ $actions = array();
61
+ if ( current_user_can( $this->post_type_obj->cap->edit_post, $post ) ) {
62
+ $actions['edit'] = sprintf( '<a href="%s">%s</a>', esc_url( get_edit_post_link( $post->ID ) ), esc_html( $this->post_type_obj->labels->edit_item ) );
63
+ }
64
+ if ( current_user_can( $this->post_type_obj->cap->delete_post, $post ) ) {
65
+ $actions['delete'] = sprintf( '<a href="%s">%s</a>', esc_url( get_delete_post_link( $post->ID ) ), esc_html__('Trash', 'jetpack') );
66
+ }
67
+ $actions['view'] = sprintf( '<a href="%s">%s</a>', esc_url( get_permalink( $post->ID ) ), esc_html( $this->post_type_obj->labels->view_item ) );
68
+ return wptexturize( $post->post_title ) . $this->row_actions( $actions );
69
+ }
70
+
71
+ function column_date( $post ) {
72
+ $html = '';
73
+
74
+ if ( '0000-00-00 00:00:00' == $post->post_date ) {
75
+ $t_time = $h_time = __('Unpublished', 'jetpack');
76
+ $time_diff = 0;
77
+ } else {
78
+ $t_time = date( __('Y/m/d g:i:s A', 'jetpack'), mysql2date( 'G', $post->post_date ) );
79
+ $m_time = $post->post_date;
80
+ $time = get_post_time( 'G', true, $post );
81
+
82
+ $time_diff = time() - $time;
83
+
84
+ if ( $time_diff > 0 && $time_diff < DAY_IN_SECONDS )
85
+ $h_time = sprintf( __('%s ago', 'jetpack'), human_time_diff( $time ) );
86
+ else
87
+ $h_time = mysql2date( __('Y/m/d', 'jetpack'), $m_time );
88
+ }
89
+
90
+ $html .= '<abbr title="' . esc_attr( $t_time ) . '">' . esc_html( $h_time ) . '</abbr>';
91
+ $html .= '<br />';
92
+ if ( 'publish' == $post->post_status ) {
93
+ $html .= esc_html__('Published', 'jetpack');
94
+ } elseif ( 'future' == $post->post_status ) {
95
+ if ( $time_diff > 0 )
96
+ $html .= '<strong class="attention">' . esc_html__('Missed schedule', 'jetpack') . '</strong>';
97
+ else
98
+ $html .= esc_html__('Scheduled', 'jetpack');
99
+ } else {
100
+ $html .= esc_html__('Last Modified', 'jetpack');
101
+ }
102
+ return $html;
103
+ }
104
+
105
+ function column_default( $post, $column_name ) {
106
+ switch ( $column_name ) {
107
+ case 'id':
108
+ return $post->ID;
109
+ case 'post_title': // Will never happen, class method overrides.
110
+ return $post->post_title;
111
+ case 'snippet':
112
+ return wp_trim_words( $post->post_content, 55 );
113
+ case 'date': // Will never happen, class method overrides.
114
+ $d = get_option('date_format');
115
+ $t = get_option('time_format');
116
+ return get_post_modified_time( $d, 0, $post, 1 ) . ' @ ' . get_post_modified_time( $t, 0, $post, 1 );
117
+ default:
118
+ return print_r( $post, true );
119
+ }
120
+ }
121
+ }
122
+
modules/omnisearch/omnisearch.css ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ h2.page-title small {
3
+ font-size: 0.6em;
4
+ font-weight: 300;
5
+ font-style: italic;
6
+ opacity: 0.6;
7
+ margin-left: 0.5em;
8
+ }
9
+
10
+ form.omnisearch-form {
11
+ position: relative;
12
+ }
13
+
14
+ input.omnisearch {
15
+ border-radius: 0.25em;
16
+ font-size: 2.2em;
17
+ line-height: 1.25;
18
+ padding: 0.25em 2em 0.25em 0.5em;
19
+ width: 100%;
20
+ }
21
+
22
+ .admin-color-mp6 input.omnisearch {
23
+ line-height: 1.35;
24
+ }
25
+
26
+ input.omnisearch::-webkit-search-cancel-button {
27
+ display: none;
28
+ }
29
+
30
+ button.omnisearch-submit {
31
+ background: transparent;
32
+ border: 0;
33
+ cursor: pointer;
34
+ display: block;
35
+ font-size: 2.45em;
36
+ padding: 0.25em 0.5em 0;
37
+ text-align: center;
38
+ position: absolute;
39
+ right: 0;
40
+ bottom: 0;
41
+ }
42
+
43
+ .admin-color-mp6 button.omnisearch-submit {
44
+ padding: 0.3em 0.5em 0.1em;
45
+ }
46
+
47
+ button.omnisearch-submit::before {
48
+ font-family: 'Genericons', Noticons;
49
+ content: '\f400';
50
+ }
51
+
52
+ button.omnisearch-submit span {
53
+ display: none;
54
+ }
55
+
56
+ #results-title,
57
+ .jump-to {
58
+ font-size: 1.2em;
59
+ line-height: 1.5;
60
+ float: left;
61
+ margin-top: 0;
62
+ padding-top: 2em;
63
+ }
64
+
65
+ #results-title,
66
+ .jump-to strong {
67
+ font-weight: 600;
68
+ }
69
+
70
+ .jump-to {
71
+ float: right;
72
+ text-align: right;
73
+ }
74
+
75
+ .jump-to strong,
76
+ .jump-to a {
77
+ color: inherit;
78
+ margin-left: 0.5em;
79
+ text-decoration: none;
80
+ }
81
+
82
+ .jump-to a:hover {
83
+ text-decoration: underline;
84
+ }
85
+
86
+ .back-to-top {
87
+ display: block;
88
+ float: right;
89
+ margin-top: 2.5em;
90
+ }
91
+
92
+ .omnisearch-results {
93
+
94
+ }
95
+
96
+ .omnisearch-results > li {
97
+ padding-top: 2.5em;
98
+ }
99
+
100
+ .omnisearch-results > li:first-child {
101
+ padding-top: 0;
102
+ }
103
+
104
+ .omnisearch-results .add-new-h2 {
105
+ display: inline;
106
+ }
107
+
108
+ .wp-list-table .column-snippet {
109
+ width: 65%;
110
+ }
111
+
112
+ .wp-list-table .column-date {
113
+ width: 15%;
114
+ }
115
+
116
+ .comments .column-author {
117
+ width: 20%;
118
+ }
119
+
120
+ .tablenav {
121
+ height: 0;
122
+ }
123
+
124
+ .omnisearch-results .tablenav.top {
125
+ margin: 5px 0;
126
+ }
modules/omnisearch/rtl/omnisearch-jetpack-rtl.css ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file was automatically generated on Jun 19 2013 20:14:22 */
2
+
3
+
4
+ .wp-admin #wpwrap {
5
+ background: url('../../../_inc/images/header-clouds.png') -100% 0 repeat-x;
6
+ }
7
+
8
+ @media print,
9
+ (-o-min-device-pixel-ratio: 5/4),
10
+ (-webkit-min-device-pixel-ratio: 1.25),
11
+ (min-resolution: 120dpi) {
12
+ #wpwrap {
13
+ background: url('../../../_inc/images/header-clouds-2x.png') 0 0 repeat-x;
14
+ background-size: 1600px 400px;
15
+ }
16
+ }
17
+
18
+ ul#adminmenu a.wp-has-current-submenu:after,
19
+ ul#adminmenu > li.current > a.current:after {
20
+ border-left-color:#8da94c;
21
+ display: none;
22
+ }
23
+
24
+ h2.page-title {
25
+ color: #fff;
26
+ text-shadow: 0 1px 1px rgba(0,0,0,0.5);
27
+ }
28
+
29
+ #results-title,
30
+ .jump-to {
31
+ color: #fff;
32
+ text-shadow: 0 1px 1px rgba(0,0,0,0.5);
33
+ }
34
+
35
+ .omnisearch-results > li:first-child > h2 {
36
+ text-shadow: none;
37
+ }
modules/omnisearch/rtl/omnisearch-rtl.css ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file was automatically generated on Jun 19 2013 20:38:31 */
2
+
3
+
4
+ h2.page-title small {
5
+ font-size: 0.6em;
6
+ font-weight: 300;
7
+ font-style: italic;
8
+ opacity: 0.6;
9
+ margin-right: 0.5em;
10
+ }
11
+
12
+ form.omnisearch-form {
13
+ position: relative;
14
+ }
15
+
16
+ input.omnisearch {
17
+ border-radius: 0.25em;
18
+ font-size: 2.2em;
19
+ line-height: 1.25;
20
+ padding: 0.25em 0.5em 0.25em 2em;
21
+ width: 100%;
22
+ }
23
+
24
+ .admin-color-mp6 input.omnisearch {
25
+ line-height: 1.35;
26
+ }
27
+
28
+ input.omnisearch::-webkit-search-cancel-button {
29
+ display: none;
30
+ }
31
+
32
+ button.omnisearch-submit {
33
+ background: transparent;
34
+ border: 0;
35
+ cursor: pointer;
36
+ display: block;
37
+ font-size: 2.45em;
38
+ padding: 0.25em 0.5em 0;
39
+ text-align: center;
40
+ position: absolute;
41
+ left: 0;
42
+ bottom: 0;
43
+ }
44
+
45
+ .admin-color-mp6 button.omnisearch-submit {
46
+ padding: 0.3em 0.5em 0.1em;
47
+ }
48
+
49
+ button.omnisearch-submit::before {
50
+ font-family: 'Genericons', Noticons;
51
+ content: '\f400';
52
+ }
53
+
54
+ button.omnisearch-submit span {
55
+ display: none;
56
+ }
57
+
58
+ #results-title,
59
+ .jump-to {
60
+ font-size: 1.2em;
61
+ line-height: 1.5;
62
+ float: right;
63
+ margin-top: 0;
64
+ padding-top: 2em;
65
+ }
66
+
67
+ #results-title,
68
+ .jump-to strong {
69
+ font-weight: 600;
70
+ }
71
+
72
+ .jump-to {
73
+ float: left;
74
+ text-align: left;
75
+ }
76
+
77
+ .jump-to strong,
78
+ .jump-to a {
79
+ color: inherit;
80
+ margin-right: 0.5em;
81
+ text-decoration: none;
82
+ }
83
+
84
+ .jump-to a:hover {
85
+ text-decoration: underline;
86
+ }
87
+
88
+ .back-to-top {
89
+ display: block;
90
+ float: left;
91
+ margin-top: 2.5em;
92
+ }
93
+
94
+ .omnisearch-results {
95
+
96
+ }
97
+
98
+ .omnisearch-results > li {
99
+ padding-top: 2.5em;
100
+ }
101
+
102
+ .omnisearch-results > li:first-child {
103
+ padding-top: 0;
104
+ }
105
+
106
+ .omnisearch-results .add-new-h2 {
107
+ display: inline;
108
+ }
109
+
110
+ .wp-list-table .column-snippet {
111
+ width: 65%;
112
+ }
113
+
114
+ .wp-list-table .column-date {
115
+ width: 15%;
116
+ }
117
+
118
+ .comments .column-author {
119
+ width: 20%;
120
+ }
121
+
122
+ .tablenav {
123
+ height: 0;
124
+ }
125
+
126
+ .omnisearch-results .tablenav.top {
127
+ margin: 5px 0;
128
+ }
modules/post-by-email.php CHANGED
@@ -26,7 +26,7 @@ Jetpack::enable_module_configurable( __FILE__ );
26
  Jetpack::module_configuration_load( __FILE__, array( 'Jetpack_Post_By_Email', 'configuration_redirect' ) );
27
 
28
  class Jetpack_Post_By_Email {
29
- function &init() {
30
  static $instance = NULL;
31
 
32
  if ( !$instance ) {
@@ -45,7 +45,7 @@ class Jetpack_Post_By_Email {
45
  $jetpack->sync->register( 'noop' );
46
  }
47
 
48
- function configuration_redirect() {
49
  wp_safe_redirect( get_edit_profile_url( get_current_user_id() ) . '#post-by-email' );
50
  exit;
51
  }
26
  Jetpack::module_configuration_load( __FILE__, array( 'Jetpack_Post_By_Email', 'configuration_redirect' ) );
27
 
28
  class Jetpack_Post_By_Email {
29
+ public static function init() {
30
  static $instance = NULL;
31
 
32
  if ( !$instance ) {
45
  $jetpack->sync->register( 'noop' );
46
  }
47
 
48
+ static function configuration_redirect() {
49
  wp_safe_redirect( get_edit_profile_url( get_current_user_id() ) . '#post-by-email' );
50
  exit;
51
  }
modules/publicize/assets/path-logo.png ADDED
Binary file
modules/publicize/assets/publicize.css CHANGED
@@ -21,6 +21,7 @@ span#facebook { background: url( facebook-logo.png ) 50% 19px no-repeat; backgro
21
  span#twitter { background: url( twitter-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
22
  span#linkedin { background: url( linkedin-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
23
  span#tumblr { background: url( tumblr-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
 
24
 
25
  a.publicize-profile-link, a.publicize-profile-link:visited {
26
  text-decoration: none;
21
  span#twitter { background: url( twitter-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
22
  span#linkedin { background: url( linkedin-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
23
  span#tumblr { background: url( tumblr-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
24
+ span#path { background: url( path-logo.png ) 50% 19px no-repeat; background-size: 85px 32px; }
25
 
26
  a.publicize-profile-link, a.publicize-profile-link:visited {
27
  text-decoration: none;
modules/publicize/assets/rtl/publicize-rtl.css CHANGED
@@ -1,4 +1,4 @@
1
- /* This file was automatically generated on Mar 27 2013 13:05:48 */
2
 
3
  div#publicize-services-block {
4
  display: inline-block;
@@ -21,7 +21,6 @@ span.pub-logos {
21
 
22
  span#facebook { background: url( ../facebook-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
23
  span#twitter { background: url( ../twitter-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
24
- span#yahoo { background: url( ../yahoo-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
25
  span#linkedin { background: url( ../linkedin-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
26
  span#tumblr { background: url( ../tumblr-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
27
 
@@ -174,4 +173,4 @@ table#option-fb-fanpage td.details span.category {
174
  input.fb-options {
175
  font-family: "Lucida Grande",Verdana,Arial,sans-serif;
176
  font-size: 12px;
177
- }
1
+ /* This file was automatically generated on Jun 24 2013 19:39:49 */
2
 
3
  div#publicize-services-block {
4
  display: inline-block;
21
 
22
  span#facebook { background: url( ../facebook-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
23
  span#twitter { background: url( ../twitter-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
 
24
  span#linkedin { background: url( ../linkedin-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
25
  span#tumblr { background: url( ../tumblr-logo.png ) 50% 19px no-repeat; background-size: 125px 47px; }
26
 
173
  input.fb-options {
174
  font-family: "Lucida Grande",Verdana,Arial,sans-serif;
175
  font-size: 12px;
176
+ }
modules/publicize/assets/yahoo-logo.png DELETED
Binary file
modules/publicize/publicize-jetpack.php CHANGED
@@ -11,13 +11,17 @@ class Publicize extends Publicize_Base {
11
  add_action( 'wp_ajax_publicize_facebook_options_page', array( $this, 'options_page_facebook' ) );
12
  add_action( 'wp_ajax_publicize_twitter_options_page', array( $this, 'options_page_twitter' ) );
13
  add_action( 'wp_ajax_publicize_linkedin_options_page', array( $this, 'options_page_linkedin' ) );
 
14
 
15
  add_action( 'wp_ajax_publicize_tumblr_options_save', array( $this, 'options_save_tumblr' ) );
16
  add_action( 'wp_ajax_publicize_facebook_options_save', array( $this, 'options_save_facebook' ) );
17
  add_action( 'wp_ajax_publicize_twitter_options_save', array( $this, 'options_save_twitter' ) );
18
  add_action( 'wp_ajax_publicize_linkedin_options_save', array( $this, 'options_save_linkedin' ) );
 
19
 
20
  add_action( 'load-settings_page_sharing', array( $this, 'force_user_connection' ) );
 
 
21
 
22
  add_action( 'transition_post_status', array( $this, 'save_publicized' ), 10, 3 );
23
  }
@@ -259,6 +263,17 @@ class Publicize extends Publicize_Base {
259
  ), menu_page_url( 'sharing', false ) );
260
  }
261
 
 
 
 
 
 
 
 
 
 
 
 
262
  function disconnect_url( $service_name, $id ) {
263
  return add_query_arg( array (
264
  'action' => 'delete',
@@ -278,6 +293,7 @@ class Publicize extends Publicize_Base {
278
  'twitter' => array(),
279
  'linkedin' => array(),
280
  'tumblr' => array(),
 
281
  );
282
 
283
  if ( 'all' == $filter ) {
@@ -324,8 +340,8 @@ class Publicize extends Publicize_Base {
324
  // Nonce check
325
  check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
326
 
327
- $me = $options_to_show[0];
328
- $pages = $options_to_show[1]['data'];
329
 
330
  $profile_checked = true;
331
  $page_selected = false;
@@ -386,7 +402,6 @@ class Publicize extends Publicize_Base {
386
  <tbody>
387
 
388
  <?php foreach ( $pages as $i => $page ) : ?>
389
- <?php if ( ! isset( $page['perms'] ) ) { continue; } ?>
390
  <?php if ( ! ( $i % 2 ) ) : ?>
391
  <tr>
392
  <?php endif; ?>
@@ -556,9 +571,11 @@ class Publicize extends Publicize_Base {
556
 
557
  function options_page_twitter() { Publicize_UI::options_page_other( 'twitter' ); }
558
  function options_page_linkedin() { Publicize_UI::options_page_other( 'linkedin' ); }
 
559
 
560
  function options_save_twitter() { $this->options_save_other( 'twitter' ); }
561
  function options_save_linkedin() { $this->options_save_other( 'linkedin' ); }
 
562
 
563
  function options_save_other( $service_name ) {
564
  // Nonce check
@@ -566,8 +583,74 @@ class Publicize extends Publicize_Base {
566
  $this->globalization();
567
  }
568
 
569
- // stub
 
 
 
 
 
 
 
 
 
 
570
  function refresh_tokens_message() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
571
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572
  }
573
  }
11
  add_action( 'wp_ajax_publicize_facebook_options_page', array( $this, 'options_page_facebook' ) );
12
  add_action( 'wp_ajax_publicize_twitter_options_page', array( $this, 'options_page_twitter' ) );
13
  add_action( 'wp_ajax_publicize_linkedin_options_page', array( $this, 'options_page_linkedin' ) );
14
+ add_action( 'wp_ajax_publicize_path_options_page', array( $this, 'options_page_path' ) );
15
 
16
  add_action( 'wp_ajax_publicize_tumblr_options_save', array( $this, 'options_save_tumblr' ) );
17
  add_action( 'wp_ajax_publicize_facebook_options_save', array( $this, 'options_save_facebook' ) );
18
  add_action( 'wp_ajax_publicize_twitter_options_save', array( $this, 'options_save_twitter' ) );
19
  add_action( 'wp_ajax_publicize_linkedin_options_save', array( $this, 'options_save_linkedin' ) );
20
+ add_action( 'wp_ajax_publicize_path_options_save', array( $this, 'options_save_path' ) );
21
 
22
  add_action( 'load-settings_page_sharing', array( $this, 'force_user_connection' ) );
23
+
24
+ add_filter( 'publicize_checkbox_default', array( $this, 'publicize_checkbox_default' ), 10, 4 );
25
 
26
  add_action( 'transition_post_status', array( $this, 'save_publicized' ), 10, 3 );
27
  }
263
  ), menu_page_url( 'sharing', false ) );
264
  }
265
 
266
+ function refresh_url( $service_name ) {
267
+ return add_query_arg( array(
268
+ 'action' => 'request',
269
+ 'service' => $service_name,
270
+ 'kr_nonce' => wp_create_nonce( 'keyring-request' ),
271
+ 'refresh' => 1,
272
+ 'for' => 'publicize',
273
+ 'nonce' => wp_create_nonce( "keyring-request-$service_name" ),
274
+ ), menu_page_url( 'sharing', false ) );
275
+ }
276
+
277
  function disconnect_url( $service_name, $id ) {
278
  return add_query_arg( array (
279
  'action' => 'delete',
293
  'twitter' => array(),
294
  'linkedin' => array(),
295
  'tumblr' => array(),
296
+ 'path' => array(),
297
  );
298
 
299
  if ( 'all' == $filter ) {
340
  // Nonce check
341
  check_admin_referer( 'options_page_facebook_' . $_REQUEST['connection'] );
342
 
343
+ $me = ( ! empty( $options_to_show[0] ) ? $options_to_show[0] : false );
344
+ $pages = ( ! empty( $options_to_show[1]['data'] ) ? $options_to_show[1]['data'] : false );
345
 
346
  $profile_checked = true;
347
  $page_selected = false;
402
  <tbody>
403
 
404
  <?php foreach ( $pages as $i => $page ) : ?>
 
405
  <?php if ( ! ( $i % 2 ) ) : ?>
406
  <tr>
407
  <?php endif; ?>
571
 
572
  function options_page_twitter() { Publicize_UI::options_page_other( 'twitter' ); }
573
  function options_page_linkedin() { Publicize_UI::options_page_other( 'linkedin' ); }
574
+ function options_page_path() { Publicize_UI::options_page_other( 'path' ); }
575
 
576
  function options_save_twitter() { $this->options_save_other( 'twitter' ); }
577
  function options_save_linkedin() { $this->options_save_other( 'linkedin' ); }
578
+ function options_save_path() { $this->options_save_other( 'path' ); }
579
 
580
  function options_save_other( $service_name ) {
581
  // Nonce check
583
  $this->globalization();
584
  }
585
 
586
+ function is_expired( $expires = false ) {
587
+ $hour_in_seconds = 3600;
588
+ if ( !$expires )
589
+ return false; // No expires value, assume it's a permanent token
590
+ if ( '0000-00-00 00:00:00' == $expires )
591
+ return false; // Doesn't expire
592
+ if ( ( time() + $hour_in_seconds ) > strtotime( $expires ) )
593
+ return true; // Token's expiry time has passed, or will pass before $window
594
+ return false;
595
+ }
596
+
597
  function refresh_tokens_message() {
598
+ global $post;
599
+ $post_id = $post ? $post->ID : 0;
600
+
601
+ $services = $this->get_services( 'all' );
602
+
603
+ // Same core nonce works for all services
604
+ $keyring_nonce = wp_create_nonce( 'keyring-request' );
605
+ $expired_tokens = false;
606
+
607
+ if ( is_array( $services ) && count( $services ) ) {
608
+ foreach ( $services as $name => $service ) {
609
+ if ( $connections = $this->get_connections( $name ) ) {
610
+
611
+ foreach ( $connections as $connection ) {
612
+
613
+ $cmeta = $this->get_connection_meta( $connection );
614
+
615
+ // If the token for this connection is expired, or expires soon, then warn
616
+ if ( !$this->is_expired( $cmeta['expires'] ) ) {
617
+ continue;
618
+ }
619
+
620
+ if ( !$expired_tokens ) {
621
+ ?>
622
+ <div class="error below-h2 publicize-token-refresh-message">
623
+ <p><?php echo esc_html( __( 'Before you hit Publish, please refresh your connection to make sure we can Publicize your post:' , 'jetpack') ); ?></p>
624
+ <?php
625
+ $expired_tokens = true;
626
+ }
627
+ // No need to request for a specific token id, since the token store detects duplication and updates a single token per service
628
+ $nonce = wp_create_nonce( "keyring-request-" . $name );
629
+ $url = $this->refresh_url( $name );
630
+ ?>
631
+ <p style="text-align: center;" id="publicize-token-refresh-<?php echo esc_attr( $name ); ?>" class="publicize-token-refresh-button">
632
+ <a href="<?php echo esc_url( $url ); ?>" class="button" target="_refresh_<?php echo esc_attr( $name ); ?>">
633
+ <?php printf( __( 'Refresh connection with %s' , 'jetpack'), Publicize::get_service_label( $name ) ); ?>
634
+ </a>
635
+ </p><?php
636
+ }
637
+ }
638
+ }
639
+ }
640
 
641
+ if ( $expired_tokens ) {
642
+ echo '</div>';
643
+ }
644
+ }
645
+
646
+ /**
647
+ * Already-published posts should not be Publicized by default. This filter sets checked to
648
+ * false if a post has already been published.
649
+ */
650
+ function publicize_checkbox_default( $checked, $post_id, $name, $connection ) {
651
+ if ( 'publish' == get_post_status( $post_id ) )
652
+ return false;
653
+
654
+ return $checked;
655
  }
656
  }
modules/publicize/publicize.php CHANGED
@@ -108,11 +108,15 @@ abstract class Publicize_Base {
108
 
109
  $profile_url_query = parse_url( $cmeta['connection_data']['meta']['profile_url'], PHP_URL_QUERY );
110
  wp_parse_str( $profile_url_query, $profile_url_query_args );
111
- if ( !isset( $profile_url_query_args['key'] ) ) {
 
 
 
 
112
  return false;
113
  }
114
 
115
- return esc_url_raw( add_query_arg( 'id', urlencode( $profile_url_query_args['key'] ), 'http://www.linkedin.com/profile/view' ) );
116
  } else {
117
  return false; // no fallback. we just won't link it
118
  }
@@ -138,7 +142,7 @@ abstract class Publicize_Base {
138
  }
139
  }
140
 
141
- function get_service_label( $service_name ) {
142
  switch ( $service_name ) {
143
  case 'linkedin':
144
  return 'LinkedIn';
@@ -207,8 +211,7 @@ abstract class Publicize_Base {
207
  $cron_user = null;
208
  $submit_post = true;
209
 
210
- // don't do anything if its not actually a post
211
- if ( 'post' !== $post->post_type )
212
  return;
213
 
214
  // Don't Publicize during certain contexts:
@@ -327,4 +330,20 @@ abstract class Publicize_Base {
327
 
328
  // Next up will be ::publicize_post()
329
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  }
108
 
109
  $profile_url_query = parse_url( $cmeta['connection_data']['meta']['profile_url'], PHP_URL_QUERY );
110
  wp_parse_str( $profile_url_query, $profile_url_query_args );
111
+ if ( isset( $profile_url_query_args['key'] ) ) {
112
+ $id = $profile_url_query_args['key'];
113
+ } elseif ( isset( $profile_url_query_args['id'] ) ) {
114
+ $id = $profile_url_query_args['id'];
115
+ } else {
116
  return false;
117
  }
118
 
119
+ return esc_url_raw( add_query_arg( 'id', urlencode( $id ), 'http://www.linkedin.com/profile/view' ) );
120
  } else {
121
  return false; // no fallback. we just won't link it
122
  }
142
  }
143
  }
144
 
145
+ public static function get_service_label( $service_name ) {
146
  switch ( $service_name ) {
147
  case 'linkedin':
148
  return 'LinkedIn';
211
  $cron_user = null;
212
  $submit_post = true;
213
 
214
+ if ( ! $this->post_type_is_publicizeable( $post->post_type ) )
 
215
  return;
216
 
217
  // Don't Publicize during certain contexts:
330
 
331
  // Next up will be ::publicize_post()
332
  }
333
+
334
+ /**
335
+ * Is a given post type Publicize-able?
336
+ *
337
+ * Not every CPT lends itself to Publicize-ation. Allow CPTs to register by adding their CPT via
338
+ * the publicize_post_types array filter.
339
+ *
340
+ * @param string $post_type The post type to check.
341
+ * $return bool True if the post type can be Publicized.
342
+ */
343
+ function post_type_is_publicizeable( $post_type ) {
344
+ if ( 'post' == $post_type )
345
+ return true;
346
+
347
+ return post_type_supports( $post_type, 'publicize' );
348
+ }
349
  }
modules/publicize/ui.php CHANGED
@@ -71,7 +71,7 @@ class Publicize_UI {
71
  add_thickbox();
72
  }
73
 
74
- function connected_notice( $service_name ) { ?>
75
  <div class='updated'>
76
  <p><?php printf( __( 'You have successfully connected your blog with your %s account.', 'jetpack' ), Publicize::get_service_label( $service_name ) ); ?></p>
77
  </div><?php
@@ -190,7 +190,7 @@ class Publicize_UI {
190
 
191
  }
192
 
193
- function global_checkbox( $service_name, $id ) {
194
  global $publicize;
195
  if ( current_user_can( $publicize->GLOBAL_CAP ) ) : ?>
196
  <p>
@@ -208,7 +208,7 @@ class Publicize_UI {
208
  </div><?php
209
  }
210
 
211
- function options_page_other( $service_name ) {
212
  // Nonce check
213
  check_admin_referer( "options_page_{$service_name}_" . $_REQUEST['connection'] );
214
  ?>
@@ -376,7 +376,7 @@ jQuery( function($) {
376
  function post_page_metabox() {
377
  global $post;
378
 
379
- if ( 'post' != $post->post_type )
380
  return;
381
 
382
  $user_id = empty( $post->post_author ) ? $GLOBALS['user_ID'] : $post->post_author;
@@ -418,7 +418,7 @@ jQuery( function($) {
418
  $connection_data = $connection->get_meta( 'connection_data' );
419
  elseif ( ! empty( $connection['connection_data'] ) )
420
  $connection_data = $connection['connection_data'];
421
-
422
  if ( !$continue = apply_filters( 'wpas_submit_post?', true, $post->ID, $name, $connection_data ) )
423
  continue;
424
 
71
  add_thickbox();
72
  }
73
 
74
+ public static function connected_notice( $service_name ) { ?>
75
  <div class='updated'>
76
  <p><?php printf( __( 'You have successfully connected your blog with your %s account.', 'jetpack' ), Publicize::get_service_label( $service_name ) ); ?></p>
77
  </div><?php
190
 
191
  }
192
 
193
+ public static function global_checkbox( $service_name, $id ) {
194
  global $publicize;
195
  if ( current_user_can( $publicize->GLOBAL_CAP ) ) : ?>
196
  <p>
208
  </div><?php
209
  }
210
 
211
+ public static function options_page_other( $service_name ) {
212
  // Nonce check
213
  check_admin_referer( "options_page_{$service_name}_" . $_REQUEST['connection'] );
214
  ?>
376
  function post_page_metabox() {
377
  global $post;
378
 
379
+ if ( ! $this->publicize->post_type_is_publicizeable( $post->post_type ) )
380
  return;
381
 
382
  $user_id = empty( $post->post_author ) ? $GLOBALS['user_ID'] : $post->post_author;
418
  $connection_data = $connection->get_meta( 'connection_data' );
419
  elseif ( ! empty( $connection['connection_data'] ) )
420
  $connection_data = $connection['connection_data'];
421
+
422
  if ( !$continue = apply_filters( 'wpas_submit_post?', true, $post->ID, $name, $connection_data ) )
423
  continue;
424
 
modules/sharedaddy/admin-sharing.css CHANGED
@@ -92,6 +92,7 @@
92
  .services ul li#google-plus-1,#available-services .preview-google-plus-1{background: #FFF url(images/googleplus1.png) no-repeat 4px 5px; padding-right: 10px;}
93
  .services ul li#pinterest,#available-services .preview-pinterest{background: #FFF url(images/pinterest.png) no-repeat 5px 6px; padding-right: 10px;}
94
  .services ul li#pocket,#available-services .preview-pocket{background: #FFF url(images/pocket.png) no-repeat 4px 5px; padding-right: 10px;}
 
95
  .services ul li.share-custom, #available-services .preview-custom{background: #FFF url(images/custom.png) no-repeat 4px 5px; no-repeat 4px 5px; padding-right: 10px;}
96
 
97
 
@@ -386,6 +387,7 @@
386
  .services ul li#google-plus-1,#available-services .preview-google-plus-1{background: #FFF url(images/googleplus1@2x.png) no-repeat 4px 5px; padding-right: 10px;}
387
  .services ul li#pinterest,#available-services .preview-pinterest{background: #FFF url(images/pinterest@2x.png) no-repeat 4px 5px; padding-right: 10px;}
388
  .services ul li#pocket,#available-services .preview-pocket{background: #FFF url(images/pocket@2x.png) no-repeat 4px 5px; padding-right: 10px;}
 
389
  .services ul li.share-custom, #available-services .preview-custom{background: #FFF url(images/custom@2x.png) no-repeat 4px 5px; no-repeat 4px 5px; padding-right: 10px;}
390
 
391
  .services ul li#facebook, #available-services .preview-facebook div.option-smart-off,
@@ -402,6 +404,7 @@
402
  .services ul li#google-plus-1,#available-services .preview-google-plus-1,
403
  .services ul li#pinterest,#available-services .preview-pinterest,
404
  .services ul li#pocket,#available-services .preview-pocket,
 
405
  .services ul li.share-custom, #available-services .preview-custom{
406
  background-size: 16px 16px;
407
  }
92
  .services ul li#google-plus-1,#available-services .preview-google-plus-1{background: #FFF url(images/googleplus1.png) no-repeat 4px 5px; padding-right: 10px;}
93
  .services ul li#pinterest,#available-services .preview-pinterest{background: #FFF url(images/pinterest.png) no-repeat 5px 6px; padding-right: 10px;}
94
  .services ul li#pocket,#available-services .preview-pocket{background: #FFF url(images/pocket.png) no-repeat 4px 5px; padding-right: 10px;}
95
+ .services ul li#kindle,#available-services .preview-kindle{background: #FFF url(images/kindle.png) no-repeat 4px 5px; padding-right: 10px;}
96
  .services ul li.share-custom, #available-services .preview-custom{background: #FFF url(images/custom.png) no-repeat 4px 5px; no-repeat 4px 5px; padding-right: 10px;}
97
 
98
 
387
  .services ul li#google-plus-1,#available-services .preview-google-plus-1{background: #FFF url(images/googleplus1@2x.png) no-repeat 4px 5px; padding-right: 10px;}
388
  .services ul li#pinterest,#available-services .preview-pinterest{background: #FFF url(images/pinterest@2x.png) no-repeat 4px 5px; padding-right: 10px;}
389
  .services ul li#pocket,#available-services .preview-pocket{background: #FFF url(images/pocket@2x.png) no-repeat 4px 5px; padding-right: 10px;}
390
+ .services ul li#kindle,#available-services .preview-kindle{background: #FFF url(images/kindle@2x.png) no-repeat 4px 5px; padding-right: 10px;}
391
  .services ul li.share-custom, #available-services .preview-custom{background: #FFF url(images/custom@2x.png) no-repeat 4px 5px; no-repeat 4px 5px; padding-right: 10px;}
392
 
393
  .services ul li#facebook, #available-services .preview-facebook div.option-smart-off,
404
  .services ul li#google-plus-1,#available-services .preview-google-plus-1,
405
  .services ul li#pinterest,#available-services .preview-pinterest,
406
  .services ul li#pocket,#available-services .preview-pocket,
407
+ .services ul li#kindle,#available-services .preview-kindle,
408
  .services ul li.share-custom, #available-services .preview-custom{
409
  background-size: 16px 16px;
410
  }
modules/sharedaddy/admin-sharing.js CHANGED
@@ -163,6 +163,14 @@
163
  return true;
164
  }
165
 
 
 
 
 
 
 
 
 
166
  function save_services() {
167
  $( '#enabled-services h3 img' ).show();
168
 
@@ -188,6 +196,13 @@
188
  if ( $( this ).hasClass( 'service' ) ) {
189
  // Ready for saving
190
  visible[visible.length] = $( this ).attr( 'id' );
 
 
 
 
 
 
 
191
  }
192
  } );
193
 
@@ -195,6 +210,7 @@
195
  if ( $( this ).hasClass( 'service' ) ) {
196
  // Ready for saving
197
  hidden[hidden.length] = $( this ).attr( 'id' );
 
198
  }
199
  } );
200
 
163
  return true;
164
  }
165
 
166
+ function showExtraOptions( service ) {
167
+ jQuery( '.' + service + '-extra-options' ).css( { backgroundColor: '#ffffcc' } ).fadeIn();
168
+ }
169
+
170
+ function hideExtraOptions( service ) {
171
+ jQuery( '.' + service + '-extra-options' ).fadeOut( 'slow' );
172
+ }
173
+
174
  function save_services() {
175
  $( '#enabled-services h3 img' ).show();
176
 
196
  if ( $( this ).hasClass( 'service' ) ) {
197
  // Ready for saving
198
  visible[visible.length] = $( this ).attr( 'id' );
199
+ showExtraOptions( $( this ).attr( 'id' ) );
200
+ }
201
+ } );
202
+
203
+ $( 'ul.services-available li' ).each( function() {
204
+ if ( $( this ).hasClass( 'service' ) ) {
205
+ hideExtraOptions( $( this ).attr( 'id' ) );
206
  }
207
  } );
208
 
210
  if ( $( this ).hasClass( 'service' ) ) {
211
  // Ready for saving
212
  hidden[hidden.length] = $( this ).attr( 'id' );
213
+ showExtraOptions( $( this ).attr( 'id' ) );
214
  }
215
  } );
216
 
modules/sharedaddy/images/googleplus1.png CHANGED
Binary file
modules/sharedaddy/images/googleplus1@2x.png CHANGED
Binary file
modules/sharedaddy/images/kindle.png ADDED
Binary file
modules/sharedaddy/images/kindle@2x.png ADDED
Binary file
modules/sharedaddy/sharing-service.php CHANGED
@@ -417,7 +417,9 @@ function sharing_add_footer() {
417
  endif;
418
  endif;
419
 
420
- wp_print_scripts( 'sharing-js' );
 
 
421
  }
422
 
423
  $sharer = new Sharing_Service();
@@ -601,3 +603,27 @@ function sharing_display( $text = '', $echo = false ) {
601
 
602
  add_filter( 'the_content', 'sharing_display', 19 );
603
  add_filter( 'the_excerpt', 'sharing_display', 19 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
  endif;
418
  endif;
419
 
420
+ wp_enqueue_script( 'sharing-js' );
421
+ $recaptcha__options = array( 'lang' => get_base_recaptcha_lang_code() );
422
+ wp_localize_script('sharing-js', 'recaptcha_options', $recaptcha__options);
423
  }
424
 
425
  $sharer = new Sharing_Service();
603
 
604
  add_filter( 'the_content', 'sharing_display', 19 );
605
  add_filter( 'the_excerpt', 'sharing_display', 19 );
606
+ function get_base_recaptcha_lang_code() {
607
+
608
+ $base_recaptcha_lang_code_mapping = array(
609
+ 'en' => 'en',
610
+ 'nl' => 'nl',
611
+ 'fr' => 'fr',
612
+ 'fr-be' => 'fr',
613
+ 'fr-ca' => 'fr',
614
+ 'fr-ch' => 'fr',
615
+ 'de' => 'de',
616
+ 'pt' => 'pt',
617
+ 'pt-br' => 'pt',
618
+ 'ru' => 'ru',
619
+ 'es' => 'es',
620
+ 'tr' => 'tr'
621
+ );
622
+
623
+ $blog_lang_code = function_exists( 'get_blog_lang_code' ) ? get_blog_lang_code() : get_bloginfo( 'language' );
624
+ if( isset( $base_recaptcha_lang_code_mapping[ $blog_lang_code ] ) )
625
+ return $base_recaptcha_lang_code_mapping[ $blog_lang_code ];
626
+
627
+ // if no base mapping is found return default 'en'
628
+ return 'en';
629
+ }
modules/sharedaddy/sharing-sources.php CHANGED
@@ -197,7 +197,7 @@ class Share_Email extends Sharing_Source {
197
  }
198
 
199
  public function get_name() {
200
- return __( 'Email', 'jetpack' );
201
  }
202
 
203
  // Default does nothing
@@ -317,6 +317,9 @@ class Share_Email extends Sharing_Source {
317
 
318
  class Share_Twitter extends Sharing_Source {
319
  var $shortname = 'twitter';
 
 
 
320
  public function __construct( $id, array $settings ) {
321
  parent::__construct( $id, $settings );
322
 
@@ -402,8 +405,8 @@ class Share_Twitter extends Sharing_Source {
402
  $sig = '';
403
  }
404
 
405
- $suffix_length = $strlen( " {$post_link}{$sig}" );
406
 
 
407
  // $sig is handled by twitter in their 'via' argument.
408
  // $post_link is handled by twitter in their 'url' argument.
409
  if ( 140 < $strlen( $post_title ) + $suffix_length ) {
@@ -600,28 +603,14 @@ class Share_LinkedIn extends Sharing_Source {
600
 
601
  public function process_request( $post, array $post_data ) {
602
 
603
- setup_postdata( $post );
604
-
605
  $post_link = $this->get_share_url( $post->ID );
606
 
607
- // http://www.linkedin.com/shareArticle?mini=true&url={articleUrl}&title={articleTitle}&summary={articleSummary}&source={articleSource}
608
-
609
- $encoded_title = rawurlencode( $post->post_title );
610
- if( strlen( $encoded_title ) > 200 )
611
- $encoded_title = substr( $encoded_title, 0, 197 ) . '...';
612
-
613
- $encoded_summary = rawurlencode( strip_tags( get_the_excerpt() ) );
614
- if( strlen( $encoded_summary ) > 256 )
615
- $encoded_summary = substr( $encoded_summary, 0, 253 ) . '...';
616
-
617
- $source = get_bloginfo( 'name' );
618
 
619
  $linkedin_url = add_query_arg( array(
620
- 'title' => $encoded_title,
621
  'url' => rawurlencode( $post_link ),
622
- 'source' => rawurlencode( $source ),
623
- 'summary' => $encoded_summary,
624
- ), 'http://www.linkedin.com/shareArticle?mini=true' );
625
 
626
  // Record stats
627
  parent::process_request( $post, $post_data );
@@ -1214,6 +1203,8 @@ class Share_Pinterest extends Sharing_Source {
1214
  s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
1215
  var x = document.getElementsByTagName("script")[0];
1216
  x.parentNode.insertBefore(s, x);
 
 
1217
  </script>
1218
  <?php else : ?>
1219
  <script type="text/javascript">
@@ -1301,3 +1292,4 @@ class Share_Pocket extends Sharing_Source {
1301
  }
1302
 
1303
  }
 
197
  }
198
 
199
  public function get_name() {
200
+ return _x( 'Email', 'as sharing source', 'jetpack' );
201
  }
202
 
203
  // Default does nothing
317
 
318
  class Share_Twitter extends Sharing_Source {
319
  var $shortname = 'twitter';
320
+ // 'https://dev.twitter.com/docs/api/1.1/get/help/configuration' ( 2013/06/24 ) short_url_length is 22
321
+ var $short_url_length = 24;
322
+
323
  public function __construct( $id, array $settings ) {
324
  parent::__construct( $id, $settings );
325
 
405
  $sig = '';
406
  }
407
 
 
408
 
409
+ $suffix_length = $this->short_url_length + $strlen( " {$sig}" );
410
  // $sig is handled by twitter in their 'via' argument.
411
  // $post_link is handled by twitter in their 'url' argument.
412
  if ( 140 < $strlen( $post_title ) + $suffix_length ) {
603
 
604
  public function process_request( $post, array $post_data ) {
605
 
 
 
606
  $post_link = $this->get_share_url( $post->ID );
607
 
608
+ // Using the same URL as the official button, which is *not* LinkedIn's documented sharing link
609
+ // http://www.linkedin.com/cws/share?url={url}&token=&isFramed=false
 
 
 
 
 
 
 
 
 
610
 
611
  $linkedin_url = add_query_arg( array(
 
612
  'url' => rawurlencode( $post_link ),
613
+ ), 'http://www.linkedin.com/cws/share?token=&isFramed=false' );
 
 
614
 
615
  // Record stats
616
  parent::process_request( $post, $post_data );
1203
  s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
1204
  var x = document.getElementsByTagName("script")[0];
1205
  x.parentNode.insertBefore(s, x);
1206
+ // if 'Pin it' button has 'counts' make container wider
1207
+ jQuery(window).load( function(){ jQuery( 'li.share-pinterest a span:visible' ).closest( '.share-pinterest' ).width( '80px' ); } );
1208
  </script>
1209
  <?php else : ?>
1210
  <script type="text/javascript">
1292
  }
1293
 
1294
  }
1295
+
modules/sharedaddy/sharing.css CHANGED
@@ -314,6 +314,10 @@ li.share-pocket a.sd-button > span {
314
  background-image: url('images/pocket.png');
315
  }
316
 
 
 
 
 
317
  li.share-email a.sd-button > span {
318
  background-image: url('images/email.png');
319
  }
@@ -383,6 +387,11 @@ a.sd-button.share-more span {
383
  background-size: 16px 16px;
384
  }
385
 
 
 
 
 
 
386
  li.share-email a.sd-button > span {
387
  background-image: url('images/email@2x.png?1');
388
  background-size: 16px 16px;
314
  background-image: url('images/pocket.png');
315
  }
316
 
317
+ li.share-kindle a.sd-button > span {
318
+ background-image: url('images/kindle.png');
319
+ }
320
+
321
  li.share-email a.sd-button > span {
322
  background-image: url('images/email.png');
323
  }
387
  background-size: 16px 16px;
388
  }
389
 
390
+ li.share-kindle a.sd-button > span {
391
+ background-image: url('images/kindle@2x.png');
392
+ background-size: 16px 16px;
393
+ }
394
+
395
  li.share-email a.sd-button > span {
396
  background-image: url('images/email@2x.png?1');
397
  background-size: 16px 16px;
modules/sharedaddy/sharing.js CHANGED
@@ -256,7 +256,7 @@ var WPCOMSharing = {
256
  key = $( '#recaptcha_public_key' ).val();
257
 
258
  // Update the recaptcha
259
- Recaptcha.create( key, 'sharing_recaptcha' );
260
 
261
  // Show dialog
262
  $( '#sharing_email' ).css( {
256
  key = $( '#recaptcha_public_key' ).val();
257
 
258
  // Update the recaptcha
259
+ Recaptcha.create( key, 'sharing_recaptcha', { lang : recaptcha_options.lang } );
260
 
261
  // Show dialog
262
  $( '#sharing_email' ).css( {
modules/shortcodes/audio.php CHANGED
@@ -41,7 +41,12 @@ class AudioShortcode {
41
  }
42
 
43
  if ( ! isset( $atts[0] ) ) {
44
- return '<!-- Audio shortcode source not set -->';
 
 
 
 
 
45
  }
46
 
47
  // add the special .js
41
  }
42
 
43
  if ( ! isset( $atts[0] ) ) {
44
+ if ( isset( $atts['src'] ) ) {
45
+ $atts[0] = $atts['src'];
46
+ unset( $atts['src'] );
47
+ } else {
48
+ return '<!-- Audio shortcode source not set -->';
49
+ }
50
  }
51
 
52
  // add the special .js
modules/shortcodes/bandcamp.php CHANGED
@@ -16,10 +16,13 @@ function shortcode_handler_bandcamp( $atts ) {
16
  'bgcol' => 'FFFFFF', // hex, no '#' prefix
17
  'linkcol' => null, // hex, no '#' prefix
18
  'layout' => null, // encoded layout url
19
- 'width' => null, // integer
20
- 'height' => null, // integer
21
- 'notracklist' => null, // may be string "true"
22
- 'package' => null // integer package id
 
 
 
23
  ), $atts );
24
 
25
  $sizes = array(
@@ -31,12 +34,14 @@ function shortcode_handler_bandcamp( $atts ) {
31
  'tall_track' => array( 'width' => 150, 'height' => 270 ),
32
  'tall2' => array( 'width' => 150, 'height' => 450 ),
33
  'short' => array( 'width' => 46, 'height' => 23 ),
34
- 'biggie' => array( 'width' => 350, 'height' => 600 ),
35
- 'minimal' => array( 'width' => 350, 'height' => 350 ),
36
- 'artonly' => array( 'width' => 350, 'height' => 350 )
37
  );
38
 
39
  $sizekey = $attributes['size'];
 
 
40
 
41
  // Build iframe url. Args are appended as
42
  // extra path segments for historical reasons having to
@@ -69,46 +74,69 @@ function shortcode_handler_bandcamp( $atts ) {
69
  $attributes['size'] = 'venti';
70
  }
71
 
72
- $height = absint( $attributes['height'] ); //|| $sizes[$sizekey]['height'];
73
- $width = absint( $attributes['width'] ); //|| $sizes[$sizekey]['width'];
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
- if ( $height ) {
76
- $url .= "/height={$height}";
77
- } else {
78
  $height = $sizes[$sizekey]['height'];
 
79
  }
80
 
81
- if ( $width ) {
82
- $url .= "/width={$width}";
83
- } else {
84
  $width = $sizes[$sizekey]['width'];
 
85
  }
86
 
87
  if ( isset( $attributes['layout'] ) ) {
88
  $url .= "/layout={$attributes['layout']}";
89
- } elseif ( isset( $attributes['size'] ) && preg_match( "|[a-zA-Z]+|", $attributes['size'] ) ) {
90
  $url .= "/size={$attributes['size']}";
91
  }
92
 
93
- if ( isset( $attributes['bgcol'] ) && preg_match( "|[0-9A-Fa-f]+|", $attributes['bgcol'] ) ) {
94
  $url .= "/bgcol={$attributes['bgcol']}";
95
  }
96
 
97
- if ( isset( $attributes['linkcol'] ) && preg_match( "|[0-9A-Fa-f]+|", $attributes['linkcol'] ) ) {
98
  $url .= "/linkcol={$attributes['linkcol']}";
99
  }
100
 
101
- if ( isset( $attributes['package'] ) && preg_match( "|[0-9]+|", $attributes['package'] ) ) {
102
  $url .= "/package={$attributes['package']}";
103
  }
104
 
 
 
 
 
105
  if ( $attributes['notracklist'] == "true" ) {
106
  $url .= "/notracklist=true";
107
  }
108
 
 
 
 
 
 
 
 
 
109
  $url .= '/';
110
 
111
- return "<iframe width='" . esc_attr( $width ) . "' height='" . esc_attr( $height ) . "' style='position: relative; display: block; width: " . esc_attr( $width ) . "px; height: " . esc_attr( $height ) . "px;' src='" . esc_url( $url ) . "' allowtransparency='true' frameborder='0'></iframe>";
112
  }
113
 
114
  add_shortcode( 'bandcamp', 'shortcode_handler_bandcamp' );
16
  'bgcol' => 'FFFFFF', // hex, no '#' prefix
17
  'linkcol' => null, // hex, no '#' prefix
18
  'layout' => null, // encoded layout url
19
+ 'width' => null, // integer with optional "%"
20
+ 'height' => null, // integer with optional "%"
21
+ 'notracklist' => null, // may be string "true" (defaults false)
22
+ 'artwork' => null, // may be string "false" (defaults true)
23
+ 'theme' => null, // may be theme identifier string ("light"|"dark" so far)
24
+ 'package' => null, // integer package id
25
+ 't' => null // integer track number
26
  ), $atts );
27
 
28
  $sizes = array(
34
  'tall_track' => array( 'width' => 150, 'height' => 270 ),
35
  'tall2' => array( 'width' => 150, 'height' => 450 ),
36
  'short' => array( 'width' => 46, 'height' => 23 ),
37
+ 'large' => array( 'width' => 350, 'height' => 470 ),
38
+ 'medium' => array( 'width' => 450, 'height' => 120 ),
39
+ 'small' => array( 'width' => 350, 'height' => 42 )
40
  );
41
 
42
  $sizekey = $attributes['size'];
43
+ $height = null;
44
+ $width = null;
45
 
46
  // Build iframe url. Args are appended as
47
  // extra path segments for historical reasons having to
74
  $attributes['size'] = 'venti';
75
  }
76
 
77
+ // use strict regex for digits + optional % instead of absint for height/width
78
+ // 'width' and 'height' params in the iframe url get the exact string from the shortcode
79
+ // args, whereas the inline style attribute must have "px" added to it if it has no "%"
80
+ if ( isset( $attributes['width'] ) && preg_match( "|^([0-9]+)(%)?$|", $attributes['width'], $matches ) ) {
81
+ $width = $csswidth = $attributes['width'];
82
+ if ( sizeof( $matches ) < 3 ) {
83
+ $csswidth .= "px";
84
+ }
85
+ }
86
+ if ( isset( $attributes['height'] ) && preg_match( "|^([0-9]+)(%)?$|", $attributes['height'], $matches ) ) {
87
+ $height = $cssheight = $attributes['height'];
88
+ if ( sizeof( $matches ) < 3 ) {
89
+ $cssheight .= "px";
90
+ }
91
+ }
92
 
93
+ if ( !$height ) {
 
 
94
  $height = $sizes[$sizekey]['height'];
95
+ $cssheight = $height . "px";
96
  }
97
 
98
+ if ( !$width ) {
 
 
99
  $width = $sizes[$sizekey]['width'];
100
+ $csswidth = $width . "px";
101
  }
102
 
103
  if ( isset( $attributes['layout'] ) ) {
104
  $url .= "/layout={$attributes['layout']}";
105
+ } elseif ( isset( $attributes['size'] ) && preg_match( "|^[a-zA-Z0-9]+$|", $attributes['size'] ) ) {
106
  $url .= "/size={$attributes['size']}";
107
  }
108
 
109
+ if ( isset( $attributes['bgcol'] ) && preg_match( "|^[0-9A-Fa-f]+$|", $attributes['bgcol'] ) ) {
110
  $url .= "/bgcol={$attributes['bgcol']}";
111
  }
112
 
113
+ if ( isset( $attributes['linkcol'] ) && preg_match( "|^[0-9A-Fa-f]+$|", $attributes['linkcol'] ) ) {
114
  $url .= "/linkcol={$attributes['linkcol']}";
115
  }
116
 
117
+ if ( isset( $attributes['package'] ) && preg_match( "|^[0-9]+$|", $attributes['package'] ) ) {
118
  $url .= "/package={$attributes['package']}";
119
  }
120
 
121
+ if ( isset( $attributes['t'] ) && preg_match( "|^[0-9]+$|", $attributes['t'] ) ) {
122
+ $url .= "/t={$attributes['t']}";
123
+ }
124
+
125
  if ( $attributes['notracklist'] == "true" ) {
126
  $url .= "/notracklist=true";
127
  }
128
 
129
+ if ( $attributes['artwork'] == "false" ) {
130
+ $url .= "/artwork=false";
131
+ }
132
+
133
+ if ( isset( $attributes['theme'] ) && preg_match( "|^[a-zA-Z_]+$|", $attributes['theme'] ) ) {
134
+ $url .= "/theme={$attributes['theme']}";
135
+ }
136
+
137
  $url .= '/';
138
 
139
+ return "<iframe width='" . esc_attr( $width ) . "' height='" . esc_attr( $height ) . "' style='position: relative; display: block; width: " . esc_attr( $csswidth ) . "; height: " . esc_attr( $cssheight ) . ";' src='" . esc_url( $url ) . "' allowtransparency='true' frameborder='0'></iframe>";
140
  }
141
 
142
  add_shortcode( 'bandcamp', 'shortcode_handler_bandcamp' );
modules/shortcodes/slideshow.php CHANGED
@@ -102,7 +102,7 @@ class Jetpack_Slideshow_Shortcode {
102
  foreach ( $attachments as $attachment ) {
103
  $attachment_image_src = wp_get_attachment_image_src( $attachment->ID, 'full' );
104
  $attachment_image_src = $attachment_image_src[0]; // [url, width, height]
105
- $caption = wptexturize( strip_tags( $attachment->post_excerpt ) );
106
 
107
  $gallery[] = (object) array(
108
  'src' => (string) esc_url_raw( $attachment_image_src ),
102
  foreach ( $attachments as $attachment ) {
103
  $attachment_image_src = wp_get_attachment_image_src( $attachment->ID, 'full' );
104
  $attachment_image_src = $attachment_image_src[0]; // [url, width, height]
105
+ $caption = apply_filters( 'jetpack_slideshow_slide_caption', wptexturize( strip_tags( $attachment->post_excerpt ) ), $attachment->ID );
106
 
107
  $gallery[] = (object) array(
108
  'src' => (string) esc_url_raw( $attachment_image_src ),
modules/social-links.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Themes must declare that they support this module by adding
4
+ * add_theme_support( 'social-links' ); on 'after_setup_theme'.
5
+ */
6
+ function jetpack_load_additional_modules() {
7
+ if ( current_theme_supports( 'social-links' ) )
8
+ require_once 'social-links/social-links.php';
9
+ }
10
+ add_action( 'init', 'jetpack_load_additional_modules' );
modules/social-links/social-links.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Social Links.
5
+ *
6
+ * This feature will only be activated for themes that declare their support.
7
+ * This can be done by adding code similar to the following during the
8
+ * 'after_setup_theme' action:
9
+ *
10
+ * add_theme_support( 'social-links', array(
11
+ * 'facebook', 'twitter', 'linkedin', 'tumblr',
12
+ * ) );
13
+ */
14
+ class Social_Links {
15
+
16
+ /**
17
+ * The links the user set for each service.
18
+ *
19
+ * @var array
20
+ */
21
+ private $links;
22
+
23
+ /**
24
+ * A Publicize object.
25
+ *
26
+ * @var Publicize
27
+ */
28
+ private $publicize;
29
+
30
+ /**
31
+ * An array with all services that are supported by both Publicize and the
32
+ * currently active theme.
33
+ *
34
+ * @var array
35
+ */
36
+ private $services = array();
37
+
38
+ /**
39
+ * Constructor.
40
+ */
41
+ public function __construct() {
42
+ $theme_support = get_theme_support( 'social-links' );
43
+
44
+ /* An array of named arguments must be passed as the second parameter
45
+ * of add_theme_support().
46
+ */
47
+ if ( ! isset( $theme_support[0] ) || empty( $theme_support[0] ) )
48
+ return;
49
+
50
+ $this->links = Jetpack_Options::get_option( 'social_links', array() );
51
+
52
+ global $publicize;
53
+
54
+ if ( is_a( $publicize, 'Publicize' ) ) {
55
+ $this->publicize = $publicize;
56
+ $this->services = array_intersect(
57
+ array_keys( $this->publicize->get_services( 'connected' ) ),
58
+ $theme_support[0]
59
+ );
60
+
61
+ add_action( 'customize_register', array( $this, 'customize_register' ) );
62
+ add_filter( 'sanitize_option_jetpack_options', array( $this, 'sanitize_link' ) );
63
+ }
64
+
65
+ add_filter( 'jetpack_has_social_links', array( $this, 'has_social_links' ) );
66
+ add_filter( 'jetpack_get_social_links', array( $this, 'get_social_links' ) );
67
+
68
+ foreach ( $theme_support[0] as $service ) {
69
+ add_filter( "pre_option_jetpack-$service", array( $this, 'get_social_link_filter' ) ); // get_option( 'jetpack-service' );
70
+ add_filter( "theme_mod_jetpack-$service", array( $this, 'get_social_link_filter' ) ); // get_theme_mod( 'jetpack-service' );
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Add social link dropdown to the Customizer.
76
+ *
77
+ * @param WP_Customize_Manager $wp_customize Theme Customizer object.
78
+ */
79
+ public function customize_register( $wp_customize ) {
80
+ $wp_customize->add_section( 'jetpack_social_links', array(
81
+ 'title' => __( 'Connect', 'jetpack' ),
82
+ 'priority' => 35,
83
+ ) );
84
+
85
+ foreach ( $this->services as $service ) {
86
+ $wp_customize->add_setting( "jetpack_options[social_links][$service]", array(
87
+ 'type' => 'option',
88
+ 'default' => '',
89
+ ) );
90
+
91
+ $wp_customize->add_control( "jetpack-$service", array(
92
+ 'label' => $this->publicize->get_service_label( $service ),
93
+ 'section' => 'jetpack_social_links',
94
+ 'settings' => "jetpack_options[social_links][$service]",
95
+ 'type' => 'select',
96
+ 'choices' => $this->get_customize_select( $service ),
97
+ ) );
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Sanitizes social links.
103
+ *
104
+ * @param array $option The incoming values to be sanitized.
105
+ * @returns array
106
+ */
107
+ public function sanitize_link( $option ) {
108
+ foreach ( $this->services as $service ) {
109
+ if ( ! empty( $option['social_links'][ $service ] ) )
110
+ $option['social_links'][ $service ] = esc_url_raw( $option['social_links'][ $service ] );
111
+ else
112
+ unset( $option['social_links'][ $service ] );
113
+ }
114
+
115
+ return $option;
116
+ }
117
+
118
+ /**
119
+ * Returns whether there are any social links set.
120
+ *
121
+ * @returns bool
122
+ */
123
+ public function has_social_links() {
124
+ return ! empty( $this->links );
125
+ }
126
+
127
+ /**
128
+ * Return available social links.
129
+ *
130
+ * @returns array
131
+ */
132
+ public function get_social_links() {
133
+ return $this->links;
134
+ }
135
+
136
+ /**
137
+ * Short-circuits get_option and get_theme_mod calls.
138
+ *
139
+ * @param string $link The incoming value to be replaced.
140
+ * @returns string $link The social link that we've got.
141
+ */
142
+ public function get_social_link_filter( $link ) {
143
+ if ( preg_match( '/_jetpack-(.+)$/i', current_filter(), $matches ) && ! empty( $this->links[ $matches[1] ] ) )
144
+ return $this->links[ $matches[1] ];
145
+
146
+ return $link;
147
+ }
148
+
149
+ /**
150
+ * Puts together an array of choices for a specific service.
151
+ *
152
+ * @param string $service The social service.
153
+ * @return array An associative array with profile links and display names.
154
+ */
155
+ private function get_customize_select( $service ) {
156
+ $choices = array(
157
+ '' => __( '&mdash; Select &mdash;', 'jetpack' )
158
+ );
159
+
160
+ $connected_services = $this->publicize->get_services( 'connected' );
161
+ if ( isset( $connected_services[ $service ] ) )
162
+ foreach ( $connected_services[ $service ] as $c )
163
+ $choices[ $this->publicize->get_profile_link( $service, $c ) ] = $this->publicize->get_display_name( $service, $c );
164
+
165
+ return $choices;
166
+ }
167
+ }
168
+
169
+ $jetpack_social_links = new Social_Links;
modules/stats.php CHANGED
@@ -215,6 +215,8 @@ function stats_upgrade_options( $options ) {
215
  );
216
 
217
  if ( isset( $options['reg_users'] ) ) {
 
 
218
  if ( $options['reg_users'] )
219
  $options['count_roles'] = array_keys( get_editable_roles() );
220
  unset( $options['reg_users'] );
@@ -918,15 +920,23 @@ function stats_dashboard_widget_content() {
918
  /* translators: Stats dashboard widget postviews list: "$post_title $views Views" */
919
  $printf = __( '%1$s %2$s Views' , 'jetpack' );
920
 
921
- foreach ( $top_posts = stats_get_csv( 'postviews', "days=$options[top]$csv_args[top]" ) as $post )
 
 
 
 
922
  $post_ids[] = $post['post_id'];
 
923
 
924
  // cache
925
  get_posts( array( 'include' => join( ',', array_unique( $post_ids ) ) ) );
926
 
927
  $searches = array();
928
- foreach ( $search_terms = stats_get_csv( 'searchterms', "days=$options[search]$csv_args[search]" ) as $search_term )
 
 
929
  $searches[] = esc_html( $search_term['searchterm'] );
 
930
 
931
  ?>
932
  <a class="button" href="admin.php?page=stats"><?php _e( 'View All', 'jetpack' ); ?></a>
215
  );
216
 
217
  if ( isset( $options['reg_users'] ) ) {
218
+ if ( ! function_exists( 'get_editable_roles' ) )
219
+ require_once( ABSPATH . 'wp-admin/includes/user.php' );
220
  if ( $options['reg_users'] )
221
  $options['count_roles'] = array_keys( get_editable_roles() );
222
  unset( $options['reg_users'] );
920
  /* translators: Stats dashboard widget postviews list: "$post_title $views Views" */
921
  $printf = __( '%1$s %2$s Views' , 'jetpack' );
922
 
923
+ foreach ( $top_posts = stats_get_csv( 'postviews', "days=$options[top]$csv_args[top]" ) as $i => $post ) {
924
+ if ( $post['post_id'] == 0 ) {
925
+ unset( $top_posts[$i] );
926
+ continue;
927
+ }
928
  $post_ids[] = $post['post_id'];
929
+ }
930
 
931
  // cache
932
  get_posts( array( 'include' => join( ',', array_unique( $post_ids ) ) ) );
933
 
934
  $searches = array();
935
+ foreach ( $search_terms = stats_get_csv( 'searchterms', "days=$options[search]$csv_args[search]" ) as $search_term ) {
936
+ if ( $search_term['searchterm'] == 'encrypted_search_terms' )
937
+ continue;
938
  $searches[] = esc_html( $search_term['searchterm'] );
939
+ }
940
 
941
  ?>
942
  <a class="button" href="admin.php?page=stats"><?php _e( 'View All', 'jetpack' ); ?></a>
modules/subscriptions.php CHANGED
@@ -43,7 +43,7 @@ class Jetpack_Subscriptions {
43
  * Singleton
44
  * @static
45
  */
46
- function init() {
47
  static $instance = false;
48
 
49
  if ( !$instance ) {
@@ -659,7 +659,7 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
659
  return $instance;
660
  }
661
 
662
- function defaults() {
663
  return array(
664
  'title' => esc_html__( 'Subscribe to Blog via Email', 'jetpack' ),
665
  'subscribe_text' => esc_html__( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
@@ -707,7 +707,7 @@ class Jetpack_Subscriptions_Widget extends WP_Widget {
707
  <p>
708
  <label for="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>">
709
  <input type="checkbox" id="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>" name="<?php echo $this->get_field_name( 'show_subscribers_total' ); ?>" value="1"<?php echo $show_subscribers_total; ?> />
710
- <?php echo esc_html( sprintf( _n( 'Show total number of subscribers? (%s subscriber)', 'Show total number of subscribers? (%s subscribers)', $subscribers_total, 'jetpack' ), number_format_i18n( $subscribers_total ) ) ); ?>
711
  </label>
712
  </p>
713
  <?php
43
  * Singleton
44
  * @static
45
  */
46
+ static function init() {
47
  static $instance = false;
48
 
49
  if ( !$instance ) {
659
  return $instance;
660
  }
661
 
662
+ public static function defaults() {
663
  return array(
664
  'title' => esc_html__( 'Subscribe to Blog via Email', 'jetpack' ),
665
  'subscribe_text' => esc_html__( 'Enter your email address to subscribe to this blog and receive notifications of new posts by email.', 'jetpack' ),
707
  <p>
708
  <label for="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>">
709
  <input type="checkbox" id="<?php echo $this->get_field_id( 'show_subscribers_total' ); ?>" name="<?php echo $this->get_field_name( 'show_subscribers_total' ); ?>" value="1"<?php echo $show_subscribers_total; ?> />
710
+ <?php echo esc_html( sprintf( _n( 'Show total number of subscribers? (%s subscriber)', 'Show total number of subscribers? (%s subscribers)', $subscribers_total, 'jetpack' ), $subscribers_total ) ); ?>
711
  </label>
712
  </p>
713
  <?php
modules/tiled-gallery/tiled-gallery.php CHANGED
@@ -273,7 +273,7 @@ class Jetpack_Tiled_Gallery {
273
  }
274
 
275
  public function gallery_classes() {
276
- $classes = 'class="tiled-gallery type-' . esc_attr( $this->atts['type'] ) . '"';
277
  return $classes;
278
  }
279
 
273
  }
274
 
275
  public function gallery_classes() {
276
+ $classes = 'class="tiled-gallery type-' . esc_attr( $this->atts['type'] ) . ' tiled-gallery-unresized"';
277
  return $classes;
278
  }
279
 
modules/tiled-gallery/tiled-gallery/rtl/tiled-gallery-rtl.css CHANGED
@@ -1,11 +1,11 @@
1
- /* This file was automatically generated on Apr 04 2013 13:33:55 */
2
 
3
  /* =Tiled Gallery Default Styles
4
  -------------------------------------------------------------- */
5
 
6
  .tiled-gallery {
7
  clear: both;
8
- margin: 0;
9
  overflow: hidden;
10
  }
11
  .tiled-gallery img {
@@ -62,6 +62,14 @@
62
  font-size: 11px;
63
  }
64
 
 
 
 
 
 
 
 
 
65
 
66
  /* =Greyscale
67
  -------------------------------------------------------------- */
@@ -85,4 +93,5 @@
85
  .tiled-gallery.type-circle .tiled-gallery-caption {
86
  display: none;
87
  opacity: 0;
88
- }
 
1
+ /* This file was automatically generated on Jul 31 2013 21:21:12 */
2
 
3
  /* =Tiled Gallery Default Styles
4
  -------------------------------------------------------------- */
5
 
6
  .tiled-gallery {
7
  clear: both;
8
+ margin: 0 0 20px;
9
  overflow: hidden;
10
  }
11
  .tiled-gallery img {
62
  font-size: 11px;
63
  }
64
 
65
+ /* Hide galleries in widgets until they've been resized to fit.
66
+ Gallery widgets are almost guaranteed to need resizing, and
67
+ the jump is a little more obvious than galleries in content. */
68
+ .widget-gallery .tiled-gallery-unresized {
69
+ visibility: hidden;
70
+ height: 0px;
71
+ overflow: hidden;
72
+ }
73
 
74
  /* =Greyscale
75
  -------------------------------------------------------------- */
93
  .tiled-gallery.type-circle .tiled-gallery-caption {
94
  display: none;
95
  opacity: 0;
96
+ }
97
+
modules/tiled-gallery/tiled-gallery/tiled-gallery.css CHANGED
@@ -3,7 +3,7 @@
3
 
4
  .tiled-gallery {
5
  clear: both;
6
- margin: 0;
7
  overflow: hidden;
8
  }
9
  .tiled-gallery img {
@@ -60,6 +60,14 @@
60
  font-size: 11px;
61
  }
62
 
 
 
 
 
 
 
 
 
63
 
64
  /* =Greyscale
65
  -------------------------------------------------------------- */
@@ -83,4 +91,5 @@
83
  .tiled-gallery.type-circle .tiled-gallery-caption {
84
  display: none;
85
  opacity: 0;
86
- }
 
3
 
4
  .tiled-gallery {
5
  clear: both;
6
+ margin: 0 0 20px;
7
  overflow: hidden;
8
  }
9
  .tiled-gallery img {
60
  font-size: 11px;
61
  }
62
 
63
+ /* Hide galleries in widgets until they've been resized to fit.
64
+ Gallery widgets are almost guaranteed to need resizing, and
65
+ the jump is a little more obvious than galleries in content. */
66
+ .widget-gallery .tiled-gallery-unresized {
67
+ visibility: hidden;
68
+ height: 0px;
69
+ overflow: hidden;
70
+ }
71
 
72
  /* =Greyscale
73
  -------------------------------------------------------------- */
91
  .tiled-gallery.type-circle .tiled-gallery-caption {
92
  display: none;
93
  opacity: 0;
94
+ }
95
+
modules/tiled-gallery/tiled-gallery/tiled-gallery.js CHANGED
@@ -51,9 +51,10 @@ TiledGallery.prototype.Captions = function() {
51
  /* Hide captions */
52
  this.caption.hide();
53
 
54
- this.item.on( 'mouseenter mouseleave', function() {
55
- $( this ).find( '.tiled-gallery-caption' ).slideToggle( 'fast' );
56
- });
 
57
  };
58
 
59
  TiledGallery.prototype.resize = function() {
@@ -134,6 +135,8 @@ TiledGallery.prototype.resize = function() {
134
  .width( Math.floor( resizeRatio * thisGalleryElement.data( 'original-width' ) ) - thisGalleryElement.data( 'extra-width' ) )
135
  .height( Math.floor( resizeRatio * thisGalleryElement.data( 'original-height' ) ) - thisGalleryElement.data( 'extra-height' ) );
136
  } );
 
 
137
  } );
138
  };
139
 
51
  /* Hide captions */
52
  this.caption.hide();
53
 
54
+ this.item.hover(
55
+ function() { $( this ).find( '.tiled-gallery-caption' ).slideDown( 'fast' ); },
56
+ function() { $( this ).find( '.tiled-gallery-caption' ).slideUp( 'fast' ); }
57
+ );
58
  };
59
 
60
  TiledGallery.prototype.resize = function() {
135
  .width( Math.floor( resizeRatio * thisGalleryElement.data( 'original-width' ) ) - thisGalleryElement.data( 'extra-width' ) )
136
  .height( Math.floor( resizeRatio * thisGalleryElement.data( 'original-height' ) ) - thisGalleryElement.data( 'extra-height' ) );
137
  } );
138
+
139
+ thisGallery.removeClass( 'tiled-gallery-unresized' );
140
  } );
141
  };
142
 
modules/widgets/facebook-likebox.php CHANGED
@@ -59,8 +59,9 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
59
  $like_args['show_faces'] = (bool) $like_args['show_faces'] ? 'true' : 'false';
60
  $like_args['stream'] = (bool) $like_args['stream'] ? 'true' : 'false';
61
  $like_args['force_wall'] = (bool) $like_args['force_wall'] ? 'true' : 'false';
 
62
  $like_args['header'] = (bool) $like_args['header'] ? 'true' : 'false';
63
- $like_bg_colour = ( 'dark' == $like_args['colorscheme'] ) ? '#000' : '#fff';
64
 
65
  $locale = $this->get_locale();
66
  if ( $locale && 'en_US' != $locale )
@@ -100,6 +101,7 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
100
  'colorscheme' => $new_instance['colorscheme'],
101
  'show_faces' => (bool) $new_instance['show_faces'],
102
  'stream' => (bool) $new_instance['stream'],
 
103
  'header' => false, // The header just displays "Find us on Facebook"; it's redundant with the title
104
  'force_wall' => (bool) $new_instance['force_wall'],
105
  );
@@ -136,14 +138,14 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
136
  <p>
137
  <label for="<?php echo $this->get_field_id( 'width' ); ?>">
138
  <?php _e( 'Width', 'jetpack' ); ?>
139
- <input type="text" maxlength="3" name="<?php echo $this->get_field_name( 'width' ); ?>" id="<?php echo $this->get_field_id( 'width' ); ?>" value="<?php echo esc_attr( $like_args['width'] ); ?>" style="width: 30px; text-align: center;" />px
140
  </label>
141
  </p>
142
 
143
  <p>
144
  <label for="<?php echo $this->get_field_id( 'height' ); ?>">
145
  <?php _e( 'Height', 'jetpack' ); ?>
146
- <input type="text" maxlength="3" name="<?php echo $this->get_field_name( 'height' ); ?>" id="<?php echo $this->get_field_id( 'height' ); ?>" value="<?php echo esc_attr( $like_args['height'] ); ?>" style="width: 30px; text-align: center;" />px
147
  </label>
148
  </p>
149
 
@@ -157,7 +159,6 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
157
  </label>
158
  </p>
159
 
160
-
161
  <p>
162
  <label for="<?php echo $this->get_field_id( 'show_faces' ); ?>">
163
  <input type="checkbox" name="<?php echo $this->get_field_name( 'show_faces' ); ?>" id="<?php echo $this->get_field_id( 'show_faces' ); ?>" <?php checked( $like_args['show_faces'] ); ?> />
@@ -176,6 +177,15 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
176
  </label>
177
  </p>
178
 
 
 
 
 
 
 
 
 
 
179
  <p>
180
  <label for="<?php echo $this->get_field_id( 'force_wall' ); ?>">
181
  <input type="checkbox" name="<?php echo $this->get_field_name( 'force_wall' ); ?>" id="<?php echo $this->get_field_id( 'force_wall' ); ?>" <?php checked( $like_args['force_wall'] ); ?> />
@@ -196,6 +206,7 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
196
  'colorscheme' => $this->default_colorscheme,
197
  'show_faces' => true,
198
  'stream' => false,
 
199
  'header' => false,
200
  'force_wall' => false,
201
  );
@@ -219,6 +230,7 @@ class WPCOM_Widget_Facebook_LikeBox extends WP_Widget {
219
  $args['colorscheme'] = $this->normalize_text_value( $args['colorscheme'], $this->default_colorscheme, $this->allowed_colorschemes );
220
  $args['show_faces'] = (bool) $args['show_faces'];
221
  $args['stream'] = (bool) $args['stream'];
 
222
  $args['force_wall'] = (bool) $args['force_wall'];
223
 
224
  // The height used to be dependent on other widget settings
59
  $like_args['show_faces'] = (bool) $like_args['show_faces'] ? 'true' : 'false';
60
  $like_args['stream'] = (bool) $like_args['stream'] ? 'true' : 'false';
61
  $like_args['force_wall'] = (bool) $like_args['force_wall'] ? 'true' : 'false';
62
+ $like_args['show_border']= (bool) $like_args['show_border'] ? 'true' : 'false';
63
  $like_args['header'] = (bool) $like_args['header'] ? 'true' : 'false';
64
+ $like_bg_colour = apply_filters( 'jetpack_fb_likebox_bg', ( 'dark' == $like_args['colorscheme'] ? '#000' : '#fff' ), $like_args['colorscheme'] );
65
 
66
  $locale = $this->get_locale();
67
  if ( $locale && 'en_US' != $locale )
101
  'colorscheme' => $new_instance['colorscheme'],
102
  'show_faces' => (bool) $new_instance['show_faces'],
103
  'stream' => (bool) $new_instance['stream'],
104
+ 'show_border' => (bool) $new_instance['show_border'],
105
  'header' => false, // The header just displays "Find us on Facebook"; it's redundant with the title
106
  'force_wall' => (bool) $new_instance['force_wall'],
107
  );
138
  <p>
139
  <label for="<?php echo $this->get_field_id( 'width' ); ?>">
140
  <?php _e( 'Width', 'jetpack' ); ?>
141
+ <input type="number" class="smalltext" min="1" max="999" maxlength="3" name="<?php echo $this->get_field_name( 'width' ); ?>" id="<?php echo $this->get_field_id( 'width' ); ?>" value="<?php echo esc_attr( $like_args['width'] ); ?>" style="text-align: center;" />px
142
  </label>
143
  </p>
144
 
145
  <p>
146
  <label for="<?php echo $this->get_field_id( 'height' ); ?>">
147
  <?php _e( 'Height', 'jetpack' ); ?>
148
+ <input type="number" class="smalltext" min="1" max="999" maxlength="3" name="<?php echo $this->get_field_name( 'height' ); ?>" id="<?php echo $this->get_field_id( 'height' ); ?>" value="<?php echo esc_attr( $like_args['height'] ); ?>" style="text-align: center;" />px
149
  </label>
150
  </p>
151
 
159
  </label>
160
  </p>
161
 
 
162
  <p>
163
  <label for="<?php echo $this->get_field_id( 'show_faces' ); ?>">
164
  <input type="checkbox" name="<?php echo $this->get_field_name( 'show_faces' ); ?>" id="<?php echo $this->get_field_id( 'show_faces' ); ?>" <?php checked( $like_args['show_faces'] ); ?> />
177
  </label>
178
  </p>
179
 
180
+ <p>
181
+ <label for="<?php echo $this->get_field_id( 'show_border' ); ?>">
182
+ <input type="checkbox" name="<?php echo $this->get_field_name( 'show_border' ); ?>" id="<?php echo $this->get_field_id( 'show_border' ); ?>" <?php checked( $like_args['show_border'] ); ?> />
183
+ <?php _e( 'Show Border', 'jetpack' ); ?>
184
+ <br />
185
+ <small><?php _e( 'Show a border around the plugin.', 'jetpack' ); ?></small>
186
+ </label>
187
+ </p>
188
+
189
  <p>
190
  <label for="<?php echo $this->get_field_id( 'force_wall' ); ?>">
191
  <input type="checkbox" name="<?php echo $this->get_field_name( 'force_wall' ); ?>" id="<?php echo $this->get_field_id( 'force_wall' ); ?>" <?php checked( $like_args['force_wall'] ); ?> />
206
  'colorscheme' => $this->default_colorscheme,
207
  'show_faces' => true,
208
  'stream' => false,
209
+ 'show_border' => true,
210
  'header' => false,
211
  'force_wall' => false,
212
  );
230
  $args['colorscheme'] = $this->normalize_text_value( $args['colorscheme'], $this->default_colorscheme, $this->allowed_colorschemes );
231
  $args['show_faces'] = (bool) $args['show_faces'];
232
  $args['stream'] = (bool) $args['stream'];
233
+ $args['show_border'] = (bool) $args['show_border'];
234
  $args['force_wall'] = (bool) $args['force_wall'];
235
 
236
  // The height used to be dependent on other widget settings
modules/widgets/top-posts.php CHANGED
@@ -57,7 +57,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
57
  }
58
 
59
  $count = isset( $instance['count'] ) ? (int) $instance['count'] : 10;
60
- if ( $count < 1 || 20 < $count ) {
61
  $count = 10;
62
  }
63
 
@@ -75,7 +75,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
75
  </p>
76
 
77
  <p>
78
- <label for="<?php echo $this->get_field_id( 'count' ); ?>"><?php esc_html_e( 'Maximum number of posts to show:', 'jetpack' ); ?></label>
79
  <input id="<?php echo $this->get_field_id( 'count' ); ?>" name="<?php echo $this->get_field_name( 'count' ); ?>" type="number" value="<?php echo (int) $count; ?>" min="1" max="10" />
80
  </p>
81
 
@@ -101,7 +101,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
101
  }
102
 
103
  $instance['count'] = (int) $new_instance['count'];
104
- if ( $instance['count'] < 1 || 20 < $instance['count'] ) {
105
  $instance['count'] = 10;
106
  }
107
 
@@ -121,7 +121,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
121
  $title = apply_filters( 'widget_title', $title );
122
 
123
  $count = isset( $instance['count'] ) ? (int) $instance['count'] : false;
124
- if ( $count < 1 || 20 < $count ) {
125
  $count = 10;
126
  }
127
 
@@ -175,7 +175,7 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
175
  case 'grid' :
176
  wp_enqueue_style( 'widget-grid-and-list' );
177
  foreach ( $posts as &$post ) {
178
- $image = Jetpack_PostImages::get_image( $post['post_id'] );
179
  $post['image'] = $image['src'];
180
  if ( 'blavatar' != $image['from'] && 'gravatar' != $image['from'] ) {
181
  $size = (int) $get_image_options['avatar_size'];
@@ -268,6 +268,10 @@ class Jetpack_Top_Posts_Widget extends WP_Widget {
268
  if ( !$post )
269
  continue;
270
 
 
 
 
 
271
  // hide private and password protected posts
272
  if ( 'publish' != $post->post_status || !empty( $post->post_password ) || empty( $post->ID ) )
273
  continue;
57
  }
58
 
59
  $count = isset( $instance['count'] ) ? (int) $instance['count'] : 10;
60
+ if ( $count < 1 || 10 < $count ) {
61
  $count = 10;
62
  }
63
 
75
  </p>
76
 
77
  <p>
78
+ <label for="<?php echo $this->get_field_id( 'count' ); ?>"><?php esc_html_e( 'Maximum number of posts to show (no more than 10):', 'jetpack' ); ?></label>
79
  <input id="<?php echo $this->get_field_id( 'count' ); ?>" name="<?php echo $this->get_field_name( 'count' ); ?>" type="number" value="<?php echo (int) $count; ?>" min="1" max="10" />
80
  </p>
81
 
101
  }
102
 
103
  $instance['count'] = (int) $new_instance['count'];
104
+ if ( $instance['count'] < 1 || 10 < $instance['count'] ) {
105
  $instance['count'] = 10;
106
  }
107
 
121
  $title = apply_filters( 'widget_title', $title );
122
 
123
  $count = isset( $instance['count'] ) ? (int) $instance['count'] : false;
124
+ if ( $count < 1 || 10 < $count ) {
125
  $count = 10;
126
  }
127
 
175
  case 'grid' :
176
  wp_enqueue_style( 'widget-grid-and-list' );
177
  foreach ( $posts as &$post ) {
178
+ $image = Jetpack_PostImages::get_image( $post['post_id'], array( 'fallback_to_avatars' => true ) );
179
  $post['image'] = $image['src'];
180
  if ( 'blavatar' != $image['from'] && 'gravatar' != $image['from'] ) {
181
  $size = (int) $get_image_options['avatar_size'];
268
  if ( !$post )
269
  continue;
270
 
271
+ // Only posts and pages, no attachments
272
+ if ( 'attachment' == $post->post_type )
273
+ continue;
274
+
275
  // hide private and password protected posts
276
  if ( 'publish' != $post->post_status || !empty( $post->post_password ) || empty( $post->ID ) )
277
  continue;
modules/widgets/twitter-timeline.php CHANGED
@@ -89,11 +89,13 @@ class Jetpack_Twitter_Timeline_Widget extends WP_Widget {
89
  * @return array Updated safe values to be saved.
90
  */
91
  public function update( $new_instance, $old_instance ) {
92
- $non_hex_regex = '/[^a-f0-9]/';
93
- $instance = array();
94
- $instance['title'] = wp_kses( $new_instance['title'], array() );
95
- $instance['width'] = (int) wp_kses( $new_instance['width'], array() );
96
- $instance['height'] = (int) wp_kses( $new_instance['height'], array() );
 
 
97
 
98
  // If they entered something that might be a full URL, try to parse it out
99
  if ( is_string( $new_instance['widget-id'] ) ) {
@@ -101,11 +103,12 @@ class Jetpack_Twitter_Timeline_Widget extends WP_Widget {
101
  $new_instance['widget-id'] = $matches[1];
102
  }
103
  }
104
- $instance['widget-id'] = wp_kses( $new_instance['widget-id'], array() );
 
105
  $instance['widget-id'] = is_numeric( $instance['widget-id'] ) ? $instance['widget-id'] : '';
106
-
107
  foreach ( array( 'link-color', 'border-color' ) as $color ) {
108
- $clean = preg_replace( $non_hex_regex, '', wp_kses( $new_instance[$color], array() ) );
109
  if ( $clean )
110
  $instance[$color] = '#' . $clean;
111
  }
@@ -117,7 +120,7 @@ class Jetpack_Twitter_Timeline_Widget extends WP_Widget {
117
  $instance['chrome'] = array();
118
  if ( isset( $new_instance['chrome'] ) ) {
119
  foreach ( $new_instance['chrome'] as $chrome ) {
120
- if ( in_array( $chrome, array( 'noheader', 'nofooter', 'noborders', 'transparent' ) ) ) {
121
  $instance['chrome'][] = $chrome;
122
  }
123
  }
@@ -145,7 +148,7 @@ class Jetpack_Twitter_Timeline_Widget extends WP_Widget {
145
  'theme' => 'light',
146
  'chrome' => array(),
147
  );
148
-
149
  $instance = wp_parse_args( (array) $instance, $defaults );
150
  ?>
151
 
@@ -166,10 +169,12 @@ class Jetpack_Twitter_Timeline_Widget extends WP_Widget {
166
 
167
  <p><small>
168
  <?php
169
- printf(
170
- esc_html__( 'You need to <a href="%1$s" target="_blank">create a widget at Twitter.com</a>, and then enter your widget id (the long number found in the URL of your widget\'s config page) in the field below. <a href="%2$s" target="_blank">Read more</a>.' ),
171
- 'https://twitter.com/settings/widgets/new/user',
172
- 'http://support.wordpress.com/widgets/twitter-timeline-widget/'
 
 
173
  );
174
  ?>
175
  </small></p>
@@ -183,6 +188,7 @@ class Jetpack_Twitter_Timeline_Widget extends WP_Widget {
183
  <input type="checkbox"<?php checked( in_array( 'noheader', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="noheader" /> <label for="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>"><?php esc_html_e( 'No Header', 'jetpack' ); ?></label><br />
184
  <input type="checkbox"<?php checked( in_array( 'nofooter', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-nofooter' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="nofooter" /> <label for="<?php echo $this->get_field_id( 'chrome-nofooter' ); ?>"><?php esc_html_e( 'No Footer', 'jetpack' ); ?></label><br />
185
  <input type="checkbox"<?php checked( in_array( 'noborders', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-noborders' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="noborders" /> <label for="<?php echo $this->get_field_id( 'chrome-noborders' ); ?>"><?php esc_html_e( 'No Borders', 'jetpack' ); ?></label><br />
 
186
  <input type="checkbox"<?php checked( in_array( 'transparent', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-transparent' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="transparent" /> <label for="<?php echo $this->get_field_id( 'chrome-transparent' ); ?>"><?php esc_html_e( 'Transparent Background', 'jetpack' ); ?></label>
187
  </p>
188
 
89
  * @return array Updated safe values to be saved.
90
  */
91
  public function update( $new_instance, $old_instance ) {
92
+ $non_hex_regex = '/[^a-f0-9]/';
93
+ $instance = array();
94
+ $instance['title'] = sanitize_text_field( $new_instance['title'] );
95
+ $instance['width'] = (int) $new_instance['width'];
96
+ $instance['height'] = (int) $new_instance['height'];
97
+ $instance['width'] = ( 0 !== (int) $instance['width'] ) ? (int) $instance['width'] : 225;
98
+ $instance['height'] = ( 0 !== (int) $instance['height'] ) ? (int) $instance['height'] : 400;
99
 
100
  // If they entered something that might be a full URL, try to parse it out
101
  if ( is_string( $new_instance['widget-id'] ) ) {
103
  $new_instance['widget-id'] = $matches[1];
104
  }
105
  }
106
+
107
+ $instance['widget-id'] = sanitize_text_field( $new_instance['widget-id'] );
108
  $instance['widget-id'] = is_numeric( $instance['widget-id'] ) ? $instance['widget-id'] : '';
109
+
110
  foreach ( array( 'link-color', 'border-color' ) as $color ) {
111
+ $clean = preg_replace( $non_hex_regex, '', sanitize_text_field( $new_instance[$color] ) );
112
  if ( $clean )
113
  $instance[$color] = '#' . $clean;
114
  }
120
  $instance['chrome'] = array();
121
  if ( isset( $new_instance['chrome'] ) ) {
122
  foreach ( $new_instance['chrome'] as $chrome ) {
123
+ if ( in_array( $chrome, array( 'noheader', 'nofooter', 'noborders', 'noscrollbar', 'transparent' ) ) ) {
124
  $instance['chrome'][] = $chrome;
125
  }
126
  }
148
  'theme' => 'light',
149
  'chrome' => array(),
150
  );
151
+
152
  $instance = wp_parse_args( (array) $instance, $defaults );
153
  ?>
154
 
169
 
170
  <p><small>
171
  <?php
172
+ echo wp_kses_post(
173
+ sprintf(
174
+ __( 'You need to <a href="%1$s" target="_blank">create a widget at Twitter.com</a>, and then enter your widget id (the long number found in the URL of your widget\'s config page) in the field below. <a href="%2$s" target="_blank">Read more</a>.', 'jetpack' ),
175
+ 'https://twitter.com/settings/widgets/new/user',
176
+ 'http://support.wordpress.com/widgets/twitter-timeline-widget/'
177
+ )
178
  );
179
  ?>
180
  </small></p>
188
  <input type="checkbox"<?php checked( in_array( 'noheader', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="noheader" /> <label for="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>"><?php esc_html_e( 'No Header', 'jetpack' ); ?></label><br />
189
  <input type="checkbox"<?php checked( in_array( 'nofooter', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-nofooter' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="nofooter" /> <label for="<?php echo $this->get_field_id( 'chrome-nofooter' ); ?>"><?php esc_html_e( 'No Footer', 'jetpack' ); ?></label><br />
190
  <input type="checkbox"<?php checked( in_array( 'noborders', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-noborders' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="noborders" /> <label for="<?php echo $this->get_field_id( 'chrome-noborders' ); ?>"><?php esc_html_e( 'No Borders', 'jetpack' ); ?></label><br />
191
+ <input type="checkbox"<?php checked( in_array( 'noscrollbar', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-noscrollbar' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="noscrollbar" /> <label for="<?php echo $this->get_field_id( 'chrome-noscrollbar' ); ?>"><?php esc_html_e( 'No Scrollbar', 'jetpack' ); ?></label><br />
192
  <input type="checkbox"<?php checked( in_array( 'transparent', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-transparent' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="transparent" /> <label for="<?php echo $this->get_field_id( 'chrome-transparent' ); ?>"><?php esc_html_e( 'Transparent Background', 'jetpack' ); ?></label>
193
  </p>
194
 
modules/widgets/twitter.php DELETED
@@ -1,434 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Twitter widget class
5
- * Display the latest N tweets from a Twitter screenname as a widget
6
- * Customize screenname, maximum number of tweets displayed, show or hide @replies, and text displayed between tweet text and a timestamp
7
- *
8
- */
9
-
10
- /**
11
- * Register the widget for use in Appearance -> Widgets
12
- */
13
- add_action( 'widgets_init', 'jetpack_twitter_widget_init' );
14
-
15
- function jetpack_twitter_widget_init() {
16
- register_widget( 'Jetpack_Widget_Twitter' );
17
- }
18
-
19
- class Jetpack_Widget_Twitter extends WP_Widget {
20
-
21
- var $twitter_v1_shutdown = 1367884800; //1367884800 = Tue, 07 May 2013 00:00:00 +0000
22
-
23
- function __construct() {
24
- parent::__construct(
25
- 'twitter',
26
- apply_filters( 'jetpack_widget_name', __( 'Twitter', 'jetpack' ) ),
27
- array(
28
- 'classname' => 'widget_twitter',
29
- 'description' => __( 'Display your Tweets from Twitter', 'jetpack' )
30
- )
31
- );
32
-
33
- if ( is_active_widget( false, false, $this->id_base ) || is_active_widget( false, false, 'monster' ) ) {
34
- add_action( 'wp_head', array( $this, 'style' ) );
35
- }
36
- }
37
-
38
- function style() {
39
- ?>
40
- <style type="text/css">
41
- .widget_twitter li {
42
- word-wrap: break-word;
43
- }
44
- </style>
45
- <?php
46
- }
47
-
48
- function widget( $args, $instance ) {
49
- $account = trim( urlencode( $instance['account'] ) );
50
-
51
- /**
52
- * After Twitter disables v1 API calls, show a message to admins/theme managers only that they can show Tweets using a different widget.
53
- */
54
- if ( time() >= $this->twitter_v1_shutdown ) {
55
-
56
- if ( current_user_can('edit_theme_options') ) {
57
- $title = apply_filters( 'widget_title', $instance['title'] );
58
- if ( empty( $title ) )
59
- $title = __( 'Twitter Updates', 'jetpack' );
60
-
61
- echo $args['before_widget'];
62
- echo "{$args['before_title']}<a href='" . esc_url( "http://twitter.com/{$account}" ) . "'>" . esc_html( $title ) . "</a>{$args['after_title']}";
63
- echo '<p>' . sprintf( __( 'Due to changes with how we interact with Twitter, this widget can no longer display Tweets. Please switch to the <a href="%s">Twitter Timeline</a> widget instead.', 'jetpack' ), admin_url( 'widgets.php' ) ) . '</p>';
64
- echo $args['after_widget'];
65
- }
66
-
67
- return;
68
- }
69
-
70
- if ( empty( $account ) ) {
71
- if ( current_user_can('edit_theme_options') ) {
72
- echo $args['before_widget'];
73
- echo '<p>' . sprintf( __( 'Please configure your Twitter username for the <a href="%s">Twitter Widget</a>.', 'jetpack' ), admin_url( 'widgets.php' ) ) . '</p>';
74
- echo $args['after_widget'];
75
- }
76
-
77
- return;
78
- }
79
-
80
- $title = apply_filters( 'widget_title', $instance['title'] );
81
-
82
- if ( empty( $title ) )
83
- $title = __( 'Twitter Updates', 'jetpack' );
84
-
85
- $show = absint( $instance['show'] ); // # of Updates to show
86
-
87
- if ( $show > 200 ) // Twitter paginates at 200 max tweets. update() should not have accepted greater than 20
88
- $show = 200;
89
-
90
- $hidereplies = (bool) $instance['hidereplies'];
91
- $hidepublicized = (bool) $instance['hidepublicized'];
92
- $include_retweets = (bool) $instance['includeretweets'];
93
- $follow_button = (bool) $instance['followbutton'];
94
-
95
- echo "{$args['before_widget']}{$args['before_title']}<a href='" . esc_url( "http://twitter.com/{$account}" ) . "'>" . esc_html( $title ) . "</a>{$args['after_title']}";
96
-
97
- $tweets = $this->fetch_twitter_user_stream( $account, $hidereplies, $show, $include_retweets );
98
-
99
- if ( isset( $tweets['error'] ) && ( isset( $tweets['data'] ) && ! empty( $tweets['data'] ) ) )
100
- $tweets['error'] = '';
101
-
102
- if ( empty( $tweets['error'] ) ) {
103
- $before_tweet = isset( $instance['beforetweet'] ) ? stripslashes( wp_filter_post_kses( $instance['beforetweet'] ) ) : '';
104
- $before_timesince = ( isset( $instance['beforetimesince'] ) && ! empty( $instance['beforetimesince'] ) ) ? esc_html( $instance['beforetimesince'] ) : ' ';
105
-
106
- $this->display_tweets( $show, $tweets['data'], $hidepublicized, $before_tweet, $before_timesince, $account );
107
-
108
- if ( $follow_button )
109
- $this->display_follow_button( $account );
110
-
111
- add_action( 'wp_footer', array( $this, 'twitter_widget_script' ) );
112
- } else {
113
- echo $tweets['error'];
114
- }
115
-
116
- echo $args['after_widget'];
117
- do_action( 'jetpack_bump_stats_extras', 'widget', 'twitter' );
118
- }
119
-
120
- function display_tweets( $show, $tweets, $hidepublicized, $before_tweet, $before_timesince, $account ) {
121
- $tweets_out = 0;
122
- ?><ul class='tweets'><?php
123
-
124
- foreach( (array) $tweets as $tweet ) {
125
- if ( $tweets_out >= $show )
126
- break;
127
-
128
- if ( empty( $tweet['text'] ) )
129
- continue;
130
-
131
- if( $hidepublicized && false !== strstr( $tweet['source'], 'http://publicize.wp.com/' ) )
132
- continue;
133
-
134
- $tweet['text'] = esc_html( $tweet['text'] ); // escape here so that Twitter handles in Tweets don't get mangled
135
- $tweet = $this->expand_tco_links( $tweet );
136
- $tweet['text'] = make_clickable( $tweet['text'] );
137
-
138
- /*
139
- * Create links from plain text based on Twitter patterns
140
- * @link http://github.com/mzsanford/twitter-text-rb/blob/master/lib/regex.rb Official Twitter regex
141
- */
142
- $tweet['text'] = preg_replace_callback( '/(^|[^0-9A-Z&\/]+)(#|\xef\xbc\x83)([0-9A-Z_]*[A-Z_]+[a-z0-9_\xc0-\xd6\xd8-\xf6\xf8\xff]*)/iu', array( $this, '_jetpack_widget_twitter_hashtag' ), $tweet['text'] );
143
- $tweet['text'] = preg_replace_callback( '/([^a-zA-Z0-9_]|^)([@\xef\xbc\xa0]+)([a-zA-Z0-9_]{1,20})(\/[a-zA-Z][a-zA-Z0-9\x80-\xff-]{0,79})?/u', array( $this, '_jetpack_widget_twitter_username' ), $tweet['text'] );
144
-
145
- if ( isset( $tweet['id_str'] ) )
146
- $tweet_id = urlencode( $tweet['id_str'] );
147
- else
148
- $tweet_id = urlencode( $tweet['id'] );
149
-
150
- ?>
151
-
152
- <li>
153
- <?php echo esc_attr( $before_tweet ) . $tweet['text'] . esc_attr( $before_timesince ) ?>
154
- <a href="<?php echo esc_url( "http://twitter.com/{$account}/statuses/{$tweet_id}" ); ?>" class="timesince"><?php echo esc_html( str_replace( ' ', '&nbsp;', $this->time_since( strtotime( $tweet['created_at'] ) ) ) ); ?>&nbsp;ago</a>
155
- </li>
156
-
157
- <?php
158
-
159
- unset( $tweet_it );
160
- $tweets_out++;
161
- }
162
-
163
- ?></ul><?php
164
- }
165
-
166
- function display_follow_button( $account ) {
167
- global $themecolors;
168
-
169
- $follow_colors = isset( $themecolors['link'] ) ? " data-link-color='#{$themecolors['link']}'" : '';
170
- $follow_colors .= isset( $themecolors['text'] ) ? " data-text-color='#{$themecolors['text']}'" : '';
171
- $follow_button_attrs = " class='twitter-follow-button' data-show-count='false'{$follow_colors}";
172
-
173
- ?><a href="http://twitter.com/<?php echo esc_attr( $account ); ?>" <?php echo $follow_button_attrs; ?>>Follow @<?php echo esc_attr( $account ); ?></a><?php
174
- }
175
-
176
- function expand_tco_links( $tweet ) {
177
- if ( ! empty( $tweet['entities']['urls'] ) && is_array( $tweet['entities']['urls'] ) ) {
178
- foreach ( $tweet['entities']['urls'] as $entity_url ) {
179
- if ( ! empty( $entity_url['expanded_url'] ) ) {
180
- $tweet['text'] = str_replace(
181
- $entity_url['url'],
182
- '<a href="' . esc_url( $entity_url['expanded_url'] ) . '"> ' . esc_html( $entity_url['display_url'] ) . '</a>',
183
- $tweet['text']
184
- );
185
- }
186
- }
187
- }
188
-
189
- return $tweet;
190
- }
191
-
192
- function fetch_twitter_user_stream( $account, $hidereplies, $show, $include_retweets ) {
193
- $tweets = get_transient( 'widget-twitter-' . $this->number );
194
- $the_error = get_transient( 'widget-twitter-error-' . $this->number );
195
-
196
- if ( ! $tweets ) {
197
- $params = array(
198
- 'screen_name' => $account, // Twitter account name
199
- 'trim_user' => true, // only basic user data (slims the result)
200
- 'include_entities' => true
201
- );
202
-
203
- // If combined with $count, $exclude_replies only filters that number of tweets (not all tweets up to the requested count).
204
- if ( $hidereplies )
205
- $params['exclude_replies'] = true;
206
- else
207
- $params['count'] = $show;
208
-
209
- if ( $include_retweets )
210
- $params['include_rts'] = true;
211
-
212
- $twitter_json_url = esc_url_raw( 'http://api.twitter.com/1/statuses/user_timeline.json?' . http_build_query( $params ), array( 'http', 'https' ) );
213
- unset( $params );
214
-
215
- $response = wp_remote_get( $twitter_json_url, array( 'User-Agent' => 'WordPress.com Twitter Widget' ) );
216
- $response_code = wp_remote_retrieve_response_code( $response );
217
-
218
- switch( $response_code ) {
219
- case 200 : // process tweets and display
220
- $tweets = json_decode( wp_remote_retrieve_body( $response ), true );
221
-
222
- if ( ! is_array( $tweets ) || isset( $tweets['error'] ) ) {
223
- do_action( 'jetpack_bump_stats_extras', 'twitter_widget', "request-fail-{$response_code}-bad-data" );
224
- $the_error = '<p>' . esc_html__( 'Error: Twitter did not respond. Please wait a few minutes and refresh this page.', 'jetpack' ) . '</p>';
225
- $tweet_cache_expire = 300;
226
- break;
227
- } else {
228
- set_transient( 'widget-twitter-backup-' . $this->number, $tweets, 86400 ); // A one day backup in case there is trouble talking to Twitter
229
- }
230
-
231
- do_action( 'jetpack_bump_stats_extras', 'twitter_widget', 'request-success' );
232
- $tweet_cache_expire = 900;
233
- break;
234
- case 401 : // display private stream notice
235
- do_action( 'jetpack_bump_stats_extras', 'twitter_widget', "request-fail-{$response_code}" );
236
-
237
- $tweets = array();
238
- $the_error = '<p>' . sprintf( esc_html__( 'Error: Please make sure the Twitter account is %1$spublic%2$s.', 'jetpack' ), '<a href="http://support.twitter.com/forums/10711/entries/14016">', '</a>' ) . '</p>';
239
- $tweet_cache_expire = 300;
240
- break;
241
- default : // display an error message
242
- do_action( 'jetpack_bump_stats_extras', 'twitter_widget', "request-fail-{$response_code}" );
243
-
244
- $tweets = get_transient( 'widget-twitter-backup-' . $this->number );
245
- $the_error = '<p>' . esc_html__( 'Error: Twitter did not respond. Please wait a few minutes and refresh this page.', 'jetpack' ) . '</p>';
246
- $tweet_cache_expire = 300;
247
- break;
248
- }
249
-
250
- set_transient( 'widget-twitter-' . $this->number, $tweets, $tweet_cache_expire );
251
- set_transient( 'widget-twitter-error-' . $this->number, $the_error, $tweet_cache_expire );
252
- }
253
-
254
- return array( 'data' => $tweets, 'error' => $the_error );
255
- }
256
-
257
- function update( $new_instance, $old_instance ) {
258
- $instance = array();
259
-
260
- $instance['account'] = trim( wp_kses( $new_instance['account'], array() ) );
261
- $instance['account'] = str_replace( array( 'http://twitter.com/', '/', '@', '#!', ), array( '', '', '', '', ), $instance['account'] );
262
-
263
- $instance['title'] = wp_kses( $new_instance['title'], array() );
264
- $instance['show'] = absint( $new_instance['show'] );
265
- $instance['hidereplies'] = isset( $new_instance['hidereplies'] );
266
- $instance['hidepublicized'] = isset( $new_instance['hidepublicized'] );
267
- $instance['includeretweets'] = isset( $new_instance['includeretweets'] );
268
-
269
- if ( $instance['followbutton'] != $new_instance['followbutton'] ) {
270
- if ( $new_instance['followbutton'] )
271
- do_action( 'jetpack_bump_stats_extras', 'twitter_widget', 'follow_button_enabled' );
272
- else
273
- do_action( 'jetpack_bump_stats_extras', 'twitter_widget', 'follow_button_disabled' );
274
- }
275
-
276
- $instance['followbutton'] = ! isset( $new_instance['followbutton'] ) ? 0 : 1;
277
- $instance['beforetimesince'] = $new_instance['beforetimesince'];
278
-
279
- delete_transient( 'widget-twitter-' . $this->number );
280
- delete_transient( 'widget-twitter-error-' . $this->number );
281
-
282
- return $instance;
283
- }
284
-
285
- function form( $instance ) {
286
- //Defaults
287
- $account = isset( $instance['account'] ) ? wp_kses( $instance['account'], array() ) : '';
288
- $title = isset( $instance['title'] ) ? $instance['title'] : '';
289
- $show = isset( $instance['show'] ) ? absint( $instance['show'] ) : 5;
290
- $show = ( $show < 1 || 20 < $show ) ? 5 : $show;
291
- $hidereplies = isset( $instance['hidereplies'] ) && ! empty( $instance['hidereplies'] ) ? (bool) $instance['hidereplies'] : false;
292
- $hidepublicized = isset( $instance['hidepublicized'] ) && ! empty( $instance['hidepublicized'] ) ? (bool) $instance['hidepublicized'] : false;
293
- $include_retweets = isset( $instance['includeretweets'] ) && ! empty( $instance['includeretweets'] ) ? (bool) $instance['includeretweets'] : false;
294
- $follow_button = isset( $instance['followbutton'] ) && ! empty( $instance['followbutton'] ) ? 1 : 0;
295
- $before_timesince = isset( $instance['beforetimesince'] ) && ! empty( $instance['beforetimesince'] ) ? esc_attr( $instance['beforetimesince'] ) : '';
296
-
297
- /**
298
- * Show a notice at the top of the widget configuation that they need to switch widgets.
299
- */
300
- ?>
301
- <p><em><?php printf( __( "On May 7th the twitter widget will stop operating due to <a href='%s'>API changes</a> that Twitter is making. To continue displaying your Tweets you should switch to the 'Twitter Timeline' widget.", 'jetpack' ), 'https://dev.twitter.com/blog/api-v1-retirement-final-dates' ); ?></em></p>
302
-
303
-
304
- <p>
305
- <label for="<?php echo $this->get_field_id( 'title' ); ?>">
306
- <?php esc_html_e( 'Title:', 'jetpack' )?>
307
- <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
308
- </label>
309
- </p>
310
-
311
- <p>
312
- <label for="<?php echo $this->get_field_id( 'account' ); ?>">
313
- <?php esc_html_e( 'Twitter username:', 'jetpack' ); ?> <a href="http://support.wordpress.com/widgets/twitter-widget/#twitter-username" target="_blank">( ? )</a>
314
- <input class="widefat" id="<?php echo $this->get_field_id( 'account' ); ?>" name="<?php echo $this->get_field_name( 'account' ); ?>" type="text" value="<?php echo esc_attr( $account ); ?>" />
315
- </label>
316
- </p>
317
-
318
- <p>
319
- <label for="<?php echo $this->get_field_id( 'show' ); ?>">
320
- <?php esc_html_e( 'Maximum number of Tweets to show:', 'jetpack' ); ?>
321
- <select id="<?php echo $this->get_field_id( 'show' ); ?>" name="<?php echo $this->get_field_name( 'show' ); ?>">
322
- <?php
323
- for ( $i = 1; $i <= 20; ++$i ) :
324
- ?><option value="<?php echo esc_attr( $i ); ?>" <?php selected( $show, $i ); ?>><?php echo esc_attr( $i ); ?></option><?php
325
- endfor;
326
- ?>
327
- </select>
328
- </label>
329
- </p>
330
-
331
- <p>
332
- <label for="<?php echo $this->get_field_id( 'hidereplies' ); ?>">
333
- <input id="<?php echo $this->get_field_id( 'hidereplies' );?>" class="checkbox" type="checkbox" name="<?php echo $this->get_field_name( 'hidereplies' ); ?>" <?php checked( $hidereplies, true ); ?> />
334
- <?php esc_html_e( 'Hide replies', 'jetpack' ); ?>
335
- </label>
336
- </p>
337
-
338
- <p>
339
- <label for="<?php echo $this->get_field_id( 'hidepublicized' ); ?>">
340
- <input id="<?php echo $this->get_field_id( 'hidepublicized' ); ?>" class="checkbox" type="checkbox" name="<?php echo $this->get_field_name( 'hidepublicized' ); ?>" <?php checked( $hidepublicized, true ); ?> />
341
- <?php esc_html_e( 'Hide Tweets pushed by Publicize', 'jetpack' ); ?>
342
- </label>
343
- </p>
344
-
345
- <p>
346
- <label for="<?php echo $this->get_field_id( 'includeretweets' ); ?>">
347
- <input id="<?php echo $this->get_field_id( 'includeretweets' ); ?>" class="checkbox" type="checkbox" name="<?php echo $this->get_field_name( 'includeretweets' ); ?>" <?php checked( $include_retweets, true ); ?> />
348
- <?php esc_html_e( 'Include retweets', 'jetpack' ); ?>
349
- </label>
350
- </p>
351
-
352
- <p>
353
- <label for="<?php echo $this->get_field_id( 'followbutton' ); ?>">
354
- <input id="<?php echo $this->get_field_id( 'followbutton' ); ?>" class="checkbox" type="checkbox" name="<?php echo $this->get_field_name( 'followbutton' ); ?>" <?php checked( $follow_button, 1 ); ?> />
355
- <?php esc_html_e( 'Display Follow Button', 'jetpack' ); ?>
356
- </label>
357
- </p>
358
-
359
- <p>
360
- <label for="<?php echo $this->get_field_id( 'beforetimesince' ); ?>">
361
- <?php esc_html_e( 'Text to display between Tweet and timestamp:', 'jetpack' ); ?>
362
- <input class="widefat" id="<?php echo $this->get_field_id( 'beforetimesince' ); ?>" name="<?php echo $this->get_field_name( 'beforetimesince' ); ?>" type="text" value="<?php echo esc_attr( $before_timesince ); ?>" />
363
- </label>
364
- </p>
365
-
366
- <?php
367
- }
368
-
369
- function time_since( $original, $do_more = 0 ) {
370
- // array of time period chunks
371
- $chunks = array(
372
- array(60 * 60 * 24 * 365 , 'year'),
373
- array(60 * 60 * 24 * 30 , 'month'),
374
- array(60 * 60 * 24 * 7, 'week'),
375
- array(60 * 60 * 24 , 'day'),
376
- array(60 * 60 , 'hour'),
377
- array(60 , 'minute'),
378
- );
379
-
380
- $today = time();
381
- $since = $today - $original;
382
-
383
- for ($i = 0, $j = count($chunks); $i < $j; $i++) {
384
- $seconds = $chunks[$i][0];
385
- $name = $chunks[$i][1];
386
-
387
- if (($count = floor($since / $seconds)) != 0)
388
- break;
389
- }
390
-
391
- $print = ($count == 1) ? '1 '.$name : "$count {$name}s";
392
-
393
- if ($i + 1 < $j) {
394
- $seconds2 = $chunks[$i + 1][0];
395
- $name2 = $chunks[$i + 1][1];
396
-
397
- // add second item if it's greater than 0
398
- if ( (($count2 = floor(($since - ($seconds * $count)) / $seconds2)) != 0) && $do_more )
399
- $print .= ($count2 == 1) ? ', 1 '.$name2 : ", $count2 {$name2}s";
400
- }
401
- return $print;
402
- }
403
-
404
- /**
405
- * Link a Twitter user mentioned in the tweet text to the user's page on Twitter.
406
- *
407
- * @param array $matches regex match
408
- * @return string Tweet text with inserted @user link
409
- */
410
- function _jetpack_widget_twitter_username( array $matches ) { // $matches has already been through wp_specialchars
411
- return "$matches[1]@<a href='" . esc_url( 'http://twitter.com/' . urlencode( $matches[3] ) ) . "'>$matches[3]</a>";
412
- }
413
-
414
- /**
415
- * Link a Twitter hashtag with a search results page on Twitter.com
416
- *
417
- * @param array $matches regex match
418
- * @return string Tweet text with inserted #hashtag link
419
- */
420
- function _jetpack_widget_twitter_hashtag( array $matches ) { // $matches has already been through wp_specialchars
421
- return "$matches[1]<a href='" . esc_url( 'http://twitter.com/search?q=%23' . urlencode( $matches[3] ) ) . "'>#$matches[3]</a>";
422
- }
423
-
424
- function twitter_widget_script() {
425
- if ( ! wp_script_is( 'twitter-widgets', 'registered' ) ) {
426
- if ( is_ssl() )
427
- $twitter_widget_js = 'https://platform.twitter.com/widgets.js';
428
- else
429
- $twitter_widget_js = 'http://platform.twitter.com/widgets.js';
430
- wp_register_script( 'twitter-widgets', $twitter_widget_js, array(), '20111117', true );
431
- wp_print_scripts( 'twitter-widgets' );
432
- }
433
- }
434
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === Jetpack by WordPress.com ===
2
- Contributors: automattic, alternatekev, andy, apeatling, azaozz, barry, beaulebens, cfinke, chellycat, danielbachhuber, daniloercoli, designsimply, eoigal, ethitter, gibrown, hew, hugobaeta, iammattthomas, jblz, jeherve, jkudish, Joen, johnjamesjacoby, jshreve, lancewillett, martinremy, matt, matveb, mdawaffe, nickmomrik, pento, stephdau, tmoorewp, viper007bond, westi, yoavf
3
  Tags: WordPress.com, statistics, stats, views, tweets, twitter, widget, gravatar, hovercards, profile, equations, latex, math, maths, youtube, shortcode, archives, audio, blip, bliptv, dailymotion, digg, flickr, googlevideo, google, googlemaps, kyte, kytetv, livevideo, redlasso, rockyou, rss, scribd, slide, slideshare, soundcloud, vimeo, shortlinks, wp.me, subscriptions, notifications, notes, json, api, rest, mosaic, gallery, slideshow
4
- Requires at least: 3.3
5
- Tested up to: 3.5
6
- Stable tag: 2.2.8
7
 
8
  Supercharge your WordPress site with powerful features previously only available to WordPress.com users.
9
 
@@ -25,7 +25,7 @@ Features include:
25
  * Hovercard popups for your commenters via [Gravatar](http://gravatar.com/).
26
  * Easily embedded media from popular sites like YouTube, Digg, and Vimeo.
27
  * The ability to post to your blog from any email client.
28
- * Integration with and automatic posting to your favorite social networks including Twitter, Facebook, Tumblr, and LinkedIn.
29
  * For the Math geeks, a simple way to include beautiful mathematical expressions on your site.
30
  * A widget for displaying recent tweets. Previously provided by [Wickett Twitter Widget](http://wordpress.org/extend/plugins/wickett-twitter-widget/)
31
  * Your readers can easily share your posts via email or their favorite social networks. Previously provided by the [Sharedaddy](http://wordpress.org/extend/plugins/sharedaddy/) WordPress plugin.
@@ -37,6 +37,7 @@ Features include:
37
  * The ability to allow applications to securely authenticate and access your site with your permission.
38
  * Creative formats for your image galleries: mosaic, circles, squares, and a slideshow view.
39
  * Add post sliders and other highlights to your theme with Featured Content.
 
40
  * and *many* more to come!
41
 
42
  Note: The stats portion of Jetpack uses Quantcast to enhance its data.
@@ -78,17 +79,110 @@ Easy! There are a couple of ways (more coming soon):
78
  8. Mobile Theme
79
 
80
  == Changelog ==
81
- = 2.2.8 =
82
  Release Date: May 26, 2016
83
 
84
  * Important security update. Please upgrade immediately.
85
 
86
- = 2.2.7 =
87
  * Bug Fix: Avoid function which isn't always defined.
88
 
89
- = 2.2.6 =
90
  * Important security update. CVE-2014-0173
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  = 2.2.5 =
93
  * Enhancement: Stats: Counting of registered users' views can now be enabled for specific roles
94
  * Bug Fix: Security tightening for metadata support in the REST API
1
  === Jetpack by WordPress.com ===
2
+ Contributors: automattic, alternatekev, andy, apeatling, azaozz, barry, beaulebens, blobaugh, cfinke, chellycat, danielbachhuber, daniloercoli, designsimply, eoigal, ethitter, gibrown, georgestephanis, hew, hugobaeta, iammattthomas, jblz, jeherve, jkudish, Joen, johnjamesjacoby, jshreve, lancewillett, martinremy, matt, matveb, mdawaffe, migueluy, nickmomrik, pento, stephdau, tmoorewp, Viper007Bond, westi, yoavf
3
  Tags: WordPress.com, statistics, stats, views, tweets, twitter, widget, gravatar, hovercards, profile, equations, latex, math, maths, youtube, shortcode, archives, audio, blip, bliptv, dailymotion, digg, flickr, googlevideo, google, googlemaps, kyte, kytetv, livevideo, redlasso, rockyou, rss, scribd, slide, slideshare, soundcloud, vimeo, shortlinks, wp.me, subscriptions, notifications, notes, json, api, rest, mosaic, gallery, slideshow
4
+ Requires at least: 3.5
5
+ Tested up to: 3.6
6
+ Stable tag: 2.3.8
7
 
8
  Supercharge your WordPress site with powerful features previously only available to WordPress.com users.
9
 
25
  * Hovercard popups for your commenters via [Gravatar](http://gravatar.com/).
26
  * Easily embedded media from popular sites like YouTube, Digg, and Vimeo.
27
  * The ability to post to your blog from any email client.
28
+ * Integration with and automatic posting to your favorite social networks including Twitter, Facebook, Tumblr, Path, and LinkedIn.
29
  * For the Math geeks, a simple way to include beautiful mathematical expressions on your site.
30
  * A widget for displaying recent tweets. Previously provided by [Wickett Twitter Widget](http://wordpress.org/extend/plugins/wickett-twitter-widget/)
31
  * Your readers can easily share your posts via email or their favorite social networks. Previously provided by the [Sharedaddy](http://wordpress.org/extend/plugins/sharedaddy/) WordPress plugin.
37
  * The ability to allow applications to securely authenticate and access your site with your permission.
38
  * Creative formats for your image galleries: mosaic, circles, squares, and a slideshow view.
39
  * Add post sliders and other highlights to your theme with Featured Content.
40
+ * Search once, get results from everything! A single search box that lets you search posts, pages, comments, and plugins
41
  * and *many* more to come!
42
 
43
  Note: The stats portion of Jetpack uses Quantcast to enhance its data.
79
  8. Mobile Theme
80
 
81
  == Changelog ==
82
+ = 2.3.8 =
83
  Release Date: May 26, 2016
84
 
85
  * Important security update. Please upgrade immediately.
86
 
87
+ = 2.3.7 =
88
  * Bug Fix: Avoid function which isn't always defined.
89
 
90
+ = 2.3.6 =
91
  * Important security update. CVE-2014-0173
92
 
93
+ = 2.3.5 =
94
+ * Enhancement: Added Path support to Publicize.
95
+
96
+ = 2.3.4 =
97
+ * Bug Fix: Correct when output occurs with CSV export for feedback.
98
+ * Bug Fix: Tidy up the Heartbeat API.
99
+ * Enhancement: User Agent: Improve detecting of bots.
100
+ * Enhancement: Genericons: Make sure we're pulling the freshest version from genericons.com on each release.
101
+ * Enhancement: JSON API: Open up replies/new endpoints so that users can comment on blogs that are not in their access token.
102
+ * Enhancement: Photon: Apply to `get_post_gallery()` function as well.
103
+ * Enhancement: Tiled Galleries: Add a default bottom margin to be more robust out of the box.
104
+ * Translations: Adding in fresher translation files.
105
+ * Deprecation: Removing the retinization code for 3.4, as it was included in WordPress trunk from 3.5 onwards.
106
+
107
+ = 2.3.3 =
108
+ * Bug Fix: We were inadvertently overwriting cron schedules with our Jetpack heartbeat. This should now be fixed.
109
+ * Enhancement: New Facebook Sharing icons.
110
+ * Enhancement: Minor update to the Minileven stylesheet.
111
+
112
+ = 2.3.2 =
113
+ * Bug Fix: Fixed an issue where Facebook Pages were not available when connecting a Publicize account.
114
+ * Bug Fix: For some web hosts, fixed an issue where 'Jetpack ID' error would occur consistently on connecting to WordPress.com.
115
+ * Enhancement: Adding some new stats and heartbeat checking to Jetpack.
116
+
117
+ = 2.3.1 =
118
+ * Enhancement: Social Links: Retooling the class for better consistency and performance behind the scenes.
119
+ * Enhancement: Omnisearch: Make it easier to search Custom Post Types. No longer need to extend the class, if all you want is a basic display. Just call `new Jetpack_Omnisearch_Posts( 'cpt' );`
120
+ * Enhancement: Sharing Buttons: LinkedIn: Use the official button's sharing link on the Jetpack implementation for a more consistent sharing experience and produce better results on LinkedIn's end.
121
+ * Enhancement: Debug / Connection: Better logic in determining whether the server can use SSL to connect to WPCOM servers.
122
+ * Enhancement: Sharing: Twitter: Calculate the size of the Tweet based on the short URL rather than the full URL size.
123
+ * Enhancement: Debug: More readable and understandable messages.
124
+ * Enhancement: Likes: Including some MP6 styles.
125
+ * Enhancement: Comments: Add new core classes to comment form. See http://core.trac.wordpress.org/changeset/24525
126
+ * Bug Fix: Omnisearch: Don't load everything initially, run the providers off admin_init, and then issue an action for folks to hook into.
127
+ * Bug Fix: Omnisearch: Modify some child class functions to match the parent's parameters and avoid strict notices in newer versions of PHP.
128
+ * Bug Fix: Omnisearch: Hide the search form in the module description if the current user can't use it.
129
+ * Bug Fix: Comment Form: Use edit_pages, not edit_page (fixes glitch in previous beta, never publicly released).
130
+ * Bug Fix: Twitter Timeline Widget: Additional testing of values and casting to default if they are nonconforming.
131
+ * Bug Fix: Sharing: Pinterest: Make the button wider if there's a count to avoid overlapping with others.
132
+ * Bug Fix: Post By Email: Change configuration_redirect to static.
133
+ * Bug Fix: Likes: Don't call configuration_redirect as a static, do it as a method.
134
+ * Bug Fix: Add some further security measures to module activation.
135
+
136
+ = 2.3 =
137
+ * Enhancement: Omnisearch: Search once, get results from everything! Omnisearch is a single search box that lets you search many different things
138
+ * Enhancement: Debugger: this module helps you debug connection issues right from your dashboard, and contact the Jetpack support team if needed
139
+ * Enhancement: Social Links: this module is a canonical source, based on Publicize, that themes can use to let users specify where social icons should link to
140
+ * Enhancement: It’s now easier to find out if a module is active or note, thanks to the new Jetpack::is_module_active()
141
+ * Enhancement: Contact Form: You are now able to customize the submit button text thanks to the submit_button_text parameter
142
+ * Enhancement: Comments: We've added a filter to let users customize the Comment Reply label, and users can now also customize the prompt on the comment form again.
143
+ * Enhancement: Mobile Theme: Add genericons.css and registering it so it’s easily accessible to other modules that may want it
144
+ * Enhancement: Tiled Galleries: You can now customize the captions, thanks to the jetpack_slideshow_slide_caption filter
145
+ * Enhancement: Widgets: Twitter Timeline: Add the noscrollbar option
146
+ * Enhancement: Widgets: Facebook Like Box Widget: add a show_border attribute
147
+ * Enhancement: Widgets: FB Like Box: let Jetpack users override the iframe background color set in an inline style attribute by using the jetpack_fb_likebox_bg filter
148
+ * Bug Fix: Carousel: Fix a bug where double-clicking a gallery thumbnail broke the carousel functionality
149
+ * Bug Fix: Comments: Change “must-log-in” to class from ID
150
+ * Bug Fix: Contact Form: Make the Add Contact Form link a button, ala Add Media in core
151
+ * Bug Fix: Contact Form: Fix encoding of field labels
152
+ * Bug Fix: Contact Form: Remove references to missing images
153
+ * Bug Fix: Fix 2 XSS vulnerabilities
154
+ * Bug Fix: JSON API: Minor fixes for bbPress compatibility
155
+ * Bug Fix: JSON API: Fix metadata bugs
156
+ * Bug Fix: JSON API: Add a new hook that is fired when a post is posted using the API
157
+ * Bug Fix: JSON API: Prefork/REST: update path normalizer to accept versions other than 1
158
+ * Bug Fix: JSON API: Remove extra parenthesis in CSS
159
+ * Bug Fix: Custom CSS: Move content width filters higher up so that they’re active for all users, not just logged-in admins.
160
+ * Bug Fix: Custom CSS: All CSS properties that accept images as values need to be allowed to be declared multiple times so that cross-browser gradients work
161
+ * Bug Fix: Infinite Scroll: Allow themes to define a custom function to render the IS footer
162
+ * Bug Fix: Infinite Scroll: Fix up Twenty Thirteen styles for RTL and small viewports.
163
+ * Bug Fix: Likes: Fix ‘Call to undefined function’
164
+ * Bug Fix: Likes: Add scrolling no to iframe to make sure that like button in admin bar does not show scrollbars
165
+ * Bug Fix: Likes: Remove setInterval( JetpackLikesWidgetQueueHandler, 250 ) call that was causing heavy CPU load
166
+ * Bug Fix: Mobile Theme: Remove unused variable & function call
167
+ * Bug Fix: Publicize: Fix LinkedIn profile URL generation
168
+ * Bug Fix: Publicize: Better refresh handling for services such as LinkedIn and Facebook
169
+ * Bug Fix: Shortcodes: Audio shortcode: Treat src as element 0. Fixes audio shortcodes created by wp_embed_register_handler when an audio url is on a line by itself
170
+ * Bug Fix: Bandcamp: Updates to the Bandcamp shortcode
171
+ * Bug Fix: Stats: Fix missing function get_editable_roles on non-admin page loads
172
+ * Bug Fix: Widgets: Twitter Timeline: Fix HTML links in admin; set default values for width/height; change some of the sanitization functions
173
+ * Bug Fix: Widgets: Top Posts Widget: Exclude attachments
174
+ * Bug Fix: Widgets: Top Posts Widget: fix data validation for number of posts
175
+ * Bug Fix: Fix PHP warnings non-static method called dynamically
176
+ * Bug Fix: Fixed an issue in image extraction from HTML content
177
+ * Bug Fix: Open Graph: Change default minimum size for og:image too 200×200
178
+ * Note: The old Twitter widget was removed in favour of Twitter Timeline widget
179
+ * Note: Add is_module_active() to make it easier to detect what is and what isn’t
180
+ * Note: Compressing images via lossless methods
181
+ * Note: Tidying up jetpack’s CSS
182
+ * Note: Set the max DB version for our retina overrides that were meant to stop for WordPress 3.5
183
+ * Note: Updating spin.js to the current version, and shifting to the canonical jquery.spin.js library
184
+ * Note: Adding Jetpack_Options class, and abstracting out options functions to it
185
+
186
  = 2.2.5 =
187
  * Enhancement: Stats: Counting of registered users' views can now be enabled for specific roles
188
  * Bug Fix: Security tightening for metadata support in the REST API